1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include <algorithm> 6 7#include "extensions/common/error_utils.h" 8#include "extensions/common/manifest_constants.h" 9#include "extensions/common/manifest_handlers/externally_connectable.h" 10#include "extensions/common/manifest_test.h" 11#include "extensions/common/permissions/permissions_data.h" 12#include "testing/gmock/include/gmock/gmock.h" 13#include "testing/gtest/include/gtest/gtest.h" 14 15using testing::ElementsAre; 16 17namespace extensions { 18 19namespace errors = externally_connectable_errors; 20 21class ExternallyConnectableTest : public ManifestTest { 22 public: 23 ExternallyConnectableTest() {} 24 virtual ~ExternallyConnectableTest() {} 25 26 protected: 27 ExternallyConnectableInfo* GetExternallyConnectableInfo( 28 scoped_refptr<Extension> extension) { 29 return static_cast<ExternallyConnectableInfo*>( 30 extension->GetManifestData(manifest_keys::kExternallyConnectable)); 31 } 32}; 33 34TEST_F(ExternallyConnectableTest, IDsAndMatches) { 35 scoped_refptr<Extension> extension = 36 LoadAndExpectSuccess("externally_connectable_ids_and_matches.json"); 37 ASSERT_TRUE(extension.get()); 38 39 EXPECT_TRUE(extension->permissions_data()->HasAPIPermission( 40 APIPermission::kWebConnectable)); 41 42 ExternallyConnectableInfo* info = 43 ExternallyConnectableInfo::Get(extension.get()); 44 ASSERT_TRUE(info); 45 46 EXPECT_THAT(info->ids, 47 ElementsAre("abcdefghijklmnopabcdefghijklmnop", 48 "ponmlkjihgfedcbaponmlkjihgfedcba")); 49 50 EXPECT_FALSE(info->all_ids); 51 52 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://example.com"))); 53 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://example.com/"))); 54 EXPECT_FALSE(info->matches.MatchesURL(GURL("http://example.com/index.html"))); 55 56 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://google.com"))); 57 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://google.com/"))); 58 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://google.com/index.html"))); 59 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://www.google.com"))); 60 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://www.google.com/"))); 61 EXPECT_TRUE(info->matches.MatchesURL(GURL("https://google.com"))); 62 EXPECT_TRUE(info->matches.MatchesURL(GURL("https://google.com/"))); 63 64 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org"))); 65 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org/"))); 66 EXPECT_TRUE( 67 info->matches.MatchesURL(GURL("http://build.chromium.org/index.html"))); 68 EXPECT_FALSE(info->matches.MatchesURL(GURL("https://build.chromium.org"))); 69 EXPECT_FALSE(info->matches.MatchesURL(GURL("https://build.chromium.org/"))); 70 EXPECT_FALSE( 71 info->matches.MatchesURL(GURL("http://foo.chromium.org/index.html"))); 72 73 EXPECT_FALSE(info->matches.MatchesURL(GURL("http://yahoo.com"))); 74 EXPECT_FALSE(info->matches.MatchesURL(GURL("http://yahoo.com/"))); 75 76 // TLD-style patterns should match just the TLD. 77 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://appspot.com/foo.html"))); 78 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://com"))); 79 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://go/here"))); 80 81 // TLD-style patterns should *not* match any subdomains of the TLD. 82 EXPECT_FALSE( 83 info->matches.MatchesURL(GURL("http://codereview.appspot.com/foo.html"))); 84 EXPECT_FALSE( 85 info->matches.MatchesURL(GURL("http://chromium.com/index.html"))); 86 EXPECT_FALSE(info->matches.MatchesURL(GURL("http://here.go/somewhere"))); 87 88 // Paths that don't have any wildcards should match the exact domain, but 89 // ignore the trailing slash. This is kind of a corner case, so let's test it. 90 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://no.wildcard.path"))); 91 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://no.wildcard.path/"))); 92 EXPECT_FALSE( 93 info->matches.MatchesURL(GURL("http://no.wildcard.path/index.html"))); 94} 95 96TEST_F(ExternallyConnectableTest, IDs) { 97 scoped_refptr<Extension> extension = 98 LoadAndExpectSuccess("externally_connectable_ids.json"); 99 ASSERT_TRUE(extension.get()); 100 101 EXPECT_FALSE(extension->permissions_data()->HasAPIPermission( 102 APIPermission::kWebConnectable)); 103 104 ExternallyConnectableInfo* info = 105 ExternallyConnectableInfo::Get(extension.get()); 106 ASSERT_TRUE(info); 107 108 EXPECT_THAT(info->ids, 109 ElementsAre("abcdefghijklmnopabcdefghijklmnop", 110 "ponmlkjihgfedcbaponmlkjihgfedcba")); 111 112 EXPECT_FALSE(info->all_ids); 113 114 EXPECT_FALSE(info->matches.MatchesURL(GURL("http://google.com/index.html"))); 115} 116 117TEST_F(ExternallyConnectableTest, Matches) { 118 scoped_refptr<Extension> extension = 119 LoadAndExpectSuccess("externally_connectable_matches.json"); 120 ASSERT_TRUE(extension.get()); 121 122 EXPECT_TRUE(extension->permissions_data()->HasAPIPermission( 123 APIPermission::kWebConnectable)); 124 125 ExternallyConnectableInfo* info = 126 ExternallyConnectableInfo::Get(extension.get()); 127 ASSERT_TRUE(info); 128 129 EXPECT_THAT(info->ids, ElementsAre()); 130 131 EXPECT_FALSE(info->all_ids); 132 133 EXPECT_FALSE(info->accepts_tls_channel_id); 134 135 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://example.com"))); 136 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://example.com/"))); 137 EXPECT_FALSE(info->matches.MatchesURL(GURL("http://example.com/index.html"))); 138 139 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://google.com"))); 140 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://google.com/"))); 141 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://google.com/index.html"))); 142 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://www.google.com"))); 143 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://www.google.com/"))); 144 EXPECT_TRUE(info->matches.MatchesURL(GURL("https://google.com"))); 145 EXPECT_TRUE(info->matches.MatchesURL(GURL("https://google.com/"))); 146 147 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org"))); 148 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org/"))); 149 EXPECT_TRUE( 150 info->matches.MatchesURL(GURL("http://build.chromium.org/index.html"))); 151 EXPECT_FALSE(info->matches.MatchesURL(GURL("https://build.chromium.org"))); 152 EXPECT_FALSE(info->matches.MatchesURL(GURL("https://build.chromium.org/"))); 153 EXPECT_FALSE( 154 info->matches.MatchesURL(GURL("http://foo.chromium.org/index.html"))); 155 156 EXPECT_FALSE(info->matches.MatchesURL(GURL("http://yahoo.com"))); 157 EXPECT_FALSE(info->matches.MatchesURL(GURL("http://yahoo.com/"))); 158} 159 160TEST_F(ExternallyConnectableTest, MatchesWithTlsChannelId) { 161 scoped_refptr<Extension> extension = LoadAndExpectSuccess( 162 "externally_connectable_matches_tls_channel_id.json"); 163 ASSERT_TRUE(extension.get()); 164 165 EXPECT_TRUE(extension->permissions_data()->HasAPIPermission( 166 APIPermission::kWebConnectable)); 167 168 ExternallyConnectableInfo* info = 169 ExternallyConnectableInfo::Get(extension.get()); 170 ASSERT_TRUE(info); 171 172 EXPECT_THAT(info->ids, ElementsAre()); 173 174 EXPECT_FALSE(info->all_ids); 175 176 EXPECT_TRUE(info->accepts_tls_channel_id); 177 178 // The matches portion of the manifest is identical to those in 179 // externally_connectable_matches, so only a subset of the Matches tests is 180 // repeated here. 181 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://example.com"))); 182 EXPECT_FALSE(info->matches.MatchesURL(GURL("http://example.com/index.html"))); 183} 184 185TEST_F(ExternallyConnectableTest, AllIDs) { 186 scoped_refptr<Extension> extension = 187 LoadAndExpectSuccess("externally_connectable_all_ids.json"); 188 ASSERT_TRUE(extension.get()); 189 190 EXPECT_FALSE(extension->permissions_data()->HasAPIPermission( 191 APIPermission::kWebConnectable)); 192 193 ExternallyConnectableInfo* info = 194 ExternallyConnectableInfo::Get(extension.get()); 195 ASSERT_TRUE(info); 196 197 EXPECT_THAT(info->ids, 198 ElementsAre("abcdefghijklmnopabcdefghijklmnop", 199 "ponmlkjihgfedcbaponmlkjihgfedcba")); 200 201 EXPECT_TRUE(info->all_ids); 202 203 EXPECT_FALSE(info->matches.MatchesURL(GURL("http://google.com/index.html"))); 204} 205 206TEST_F(ExternallyConnectableTest, IdCanConnect) { 207 // Not in order to test that ExternallyConnectableInfo sorts it. 208 std::string matches_ids_array[] = {"g", "h", "c", "i", "a", "z", "b"}; 209 std::vector<std::string> matches_ids( 210 matches_ids_array, matches_ids_array + arraysize(matches_ids_array)); 211 212 std::string nomatches_ids_array[] = {"2", "3", "1"}; 213 214 // all_ids = false. 215 { 216 ExternallyConnectableInfo info(URLPatternSet(), matches_ids, false, false); 217 for (size_t i = 0; i < matches_ids.size(); ++i) 218 EXPECT_TRUE(info.IdCanConnect(matches_ids[i])); 219 for (size_t i = 0; i < arraysize(nomatches_ids_array); ++i) 220 EXPECT_FALSE(info.IdCanConnect(nomatches_ids_array[i])); 221 } 222 223 // all_ids = true. 224 { 225 ExternallyConnectableInfo info(URLPatternSet(), matches_ids, true, false); 226 for (size_t i = 0; i < matches_ids.size(); ++i) 227 EXPECT_TRUE(info.IdCanConnect(matches_ids[i])); 228 for (size_t i = 0; i < arraysize(nomatches_ids_array); ++i) 229 EXPECT_TRUE(info.IdCanConnect(nomatches_ids_array[i])); 230 } 231} 232 233TEST_F(ExternallyConnectableTest, ErrorWrongFormat) { 234 LoadAndExpectError("externally_connectable_error_wrong_format.json", 235 "expected dictionary, got string"); 236} 237 238TEST_F(ExternallyConnectableTest, ErrorBadID) { 239 LoadAndExpectError( 240 "externally_connectable_bad_id.json", 241 ErrorUtils::FormatErrorMessage(errors::kErrorInvalidId, "badid")); 242} 243 244TEST_F(ExternallyConnectableTest, ErrorBadMatches) { 245 LoadAndExpectError("externally_connectable_error_bad_matches.json", 246 ErrorUtils::FormatErrorMessage( 247 errors::kErrorInvalidMatchPattern, "www.yahoo.com")); 248} 249 250TEST_F(ExternallyConnectableTest, WarningNoAllURLs) { 251 scoped_refptr<Extension> extension = LoadAndExpectWarning( 252 "externally_connectable_error_all_urls.json", 253 ErrorUtils::FormatErrorMessage(errors::kErrorWildcardHostsNotAllowed, 254 "<all_urls>")); 255 ExternallyConnectableInfo* info = GetExternallyConnectableInfo(extension); 256 EXPECT_FALSE(info->matches.MatchesAllURLs()); 257 EXPECT_FALSE(info->matches.ContainsPattern( 258 URLPattern(URLPattern::SCHEME_ALL, "<all_urls>"))); 259 EXPECT_TRUE(info->matches.MatchesURL(GURL("https://example.com"))); 260 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org"))); 261} 262 263TEST_F(ExternallyConnectableTest, AllURLsNotWhitelisted) { 264 scoped_refptr<Extension> extension = LoadAndExpectSuccess( 265 "externally_connectable_all_urls_not_whitelisted.json"); 266 ExternallyConnectableInfo* info = GetExternallyConnectableInfo(extension); 267 EXPECT_FALSE(info->matches.MatchesAllURLs()); 268} 269 270TEST_F(ExternallyConnectableTest, AllURLsWhitelisted) { 271 scoped_refptr<Extension> extension = 272 LoadAndExpectSuccess("externally_connectable_all_urls_whitelisted.json"); 273 ExternallyConnectableInfo* info = GetExternallyConnectableInfo(extension); 274 EXPECT_TRUE(info->matches.MatchesAllURLs()); 275 URLPattern pattern(URLPattern::SCHEME_ALL, "<all_urls>"); 276 EXPECT_TRUE(info->matches.ContainsPattern(pattern)); 277 EXPECT_TRUE(info->matches.MatchesURL(GURL("https://example.com"))); 278 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org"))); 279} 280 281TEST_F(ExternallyConnectableTest, WarningWildcardHost) { 282 scoped_refptr<Extension> extension = LoadAndExpectWarning( 283 "externally_connectable_error_wildcard_host.json", 284 ErrorUtils::FormatErrorMessage(errors::kErrorWildcardHostsNotAllowed, 285 "http://*/*")); 286 ExternallyConnectableInfo* info = GetExternallyConnectableInfo(extension); 287 EXPECT_FALSE(info->matches.ContainsPattern( 288 URLPattern(URLPattern::SCHEME_ALL, "http://*/*"))); 289 EXPECT_TRUE(info->matches.MatchesURL(GURL("https://example.com"))); 290 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org"))); 291} 292 293TEST_F(ExternallyConnectableTest, WarningNoTLD) { 294 scoped_refptr<Extension> extension = LoadAndExpectWarning( 295 "externally_connectable_error_tld.json", 296 ErrorUtils::FormatErrorMessage(errors::kErrorTopLevelDomainsNotAllowed, 297 "co.uk", 298 "http://*.co.uk/*")); 299 ExternallyConnectableInfo* info = GetExternallyConnectableInfo(extension); 300 EXPECT_FALSE(info->matches.ContainsPattern( 301 URLPattern(URLPattern::SCHEME_ALL, "http://*.co.uk/*"))); 302 EXPECT_TRUE(info->matches.MatchesURL(GURL("https://example.com"))); 303 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org"))); 304} 305 306TEST_F(ExternallyConnectableTest, WarningNoEffectiveTLD) { 307 scoped_refptr<Extension> extension = LoadAndExpectWarning( 308 "externally_connectable_error_effective_tld.json", 309 ErrorUtils::FormatErrorMessage(errors::kErrorTopLevelDomainsNotAllowed, 310 "appspot.com", 311 "http://*.appspot.com/*")); 312 ExternallyConnectableInfo* info = GetExternallyConnectableInfo(extension); 313 EXPECT_FALSE(info->matches.ContainsPattern( 314 URLPattern(URLPattern::SCHEME_ALL, "http://*.appspot.com/*"))); 315 EXPECT_TRUE(info->matches.MatchesURL(GURL("https://example.com"))); 316 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org"))); 317} 318 319TEST_F(ExternallyConnectableTest, WarningUnknownTLD) { 320 scoped_refptr<Extension> extension = LoadAndExpectWarning( 321 "externally_connectable_error_unknown_tld.json", 322 ErrorUtils::FormatErrorMessage(errors::kErrorTopLevelDomainsNotAllowed, 323 "notatld", 324 "http://*.notatld/*")); 325 ExternallyConnectableInfo* info = GetExternallyConnectableInfo(extension); 326 EXPECT_FALSE(info->matches.ContainsPattern( 327 URLPattern(URLPattern::SCHEME_ALL, "http://*.notatld/*"))); 328 EXPECT_TRUE(info->matches.MatchesURL(GURL("https://example.com"))); 329 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org"))); 330} 331 332TEST_F(ExternallyConnectableTest, WarningNothingSpecified) { 333 LoadAndExpectWarning("externally_connectable_nothing_specified.json", 334 errors::kErrorNothingSpecified); 335} 336 337} // namespace extensions 338