OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/files/file_path.h" | 5 #include "base/files/file_path.h" |
6 #include "base/json/json_file_value_serializer.h" | 6 #include "base/json/json_file_value_serializer.h" |
7 #include "base/memory/ref_counted.h" | 7 #include "base/memory/ref_counted.h" |
8 #include "base/path_service.h" | 8 #include "base/path_service.h" |
9 #include "base/run_loop.h" | 9 #include "base/run_loop.h" |
| 10 #include "base/strings/stringprintf.h" |
10 #include "base/values.h" | 11 #include "base/values.h" |
11 #include "chrome/browser/chrome_notification_types.h" | 12 #include "chrome/browser/chrome_notification_types.h" |
12 #include "chrome/browser/extensions/extension_service.h" | 13 #include "chrome/browser/extensions/extension_service.h" |
13 #include "chrome/browser/extensions/extension_service_test_base.h" | 14 #include "chrome/browser/extensions/extension_service_test_base.h" |
14 #include "chrome/browser/extensions/permissions_updater.h" | 15 #include "chrome/browser/extensions/permissions_updater.h" |
15 #include "chrome/common/chrome_paths.h" | 16 #include "chrome/common/chrome_paths.h" |
16 #include "chrome/common/extensions/extension_test_util.h" | 17 #include "chrome/common/extensions/extension_test_util.h" |
17 #include "chrome/test/base/testing_profile.h" | 18 #include "chrome/test/base/testing_profile.h" |
18 #include "content/public/browser/notification_observer.h" | 19 #include "content/public/browser/notification_observer.h" |
19 #include "content/public/browser/notification_registrar.h" | 20 #include "content/public/browser/notification_registrar.h" |
20 #include "content/public/browser/notification_service.h" | 21 #include "content/public/browser/notification_service.h" |
21 #include "extensions/browser/extension_prefs.h" | 22 #include "extensions/browser/extension_prefs.h" |
22 #include "extensions/common/extension.h" | 23 #include "extensions/common/extension.h" |
| 24 #include "extensions/common/extension_builder.h" |
| 25 #include "extensions/common/feature_switch.h" |
23 #include "extensions/common/permissions/permission_set.h" | 26 #include "extensions/common/permissions/permission_set.h" |
24 #include "extensions/common/permissions/permissions_data.h" | 27 #include "extensions/common/permissions/permissions_data.h" |
| 28 #include "extensions/common/value_builder.h" |
25 #include "testing/gtest/include/gtest/gtest.h" | 29 #include "testing/gtest/include/gtest/gtest.h" |
26 | 30 |
27 using extension_test_util::LoadManifest; | 31 using extension_test_util::LoadManifest; |
28 | 32 |
29 namespace extensions { | 33 namespace extensions { |
30 | 34 |
31 namespace { | 35 namespace { |
32 | 36 |
| 37 scoped_refptr<const Extension> CreateExtensionWithPermissions( |
| 38 const std::set<URLPattern>& scriptable_hosts, |
| 39 const std::set<URLPattern>& explicit_hosts, |
| 40 Manifest::Location location) { |
| 41 ListBuilder scriptable_host_list; |
| 42 for (std::set<URLPattern>::const_iterator pattern = scriptable_hosts.begin(); |
| 43 pattern != scriptable_hosts.end(); |
| 44 ++pattern) { |
| 45 scriptable_host_list.Append(pattern->GetAsString()); |
| 46 } |
| 47 |
| 48 ListBuilder explicit_host_list; |
| 49 for (std::set<URLPattern>::const_iterator pattern = explicit_hosts.begin(); |
| 50 pattern != explicit_hosts.end(); |
| 51 ++pattern) { |
| 52 explicit_host_list.Append(pattern->GetAsString()); |
| 53 } |
| 54 |
| 55 DictionaryBuilder script; |
| 56 script.Set("matches", scriptable_host_list.Pass()) |
| 57 .Set("js", ListBuilder().Append("foo.js")); |
| 58 |
| 59 return ExtensionBuilder() |
| 60 .SetLocation(location) |
| 61 .SetManifest( |
| 62 DictionaryBuilder() |
| 63 .Set("name", "extension") |
| 64 .Set("description", "foo") |
| 65 .Set("manifest_version", 2) |
| 66 .Set("version", "0.1.2.3") |
| 67 .Set("content_scripts", ListBuilder().Append(script.Pass())) |
| 68 .Set("permissions", explicit_host_list.Pass())) |
| 69 .Build(); |
| 70 } |
| 71 |
| 72 testing::AssertionResult SetsAreEqual(const std::set<URLPattern>& set1, |
| 73 const std::set<URLPattern>& set2) { |
| 74 // Take the (set1 - set2) U (set2 - set1). This is then the set of all |
| 75 // elements which are in either set1 or set2, but not both. |
| 76 // If the sets are equal, this is none. |
| 77 std::set<URLPattern> difference = base::STLSetUnion<std::set<URLPattern> >( |
| 78 base::STLSetDifference<std::set<URLPattern> >(set1, set2), |
| 79 base::STLSetDifference<std::set<URLPattern> >(set2, set1)); |
| 80 |
| 81 std::string error; |
| 82 for (std::set<URLPattern>::const_iterator iter = difference.begin(); |
| 83 iter != difference.end(); |
| 84 ++iter) { |
| 85 if (iter->GetAsString() == "chrome://favicon/*") |
| 86 continue; // Grr... This is auto-added for extensions with <all_urls> |
| 87 error = base::StringPrintf("%s\n%s contains %s and the other does not.", |
| 88 error.c_str(), |
| 89 (set1.count(*iter) ? "Set1" : "Set2"), |
| 90 iter->GetAsString().c_str()); |
| 91 } |
| 92 |
| 93 if (!error.empty()) |
| 94 return testing::AssertionFailure() << error; |
| 95 return testing::AssertionSuccess(); |
| 96 } |
| 97 |
33 // A helper class that listens for NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED. | 98 // A helper class that listens for NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED. |
34 class PermissionsUpdaterListener : public content::NotificationObserver { | 99 class PermissionsUpdaterListener : public content::NotificationObserver { |
35 public: | 100 public: |
36 PermissionsUpdaterListener() | 101 PermissionsUpdaterListener() |
37 : received_notification_(false), waiting_(false) { | 102 : received_notification_(false), waiting_(false) { |
38 registrar_.Add(this, | 103 registrar_.Add(this, |
39 chrome::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED, | 104 chrome::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED, |
40 content::NotificationService::AllSources()); | 105 content::NotificationService::AllSources()); |
41 } | 106 } |
42 | 107 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 | 168 |
104 void AddPattern(URLPatternSet* extent, const std::string& pattern) { | 169 void AddPattern(URLPatternSet* extent, const std::string& pattern) { |
105 int schemes = URLPattern::SCHEME_ALL; | 170 int schemes = URLPattern::SCHEME_ALL; |
106 extent->AddPattern(URLPattern(schemes, pattern)); | 171 extent->AddPattern(URLPattern(schemes, pattern)); |
107 } | 172 } |
108 | 173 |
109 } // namespace | 174 } // namespace |
110 | 175 |
111 // Test that the PermissionUpdater can correctly add and remove active | 176 // Test that the PermissionUpdater can correctly add and remove active |
112 // permissions. This tests all of PermissionsUpdater's public methods because | 177 // permissions. This tests all of PermissionsUpdater's public methods because |
113 // GrantActivePermissions and SetActivePermissions are used by AddPermissions. | 178 // GrantActivePermissions and SetPermissions are used by AddPermissions. |
114 TEST_F(PermissionsUpdaterTest, AddAndRemovePermissions) { | 179 TEST_F(PermissionsUpdaterTest, AddAndRemovePermissions) { |
115 InitializeEmptyExtensionService(); | 180 InitializeEmptyExtensionService(); |
116 | 181 |
117 // Load the test extension. | 182 // Load the test extension. |
118 scoped_refptr<Extension> extension = LoadOurManifest(); | 183 scoped_refptr<Extension> extension = LoadOurManifest(); |
119 ASSERT_TRUE(extension.get()); | 184 ASSERT_TRUE(extension.get()); |
120 | 185 |
121 APIPermissionSet default_apis; | 186 APIPermissionSet default_apis; |
122 default_apis.insert(APIPermission::kManagement); | 187 default_apis.insert(APIPermission::kManagement); |
123 ManifestPermissionSet empty_manifest_permissions; | 188 ManifestPermissionSet empty_manifest_permissions; |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 | 266 |
202 // Verify that the extension prefs hold the new active permissions and the | 267 // Verify that the extension prefs hold the new active permissions and the |
203 // same granted permissions. | 268 // same granted permissions. |
204 from_prefs = prefs->GetActivePermissions(extension->id()); | 269 from_prefs = prefs->GetActivePermissions(extension->id()); |
205 ASSERT_EQ(*active_permissions.get(), *from_prefs.get()); | 270 ASSERT_EQ(*active_permissions.get(), *from_prefs.get()); |
206 | 271 |
207 from_prefs = prefs->GetGrantedPermissions(extension->id()); | 272 from_prefs = prefs->GetGrantedPermissions(extension->id()); |
208 ASSERT_EQ(*granted_permissions.get(), *from_prefs.get()); | 273 ASSERT_EQ(*granted_permissions.get(), *from_prefs.get()); |
209 } | 274 } |
210 | 275 |
| 276 TEST_F(PermissionsUpdaterTest, WithholdAllHosts) { |
| 277 InitializeEmptyExtensionService(); |
| 278 |
| 279 // Permissions are only withheld with the appropriate switch turned on. |
| 280 scoped_ptr<FeatureSwitch::ScopedOverride> switch_override( |
| 281 new FeatureSwitch::ScopedOverride(FeatureSwitch::scripts_require_action(), |
| 282 FeatureSwitch::OVERRIDE_ENABLED)); |
| 283 |
| 284 URLPattern google(URLPattern::SCHEME_ALL, "http://www.google.com/*"); |
| 285 URLPattern sub_google(URLPattern::SCHEME_ALL, "http://*.google.com/*"); |
| 286 URLPattern all_http(URLPattern::SCHEME_ALL, "http://*/*"); |
| 287 URLPattern all_hosts(URLPattern::SCHEME_ALL, "<all_urls>"); |
| 288 URLPattern all_com(URLPattern::SCHEME_ALL, "http://*.com/*"); |
| 289 |
| 290 std::set<URLPattern> all_host_patterns; |
| 291 std::set<URLPattern> safe_patterns; |
| 292 |
| 293 all_host_patterns.insert(all_http); |
| 294 all_host_patterns.insert(all_hosts); |
| 295 all_host_patterns.insert(all_com); |
| 296 |
| 297 safe_patterns.insert(google); |
| 298 safe_patterns.insert(sub_google); |
| 299 |
| 300 std::set<URLPattern> all_patterns = base::STLSetUnion<std::set<URLPattern> >( |
| 301 all_host_patterns, safe_patterns); |
| 302 |
| 303 scoped_refptr<const Extension> extension = CreateExtensionWithPermissions( |
| 304 all_patterns, all_patterns, Manifest::INTERNAL); |
| 305 const PermissionsData* permissions_data = extension->permissions_data(); |
| 306 PermissionsUpdater updater(profile_.get()); |
| 307 updater.InitializePermissions(extension); |
| 308 |
| 309 // At first, the active permissions should have only the safe patterns and |
| 310 // the withheld permissions should have only the all host patterns. |
| 311 EXPECT_TRUE(SetsAreEqual( |
| 312 permissions_data->active_permissions()->scriptable_hosts().patterns(), |
| 313 safe_patterns)); |
| 314 EXPECT_TRUE(SetsAreEqual( |
| 315 permissions_data->active_permissions()->explicit_hosts().patterns(), |
| 316 safe_patterns)); |
| 317 EXPECT_TRUE(SetsAreEqual( |
| 318 permissions_data->withheld_permissions()->scriptable_hosts().patterns(), |
| 319 all_host_patterns)); |
| 320 EXPECT_TRUE(SetsAreEqual( |
| 321 permissions_data->withheld_permissions()->explicit_hosts().patterns(), |
| 322 all_host_patterns)); |
| 323 |
| 324 // Then, we grant the withheld all-hosts permissions. |
| 325 updater.GrantWithheldAllHosts(extension); |
| 326 // Now, active permissions should have all patterns, and withheld permissions |
| 327 // should have none. |
| 328 EXPECT_TRUE(SetsAreEqual( |
| 329 permissions_data->active_permissions()->scriptable_hosts().patterns(), |
| 330 all_patterns)); |
| 331 EXPECT_TRUE(permissions_data->withheld_permissions() |
| 332 ->scriptable_hosts() |
| 333 .patterns() |
| 334 .empty()); |
| 335 EXPECT_TRUE(SetsAreEqual( |
| 336 permissions_data->active_permissions()->explicit_hosts().patterns(), |
| 337 all_patterns)); |
| 338 EXPECT_TRUE(permissions_data->withheld_permissions() |
| 339 ->explicit_hosts() |
| 340 .patterns() |
| 341 .empty()); |
| 342 |
| 343 // Finally, we revoke the all hosts permissions. |
| 344 updater.WithholdAllHosts(extension); |
| 345 |
| 346 // We should be back to our initial state - all_hosts should be withheld, and |
| 347 // the safe patterns should be granted. |
| 348 EXPECT_TRUE(SetsAreEqual( |
| 349 permissions_data->active_permissions()->scriptable_hosts().patterns(), |
| 350 safe_patterns)); |
| 351 EXPECT_TRUE(SetsAreEqual( |
| 352 permissions_data->active_permissions()->explicit_hosts().patterns(), |
| 353 safe_patterns)); |
| 354 EXPECT_TRUE(SetsAreEqual( |
| 355 permissions_data->withheld_permissions()->scriptable_hosts().patterns(), |
| 356 all_host_patterns)); |
| 357 EXPECT_TRUE(SetsAreEqual( |
| 358 permissions_data->withheld_permissions()->explicit_hosts().patterns(), |
| 359 all_host_patterns)); |
| 360 |
| 361 // Creating a component extension should result in no withheld permissions. |
| 362 extension = CreateExtensionWithPermissions( |
| 363 all_patterns, all_patterns, Manifest::COMPONENT); |
| 364 permissions_data = extension->permissions_data(); |
| 365 EXPECT_TRUE(SetsAreEqual( |
| 366 permissions_data->active_permissions()->scriptable_hosts().patterns(), |
| 367 all_patterns)); |
| 368 EXPECT_TRUE(permissions_data->withheld_permissions() |
| 369 ->scriptable_hosts() |
| 370 .patterns() |
| 371 .empty()); |
| 372 EXPECT_TRUE(SetsAreEqual( |
| 373 permissions_data->active_permissions()->explicit_hosts().patterns(), |
| 374 all_patterns)); |
| 375 EXPECT_TRUE(permissions_data->withheld_permissions() |
| 376 ->explicit_hosts() |
| 377 .patterns() |
| 378 .empty()); |
| 379 |
| 380 // Without the switch, we shouldn't withhold anything. |
| 381 switch_override.reset(); |
| 382 extension = CreateExtensionWithPermissions( |
| 383 all_patterns, all_patterns, Manifest::INTERNAL); |
| 384 permissions_data = extension->permissions_data(); |
| 385 updater.InitializePermissions(extension); |
| 386 EXPECT_TRUE(SetsAreEqual( |
| 387 permissions_data->active_permissions()->scriptable_hosts().patterns(), |
| 388 all_patterns)); |
| 389 EXPECT_TRUE(permissions_data->withheld_permissions() |
| 390 ->scriptable_hosts() |
| 391 .patterns() |
| 392 .empty()); |
| 393 EXPECT_TRUE(SetsAreEqual( |
| 394 permissions_data->active_permissions()->explicit_hosts().patterns(), |
| 395 all_patterns)); |
| 396 EXPECT_TRUE(permissions_data->withheld_permissions() |
| 397 ->explicit_hosts() |
| 398 .patterns() |
| 399 .empty()); |
| 400 } |
| 401 |
211 } // namespace extensions | 402 } // namespace extensions |
OLD | NEW |