1// Copyright 2013 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 "chrome/common/extensions/extension_manifest_constants.h" 8#include "chrome/common/extensions/features/feature_channel.h" 9#include "chrome/common/extensions/manifest_handlers/externally_connectable.h" 10#include "chrome/common/extensions/manifest_tests/extension_manifest_test.h" 11#include "extensions/common/error_utils.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 ExtensionManifestTest { 22 public: 23 ExternallyConnectableTest() : channel_(chrome::VersionInfo::CHANNEL_DEV) {} 24 25 protected: 26 ExternallyConnectableInfo* GetExternallyConnectableInfo( 27 scoped_refptr<Extension> extension) { 28 return static_cast<ExternallyConnectableInfo*>(extension->GetManifestData( 29 extension_manifest_keys::kExternallyConnectable)); 30 } 31 32 private: 33 ScopedCurrentChannel channel_; 34}; 35 36TEST_F(ExternallyConnectableTest, IDsAndMatches) { 37 scoped_refptr<Extension> extension = 38 LoadAndExpectSuccess("externally_connectable_ids_and_matches.json"); 39 ASSERT_TRUE(extension.get()); 40 41 EXPECT_TRUE(extension->HasAPIPermission(APIPermission::kWebConnectable)); 42 43 ExternallyConnectableInfo* info = 44 ExternallyConnectableInfo::Get(extension.get()); 45 ASSERT_TRUE(info); 46 47 EXPECT_THAT(info->ids, 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(info->matches.MatchesURL( 93 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->HasAPIPermission(APIPermission::kWebConnectable)); 102 103 ExternallyConnectableInfo* info = 104 ExternallyConnectableInfo::Get(extension.get()); 105 ASSERT_TRUE(info); 106 107 EXPECT_THAT(info->ids, ElementsAre("abcdefghijklmnopabcdefghijklmnop", 108 "ponmlkjihgfedcbaponmlkjihgfedcba")); 109 110 EXPECT_FALSE(info->all_ids); 111 112 EXPECT_FALSE(info->matches.MatchesURL(GURL("http://google.com/index.html"))); 113} 114 115TEST_F(ExternallyConnectableTest, Matches) { 116 scoped_refptr<Extension> extension = 117 LoadAndExpectSuccess("externally_connectable_matches.json"); 118 ASSERT_TRUE(extension.get()); 119 120 EXPECT_TRUE(extension->HasAPIPermission(APIPermission::kWebConnectable)); 121 122 ExternallyConnectableInfo* info = 123 ExternallyConnectableInfo::Get(extension.get()); 124 ASSERT_TRUE(info); 125 126 EXPECT_THAT(info->ids, ElementsAre()); 127 128 EXPECT_FALSE(info->all_ids); 129 130 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://example.com"))); 131 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://example.com/"))); 132 EXPECT_FALSE(info->matches.MatchesURL(GURL("http://example.com/index.html"))); 133 134 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://google.com"))); 135 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://google.com/"))); 136 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://google.com/index.html"))); 137 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://www.google.com"))); 138 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://www.google.com/"))); 139 EXPECT_TRUE(info->matches.MatchesURL(GURL("https://google.com"))); 140 EXPECT_TRUE(info->matches.MatchesURL(GURL("https://google.com/"))); 141 142 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org"))); 143 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org/"))); 144 EXPECT_TRUE( 145 info->matches.MatchesURL(GURL("http://build.chromium.org/index.html"))); 146 EXPECT_FALSE(info->matches.MatchesURL(GURL("https://build.chromium.org"))); 147 EXPECT_FALSE(info->matches.MatchesURL(GURL("https://build.chromium.org/"))); 148 EXPECT_FALSE( 149 info->matches.MatchesURL(GURL("http://foo.chromium.org/index.html"))); 150 151 EXPECT_FALSE(info->matches.MatchesURL(GURL("http://yahoo.com"))); 152 EXPECT_FALSE(info->matches.MatchesURL(GURL("http://yahoo.com/"))); 153} 154 155TEST_F(ExternallyConnectableTest, AllIDs) { 156 scoped_refptr<Extension> extension = 157 LoadAndExpectSuccess("externally_connectable_all_ids.json"); 158 ASSERT_TRUE(extension.get()); 159 160 EXPECT_FALSE(extension->HasAPIPermission(APIPermission::kWebConnectable)); 161 162 ExternallyConnectableInfo* info = 163 ExternallyConnectableInfo::Get(extension.get()); 164 ASSERT_TRUE(info); 165 166 EXPECT_THAT(info->ids, ElementsAre("abcdefghijklmnopabcdefghijklmnop", 167 "ponmlkjihgfedcbaponmlkjihgfedcba")); 168 169 EXPECT_TRUE(info->all_ids); 170 171 EXPECT_FALSE(info->matches.MatchesURL(GURL("http://google.com/index.html"))); 172} 173 174TEST_F(ExternallyConnectableTest, IdCanConnect) { 175 // Not in order to test that ExternallyConnectableInfo sorts it. 176 std::string matches_ids_array[] = { "g", "h", "c", "i", "a", "z", "b" }; 177 std::vector<std::string> matches_ids( 178 matches_ids_array, matches_ids_array + arraysize(matches_ids_array)); 179 180 std::string nomatches_ids_array[] = { "2", "3", "1" }; 181 182 // all_ids = false. 183 { 184 ExternallyConnectableInfo info(URLPatternSet(), matches_ids, false); 185 for (size_t i = 0; i < matches_ids.size(); ++i) 186 EXPECT_TRUE(info.IdCanConnect(matches_ids[i])); 187 for (size_t i = 0; i < arraysize(nomatches_ids_array); ++i) 188 EXPECT_FALSE(info.IdCanConnect(nomatches_ids_array[i])); 189 } 190 191 // all_ids = true. 192 { 193 ExternallyConnectableInfo info(URLPatternSet(), matches_ids, true); 194 for (size_t i = 0; i < matches_ids.size(); ++i) 195 EXPECT_TRUE(info.IdCanConnect(matches_ids[i])); 196 for (size_t i = 0; i < arraysize(nomatches_ids_array); ++i) 197 EXPECT_TRUE(info.IdCanConnect(nomatches_ids_array[i])); 198 } 199} 200 201TEST_F(ExternallyConnectableTest, ErrorWrongFormat) { 202 LoadAndExpectError("externally_connectable_error_wrong_format.json", 203 errors::kErrorInvalid); 204} 205 206TEST_F(ExternallyConnectableTest, ErrorBadID) { 207 LoadAndExpectError( 208 "externally_connectable_bad_id.json", 209 ErrorUtils::FormatErrorMessage(errors::kErrorInvalidId, "badid")); 210} 211 212TEST_F(ExternallyConnectableTest, ErrorBadMatches) { 213 LoadAndExpectError( 214 "externally_connectable_error_bad_matches.json", 215 ErrorUtils::FormatErrorMessage(errors::kErrorInvalidMatchPattern, 216 "www.yahoo.com")); 217} 218 219TEST_F(ExternallyConnectableTest, WarningNoAllURLs) { 220 scoped_refptr<Extension> extension = LoadAndExpectWarning( 221 "externally_connectable_error_all_urls.json", 222 ErrorUtils::FormatErrorMessage(errors::kErrorWildcardHostsNotAllowed, 223 "<all_urls>")); 224 ExternallyConnectableInfo* info = GetExternallyConnectableInfo(extension); 225 EXPECT_FALSE(info->matches.ContainsPattern( 226 URLPattern(URLPattern::SCHEME_ALL, "<all_urls>"))); 227 EXPECT_TRUE(info->matches.MatchesURL(GURL("https://example.com"))); 228 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org"))); 229} 230 231TEST_F(ExternallyConnectableTest, WarningWildcardHost) { 232 scoped_refptr<Extension> extension = LoadAndExpectWarning( 233 "externally_connectable_error_wildcard_host.json", 234 ErrorUtils::FormatErrorMessage(errors::kErrorWildcardHostsNotAllowed, 235 "http://*/*")); 236 ExternallyConnectableInfo* info = GetExternallyConnectableInfo(extension); 237 EXPECT_FALSE(info->matches.ContainsPattern( 238 URLPattern(URLPattern::SCHEME_ALL, "http://*/*"))); 239 EXPECT_TRUE(info->matches.MatchesURL(GURL("https://example.com"))); 240 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org"))); 241} 242 243TEST_F(ExternallyConnectableTest, WarningNoTLD) { 244 scoped_refptr<Extension> extension = LoadAndExpectWarning( 245 "externally_connectable_error_tld.json", 246 ErrorUtils::FormatErrorMessage( 247 errors::kErrorTopLevelDomainsNotAllowed, 248 "co.uk", 249 "http://*.co.uk/*")); 250 ExternallyConnectableInfo* info = GetExternallyConnectableInfo(extension); 251 EXPECT_FALSE(info->matches.ContainsPattern( 252 URLPattern(URLPattern::SCHEME_ALL, "http://*.co.uk/*"))); 253 EXPECT_TRUE(info->matches.MatchesURL(GURL("https://example.com"))); 254 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org"))); 255} 256 257TEST_F(ExternallyConnectableTest, WarningNoEffectiveTLD) { 258 scoped_refptr<Extension> extension = LoadAndExpectWarning( 259 "externally_connectable_error_effective_tld.json", 260 ErrorUtils::FormatErrorMessage( 261 errors::kErrorTopLevelDomainsNotAllowed, 262 "appspot.com", 263 "http://*.appspot.com/*")); 264 ExternallyConnectableInfo* info = GetExternallyConnectableInfo(extension); 265 EXPECT_FALSE(info->matches.ContainsPattern( 266 URLPattern(URLPattern::SCHEME_ALL, "http://*.appspot.com/*"))); 267 EXPECT_TRUE(info->matches.MatchesURL(GURL("https://example.com"))); 268 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org"))); 269} 270 271TEST_F(ExternallyConnectableTest, WarningUnknownTLD) { 272 scoped_refptr<Extension> extension = LoadAndExpectWarning( 273 "externally_connectable_error_unknown_tld.json", 274 ErrorUtils::FormatErrorMessage( 275 errors::kErrorTopLevelDomainsNotAllowed, 276 "notatld", 277 "http://*.notatld/*")); 278 ExternallyConnectableInfo* info = GetExternallyConnectableInfo(extension); 279 EXPECT_FALSE(info->matches.ContainsPattern( 280 URLPattern(URLPattern::SCHEME_ALL, "http://*.notatld/*"))); 281 EXPECT_TRUE(info->matches.MatchesURL(GURL("https://example.com"))); 282 EXPECT_TRUE(info->matches.MatchesURL(GURL("http://build.chromium.org"))); 283} 284 285TEST_F(ExternallyConnectableTest, WarningNothingSpecified) { 286 LoadAndExpectWarning("externally_connectable_nothing_specified.json", 287 errors::kErrorNothingSpecified); 288} 289 290} // namespace extensions 291