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/path_service.h"
9 #include "base/run_loop.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_unittest.h"
14 #include "chrome/browser/extensions/permissions_updater.h"
15 #include "chrome/common/chrome_paths.h"
16 #include "chrome/common/extensions/extension_test_util.h"
17 #include "chrome/test/base/testing_profile.h"
18 #include "content/public/browser/notification_observer.h"
19 #include "content/public/browser/notification_registrar.h"
20 #include "content/public/browser/notification_service.h"
21 #include "extensions/common/extension.h"
22 #include "extensions/common/permissions/permission_set.h"
23 #include "testing/gtest/include/gtest/gtest.h"
25 using extension_test_util::LoadManifest
;
27 namespace extensions
{
31 // A helper class that listens for NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED.
32 class PermissionsUpdaterListener
: public content::NotificationObserver
{
34 PermissionsUpdaterListener()
35 : received_notification_(false), waiting_(false) {
37 chrome::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED
,
38 content::NotificationService::AllSources());
42 received_notification_
= false;
49 if (received_notification_
)
53 base::RunLoop run_loop
;
57 bool received_notification() const { return received_notification_
; }
58 const Extension
* extension() const { return extension_
.get(); }
59 const PermissionSet
* permissions() const { return permissions_
.get(); }
60 UpdatedExtensionPermissionsInfo::Reason
reason() const { return reason_
; }
63 virtual void Observe(int type
,
64 const content::NotificationSource
& source
,
65 const content::NotificationDetails
& details
) OVERRIDE
{
66 received_notification_
= true;
67 UpdatedExtensionPermissionsInfo
* info
=
68 content::Details
<UpdatedExtensionPermissionsInfo
>(details
).ptr();
70 extension_
= info
->extension
;
71 permissions_
= info
->permissions
;
72 reason_
= info
->reason
;
76 base::MessageLoopForUI::current()->Quit();
80 bool received_notification_
;
82 content::NotificationRegistrar registrar_
;
83 scoped_refptr
<const Extension
> extension_
;
84 scoped_refptr
<const PermissionSet
> permissions_
;
85 UpdatedExtensionPermissionsInfo::Reason reason_
;
88 class PermissionsUpdaterTest
: public ExtensionServiceTestBase
{
91 scoped_refptr
<Extension
> LoadOurManifest() {
93 path
= path
.AppendASCII("api_test")
94 .AppendASCII("permissions")
95 .AppendASCII("optional");
96 return LoadManifest(path
.AsUTF8Unsafe(),
102 void AddPattern(URLPatternSet
* extent
, const std::string
& pattern
) {
103 int schemes
= URLPattern::SCHEME_ALL
;
104 extent
->AddPattern(URLPattern(schemes
, pattern
));
109 // Test that the PermissionUpdater can correctly add and remove active
110 // permissions. This tests all of PermissionsUpdater's public methods because
111 // GrantActivePermissions and UpdateActivePermissions are used by
113 TEST_F(PermissionsUpdaterTest
, AddAndRemovePermissions
) {
114 InitializeEmptyExtensionService();
116 // Load the test extension.
117 scoped_refptr
<Extension
> extension
= LoadOurManifest();
118 ASSERT_TRUE(extension
.get());
120 APIPermissionSet default_apis
;
121 default_apis
.insert(APIPermission::kManagement
);
122 ManifestPermissionSet empty_manifest_permissions
;
124 URLPatternSet default_hosts
;
125 AddPattern(&default_hosts
, "http://a.com/*");
126 scoped_refptr
<PermissionSet
> default_permissions
=
127 new PermissionSet(default_apis
, empty_manifest_permissions
,
128 default_hosts
, URLPatternSet());
130 // Make sure it loaded properly.
131 scoped_refptr
<const PermissionSet
> permissions
=
132 extension
->GetActivePermissions();
133 ASSERT_EQ(*default_permissions
.get(),
134 *extension
->GetActivePermissions().get());
136 // Add a few permissions.
137 APIPermissionSet apis
;
138 apis
.insert(APIPermission::kTab
);
139 apis
.insert(APIPermission::kNotification
);
141 AddPattern(&hosts
, "http://*.c.com/*");
143 scoped_refptr
<PermissionSet
> delta
=
144 new PermissionSet(apis
, empty_manifest_permissions
,
145 hosts
, URLPatternSet());
147 PermissionsUpdaterListener listener
;
148 PermissionsUpdater
updater(profile_
.get());
149 updater
.AddPermissions(extension
.get(), delta
.get());
153 // Verify that the permission notification was sent correctly.
154 ASSERT_TRUE(listener
.received_notification());
155 ASSERT_EQ(extension
, listener
.extension());
156 ASSERT_EQ(UpdatedExtensionPermissionsInfo::ADDED
, listener
.reason());
157 ASSERT_EQ(*delta
.get(), *listener
.permissions());
159 // Make sure the extension's active permissions reflect the change.
160 scoped_refptr
<PermissionSet
> active_permissions
=
161 PermissionSet::CreateUnion(default_permissions
.get(), delta
.get());
162 ASSERT_EQ(*active_permissions
.get(),
163 *extension
->GetActivePermissions().get());
165 // Verify that the new granted and active permissions were also stored
166 // in the extension preferences. In this case, the granted permissions should
167 // be equal to the active permissions.
168 ExtensionPrefs
* prefs
= service_
->extension_prefs();
169 scoped_refptr
<PermissionSet
> granted_permissions
=
172 scoped_refptr
<PermissionSet
> from_prefs
=
173 prefs
->GetActivePermissions(extension
->id());
174 ASSERT_EQ(*active_permissions
.get(), *from_prefs
.get());
176 from_prefs
= prefs
->GetGrantedPermissions(extension
->id());
177 ASSERT_EQ(*active_permissions
.get(), *from_prefs
.get());
179 // In the second part of the test, we'll remove the permissions that we
180 // just added except for 'notification'.
181 apis
.erase(APIPermission::kNotification
);
182 delta
= new PermissionSet(apis
, empty_manifest_permissions
,
183 hosts
, URLPatternSet());
186 updater
.RemovePermissions(extension
.get(), delta
.get());
189 // Verify that the notification was correct.
190 ASSERT_TRUE(listener
.received_notification());
191 ASSERT_EQ(extension
, listener
.extension());
192 ASSERT_EQ(UpdatedExtensionPermissionsInfo::REMOVED
, listener
.reason());
193 ASSERT_EQ(*delta
.get(), *listener
.permissions());
195 // Make sure the extension's active permissions reflect the change.
197 PermissionSet::CreateDifference(active_permissions
.get(), delta
.get());
198 ASSERT_EQ(*active_permissions
.get(),
199 *extension
->GetActivePermissions().get());
201 // Verify that the extension prefs hold the new active permissions and the
202 // same granted permissions.
203 from_prefs
= prefs
->GetActivePermissions(extension
->id());
204 ASSERT_EQ(*active_permissions
.get(), *from_prefs
.get());
206 from_prefs
= prefs
->GetGrantedPermissions(extension
->id());
207 ASSERT_EQ(*granted_permissions
.get(), *from_prefs
.get());
210 } // namespace extensions