| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 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 <vector> | |
| 6 | |
| 7 #include "base/command_line.h" | |
| 8 #include "base/memory/ref_counted.h" | |
| 9 #include "base/strings/string16.h" | |
| 10 #include "base/strings/utf_string_conversions.h" | |
| 11 #include "chrome/common/chrome_version_info.h" | |
| 12 #include "chrome/common/extensions/extension_test_util.h" | |
| 13 #include "chrome/common/extensions/features/feature_channel.h" | |
| 14 #include "components/crx_file/id_util.h" | |
| 15 #include "content/public/common/socket_permission_request.h" | |
| 16 #include "extensions/common/error_utils.h" | |
| 17 #include "extensions/common/extension.h" | |
| 18 #include "extensions/common/extension_builder.h" | |
| 19 #include "extensions/common/manifest.h" | |
| 20 #include "extensions/common/manifest_constants.h" | |
| 21 #include "extensions/common/permissions/api_permission.h" | |
| 22 #include "extensions/common/permissions/permission_set.h" | |
| 23 #include "extensions/common/permissions/permissions_data.h" | |
| 24 #include "extensions/common/permissions/socket_permission.h" | |
| 25 #include "extensions/common/switches.h" | |
| 26 #include "extensions/common/url_pattern_set.h" | |
| 27 #include "extensions/common/value_builder.h" | |
| 28 #include "testing/gtest/include/gtest/gtest.h" | |
| 29 #include "url/gurl.h" | |
| 30 | |
| 31 using base::UTF16ToUTF8; | |
| 32 using content::SocketPermissionRequest; | |
| 33 using extension_test_util::LoadManifest; | |
| 34 using extension_test_util::LoadManifestUnchecked; | |
| 35 using extension_test_util::LoadManifestStrict; | |
| 36 | |
| 37 namespace extensions { | |
| 38 | |
| 39 namespace { | |
| 40 | |
| 41 const char kAllHostsPermission[] = "*://*/*"; | |
| 42 | |
| 43 bool CheckSocketPermission( | |
| 44 scoped_refptr<Extension> extension, | |
| 45 SocketPermissionRequest::OperationType type, | |
| 46 const char* host, | |
| 47 int port) { | |
| 48 SocketPermission::CheckParam param(type, host, port); | |
| 49 return extension->permissions_data()->CheckAPIPermissionWithParam( | |
| 50 APIPermission::kSocket, ¶m); | |
| 51 } | |
| 52 | |
| 53 // Creates and returns an extension with the given |id|, |host_permissions|, and | |
| 54 // manifest |location|. | |
| 55 scoped_refptr<const Extension> GetExtensionWithHostPermission( | |
| 56 const std::string& id, | |
| 57 const std::string& host_permissions, | |
| 58 Manifest::Location location) { | |
| 59 ListBuilder permissions; | |
| 60 if (!host_permissions.empty()) | |
| 61 permissions.Append(host_permissions); | |
| 62 | |
| 63 return ExtensionBuilder() | |
| 64 .SetManifest( | |
| 65 DictionaryBuilder() | |
| 66 .Set("name", id) | |
| 67 .Set("description", "an extension") | |
| 68 .Set("manifest_version", 2) | |
| 69 .Set("version", "1.0.0") | |
| 70 .Set("permissions", permissions.Pass()) | |
| 71 .Build()) | |
| 72 .SetLocation(location) | |
| 73 .SetID(id) | |
| 74 .Build(); | |
| 75 } | |
| 76 | |
| 77 // Checks that urls are properly restricted for the given extension. | |
| 78 void CheckRestrictedUrls(const Extension* extension, | |
| 79 bool block_chrome_urls) { | |
| 80 // We log the name so we know _which_ extension failed here. | |
| 81 const std::string& name = extension->name(); | |
| 82 const GURL chrome_settings_url("chrome://settings/"); | |
| 83 const GURL chrome_extension_url("chrome-extension://foo/bar.html"); | |
| 84 const GURL google_url("https://www.google.com/"); | |
| 85 const GURL self_url("chrome-extension://" + extension->id() + "/foo.html"); | |
| 86 const GURL invalid_url("chrome-debugger://foo/bar.html"); | |
| 87 | |
| 88 std::string error; | |
| 89 EXPECT_EQ(block_chrome_urls, | |
| 90 PermissionsData::IsRestrictedUrl( | |
| 91 chrome_settings_url, | |
| 92 chrome_settings_url, | |
| 93 extension, | |
| 94 &error)) << name; | |
| 95 if (block_chrome_urls) | |
| 96 EXPECT_EQ(manifest_errors::kCannotAccessChromeUrl, error) << name; | |
| 97 else | |
| 98 EXPECT_TRUE(error.empty()) << name; | |
| 99 | |
| 100 error.clear(); | |
| 101 EXPECT_EQ(block_chrome_urls, | |
| 102 PermissionsData::IsRestrictedUrl( | |
| 103 chrome_extension_url, | |
| 104 chrome_extension_url, | |
| 105 extension, | |
| 106 &error)) << name; | |
| 107 if (block_chrome_urls) | |
| 108 EXPECT_EQ(manifest_errors::kCannotAccessExtensionUrl, error) << name; | |
| 109 else | |
| 110 EXPECT_TRUE(error.empty()) << name; | |
| 111 | |
| 112 // Google should never be a restricted url. | |
| 113 error.clear(); | |
| 114 EXPECT_FALSE(PermissionsData::IsRestrictedUrl( | |
| 115 google_url, google_url, extension, &error)) << name; | |
| 116 EXPECT_TRUE(error.empty()) << name; | |
| 117 | |
| 118 // We should always be able to access our own extension pages. | |
| 119 error.clear(); | |
| 120 EXPECT_FALSE(PermissionsData::IsRestrictedUrl( | |
| 121 self_url, self_url, extension, &error)) << name; | |
| 122 EXPECT_TRUE(error.empty()) << name; | |
| 123 | |
| 124 // We should only allow other schemes for extensions when it's a whitelisted | |
| 125 // extension. | |
| 126 error.clear(); | |
| 127 bool allow_on_other_schemes = | |
| 128 PermissionsData::CanExecuteScriptEverywhere(extension); | |
| 129 EXPECT_EQ(!allow_on_other_schemes, | |
| 130 PermissionsData::IsRestrictedUrl( | |
| 131 invalid_url, invalid_url, extension, &error)) << name; | |
| 132 if (!allow_on_other_schemes) { | |
| 133 EXPECT_EQ(ErrorUtils::FormatErrorMessage( | |
| 134 manifest_errors::kCannotAccessPage, | |
| 135 invalid_url.spec()), | |
| 136 error) << name; | |
| 137 } else { | |
| 138 EXPECT_TRUE(error.empty()); | |
| 139 } | |
| 140 } | |
| 141 | |
| 142 } // namespace | |
| 143 | |
| 144 TEST(ExtensionPermissionsTest, EffectiveHostPermissions) { | |
| 145 scoped_refptr<Extension> extension; | |
| 146 URLPatternSet hosts; | |
| 147 | |
| 148 extension = LoadManifest("effective_host_permissions", "empty.json"); | |
| 149 EXPECT_EQ(0u, | |
| 150 extension->permissions_data() | |
| 151 ->GetEffectiveHostPermissions() | |
| 152 .patterns() | |
| 153 .size()); | |
| 154 EXPECT_FALSE(hosts.MatchesURL(GURL("http://www.google.com"))); | |
| 155 EXPECT_FALSE(extension->permissions_data()->HasEffectiveAccessToAllHosts()); | |
| 156 | |
| 157 extension = LoadManifest("effective_host_permissions", "one_host.json"); | |
| 158 hosts = extension->permissions_data()->GetEffectiveHostPermissions(); | |
| 159 EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.google.com"))); | |
| 160 EXPECT_FALSE(hosts.MatchesURL(GURL("https://www.google.com"))); | |
| 161 EXPECT_FALSE(extension->permissions_data()->HasEffectiveAccessToAllHosts()); | |
| 162 | |
| 163 extension = LoadManifest("effective_host_permissions", | |
| 164 "one_host_wildcard.json"); | |
| 165 hosts = extension->permissions_data()->GetEffectiveHostPermissions(); | |
| 166 EXPECT_TRUE(hosts.MatchesURL(GURL("http://google.com"))); | |
| 167 EXPECT_TRUE(hosts.MatchesURL(GURL("http://foo.google.com"))); | |
| 168 EXPECT_FALSE(extension->permissions_data()->HasEffectiveAccessToAllHosts()); | |
| 169 | |
| 170 extension = LoadManifest("effective_host_permissions", "two_hosts.json"); | |
| 171 hosts = extension->permissions_data()->GetEffectiveHostPermissions(); | |
| 172 EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.google.com"))); | |
| 173 EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.reddit.com"))); | |
| 174 EXPECT_FALSE(extension->permissions_data()->HasEffectiveAccessToAllHosts()); | |
| 175 | |
| 176 extension = LoadManifest("effective_host_permissions", | |
| 177 "https_not_considered.json"); | |
| 178 hosts = extension->permissions_data()->GetEffectiveHostPermissions(); | |
| 179 EXPECT_TRUE(hosts.MatchesURL(GURL("http://google.com"))); | |
| 180 EXPECT_TRUE(hosts.MatchesURL(GURL("https://google.com"))); | |
| 181 EXPECT_FALSE(extension->permissions_data()->HasEffectiveAccessToAllHosts()); | |
| 182 | |
| 183 extension = LoadManifest("effective_host_permissions", | |
| 184 "two_content_scripts.json"); | |
| 185 hosts = extension->permissions_data()->GetEffectiveHostPermissions(); | |
| 186 EXPECT_TRUE(hosts.MatchesURL(GURL("http://google.com"))); | |
| 187 EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.reddit.com"))); | |
| 188 EXPECT_TRUE(extension->permissions_data() | |
| 189 ->active_permissions() | |
| 190 ->HasEffectiveAccessToURL(GURL("http://www.reddit.com"))); | |
| 191 EXPECT_TRUE(hosts.MatchesURL(GURL("http://news.ycombinator.com"))); | |
| 192 EXPECT_TRUE( | |
| 193 extension->permissions_data() | |
| 194 ->active_permissions() | |
| 195 ->HasEffectiveAccessToURL(GURL("http://news.ycombinator.com"))); | |
| 196 EXPECT_FALSE(extension->permissions_data()->HasEffectiveAccessToAllHosts()); | |
| 197 | |
| 198 extension = LoadManifest("effective_host_permissions", "all_hosts.json"); | |
| 199 hosts = extension->permissions_data()->GetEffectiveHostPermissions(); | |
| 200 EXPECT_TRUE(hosts.MatchesURL(GURL("http://test/"))); | |
| 201 EXPECT_FALSE(hosts.MatchesURL(GURL("https://test/"))); | |
| 202 EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.google.com"))); | |
| 203 EXPECT_TRUE(extension->permissions_data()->HasEffectiveAccessToAllHosts()); | |
| 204 | |
| 205 extension = LoadManifest("effective_host_permissions", "all_hosts2.json"); | |
| 206 hosts = extension->permissions_data()->GetEffectiveHostPermissions(); | |
| 207 EXPECT_TRUE(hosts.MatchesURL(GURL("http://test/"))); | |
| 208 EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.google.com"))); | |
| 209 EXPECT_TRUE(extension->permissions_data()->HasEffectiveAccessToAllHosts()); | |
| 210 | |
| 211 extension = LoadManifest("effective_host_permissions", "all_hosts3.json"); | |
| 212 hosts = extension->permissions_data()->GetEffectiveHostPermissions(); | |
| 213 EXPECT_FALSE(hosts.MatchesURL(GURL("http://test/"))); | |
| 214 EXPECT_TRUE(hosts.MatchesURL(GURL("https://test/"))); | |
| 215 EXPECT_TRUE(hosts.MatchesURL(GURL("http://www.google.com"))); | |
| 216 EXPECT_TRUE(extension->permissions_data()->HasEffectiveAccessToAllHosts()); | |
| 217 } | |
| 218 | |
| 219 TEST(ExtensionPermissionsTest, SocketPermissions) { | |
| 220 // Set feature current channel to appropriate value. | |
| 221 ScopedCurrentChannel scoped_channel(chrome::VersionInfo::CHANNEL_DEV); | |
| 222 scoped_refptr<Extension> extension; | |
| 223 std::string error; | |
| 224 | |
| 225 extension = LoadManifest("socket_permissions", "empty.json"); | |
| 226 EXPECT_FALSE(CheckSocketPermission(extension, | |
| 227 SocketPermissionRequest::TCP_CONNECT, "www.example.com", 80)); | |
| 228 | |
| 229 extension = LoadManifestUnchecked("socket_permissions", | |
| 230 "socket1.json", | |
| 231 Manifest::INTERNAL, Extension::NO_FLAGS, | |
| 232 &error); | |
| 233 EXPECT_TRUE(extension.get() == NULL); | |
| 234 std::string expected_error_msg_header = ErrorUtils::FormatErrorMessage( | |
| 235 manifest_errors::kInvalidPermissionWithDetail, | |
| 236 "socket", | |
| 237 "NULL or empty permission list"); | |
| 238 EXPECT_EQ(expected_error_msg_header, error); | |
| 239 | |
| 240 extension = LoadManifest("socket_permissions", "socket2.json"); | |
| 241 EXPECT_TRUE(CheckSocketPermission(extension, | |
| 242 SocketPermissionRequest::TCP_CONNECT, "www.example.com", 80)); | |
| 243 EXPECT_FALSE(CheckSocketPermission( | |
| 244 extension, SocketPermissionRequest::UDP_BIND, "", 80)); | |
| 245 EXPECT_TRUE(CheckSocketPermission( | |
| 246 extension, SocketPermissionRequest::UDP_BIND, "", 8888)); | |
| 247 | |
| 248 EXPECT_FALSE(CheckSocketPermission( | |
| 249 extension, SocketPermissionRequest::UDP_SEND_TO, "example.com", 1900)); | |
| 250 EXPECT_TRUE(CheckSocketPermission( | |
| 251 extension, | |
| 252 SocketPermissionRequest::UDP_SEND_TO, | |
| 253 "239.255.255.250", 1900)); | |
| 254 } | |
| 255 | |
| 256 TEST(ExtensionPermissionsTest, IsRestrictedUrl) { | |
| 257 scoped_refptr<const Extension> extension = | |
| 258 GetExtensionWithHostPermission("normal_extension", | |
| 259 kAllHostsPermission, | |
| 260 Manifest::INTERNAL); | |
| 261 // Chrome urls should be blocked for normal extensions. | |
| 262 CheckRestrictedUrls(extension.get(), true); | |
| 263 | |
| 264 scoped_refptr<const Extension> component = | |
| 265 GetExtensionWithHostPermission("component", | |
| 266 kAllHostsPermission, | |
| 267 Manifest::COMPONENT); | |
| 268 // Chrome urls should be accessible by component extensions. | |
| 269 CheckRestrictedUrls(component.get(), false); | |
| 270 | |
| 271 base::CommandLine::ForCurrentProcess()->AppendSwitch( | |
| 272 switches::kExtensionsOnChromeURLs); | |
| 273 // Enabling the switch should allow all extensions to access chrome urls. | |
| 274 CheckRestrictedUrls(extension.get(), false); | |
| 275 } | |
| 276 | |
| 277 TEST(ExtensionPermissionsTest, GetPermissionMessages_ManyAPIPermissions) { | |
| 278 scoped_refptr<Extension> extension; | |
| 279 extension = LoadManifest("permissions", "many-apis.json"); | |
| 280 std::vector<base::string16> warnings = | |
| 281 extension->permissions_data()->GetPermissionMessageStrings(); | |
| 282 // Warning for "tabs" is suppressed by "history" permission. | |
| 283 ASSERT_EQ(5u, warnings.size()); | |
| 284 EXPECT_EQ("Read and change your data on api.flickr.com", | |
| 285 UTF16ToUTF8(warnings[0])); | |
| 286 EXPECT_EQ("Read and change your bookmarks", UTF16ToUTF8(warnings[1])); | |
| 287 EXPECT_EQ("Detect your physical location", UTF16ToUTF8(warnings[2])); | |
| 288 EXPECT_EQ("Read and change your browsing history", UTF16ToUTF8(warnings[3])); | |
| 289 EXPECT_EQ("Manage your apps, extensions, and themes", | |
| 290 UTF16ToUTF8(warnings[4])); | |
| 291 } | |
| 292 | |
| 293 TEST(ExtensionPermissionsTest, GetPermissionMessages_ManyHostsPermissions) { | |
| 294 scoped_refptr<Extension> extension; | |
| 295 extension = LoadManifest("permissions", "more-than-3-hosts.json"); | |
| 296 std::vector<base::string16> warnings = | |
| 297 extension->permissions_data()->GetPermissionMessageStrings(); | |
| 298 std::vector<base::string16> warnings_details = | |
| 299 extension->permissions_data()->GetPermissionMessageDetailsStrings(); | |
| 300 ASSERT_EQ(1u, warnings.size()); | |
| 301 ASSERT_EQ(1u, warnings_details.size()); | |
| 302 EXPECT_EQ("Read and change your data on a number of websites", | |
| 303 UTF16ToUTF8(warnings[0])); | |
| 304 EXPECT_EQ("- www.a.com\n- www.b.com\n- www.c.com\n- www.d.com\n- www.e.com", | |
| 305 UTF16ToUTF8(warnings_details[0])); | |
| 306 } | |
| 307 | |
| 308 TEST(ExtensionPermissionsTest, GetPermissionMessages_LocationApiPermission) { | |
| 309 scoped_refptr<Extension> extension; | |
| 310 extension = LoadManifest("permissions", | |
| 311 "location-api.json", | |
| 312 Manifest::COMPONENT, | |
| 313 Extension::NO_FLAGS); | |
| 314 std::vector<base::string16> warnings = | |
| 315 extension->permissions_data()->GetPermissionMessageStrings(); | |
| 316 ASSERT_EQ(1u, warnings.size()); | |
| 317 EXPECT_EQ("Detect your physical location", UTF16ToUTF8(warnings[0])); | |
| 318 } | |
| 319 | |
| 320 TEST(ExtensionPermissionsTest, GetPermissionMessages_ManyHosts) { | |
| 321 scoped_refptr<Extension> extension; | |
| 322 extension = LoadManifest("permissions", "many-hosts.json"); | |
| 323 std::vector<base::string16> warnings = | |
| 324 extension->permissions_data()->GetPermissionMessageStrings(); | |
| 325 ASSERT_EQ(1u, warnings.size()); | |
| 326 EXPECT_EQ( | |
| 327 "Read and change your data on encrypted.google.com and www.google.com", | |
| 328 UTF16ToUTF8(warnings[0])); | |
| 329 } | |
| 330 | |
| 331 TEST(ExtensionPermissionsTest, GetPermissionMessages_Plugins) { | |
| 332 scoped_refptr<Extension> extension; | |
| 333 extension = LoadManifest("permissions", "plugins.json"); | |
| 334 std::vector<base::string16> warnings = | |
| 335 extension->permissions_data()->GetPermissionMessageStrings(); | |
| 336 // We don't parse the plugins key on Chrome OS, so it should not ask for any | |
| 337 // permissions. | |
| 338 #if defined(OS_CHROMEOS) | |
| 339 ASSERT_EQ(0u, warnings.size()); | |
| 340 #else | |
| 341 ASSERT_EQ(1u, warnings.size()); | |
| 342 EXPECT_EQ( | |
| 343 "Read and change all your data on your computer and the websites you " | |
| 344 "visit", | |
| 345 UTF16ToUTF8(warnings[0])); | |
| 346 #endif | |
| 347 } | |
| 348 | |
| 349 // Base class for testing the CanAccessPage and CanCaptureVisiblePage | |
| 350 // methods of Extension for extensions with various permissions. | |
| 351 class ExtensionScriptAndCaptureVisibleTest : public testing::Test { | |
| 352 protected: | |
| 353 ExtensionScriptAndCaptureVisibleTest() | |
| 354 : http_url("http://www.google.com"), | |
| 355 http_url_with_path("http://www.google.com/index.html"), | |
| 356 https_url("https://www.google.com"), | |
| 357 file_url("file:///foo/bar"), | |
| 358 favicon_url("chrome://favicon/http://www.google.com"), | |
| 359 extension_url("chrome-extension://" + | |
| 360 crx_file::id_util::GenerateIdForPath( | |
| 361 base::FilePath(FILE_PATH_LITERAL("foo")))), | |
| 362 settings_url("chrome://settings"), | |
| 363 about_url("about:flags") { | |
| 364 urls_.insert(http_url); | |
| 365 urls_.insert(http_url_with_path); | |
| 366 urls_.insert(https_url); | |
| 367 urls_.insert(file_url); | |
| 368 urls_.insert(favicon_url); | |
| 369 urls_.insert(extension_url); | |
| 370 urls_.insert(settings_url); | |
| 371 urls_.insert(about_url); | |
| 372 // Ignore the policy delegate for this test. | |
| 373 PermissionsData::SetPolicyDelegate(NULL); | |
| 374 } | |
| 375 | |
| 376 bool AllowedScript(const Extension* extension, const GURL& url, | |
| 377 const GURL& top_url) { | |
| 378 return AllowedScript(extension, url, top_url, -1); | |
| 379 } | |
| 380 | |
| 381 bool AllowedScript(const Extension* extension, const GURL& url, | |
| 382 const GURL& top_url, int tab_id) { | |
| 383 return extension->permissions_data()->CanAccessPage( | |
| 384 extension, url, top_url, tab_id, -1, NULL); | |
| 385 } | |
| 386 | |
| 387 bool BlockedScript(const Extension* extension, const GURL& url, | |
| 388 const GURL& top_url) { | |
| 389 return !extension->permissions_data()->CanAccessPage( | |
| 390 extension, url, top_url, -1, -1, NULL); | |
| 391 } | |
| 392 | |
| 393 bool Allowed(const Extension* extension, const GURL& url) { | |
| 394 return Allowed(extension, url, -1); | |
| 395 } | |
| 396 | |
| 397 bool Allowed(const Extension* extension, const GURL& url, int tab_id) { | |
| 398 return (extension->permissions_data()->CanAccessPage( | |
| 399 extension, url, url, tab_id, -1, NULL) && | |
| 400 extension->permissions_data()->CanCaptureVisiblePage(tab_id, NULL)); | |
| 401 } | |
| 402 | |
| 403 bool CaptureOnly(const Extension* extension, const GURL& url) { | |
| 404 return CaptureOnly(extension, url, -1); | |
| 405 } | |
| 406 | |
| 407 bool CaptureOnly(const Extension* extension, const GURL& url, int tab_id) { | |
| 408 return !extension->permissions_data()->CanAccessPage( | |
| 409 extension, url, url, tab_id, -1, NULL) && | |
| 410 extension->permissions_data()->CanCaptureVisiblePage(tab_id, NULL); | |
| 411 } | |
| 412 | |
| 413 bool ScriptOnly(const Extension* extension, const GURL& url, | |
| 414 const GURL& top_url) { | |
| 415 return ScriptOnly(extension, url, top_url, -1); | |
| 416 } | |
| 417 | |
| 418 bool ScriptOnly(const Extension* extension, const GURL& url, | |
| 419 const GURL& top_url, int tab_id) { | |
| 420 return AllowedScript(extension, url, top_url, tab_id) && | |
| 421 !extension->permissions_data()->CanCaptureVisiblePage(tab_id, NULL); | |
| 422 } | |
| 423 | |
| 424 bool Blocked(const Extension* extension, const GURL& url) { | |
| 425 return Blocked(extension, url, -1); | |
| 426 } | |
| 427 | |
| 428 bool Blocked(const Extension* extension, const GURL& url, int tab_id) { | |
| 429 return !(extension->permissions_data()->CanAccessPage( | |
| 430 extension, url, url, tab_id, -1, NULL) || | |
| 431 extension->permissions_data()->CanCaptureVisiblePage(tab_id, | |
| 432 NULL)); | |
| 433 } | |
| 434 | |
| 435 bool ScriptAllowedExclusivelyOnTab( | |
| 436 const Extension* extension, | |
| 437 const std::set<GURL>& allowed_urls, | |
| 438 int tab_id) { | |
| 439 bool result = true; | |
| 440 for (std::set<GURL>::iterator it = urls_.begin(); it != urls_.end(); ++it) { | |
| 441 const GURL& url = *it; | |
| 442 if (allowed_urls.count(url)) | |
| 443 result &= AllowedScript(extension, url, url, tab_id); | |
| 444 else | |
| 445 result &= Blocked(extension, url, tab_id); | |
| 446 } | |
| 447 return result; | |
| 448 } | |
| 449 | |
| 450 // URLs that are "safe" to provide scripting and capture visible tab access | |
| 451 // to if the permissions allow it. | |
| 452 const GURL http_url; | |
| 453 const GURL http_url_with_path; | |
| 454 const GURL https_url; | |
| 455 const GURL file_url; | |
| 456 | |
| 457 // We should allow host permission but not scripting permission for favicon | |
| 458 // urls. | |
| 459 const GURL favicon_url; | |
| 460 | |
| 461 // URLs that regular extensions should never get access to. | |
| 462 const GURL extension_url; | |
| 463 const GURL settings_url; | |
| 464 const GURL about_url; | |
| 465 | |
| 466 private: | |
| 467 // The set of all URLs above. | |
| 468 std::set<GURL> urls_; | |
| 469 }; | |
| 470 | |
| 471 TEST_F(ExtensionScriptAndCaptureVisibleTest, Permissions) { | |
| 472 // Test <all_urls> for regular extensions. | |
| 473 scoped_refptr<Extension> extension = LoadManifestStrict("script_and_capture", | |
| 474 "extension_regular_all.json"); | |
| 475 | |
| 476 EXPECT_TRUE(Allowed(extension.get(), http_url)); | |
| 477 EXPECT_TRUE(Allowed(extension.get(), https_url)); | |
| 478 EXPECT_TRUE(CaptureOnly(extension.get(), file_url)); | |
| 479 EXPECT_TRUE(CaptureOnly(extension.get(), settings_url)); | |
| 480 EXPECT_TRUE(CaptureOnly(extension.get(), favicon_url)); | |
| 481 EXPECT_TRUE(CaptureOnly(extension.get(), about_url)); | |
| 482 EXPECT_TRUE(CaptureOnly(extension.get(), extension_url)); | |
| 483 | |
| 484 // Test access to iframed content. | |
| 485 GURL within_extension_url = extension->GetResourceURL("page.html"); | |
| 486 EXPECT_TRUE(AllowedScript(extension.get(), http_url, http_url_with_path)); | |
| 487 EXPECT_TRUE(AllowedScript(extension.get(), https_url, http_url_with_path)); | |
| 488 EXPECT_TRUE(AllowedScript(extension.get(), http_url, within_extension_url)); | |
| 489 EXPECT_TRUE(AllowedScript(extension.get(), https_url, within_extension_url)); | |
| 490 EXPECT_TRUE(BlockedScript(extension.get(), http_url, extension_url)); | |
| 491 EXPECT_TRUE(BlockedScript(extension.get(), https_url, extension_url)); | |
| 492 | |
| 493 EXPECT_FALSE(extension->permissions_data()->HasHostPermission(settings_url)); | |
| 494 EXPECT_FALSE(extension->permissions_data()->HasHostPermission(about_url)); | |
| 495 EXPECT_TRUE(extension->permissions_data()->HasHostPermission(favicon_url)); | |
| 496 | |
| 497 // Test * for scheme, which implies just the http/https schemes. | |
| 498 extension = LoadManifestStrict("script_and_capture", | |
| 499 "extension_wildcard.json"); | |
| 500 EXPECT_TRUE(ScriptOnly(extension.get(), http_url, http_url)); | |
| 501 EXPECT_TRUE(ScriptOnly(extension.get(), https_url, https_url)); | |
| 502 EXPECT_TRUE(Blocked(extension.get(), settings_url)); | |
| 503 EXPECT_TRUE(Blocked(extension.get(), about_url)); | |
| 504 EXPECT_TRUE(Blocked(extension.get(), file_url)); | |
| 505 EXPECT_TRUE(Blocked(extension.get(), favicon_url)); | |
| 506 extension = | |
| 507 LoadManifest("script_and_capture", "extension_wildcard_settings.json"); | |
| 508 EXPECT_TRUE(Blocked(extension.get(), settings_url)); | |
| 509 | |
| 510 // Having chrome://*/ should not work for regular extensions. Note that | |
| 511 // for favicon access, we require the explicit pattern chrome://favicon/*. | |
| 512 std::string error; | |
| 513 extension = LoadManifestUnchecked("script_and_capture", | |
| 514 "extension_wildcard_chrome.json", | |
| 515 Manifest::INTERNAL, Extension::NO_FLAGS, | |
| 516 &error); | |
| 517 std::vector<InstallWarning> warnings = extension->install_warnings(); | |
| 518 EXPECT_FALSE(warnings.empty()); | |
| 519 EXPECT_EQ(ErrorUtils::FormatErrorMessage( | |
| 520 manifest_errors::kInvalidPermissionScheme, | |
| 521 "chrome://*/"), | |
| 522 warnings[0].message); | |
| 523 EXPECT_TRUE(Blocked(extension.get(), settings_url)); | |
| 524 EXPECT_TRUE(Blocked(extension.get(), favicon_url)); | |
| 525 EXPECT_TRUE(Blocked(extension.get(), about_url)); | |
| 526 | |
| 527 // Having chrome://favicon/* should not give you chrome://* | |
| 528 extension = LoadManifestStrict("script_and_capture", | |
| 529 "extension_chrome_favicon_wildcard.json"); | |
| 530 EXPECT_TRUE(Blocked(extension.get(), settings_url)); | |
| 531 EXPECT_TRUE(Blocked(extension.get(), favicon_url)); | |
| 532 EXPECT_TRUE(Blocked(extension.get(), about_url)); | |
| 533 EXPECT_TRUE(extension->permissions_data()->HasHostPermission(favicon_url)); | |
| 534 | |
| 535 // Having http://favicon should not give you chrome://favicon | |
| 536 extension = LoadManifestStrict("script_and_capture", | |
| 537 "extension_http_favicon.json"); | |
| 538 EXPECT_TRUE(Blocked(extension.get(), settings_url)); | |
| 539 EXPECT_TRUE(Blocked(extension.get(), favicon_url)); | |
| 540 | |
| 541 // Component extensions with <all_urls> should get everything. | |
| 542 extension = LoadManifest("script_and_capture", "extension_component_all.json", | |
| 543 Manifest::COMPONENT, Extension::NO_FLAGS); | |
| 544 EXPECT_TRUE(Allowed(extension.get(), http_url)); | |
| 545 EXPECT_TRUE(Allowed(extension.get(), https_url)); | |
| 546 EXPECT_TRUE(Allowed(extension.get(), settings_url)); | |
| 547 EXPECT_TRUE(Allowed(extension.get(), about_url)); | |
| 548 EXPECT_TRUE(Allowed(extension.get(), favicon_url)); | |
| 549 EXPECT_TRUE(extension->permissions_data()->HasHostPermission(favicon_url)); | |
| 550 | |
| 551 // Component extensions should only get access to what they ask for. | |
| 552 extension = LoadManifest("script_and_capture", | |
| 553 "extension_component_google.json", Manifest::COMPONENT, | |
| 554 Extension::NO_FLAGS); | |
| 555 EXPECT_TRUE(ScriptOnly(extension.get(), http_url, http_url)); | |
| 556 EXPECT_TRUE(Blocked(extension.get(), https_url)); | |
| 557 EXPECT_TRUE(Blocked(extension.get(), file_url)); | |
| 558 EXPECT_TRUE(Blocked(extension.get(), settings_url)); | |
| 559 EXPECT_TRUE(Blocked(extension.get(), favicon_url)); | |
| 560 EXPECT_TRUE(Blocked(extension.get(), about_url)); | |
| 561 EXPECT_TRUE(Blocked(extension.get(), extension_url)); | |
| 562 EXPECT_FALSE(extension->permissions_data()->HasHostPermission(settings_url)); | |
| 563 } | |
| 564 | |
| 565 TEST_F(ExtensionScriptAndCaptureVisibleTest, PermissionsWithChromeURLsEnabled) { | |
| 566 CommandLine::ForCurrentProcess()->AppendSwitch( | |
| 567 switches::kExtensionsOnChromeURLs); | |
| 568 | |
| 569 scoped_refptr<Extension> extension; | |
| 570 | |
| 571 // Test <all_urls> for regular extensions. | |
| 572 extension = LoadManifestStrict("script_and_capture", | |
| 573 "extension_regular_all.json"); | |
| 574 EXPECT_TRUE(Allowed(extension.get(), http_url)); | |
| 575 EXPECT_TRUE(Allowed(extension.get(), https_url)); | |
| 576 EXPECT_TRUE(CaptureOnly(extension.get(), file_url)); | |
| 577 EXPECT_TRUE(CaptureOnly(extension.get(), settings_url)); | |
| 578 EXPECT_TRUE(Allowed(extension.get(), favicon_url)); // chrome:// requested | |
| 579 EXPECT_TRUE(CaptureOnly(extension.get(), about_url)); | |
| 580 EXPECT_TRUE(CaptureOnly(extension.get(), extension_url)); | |
| 581 | |
| 582 // Test access to iframed content. | |
| 583 GURL within_extension_url = extension->GetResourceURL("page.html"); | |
| 584 EXPECT_TRUE(AllowedScript(extension.get(), http_url, http_url_with_path)); | |
| 585 EXPECT_TRUE(AllowedScript(extension.get(), https_url, http_url_with_path)); | |
| 586 EXPECT_TRUE(AllowedScript(extension.get(), http_url, within_extension_url)); | |
| 587 EXPECT_TRUE(AllowedScript(extension.get(), https_url, within_extension_url)); | |
| 588 EXPECT_TRUE(AllowedScript(extension.get(), http_url, extension_url)); | |
| 589 EXPECT_TRUE(AllowedScript(extension.get(), https_url, extension_url)); | |
| 590 | |
| 591 const PermissionsData* permissions_data = extension->permissions_data(); | |
| 592 EXPECT_FALSE(permissions_data->HasHostPermission(settings_url)); | |
| 593 EXPECT_FALSE(permissions_data->HasHostPermission(about_url)); | |
| 594 EXPECT_TRUE(permissions_data->HasHostPermission(favicon_url)); | |
| 595 | |
| 596 // Test * for scheme, which implies just the http/https schemes. | |
| 597 extension = LoadManifestStrict("script_and_capture", | |
| 598 "extension_wildcard.json"); | |
| 599 EXPECT_TRUE(ScriptOnly(extension.get(), http_url, http_url)); | |
| 600 EXPECT_TRUE(ScriptOnly(extension.get(), https_url, https_url)); | |
| 601 EXPECT_TRUE(Blocked(extension.get(), settings_url)); | |
| 602 EXPECT_TRUE(Blocked(extension.get(), about_url)); | |
| 603 EXPECT_TRUE(Blocked(extension.get(), file_url)); | |
| 604 EXPECT_TRUE(Blocked(extension.get(), favicon_url)); | |
| 605 extension = | |
| 606 LoadManifest("script_and_capture", "extension_wildcard_settings.json"); | |
| 607 EXPECT_TRUE(Blocked(extension.get(), settings_url)); | |
| 608 | |
| 609 // Having chrome://*/ should work for regular extensions with the flag | |
| 610 // enabled. | |
| 611 std::string error; | |
| 612 extension = LoadManifestUnchecked("script_and_capture", | |
| 613 "extension_wildcard_chrome.json", | |
| 614 Manifest::INTERNAL, Extension::NO_FLAGS, | |
| 615 &error); | |
| 616 EXPECT_FALSE(extension.get() == NULL); | |
| 617 EXPECT_TRUE(Blocked(extension.get(), http_url)); | |
| 618 EXPECT_TRUE(Blocked(extension.get(), https_url)); | |
| 619 EXPECT_TRUE(ScriptOnly(extension.get(), settings_url, settings_url)); | |
| 620 EXPECT_TRUE(Blocked(extension.get(), about_url)); | |
| 621 EXPECT_TRUE(Blocked(extension.get(), file_url)); | |
| 622 EXPECT_TRUE(ScriptOnly(extension.get(), favicon_url, favicon_url)); | |
| 623 | |
| 624 // Having chrome://favicon/* should not give you chrome://* | |
| 625 extension = LoadManifestStrict("script_and_capture", | |
| 626 "extension_chrome_favicon_wildcard.json"); | |
| 627 EXPECT_TRUE(Blocked(extension.get(), settings_url)); | |
| 628 EXPECT_TRUE(ScriptOnly(extension.get(), favicon_url, favicon_url)); | |
| 629 EXPECT_TRUE(Blocked(extension.get(), about_url)); | |
| 630 EXPECT_TRUE(extension->permissions_data()->HasHostPermission(favicon_url)); | |
| 631 | |
| 632 // Having http://favicon should not give you chrome://favicon | |
| 633 extension = LoadManifestStrict("script_and_capture", | |
| 634 "extension_http_favicon.json"); | |
| 635 EXPECT_TRUE(Blocked(extension.get(), settings_url)); | |
| 636 EXPECT_TRUE(Blocked(extension.get(), favicon_url)); | |
| 637 | |
| 638 // Component extensions with <all_urls> should get everything. | |
| 639 extension = LoadManifest("script_and_capture", "extension_component_all.json", | |
| 640 Manifest::COMPONENT, Extension::NO_FLAGS); | |
| 641 EXPECT_TRUE(Allowed(extension.get(), http_url)); | |
| 642 EXPECT_TRUE(Allowed(extension.get(), https_url)); | |
| 643 EXPECT_TRUE(Allowed(extension.get(), settings_url)); | |
| 644 EXPECT_TRUE(Allowed(extension.get(), about_url)); | |
| 645 EXPECT_TRUE(Allowed(extension.get(), favicon_url)); | |
| 646 EXPECT_TRUE(extension->permissions_data()->HasHostPermission(favicon_url)); | |
| 647 | |
| 648 // Component extensions should only get access to what they ask for. | |
| 649 extension = LoadManifest("script_and_capture", | |
| 650 "extension_component_google.json", Manifest::COMPONENT, | |
| 651 Extension::NO_FLAGS); | |
| 652 EXPECT_TRUE(ScriptOnly(extension.get(), http_url, http_url)); | |
| 653 EXPECT_TRUE(Blocked(extension.get(), https_url)); | |
| 654 EXPECT_TRUE(Blocked(extension.get(), file_url)); | |
| 655 EXPECT_TRUE(Blocked(extension.get(), settings_url)); | |
| 656 EXPECT_TRUE(Blocked(extension.get(), favicon_url)); | |
| 657 EXPECT_TRUE(Blocked(extension.get(), about_url)); | |
| 658 EXPECT_TRUE(Blocked(extension.get(), extension_url)); | |
| 659 EXPECT_FALSE(extension->permissions_data()->HasHostPermission(settings_url)); | |
| 660 } | |
| 661 | |
| 662 TEST_F(ExtensionScriptAndCaptureVisibleTest, TabSpecific) { | |
| 663 scoped_refptr<Extension> extension = | |
| 664 LoadManifestStrict("script_and_capture", "tab_specific.json"); | |
| 665 | |
| 666 const PermissionsData* permissions_data = extension->permissions_data(); | |
| 667 EXPECT_FALSE(permissions_data->GetTabSpecificPermissionsForTesting(0).get()); | |
| 668 EXPECT_FALSE(permissions_data->GetTabSpecificPermissionsForTesting(1).get()); | |
| 669 EXPECT_FALSE(permissions_data->GetTabSpecificPermissionsForTesting(2).get()); | |
| 670 | |
| 671 std::set<GURL> no_urls; | |
| 672 | |
| 673 EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 0)); | |
| 674 EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 1)); | |
| 675 EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 2)); | |
| 676 | |
| 677 URLPatternSet allowed_hosts; | |
| 678 allowed_hosts.AddPattern(URLPattern(URLPattern::SCHEME_ALL, | |
| 679 http_url.spec())); | |
| 680 std::set<GURL> allowed_urls; | |
| 681 allowed_urls.insert(http_url); | |
| 682 // http_url_with_path() will also be allowed, because Extension should be | |
| 683 // considering the security origin of the URL not the URL itself, and | |
| 684 // http_url is in allowed_hosts. | |
| 685 allowed_urls.insert(http_url_with_path); | |
| 686 | |
| 687 { | |
| 688 scoped_refptr<PermissionSet> permissions( | |
| 689 new PermissionSet(APIPermissionSet(), ManifestPermissionSet(), | |
| 690 allowed_hosts, URLPatternSet())); | |
| 691 permissions_data->UpdateTabSpecificPermissions(0, permissions); | |
| 692 EXPECT_EQ(permissions->explicit_hosts(), | |
| 693 permissions_data->GetTabSpecificPermissionsForTesting(0) | |
| 694 ->explicit_hosts()); | |
| 695 } | |
| 696 | |
| 697 EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), allowed_urls, 0)); | |
| 698 EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 1)); | |
| 699 EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 2)); | |
| 700 | |
| 701 permissions_data->ClearTabSpecificPermissions(0); | |
| 702 EXPECT_FALSE(permissions_data->GetTabSpecificPermissionsForTesting(0).get()); | |
| 703 | |
| 704 EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 0)); | |
| 705 EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 1)); | |
| 706 EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 2)); | |
| 707 | |
| 708 std::set<GURL> more_allowed_urls = allowed_urls; | |
| 709 more_allowed_urls.insert(https_url); | |
| 710 URLPatternSet more_allowed_hosts = allowed_hosts; | |
| 711 more_allowed_hosts.AddPattern(URLPattern(URLPattern::SCHEME_ALL, | |
| 712 https_url.spec())); | |
| 713 | |
| 714 { | |
| 715 scoped_refptr<PermissionSet> permissions( | |
| 716 new PermissionSet(APIPermissionSet(), ManifestPermissionSet(), | |
| 717 allowed_hosts, URLPatternSet())); | |
| 718 permissions_data->UpdateTabSpecificPermissions(0, permissions); | |
| 719 EXPECT_EQ(permissions->explicit_hosts(), | |
| 720 permissions_data->GetTabSpecificPermissionsForTesting(0) | |
| 721 ->explicit_hosts()); | |
| 722 | |
| 723 permissions = new PermissionSet(APIPermissionSet(), | |
| 724 ManifestPermissionSet(), | |
| 725 more_allowed_hosts, | |
| 726 URLPatternSet()); | |
| 727 permissions_data->UpdateTabSpecificPermissions(1, permissions); | |
| 728 EXPECT_EQ(permissions->explicit_hosts(), | |
| 729 permissions_data->GetTabSpecificPermissionsForTesting(1) | |
| 730 ->explicit_hosts()); | |
| 731 } | |
| 732 | |
| 733 EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), allowed_urls, 0)); | |
| 734 EXPECT_TRUE( | |
| 735 ScriptAllowedExclusivelyOnTab(extension.get(), more_allowed_urls, 1)); | |
| 736 EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 2)); | |
| 737 | |
| 738 permissions_data->ClearTabSpecificPermissions(0); | |
| 739 EXPECT_FALSE(permissions_data->GetTabSpecificPermissionsForTesting(0).get()); | |
| 740 | |
| 741 EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 0)); | |
| 742 EXPECT_TRUE( | |
| 743 ScriptAllowedExclusivelyOnTab(extension.get(), more_allowed_urls, 1)); | |
| 744 EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 2)); | |
| 745 | |
| 746 permissions_data->ClearTabSpecificPermissions(1); | |
| 747 EXPECT_FALSE(permissions_data->GetTabSpecificPermissionsForTesting(1).get()); | |
| 748 | |
| 749 EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 0)); | |
| 750 EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 1)); | |
| 751 EXPECT_TRUE(ScriptAllowedExclusivelyOnTab(extension.get(), no_urls, 2)); | |
| 752 } | |
| 753 | |
| 754 } // namespace extensions | |
| OLD | NEW |