Elim cr-checkbox
[chromium-blink-merge.git] / chrome / browser / extensions / permissions_updater_unittest.cc
blob4621b9ce36025b8e2158253b78eb94b45133791b
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
3 // found in the LICENSE file.
5 #include "base/files/file_path.h"
6 #include "base/json/json_file_value_serializer.h"
7 #include "base/memory/ref_counted.h"
8 #include "base/run_loop.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/values.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/extensions/extension_service_test_base.h"
14 #include "chrome/browser/extensions/extension_util.h"
15 #include "chrome/browser/extensions/permissions_updater.h"
16 #include "chrome/common/chrome_paths.h"
17 #include "chrome/common/extensions/extension_test_util.h"
18 #include "chrome/test/base/testing_profile.h"
19 #include "components/crx_file/id_util.h"
20 #include "content/public/browser/notification_observer.h"
21 #include "content/public/browser/notification_registrar.h"
22 #include "content/public/browser/notification_service.h"
23 #include "extensions/browser/extension_prefs.h"
24 #include "extensions/common/extension.h"
25 #include "extensions/common/extension_builder.h"
26 #include "extensions/common/feature_switch.h"
27 #include "extensions/common/permissions/permission_set.h"
28 #include "extensions/common/permissions/permissions_data.h"
29 #include "extensions/common/value_builder.h"
30 #include "testing/gtest/include/gtest/gtest.h"
32 using extension_test_util::LoadManifest;
34 namespace extensions {
36 namespace {
38 scoped_refptr<const Extension> CreateExtensionWithOptionalPermissions(
39 scoped_ptr<base::Value> optional_permissions,
40 scoped_ptr<base::Value> permissions,
41 const std::string& name) {
42 return ExtensionBuilder()
43 .SetLocation(Manifest::INTERNAL)
44 .SetManifest(
45 DictionaryBuilder()
46 .Set("name", name)
47 .Set("description", "foo")
48 .Set("manifest_version", 2)
49 .Set("version", "0.1.2.3")
50 .Set("permissions", permissions.Pass())
51 .Set("optional_permissions", optional_permissions.Pass()))
52 .SetID(crx_file::id_util::GenerateId(name))
53 .Build();
56 scoped_refptr<const Extension> CreateExtensionWithPermissions(
57 const std::set<URLPattern>& scriptable_hosts,
58 const std::set<URLPattern>& explicit_hosts,
59 Manifest::Location location,
60 const std::string& name) {
61 ListBuilder scriptable_host_list;
62 for (std::set<URLPattern>::const_iterator pattern = scriptable_hosts.begin();
63 pattern != scriptable_hosts.end();
64 ++pattern) {
65 scriptable_host_list.Append(pattern->GetAsString());
68 ListBuilder explicit_host_list;
69 for (std::set<URLPattern>::const_iterator pattern = explicit_hosts.begin();
70 pattern != explicit_hosts.end();
71 ++pattern) {
72 explicit_host_list.Append(pattern->GetAsString());
75 DictionaryBuilder script;
76 script.Set("matches", scriptable_host_list.Pass())
77 .Set("js", ListBuilder().Append("foo.js"));
79 return ExtensionBuilder()
80 .SetLocation(location)
81 .SetManifest(
82 DictionaryBuilder()
83 .Set("name", name)
84 .Set("description", "foo")
85 .Set("manifest_version", 2)
86 .Set("version", "0.1.2.3")
87 .Set("content_scripts", ListBuilder().Append(script.Pass()))
88 .Set("permissions", explicit_host_list.Pass()))
89 .SetID(crx_file::id_util::GenerateId(name))
90 .Build();
93 testing::AssertionResult SetsAreEqual(const std::set<URLPattern>& set1,
94 const std::set<URLPattern>& set2) {
95 // Take the (set1 - set2) U (set2 - set1). This is then the set of all
96 // elements which are in either set1 or set2, but not both.
97 // If the sets are equal, this is none.
98 std::set<URLPattern> difference = base::STLSetUnion<std::set<URLPattern> >(
99 base::STLSetDifference<std::set<URLPattern> >(set1, set2),
100 base::STLSetDifference<std::set<URLPattern> >(set2, set1));
102 std::string error;
103 for (std::set<URLPattern>::const_iterator iter = difference.begin();
104 iter != difference.end();
105 ++iter) {
106 if (iter->GetAsString() == "chrome://favicon/*")
107 continue; // Grr... This is auto-added for extensions with <all_urls>
108 error = base::StringPrintf("%s\n%s contains %s and the other does not.",
109 error.c_str(),
110 (set1.count(*iter) ? "Set1" : "Set2"),
111 iter->GetAsString().c_str());
114 if (!error.empty())
115 return testing::AssertionFailure() << error;
116 return testing::AssertionSuccess();
119 // A helper class that listens for NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED.
120 class PermissionsUpdaterListener : public content::NotificationObserver {
121 public:
122 PermissionsUpdaterListener()
123 : received_notification_(false), waiting_(false) {
124 registrar_.Add(this,
125 extensions::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED,
126 content::NotificationService::AllSources());
129 void Reset() {
130 received_notification_ = false;
131 waiting_ = false;
132 extension_ = NULL;
133 permissions_ = NULL;
136 void Wait() {
137 if (received_notification_)
138 return;
140 waiting_ = true;
141 base::RunLoop run_loop;
142 run_loop.Run();
145 bool received_notification() const { return received_notification_; }
146 const Extension* extension() const { return extension_.get(); }
147 const PermissionSet* permissions() const { return permissions_.get(); }
148 UpdatedExtensionPermissionsInfo::Reason reason() const { return reason_; }
150 private:
151 void Observe(int type,
152 const content::NotificationSource& source,
153 const content::NotificationDetails& details) override {
154 received_notification_ = true;
155 UpdatedExtensionPermissionsInfo* info =
156 content::Details<UpdatedExtensionPermissionsInfo>(details).ptr();
158 extension_ = info->extension;
159 permissions_ = info->permissions;
160 reason_ = info->reason;
162 if (waiting_) {
163 waiting_ = false;
164 base::MessageLoopForUI::current()->Quit();
168 bool received_notification_;
169 bool waiting_;
170 content::NotificationRegistrar registrar_;
171 scoped_refptr<const Extension> extension_;
172 scoped_refptr<const PermissionSet> permissions_;
173 UpdatedExtensionPermissionsInfo::Reason reason_;
176 class PermissionsUpdaterTest : public ExtensionServiceTestBase {
179 scoped_refptr<Extension> LoadOurManifest() {
180 base::FilePath path;
181 path = path.AppendASCII("api_test")
182 .AppendASCII("permissions")
183 .AppendASCII("optional");
184 return LoadManifest(path.AsUTF8Unsafe(),
185 "manifest.json",
186 Manifest::INTERNAL,
187 Extension::NO_FLAGS);
190 void AddPattern(URLPatternSet* extent, const std::string& pattern) {
191 int schemes = URLPattern::SCHEME_ALL;
192 extent->AddPattern(URLPattern(schemes, pattern));
195 } // namespace
197 // Test that the PermissionUpdater can correctly add and remove active
198 // permissions. This tests all of PermissionsUpdater's public methods because
199 // GrantActivePermissions and SetPermissions are used by AddPermissions.
200 TEST_F(PermissionsUpdaterTest, AddAndRemovePermissions) {
201 InitializeEmptyExtensionService();
203 // Load the test extension.
204 scoped_refptr<Extension> extension = LoadOurManifest();
205 ASSERT_TRUE(extension.get());
207 APIPermissionSet default_apis;
208 default_apis.insert(APIPermission::kManagement);
209 ManifestPermissionSet empty_manifest_permissions;
211 URLPatternSet default_hosts;
212 AddPattern(&default_hosts, "http://a.com/*");
213 scoped_refptr<const PermissionSet> default_permissions = new PermissionSet(
214 default_apis, empty_manifest_permissions, default_hosts, URLPatternSet());
216 // Make sure it loaded properly.
217 scoped_refptr<const PermissionSet> permissions =
218 extension->permissions_data()->active_permissions();
219 ASSERT_EQ(*default_permissions.get(),
220 *extension->permissions_data()->active_permissions().get());
222 // Add a few permissions.
223 APIPermissionSet apis;
224 apis.insert(APIPermission::kNotifications);
225 URLPatternSet hosts;
226 AddPattern(&hosts, "http://*.c.com/*");
228 scoped_refptr<const PermissionSet> delta = new PermissionSet(
229 apis, empty_manifest_permissions, hosts, URLPatternSet());
231 PermissionsUpdaterListener listener;
232 PermissionsUpdater updater(profile_.get());
233 updater.AddPermissions(extension.get(), delta.get());
235 listener.Wait();
237 // Verify that the permission notification was sent correctly.
238 ASSERT_TRUE(listener.received_notification());
239 ASSERT_EQ(extension.get(), listener.extension());
240 ASSERT_EQ(UpdatedExtensionPermissionsInfo::ADDED, listener.reason());
241 ASSERT_EQ(*delta.get(), *listener.permissions());
243 // Make sure the extension's active permissions reflect the change.
244 scoped_refptr<const PermissionSet> active_permissions =
245 PermissionSet::CreateUnion(*default_permissions, *delta);
246 ASSERT_EQ(*active_permissions.get(),
247 *extension->permissions_data()->active_permissions().get());
249 // Verify that the new granted and active permissions were also stored
250 // in the extension preferences. In this case, the granted permissions should
251 // be equal to the active permissions.
252 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_.get());
253 scoped_refptr<const PermissionSet> granted_permissions = active_permissions;
255 scoped_refptr<const PermissionSet> from_prefs =
256 prefs->GetActivePermissions(extension->id());
257 ASSERT_EQ(*active_permissions.get(), *from_prefs.get());
259 from_prefs = prefs->GetGrantedPermissions(extension->id());
260 ASSERT_EQ(*active_permissions.get(), *from_prefs.get());
262 // In the second part of the test, we'll remove the permissions that we
263 // just added except for 'notifications'.
264 apis.erase(APIPermission::kNotifications);
265 delta = new PermissionSet(apis, empty_manifest_permissions,
266 hosts, URLPatternSet());
268 listener.Reset();
269 updater.RemovePermissions(extension.get(), delta.get(),
270 PermissionsUpdater::REMOVE_SOFT);
271 listener.Wait();
273 // Verify that the notification was correct.
274 ASSERT_TRUE(listener.received_notification());
275 ASSERT_EQ(extension.get(), listener.extension());
276 ASSERT_EQ(UpdatedExtensionPermissionsInfo::REMOVED, listener.reason());
277 ASSERT_EQ(*delta.get(), *listener.permissions());
279 // Make sure the extension's active permissions reflect the change.
280 active_permissions =
281 PermissionSet::CreateDifference(*active_permissions, *delta);
282 ASSERT_EQ(*active_permissions.get(),
283 *extension->permissions_data()->active_permissions().get());
285 // Verify that the extension prefs hold the new active permissions and the
286 // same granted permissions.
287 from_prefs = prefs->GetActivePermissions(extension->id());
288 ASSERT_EQ(*active_permissions.get(), *from_prefs.get());
290 from_prefs = prefs->GetGrantedPermissions(extension->id());
291 ASSERT_EQ(*granted_permissions.get(), *from_prefs.get());
294 TEST_F(PermissionsUpdaterTest, WithholdAllHosts) {
295 InitializeEmptyExtensionService();
297 // Permissions are only withheld with the appropriate switch turned on.
298 scoped_ptr<FeatureSwitch::ScopedOverride> switch_override(
299 new FeatureSwitch::ScopedOverride(FeatureSwitch::scripts_require_action(),
300 FeatureSwitch::OVERRIDE_ENABLED));
302 URLPattern google(URLPattern::SCHEME_ALL, "http://www.google.com/*");
303 URLPattern sub_google(URLPattern::SCHEME_ALL, "http://*.google.com/*");
304 URLPattern all_http(URLPattern::SCHEME_ALL, "http://*/*");
305 URLPattern all_hosts(URLPattern::SCHEME_ALL, "<all_urls>");
306 URLPattern all_com(URLPattern::SCHEME_ALL, "http://*.com/*");
308 std::set<URLPattern> all_host_patterns;
309 std::set<URLPattern> safe_patterns;
311 all_host_patterns.insert(all_http);
312 all_host_patterns.insert(all_hosts);
313 all_host_patterns.insert(all_com);
315 safe_patterns.insert(google);
316 safe_patterns.insert(sub_google);
318 std::set<URLPattern> all_patterns = base::STLSetUnion<std::set<URLPattern> >(
319 all_host_patterns, safe_patterns);
321 scoped_refptr<const Extension> extension = CreateExtensionWithPermissions(
322 all_patterns, all_patterns, Manifest::INTERNAL, "a");
323 const PermissionsData* permissions_data = extension->permissions_data();
324 PermissionsUpdater updater(profile_.get());
325 updater.InitializePermissions(extension.get());
327 // At first, the active permissions should have only the safe patterns and
328 // the withheld permissions should have only the all host patterns.
329 EXPECT_TRUE(SetsAreEqual(
330 permissions_data->active_permissions()->scriptable_hosts().patterns(),
331 safe_patterns));
332 EXPECT_TRUE(SetsAreEqual(
333 permissions_data->active_permissions()->explicit_hosts().patterns(),
334 safe_patterns));
335 EXPECT_TRUE(SetsAreEqual(
336 permissions_data->withheld_permissions()->scriptable_hosts().patterns(),
337 all_host_patterns));
338 EXPECT_TRUE(SetsAreEqual(
339 permissions_data->withheld_permissions()->explicit_hosts().patterns(),
340 all_host_patterns));
342 // Then, we grant the withheld all-hosts permissions.
343 updater.GrantWithheldImpliedAllHosts(extension.get());
344 // Now, active permissions should have all patterns, and withheld permissions
345 // should have none.
346 EXPECT_TRUE(SetsAreEqual(
347 permissions_data->active_permissions()->scriptable_hosts().patterns(),
348 all_patterns));
349 EXPECT_TRUE(permissions_data->withheld_permissions()
350 ->scriptable_hosts()
351 .patterns()
352 .empty());
353 EXPECT_TRUE(SetsAreEqual(
354 permissions_data->active_permissions()->explicit_hosts().patterns(),
355 all_patterns));
356 EXPECT_TRUE(permissions_data->withheld_permissions()
357 ->explicit_hosts()
358 .patterns()
359 .empty());
361 // Finally, we revoke the all hosts permissions.
362 updater.WithholdImpliedAllHosts(extension.get());
364 // We should be back to our initial state - all_hosts should be withheld, and
365 // the safe patterns should be granted.
366 EXPECT_TRUE(SetsAreEqual(
367 permissions_data->active_permissions()->scriptable_hosts().patterns(),
368 safe_patterns));
369 EXPECT_TRUE(SetsAreEqual(
370 permissions_data->active_permissions()->explicit_hosts().patterns(),
371 safe_patterns));
372 EXPECT_TRUE(SetsAreEqual(
373 permissions_data->withheld_permissions()->scriptable_hosts().patterns(),
374 all_host_patterns));
375 EXPECT_TRUE(SetsAreEqual(
376 permissions_data->withheld_permissions()->explicit_hosts().patterns(),
377 all_host_patterns));
379 // Creating a component extension should result in no withheld permissions.
380 extension = CreateExtensionWithPermissions(
381 all_patterns, all_patterns, Manifest::COMPONENT, "b");
382 permissions_data = extension->permissions_data();
383 updater.InitializePermissions(extension.get());
384 EXPECT_TRUE(SetsAreEqual(
385 permissions_data->active_permissions()->scriptable_hosts().patterns(),
386 all_patterns));
387 EXPECT_TRUE(permissions_data->withheld_permissions()
388 ->scriptable_hosts()
389 .patterns()
390 .empty());
391 EXPECT_TRUE(SetsAreEqual(
392 permissions_data->active_permissions()->explicit_hosts().patterns(),
393 all_patterns));
394 EXPECT_TRUE(permissions_data->withheld_permissions()
395 ->explicit_hosts()
396 .patterns()
397 .empty());
399 // Without the switch, we shouldn't withhold anything.
400 switch_override.reset();
401 extension = CreateExtensionWithPermissions(
402 all_patterns, all_patterns, Manifest::INTERNAL, "c");
403 permissions_data = extension->permissions_data();
404 updater.InitializePermissions(extension.get());
405 EXPECT_TRUE(SetsAreEqual(
406 permissions_data->active_permissions()->scriptable_hosts().patterns(),
407 all_patterns));
408 EXPECT_TRUE(permissions_data->withheld_permissions()
409 ->scriptable_hosts()
410 .patterns()
411 .empty());
412 EXPECT_TRUE(SetsAreEqual(
413 permissions_data->active_permissions()->explicit_hosts().patterns(),
414 all_patterns));
415 EXPECT_TRUE(permissions_data->withheld_permissions()
416 ->explicit_hosts()
417 .patterns()
418 .empty());
421 // Tests that withholding all hosts behaves properly with extensions installed
422 // when the switch is turned on and off.
423 TEST_F(PermissionsUpdaterTest, WithholdAllHostsWithTransientSwitch) {
424 InitializeEmptyExtensionService();
426 URLPattern all_hosts(URLPattern::SCHEME_ALL, "<all_urls>");
427 std::set<URLPattern> all_host_patterns;
428 all_host_patterns.insert(all_hosts);
430 scoped_refptr<const Extension> extension_a = CreateExtensionWithPermissions(
431 all_host_patterns, all_host_patterns, Manifest::INTERNAL, "a");
432 PermissionsUpdater updater(profile());
433 updater.InitializePermissions(extension_a.get());
434 const PermissionsData* permissions_data = extension_a->permissions_data();
436 // Since the extension was created without the switch on, it should default
437 // to having all urls access.
438 EXPECT_TRUE(SetsAreEqual(
439 permissions_data->active_permissions()->scriptable_hosts().patterns(),
440 all_host_patterns));
441 EXPECT_TRUE(
442 permissions_data->withheld_permissions()->scriptable_hosts().is_empty());
443 EXPECT_TRUE(util::AllowedScriptingOnAllUrls(extension_a->id(), profile()));
445 // Enable the switch, and re-init permission for the extension.
446 scoped_ptr<FeatureSwitch::ScopedOverride> switch_override(
447 new FeatureSwitch::ScopedOverride(FeatureSwitch::scripts_require_action(),
448 FeatureSwitch::OVERRIDE_ENABLED));
449 updater.InitializePermissions(extension_a.get());
451 // Since the extension was installed when the switch was off, it should still
452 // have the all urls pref.
453 permissions_data = extension_a->permissions_data();
454 EXPECT_TRUE(SetsAreEqual(
455 permissions_data->active_permissions()->scriptable_hosts().patterns(),
456 all_host_patterns));
457 EXPECT_TRUE(
458 permissions_data->withheld_permissions()->scriptable_hosts().is_empty());
459 EXPECT_TRUE(util::AllowedScriptingOnAllUrls(extension_a->id(), profile()));
461 // Load a new extension, which also has all urls. Since the switch is now on,
462 // the permissions should be withheld.
463 scoped_refptr<const Extension> extension_b = CreateExtensionWithPermissions(
464 all_host_patterns, all_host_patterns, Manifest::INTERNAL, "b");
465 updater.InitializePermissions(extension_b.get());
466 permissions_data = extension_b->permissions_data();
468 EXPECT_TRUE(
469 permissions_data->active_permissions()->scriptable_hosts().is_empty());
470 EXPECT_TRUE(SetsAreEqual(
471 permissions_data->withheld_permissions()->scriptable_hosts().patterns(),
472 all_host_patterns));
473 EXPECT_FALSE(util::AllowedScriptingOnAllUrls(extension_b->id(), profile()));
475 // Disable the switch, and reload the extension.
476 switch_override.reset();
477 updater.InitializePermissions(extension_b.get());
479 // Since the extension was installed with the switch on, it should still be
480 // restricted with the switch off.
481 permissions_data = extension_b->permissions_data();
482 EXPECT_TRUE(
483 permissions_data->active_permissions()->scriptable_hosts().is_empty());
484 EXPECT_TRUE(SetsAreEqual(
485 permissions_data->withheld_permissions()->scriptable_hosts().patterns(),
486 all_host_patterns));
487 EXPECT_FALSE(util::AllowedScriptingOnAllUrls(extension_b->id(), profile()));
490 TEST_F(PermissionsUpdaterTest, RevokingPermissions) {
491 InitializeEmptyExtensionService();
493 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
495 auto api_permission_set = [](APIPermission::ID id) {
496 APIPermissionSet apis;
497 apis.insert(id);
498 return make_scoped_refptr(new PermissionSet(
499 apis, ManifestPermissionSet(), URLPatternSet(), URLPatternSet()));
502 auto url_permission_set = [](const GURL& url) {
503 URLPatternSet set;
504 URLPattern pattern(URLPattern::SCHEME_ALL, url.spec());
505 set.AddPattern(pattern);
506 return make_scoped_refptr(new PermissionSet(
507 APIPermissionSet(), ManifestPermissionSet(), set, URLPatternSet()));
511 // Test revoking optional permissions.
512 ListBuilder optional_permissions;
513 optional_permissions.Append("tabs").Append("cookies").Append("management");
514 ListBuilder required_permissions;
515 required_permissions.Append("topSites");
516 scoped_refptr<const Extension> extension =
517 CreateExtensionWithOptionalPermissions(optional_permissions.Build(),
518 required_permissions.Build(),
519 "My Extension");
521 PermissionsUpdater updater(profile());
522 EXPECT_TRUE(updater.GetRevokablePermissions(extension.get())->IsEmpty());
524 // Add the optional "cookies" permission.
525 updater.AddPermissions(extension.get(),
526 api_permission_set(APIPermission::kCookie).get());
527 const PermissionsData* permissions = extension->permissions_data();
528 // The extension should have the permission in its active permissions and
529 // its granted permissions (stored in prefs). And, the permission should
530 // be revokable.
531 EXPECT_TRUE(permissions->HasAPIPermission(APIPermission::kCookie));
532 scoped_refptr<const PermissionSet> granted_permissions =
533 prefs->GetGrantedPermissions(extension->id());
534 EXPECT_TRUE(granted_permissions->HasAPIPermission(APIPermission::kCookie));
535 EXPECT_TRUE(updater.GetRevokablePermissions(extension.get())
536 ->HasAPIPermission(APIPermission::kCookie));
538 // Repeat with "tabs".
539 updater.AddPermissions(extension.get(),
540 api_permission_set(APIPermission::kTab).get());
541 EXPECT_TRUE(permissions->HasAPIPermission(APIPermission::kTab));
542 granted_permissions = prefs->GetGrantedPermissions(extension->id());
543 EXPECT_TRUE(granted_permissions->HasAPIPermission(APIPermission::kTab));
544 EXPECT_TRUE(updater.GetRevokablePermissions(extension.get())
545 ->HasAPIPermission(APIPermission::kTab));
547 // Remove the "tabs" permission. The extension should no longer have it
548 // in its active or granted permissions, and it shouldn't be revokable.
549 // The extension should still have the "cookies" permission.
550 updater.RemovePermissions(extension.get(),
551 api_permission_set(APIPermission::kTab).get(),
552 PermissionsUpdater::REMOVE_HARD);
553 EXPECT_FALSE(permissions->HasAPIPermission(APIPermission::kTab));
554 granted_permissions = prefs->GetGrantedPermissions(extension->id());
555 EXPECT_FALSE(granted_permissions->HasAPIPermission(APIPermission::kTab));
556 EXPECT_FALSE(updater.GetRevokablePermissions(extension.get())
557 ->HasAPIPermission(APIPermission::kTab));
558 EXPECT_TRUE(permissions->HasAPIPermission(APIPermission::kCookie));
559 granted_permissions = prefs->GetGrantedPermissions(extension->id());
560 EXPECT_TRUE(granted_permissions->HasAPIPermission(APIPermission::kCookie));
561 EXPECT_TRUE(updater.GetRevokablePermissions(extension.get())
562 ->HasAPIPermission(APIPermission::kCookie));
566 // Test revoking non-optional host permissions with click-to-script.
567 FeatureSwitch::ScopedOverride scoped_override(
568 FeatureSwitch::scripts_require_action(), true);
569 ListBuilder optional_permissions;
570 optional_permissions.Append("tabs");
571 ListBuilder required_permissions;
572 required_permissions.Append("topSites")
573 .Append("http://*/*")
574 .Append("http://*.google.com/*");
575 scoped_refptr<const Extension> extension =
576 CreateExtensionWithOptionalPermissions(optional_permissions.Build(),
577 required_permissions.Build(),
578 "My Extension");
579 PermissionsUpdater updater(profile());
580 updater.InitializePermissions(extension.get());
582 // By default, all-hosts was withheld, so the extension shouldn't have
583 // access to any site (like foo.com).
584 const GURL kOrigin("http://foo.com");
585 EXPECT_FALSE(extension->permissions_data()
586 ->active_permissions()
587 ->HasExplicitAccessToOrigin(kOrigin));
588 EXPECT_TRUE(extension->permissions_data()
589 ->withheld_permissions()
590 ->HasExplicitAccessToOrigin(kOrigin));
592 const GURL kRequiredOrigin("http://www.google.com/");
593 EXPECT_TRUE(extension->permissions_data()
594 ->active_permissions()
595 ->HasExplicitAccessToOrigin(kRequiredOrigin));
596 EXPECT_FALSE(updater.GetRevokablePermissions(extension.get())
597 ->HasExplicitAccessToOrigin(kRequiredOrigin));
599 // Give the extension access to foo.com. Now, the foo.com permission should
600 // be revokable.
601 updater.AddPermissions(extension.get(), url_permission_set(kOrigin).get());
602 EXPECT_TRUE(extension->permissions_data()
603 ->active_permissions()
604 ->HasExplicitAccessToOrigin(kOrigin));
605 EXPECT_TRUE(updater.GetRevokablePermissions(extension.get())
606 ->HasExplicitAccessToOrigin(kOrigin));
608 // Revoke the foo.com permission. The extension should no longer have
609 // access to foo.com, and the revokable permissions should be empty.
610 updater.RemovePermissions(extension.get(),
611 url_permission_set(kOrigin).get(),
612 PermissionsUpdater::REMOVE_HARD);
613 EXPECT_FALSE(extension->permissions_data()
614 ->active_permissions()
615 ->HasExplicitAccessToOrigin(kOrigin));
616 EXPECT_TRUE(extension->permissions_data()
617 ->withheld_permissions()
618 ->HasExplicitAccessToOrigin(kOrigin));
619 EXPECT_TRUE(updater.GetRevokablePermissions(extension.get())->IsEmpty());
623 } // namespace extensions