blob: 77c681044f7ba61dbd41e0d114d981f476012fee [file] [log] [blame]
[email protected]c333e792012-01-06 16:57:391// 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.
4
dcheng1fc00f12015-12-26 22:18:035#include "chrome/browser/extensions/permissions_updater.h"
6
7#include <utility>
8
[email protected]57999812013-02-24 05:40:529#include "base/files/file_path.h"
[email protected]ffbec692012-02-26 20:26:4210#include "base/json/json_file_value_serializer.h"
[email protected]c333e792012-01-06 16:57:3911#include "base/memory/ref_counted.h"
[email protected]78089f02012-07-19 06:11:2812#include "base/run_loop.h"
Devlin Cronincac45cb2018-04-25 04:43:0313#include "base/test/scoped_feature_list.h"
[email protected]c333e792012-01-06 16:57:3914#include "base/values.h"
[email protected]49a01e642013-07-12 00:29:4515#include "chrome/browser/chrome_notification_types.h"
[email protected]c333e792012-01-06 16:57:3916#include "chrome/browser/extensions/extension_service.h"
[email protected]f484f8d52014-06-12 08:38:1817#include "chrome/browser/extensions/extension_service_test_base.h"
rdevlin.croninb8dffe52015-02-07 00:58:0118#include "chrome/browser/extensions/extension_util.h"
Devlin Croninf355f1de2018-05-14 15:27:2419#include "chrome/browser/extensions/scripting_permissions_modifier.h"
[email protected]c333e792012-01-06 16:57:3920#include "chrome/common/chrome_paths.h"
[email protected]04e4bbe2013-04-27 07:44:2421#include "chrome/common/extensions/extension_test_util.h"
[email protected]c333e792012-01-06 16:57:3922#include "chrome/test/base/testing_profile.h"
rdevlin.croninb8dffe52015-02-07 00:58:0123#include "components/crx_file/id_util.h"
[email protected]c333e792012-01-06 16:57:3924#include "content/public/browser/notification_observer.h"
25#include "content/public/browser/notification_registrar.h"
26#include "content/public/browser/notification_service.h"
[email protected]dccba4f82014-05-29 00:52:5627#include "extensions/browser/extension_prefs.h"
[email protected]e4452d32013-11-15 23:07:4128#include "extensions/common/extension.h"
[email protected]23a85362014-07-07 23:26:1929#include "extensions/common/extension_builder.h"
Devlin Cronincac45cb2018-04-25 04:43:0330#include "extensions/common/extension_features.h"
[email protected]5a55f3f2013-10-29 01:08:2931#include "extensions/common/permissions/permission_set.h"
[email protected]076ebeda2014-06-06 21:47:2632#include "extensions/common/permissions/permissions_data.h"
[email protected]23a85362014-07-07 23:26:1933#include "extensions/common/value_builder.h"
[email protected]c333e792012-01-06 16:57:3934#include "testing/gtest/include/gtest/gtest.h"
35
[email protected]04e4bbe2013-04-27 07:44:2436using extension_test_util::LoadManifest;
37
[email protected]c333e792012-01-06 16:57:3938namespace extensions {
39
40namespace {
41
rdevlin.cronin77cb0ef2015-09-16 17:03:4842scoped_refptr<const Extension> CreateExtensionWithOptionalPermissions(
dchengc963c7142016-04-08 03:55:2243 std::unique_ptr<base::Value> optional_permissions,
44 std::unique_ptr<base::Value> permissions,
rdevlin.cronin77cb0ef2015-09-16 17:03:4845 const std::string& name) {
46 return ExtensionBuilder()
47 .SetLocation(Manifest::INTERNAL)
dcheng794d2bd2016-02-27 03:51:3248 .SetManifest(
rdevlin.cronin77cb0ef2015-09-16 17:03:4849 DictionaryBuilder()
50 .Set("name", name)
51 .Set("description", "foo")
52 .Set("manifest_version", 2)
53 .Set("version", "0.1.2.3")
dcheng1fc00f12015-12-26 22:18:0354 .Set("permissions", std::move(permissions))
dcheng794d2bd2016-02-27 03:51:3255 .Set("optional_permissions", std::move(optional_permissions))
56 .Build())
rdevlin.cronin77cb0ef2015-09-16 17:03:4857 .SetID(crx_file::id_util::GenerateId(name))
58 .Build();
59}
60
[email protected]c333e792012-01-06 16:57:3961// A helper class that listens for NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED.
62class PermissionsUpdaterListener : public content::NotificationObserver {
63 public:
64 PermissionsUpdaterListener()
65 : received_notification_(false), waiting_(false) {
66 registrar_.Add(this,
[email protected]adf5a102014-07-31 12:44:0667 extensions::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED,
[email protected]c333e792012-01-06 16:57:3968 content::NotificationService::AllSources());
69 }
70
71 void Reset() {
72 received_notification_ = false;
73 waiting_ = false;
74 extension_ = NULL;
75 permissions_ = NULL;
76 }
77
78 void Wait() {
79 if (received_notification_)
80 return;
81
82 waiting_ = true;
[email protected]78089f02012-07-19 06:11:2883 base::RunLoop run_loop;
84 run_loop.Run();
[email protected]c333e792012-01-06 16:57:3985 }
86
87 bool received_notification() const { return received_notification_; }
[email protected]dc24976f2013-06-02 21:15:0988 const Extension* extension() const { return extension_.get(); }
89 const PermissionSet* permissions() const { return permissions_.get(); }
90 UpdatedExtensionPermissionsInfo::Reason reason() const { return reason_; }
[email protected]c333e792012-01-06 16:57:3991
92 private:
dchengae36a4a2014-10-21 12:36:3693 void Observe(int type,
94 const content::NotificationSource& source,
95 const content::NotificationDetails& details) override {
[email protected]c333e792012-01-06 16:57:3996 received_notification_ = true;
97 UpdatedExtensionPermissionsInfo* info =
98 content::Details<UpdatedExtensionPermissionsInfo>(details).ptr();
99
100 extension_ = info->extension;
rdevlin.cronine2d0fd02015-09-24 22:35:49101 permissions_ = info->permissions.Clone();
[email protected]c333e792012-01-06 16:57:39102 reason_ = info->reason;
103
104 if (waiting_) {
105 waiting_ = false;
Gabriel Charette53a9ef812017-07-26 12:36:23106 base::RunLoop::QuitCurrentWhenIdleDeprecated();
[email protected]c333e792012-01-06 16:57:39107 }
108 }
109
110 bool received_notification_;
111 bool waiting_;
112 content::NotificationRegistrar registrar_;
113 scoped_refptr<const Extension> extension_;
dchengc963c7142016-04-08 03:55:22114 std::unique_ptr<const PermissionSet> permissions_;
[email protected]c333e792012-01-06 16:57:39115 UpdatedExtensionPermissionsInfo::Reason reason_;
116};
117
118class PermissionsUpdaterTest : public ExtensionServiceTestBase {
119};
120
[email protected]04e4bbe2013-04-27 07:44:24121scoped_refptr<Extension> LoadOurManifest() {
[email protected]650b2d52013-02-10 03:41:45122 base::FilePath path;
[email protected]04e4bbe2013-04-27 07:44:24123 path = path.AppendASCII("api_test")
[email protected]c333e792012-01-06 16:57:39124 .AppendASCII("permissions")
[email protected]04e4bbe2013-04-27 07:44:24125 .AppendASCII("optional");
126 return LoadManifest(path.AsUTF8Unsafe(),
127 "manifest.json",
128 Manifest::INTERNAL,
129 Extension::NO_FLAGS);
[email protected]c333e792012-01-06 16:57:39130}
131
132void AddPattern(URLPatternSet* extent, const std::string& pattern) {
133 int schemes = URLPattern::SCHEME_ALL;
134 extent->AddPattern(URLPattern(schemes, pattern));
135}
136
isandrk80e3eb92017-04-12 15:22:14137class PermissionsUpdaterTestDelegate : public PermissionsUpdater::Delegate {
138 public:
139 PermissionsUpdaterTestDelegate() {}
140 ~PermissionsUpdaterTestDelegate() override {}
141
142 // PermissionsUpdater::Delegate
143 void InitializePermissions(
144 const Extension* extension,
145 std::unique_ptr<const PermissionSet>* granted_permissions) override {
146 // Remove the cookie permission.
147 APIPermissionSet api_permission_set((*granted_permissions)->apis());
148 api_permission_set.erase(APIPermission::kCookie);
149 granted_permissions->reset(
150 new PermissionSet(api_permission_set, ManifestPermissionSet(),
151 URLPatternSet(), URLPatternSet()));
152 }
153
154 private:
155 DISALLOW_COPY_AND_ASSIGN(PermissionsUpdaterTestDelegate);
156};
157
[email protected]c333e792012-01-06 16:57:39158} // namespace
159
160// Test that the PermissionUpdater can correctly add and remove active
161// permissions. This tests all of PermissionsUpdater's public methods because
[email protected]23a85362014-07-07 23:26:19162// GrantActivePermissions and SetPermissions are used by AddPermissions.
[email protected]c333e792012-01-06 16:57:39163TEST_F(PermissionsUpdaterTest, AddAndRemovePermissions) {
164 InitializeEmptyExtensionService();
165
166 // Load the test extension.
[email protected]04e4bbe2013-04-27 07:44:24167 scoped_refptr<Extension> extension = LoadOurManifest();
168 ASSERT_TRUE(extension.get());
[email protected]c333e792012-01-06 16:57:39169
[email protected]c2e66e12012-06-27 06:27:06170 APIPermissionSet default_apis;
171 default_apis.insert(APIPermission::kManagement);
[email protected]e737c442013-11-15 15:55:24172 ManifestPermissionSet empty_manifest_permissions;
173
[email protected]c333e792012-01-06 16:57:39174 URLPatternSet default_hosts;
175 AddPattern(&default_hosts, "http://a.com/*");
rdevlin.cronine2d0fd02015-09-24 22:35:49176 PermissionSet default_permissions(default_apis, empty_manifest_permissions,
177 default_hosts, URLPatternSet());
[email protected]c333e792012-01-06 16:57:39178
179 // Make sure it loaded properly.
rdevlin.cronine2d0fd02015-09-24 22:35:49180 ASSERT_EQ(default_permissions,
rdevlin.cronind630c302015-09-30 20:19:33181 extension->permissions_data()->active_permissions());
rdevlin.cronine2d0fd02015-09-24 22:35:49182
183 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile_.get());
dchengc963c7142016-04-08 03:55:22184 std::unique_ptr<const PermissionSet> active_permissions;
185 std::unique_ptr<const PermissionSet> granted_permissions;
[email protected]c333e792012-01-06 16:57:39186
187 // Add a few permissions.
[email protected]c2e66e12012-06-27 06:27:06188 APIPermissionSet apis;
[email protected]81327f12014-07-29 04:24:11189 apis.insert(APIPermission::kNotifications);
[email protected]c333e792012-01-06 16:57:39190 URLPatternSet hosts;
191 AddPattern(&hosts, "http://*.c.com/*");
Karan Bhatia599a50b2018-02-03 04:56:30192 URLPatternSet scriptable_hosts;
193 AddPattern(&scriptable_hosts, "http://*.example.com/*");
[email protected]c333e792012-01-06 16:57:39194
rdevlin.cronine2d0fd02015-09-24 22:35:49195 {
196 PermissionSet delta(apis, empty_manifest_permissions, hosts,
Karan Bhatia599a50b2018-02-03 04:56:30197 scriptable_hosts);
[email protected]c333e792012-01-06 16:57:39198
Karan Bhatia599a50b2018-02-03 04:56:30199 PermissionsUpdaterListener listener;
200 PermissionsUpdater(profile_.get()).AddPermissions(extension.get(), delta);
[email protected]c333e792012-01-06 16:57:39201
Karan Bhatia599a50b2018-02-03 04:56:30202 listener.Wait();
[email protected]c333e792012-01-06 16:57:39203
Karan Bhatia599a50b2018-02-03 04:56:30204 // Verify that the permission notification was sent correctly.
205 ASSERT_TRUE(listener.received_notification());
206 ASSERT_EQ(extension.get(), listener.extension());
207 ASSERT_EQ(UpdatedExtensionPermissionsInfo::ADDED, listener.reason());
208 ASSERT_EQ(delta, *listener.permissions());
[email protected]c333e792012-01-06 16:57:39209
Karan Bhatia599a50b2018-02-03 04:56:30210 // Make sure the extension's active permissions reflect the change.
211 active_permissions = PermissionSet::CreateUnion(default_permissions, delta);
212 ASSERT_EQ(*active_permissions,
213 extension->permissions_data()->active_permissions());
[email protected]c333e792012-01-06 16:57:39214
Karan Bhatia599a50b2018-02-03 04:56:30215 // Verify that the new granted and active permissions were also stored
216 // in the extension preferences. In this case, the granted permissions
217 // should be equal to the active permissions.
218 ASSERT_EQ(*active_permissions,
219 *prefs->GetActivePermissions(extension->id()));
220 granted_permissions = active_permissions->Clone();
221 ASSERT_EQ(*granted_permissions,
222 *prefs->GetGrantedPermissions(extension->id()));
rdevlin.cronine2d0fd02015-09-24 22:35:49223 }
[email protected]c333e792012-01-06 16:57:39224
rdevlin.cronine2d0fd02015-09-24 22:35:49225 {
[email protected]c333e792012-01-06 16:57:39226 // In the second part of the test, we'll remove the permissions that we
[email protected]81327f12014-07-29 04:24:11227 // just added except for 'notifications'.
228 apis.erase(APIPermission::kNotifications);
Karan Bhatia599a50b2018-02-03 04:56:30229 PermissionSet delta(apis, empty_manifest_permissions, hosts,
230 scriptable_hosts);
[email protected]c333e792012-01-06 16:57:39231
rdevlin.cronine2d0fd02015-09-24 22:35:49232 PermissionsUpdaterListener listener;
233 PermissionsUpdater(profile_.get())
rdevlin.cronind630c302015-09-30 20:19:33234 .RemovePermissions(extension.get(), delta,
rdevlin.cronine2d0fd02015-09-24 22:35:49235 PermissionsUpdater::REMOVE_SOFT);
[email protected]c333e792012-01-06 16:57:39236 listener.Wait();
237
238 // Verify that the notification was correct.
239 ASSERT_TRUE(listener.received_notification());
dchengc7047942014-08-26 05:05:31240 ASSERT_EQ(extension.get(), listener.extension());
[email protected]c333e792012-01-06 16:57:39241 ASSERT_EQ(UpdatedExtensionPermissionsInfo::REMOVED, listener.reason());
rdevlin.cronine2d0fd02015-09-24 22:35:49242 ASSERT_EQ(delta, *listener.permissions());
[email protected]c333e792012-01-06 16:57:39243
244 // Make sure the extension's active permissions reflect the change.
245 active_permissions =
rdevlin.cronine2d0fd02015-09-24 22:35:49246 PermissionSet::CreateDifference(*active_permissions, delta);
rdevlin.cronind630c302015-09-30 20:19:33247 ASSERT_EQ(*active_permissions,
248 extension->permissions_data()->active_permissions());
[email protected]c333e792012-01-06 16:57:39249
250 // Verify that the extension prefs hold the new active permissions and the
251 // same granted permissions.
rdevlin.cronine2d0fd02015-09-24 22:35:49252 ASSERT_EQ(*active_permissions, *prefs->GetActivePermissions(extension->id()));
[email protected]c333e792012-01-06 16:57:39253
rdevlin.cronine2d0fd02015-09-24 22:35:49254 ASSERT_EQ(*granted_permissions,
255 *prefs->GetGrantedPermissions(extension->id()));
256 }
[email protected]c333e792012-01-06 16:57:39257}
258
rdevlin.cronin77cb0ef2015-09-16 17:03:48259TEST_F(PermissionsUpdaterTest, RevokingPermissions) {
260 InitializeEmptyExtensionService();
261
262 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
263
264 auto api_permission_set = [](APIPermission::ID id) {
265 APIPermissionSet apis;
266 apis.insert(id);
Jinho Bangb5216cec2018-01-17 19:43:11267 return std::make_unique<PermissionSet>(apis, ManifestPermissionSet(),
ricea91d6fc122016-08-30 08:47:14268 URLPatternSet(), URLPatternSet());
rdevlin.cronin77cb0ef2015-09-16 17:03:48269 };
270
271 auto url_permission_set = [](const GURL& url) {
272 URLPatternSet set;
273 URLPattern pattern(URLPattern::SCHEME_ALL, url.spec());
274 set.AddPattern(pattern);
Jinho Bangb5216cec2018-01-17 19:43:11275 return std::make_unique<PermissionSet>(
ricea91d6fc122016-08-30 08:47:14276 APIPermissionSet(), ManifestPermissionSet(), set, URLPatternSet());
rdevlin.cronin77cb0ef2015-09-16 17:03:48277 };
278
nrpetere33d2a5b2017-04-25 00:12:31279 auto can_access_page =
280 [](scoped_refptr<const extensions::Extension> extension,
281 const GURL& document_url) -> bool {
Devlin Cronin3e532b82018-05-03 21:27:19282 PermissionsData::PageAccess access =
Devlin Cronin5cb437832018-05-17 20:14:41283 extension->permissions_data()->GetPageAccess(document_url, -1, nullptr);
Devlin Cronin3e532b82018-05-03 21:27:19284 return access == PermissionsData::PageAccess::kAllowed;
nrpetere33d2a5b2017-04-25 00:12:31285 };
286
rdevlin.cronin77cb0ef2015-09-16 17:03:48287 {
288 // Test revoking optional permissions.
289 ListBuilder optional_permissions;
290 optional_permissions.Append("tabs").Append("cookies").Append("management");
291 ListBuilder required_permissions;
292 required_permissions.Append("topSites");
293 scoped_refptr<const Extension> extension =
294 CreateExtensionWithOptionalPermissions(optional_permissions.Build(),
295 required_permissions.Build(),
296 "My Extension");
297
298 PermissionsUpdater updater(profile());
299 EXPECT_TRUE(updater.GetRevokablePermissions(extension.get())->IsEmpty());
300
301 // Add the optional "cookies" permission.
302 updater.AddPermissions(extension.get(),
rdevlin.cronind630c302015-09-30 20:19:33303 *api_permission_set(APIPermission::kCookie));
rdevlin.cronin77cb0ef2015-09-16 17:03:48304 const PermissionsData* permissions = extension->permissions_data();
305 // The extension should have the permission in its active permissions and
306 // its granted permissions (stored in prefs). And, the permission should
307 // be revokable.
308 EXPECT_TRUE(permissions->HasAPIPermission(APIPermission::kCookie));
dchengc963c7142016-04-08 03:55:22309 std::unique_ptr<const PermissionSet> granted_permissions =
rdevlin.cronin77cb0ef2015-09-16 17:03:48310 prefs->GetGrantedPermissions(extension->id());
311 EXPECT_TRUE(granted_permissions->HasAPIPermission(APIPermission::kCookie));
312 EXPECT_TRUE(updater.GetRevokablePermissions(extension.get())
313 ->HasAPIPermission(APIPermission::kCookie));
314
315 // Repeat with "tabs".
316 updater.AddPermissions(extension.get(),
rdevlin.cronind630c302015-09-30 20:19:33317 *api_permission_set(APIPermission::kTab));
rdevlin.cronin77cb0ef2015-09-16 17:03:48318 EXPECT_TRUE(permissions->HasAPIPermission(APIPermission::kTab));
319 granted_permissions = prefs->GetGrantedPermissions(extension->id());
320 EXPECT_TRUE(granted_permissions->HasAPIPermission(APIPermission::kTab));
321 EXPECT_TRUE(updater.GetRevokablePermissions(extension.get())
322 ->HasAPIPermission(APIPermission::kTab));
323
324 // Remove the "tabs" permission. The extension should no longer have it
325 // in its active or granted permissions, and it shouldn't be revokable.
326 // The extension should still have the "cookies" permission.
327 updater.RemovePermissions(extension.get(),
rdevlin.cronind630c302015-09-30 20:19:33328 *api_permission_set(APIPermission::kTab),
rdevlin.cronin77cb0ef2015-09-16 17:03:48329 PermissionsUpdater::REMOVE_HARD);
330 EXPECT_FALSE(permissions->HasAPIPermission(APIPermission::kTab));
331 granted_permissions = prefs->GetGrantedPermissions(extension->id());
332 EXPECT_FALSE(granted_permissions->HasAPIPermission(APIPermission::kTab));
333 EXPECT_FALSE(updater.GetRevokablePermissions(extension.get())
334 ->HasAPIPermission(APIPermission::kTab));
335 EXPECT_TRUE(permissions->HasAPIPermission(APIPermission::kCookie));
336 granted_permissions = prefs->GetGrantedPermissions(extension->id());
337 EXPECT_TRUE(granted_permissions->HasAPIPermission(APIPermission::kCookie));
338 EXPECT_TRUE(updater.GetRevokablePermissions(extension.get())
339 ->HasAPIPermission(APIPermission::kCookie));
340 }
341
342 {
343 // Test revoking non-optional host permissions with click-to-script.
Devlin Cronincac45cb2018-04-25 04:43:03344 base::test::ScopedFeatureList scoped_feature_list;
345 scoped_feature_list.InitAndEnableFeature(features::kRuntimeHostPermissions);
rdevlin.cronin77cb0ef2015-09-16 17:03:48346 ListBuilder optional_permissions;
347 optional_permissions.Append("tabs");
348 ListBuilder required_permissions;
349 required_permissions.Append("topSites")
350 .Append("http://*/*")
351 .Append("http://*.google.com/*");
352 scoped_refptr<const Extension> extension =
353 CreateExtensionWithOptionalPermissions(optional_permissions.Build(),
354 required_permissions.Build(),
355 "My Extension");
356 PermissionsUpdater updater(profile());
357 updater.InitializePermissions(extension.get());
358
Devlin Croninff97e922018-06-01 06:51:07359 ScriptingPermissionsModifier(profile(), extension).SetWithholdAllUrls(true);
Devlin Croninf355f1de2018-05-14 15:27:24360
361 // All-hosts was withheld, so the extension shouldn't have access to any
362 // site (like foo.com).
rdevlin.cronin77cb0ef2015-09-16 17:03:48363 const GURL kOrigin("http://foo.com");
nrpetere33d2a5b2017-04-25 00:12:31364
rdevlin.cronin77cb0ef2015-09-16 17:03:48365 EXPECT_FALSE(extension->permissions_data()
366 ->active_permissions()
rdevlin.cronind630c302015-09-30 20:19:33367 .HasExplicitAccessToOrigin(kOrigin));
rdevlin.cronin77cb0ef2015-09-16 17:03:48368 EXPECT_TRUE(extension->permissions_data()
369 ->withheld_permissions()
rdevlin.cronind630c302015-09-30 20:19:33370 .HasExplicitAccessToOrigin(kOrigin));
rdevlin.cronin77cb0ef2015-09-16 17:03:48371
372 const GURL kRequiredOrigin("http://www.google.com/");
373 EXPECT_TRUE(extension->permissions_data()
374 ->active_permissions()
rdevlin.cronind630c302015-09-30 20:19:33375 .HasExplicitAccessToOrigin(kRequiredOrigin));
rdevlin.cronin77cb0ef2015-09-16 17:03:48376 EXPECT_FALSE(updater.GetRevokablePermissions(extension.get())
377 ->HasExplicitAccessToOrigin(kRequiredOrigin));
378
379 // Give the extension access to foo.com. Now, the foo.com permission should
380 // be revokable.
rdevlin.cronind630c302015-09-30 20:19:33381 updater.AddPermissions(extension.get(), *url_permission_set(kOrigin));
rdevlin.cronin77cb0ef2015-09-16 17:03:48382 EXPECT_TRUE(extension->permissions_data()
383 ->active_permissions()
rdevlin.cronind630c302015-09-30 20:19:33384 .HasExplicitAccessToOrigin(kOrigin));
rdevlin.cronin77cb0ef2015-09-16 17:03:48385 EXPECT_TRUE(updater.GetRevokablePermissions(extension.get())
386 ->HasExplicitAccessToOrigin(kOrigin));
387
388 // Revoke the foo.com permission. The extension should no longer have
389 // access to foo.com, and the revokable permissions should be empty.
rdevlin.cronind630c302015-09-30 20:19:33390 updater.RemovePermissions(extension.get(), *url_permission_set(kOrigin),
rdevlin.cronin77cb0ef2015-09-16 17:03:48391 PermissionsUpdater::REMOVE_HARD);
392 EXPECT_FALSE(extension->permissions_data()
393 ->active_permissions()
rdevlin.cronind630c302015-09-30 20:19:33394 .HasExplicitAccessToOrigin(kOrigin));
rdevlin.cronin77cb0ef2015-09-16 17:03:48395 EXPECT_TRUE(extension->permissions_data()
396 ->withheld_permissions()
rdevlin.cronind630c302015-09-30 20:19:33397 .HasExplicitAccessToOrigin(kOrigin));
rdevlin.cronin77cb0ef2015-09-16 17:03:48398 EXPECT_TRUE(updater.GetRevokablePermissions(extension.get())->IsEmpty());
399 }
nrpetere33d2a5b2017-04-25 00:12:31400
401 {
402 // Make sure policy restriction updates update permission data.
403 URLPatternSet default_policy_blocked_hosts;
404 URLPatternSet default_policy_allowed_hosts;
405 URLPatternSet policy_blocked_hosts;
406 URLPatternSet policy_allowed_hosts;
407 ListBuilder optional_permissions;
408 ListBuilder required_permissions;
409 required_permissions.Append("tabs").Append("http://*/*");
410 scoped_refptr<const Extension> extension =
411 CreateExtensionWithOptionalPermissions(optional_permissions.Build(),
412 required_permissions.Build(),
413 "ExtensionSettings");
414 AddPattern(&default_policy_blocked_hosts, "http://*.google.com/*");
415 PermissionsUpdater updater(profile());
416 updater.InitializePermissions(extension.get());
417 extension->permissions_data()->SetDefaultPolicyHostRestrictions(
418 default_policy_blocked_hosts, default_policy_allowed_hosts);
419
420 // By default, all subdomains of google.com should be blocked.
421 const GURL kOrigin("http://foo.com");
422 const GURL kGoogle("http://www.google.com");
423 const GURL kExampleGoogle("http://example.google.com");
424 EXPECT_TRUE(
425 extension->permissions_data()->UsesDefaultPolicyHostRestrictions());
426 EXPECT_TRUE(can_access_page(extension, kOrigin));
427 EXPECT_FALSE(can_access_page(extension, kGoogle));
428 EXPECT_FALSE(can_access_page(extension, kExampleGoogle));
429
430 AddPattern(&default_policy_allowed_hosts, "http://example.google.com/*");
431 // Give the extension access to example.google.com. Now the
432 // example.google.com should not be a runtime blocked host.
433 updater.SetDefaultPolicyHostRestrictions(default_policy_blocked_hosts,
434 default_policy_allowed_hosts);
435
436 EXPECT_TRUE(
437 extension->permissions_data()->UsesDefaultPolicyHostRestrictions());
438 EXPECT_TRUE(can_access_page(extension, kOrigin));
439 EXPECT_FALSE(can_access_page(extension, kGoogle));
440 EXPECT_TRUE(can_access_page(extension, kExampleGoogle));
441
442 // Revoke extension access to foo.com. Now, foo.com should be a runtime
443 // blocked host.
444 AddPattern(&default_policy_blocked_hosts, "*://*.foo.com/");
445 updater.SetDefaultPolicyHostRestrictions(default_policy_blocked_hosts,
446 default_policy_allowed_hosts);
447 EXPECT_TRUE(
448 extension->permissions_data()->UsesDefaultPolicyHostRestrictions());
449 EXPECT_FALSE(can_access_page(extension, kOrigin));
450 EXPECT_FALSE(can_access_page(extension, kGoogle));
451 EXPECT_TRUE(can_access_page(extension, kExampleGoogle));
452
453 // Remove foo.com from blocked hosts. The extension should no longer have
454 // be a runtime blocked host.
455 default_policy_blocked_hosts.ClearPatterns();
456 AddPattern(&default_policy_blocked_hosts, "*://*.foo.com/");
457 updater.SetDefaultPolicyHostRestrictions(default_policy_blocked_hosts,
458 default_policy_allowed_hosts);
459 EXPECT_TRUE(
460 extension->permissions_data()->UsesDefaultPolicyHostRestrictions());
461 EXPECT_FALSE(can_access_page(extension, kOrigin));
462 EXPECT_TRUE(can_access_page(extension, kGoogle));
463 EXPECT_TRUE(can_access_page(extension, kExampleGoogle));
464
465 // Set an empty individual policy, should not affect default policy.
466 updater.SetPolicyHostRestrictions(extension.get(), policy_blocked_hosts,
467 policy_allowed_hosts);
468 EXPECT_FALSE(
469 extension->permissions_data()->UsesDefaultPolicyHostRestrictions());
470 EXPECT_TRUE(can_access_page(extension, kOrigin));
471 EXPECT_TRUE(can_access_page(extension, kGoogle));
472 EXPECT_TRUE(can_access_page(extension, kExampleGoogle));
473
474 // Block google.com for the Individual scope.
475 // Whitelist example.google.com for the Indiviaul scope.
476 // Leave google.com and example.google.com off both the whitelist and
477 // blacklist for Default scope.
478 AddPattern(&policy_blocked_hosts, "*://*.google.com/*");
479 AddPattern(&policy_allowed_hosts, "*://example.google.com/*");
480 updater.SetPolicyHostRestrictions(extension.get(), policy_blocked_hosts,
481 policy_allowed_hosts);
482 EXPECT_FALSE(
483 extension->permissions_data()->UsesDefaultPolicyHostRestrictions());
484 EXPECT_TRUE(can_access_page(extension, kOrigin));
485 EXPECT_FALSE(can_access_page(extension, kGoogle));
486 EXPECT_TRUE(can_access_page(extension, kExampleGoogle));
487
488 // Switch back to default scope for extension.
489 updater.SetUsesDefaultHostRestrictions(extension.get());
490 EXPECT_TRUE(
491 extension->permissions_data()->UsesDefaultPolicyHostRestrictions());
492 default_policy_blocked_hosts.ClearPatterns();
493 default_policy_allowed_hosts.ClearPatterns();
494 updater.SetDefaultPolicyHostRestrictions(default_policy_blocked_hosts,
495 default_policy_allowed_hosts);
496 }
rdevlin.cronin77cb0ef2015-09-16 17:03:48497}
498
isandrk80e3eb92017-04-12 15:22:14499// Test that the permissions updater delegate works - in this test it removes
500// the cookies permission.
501TEST_F(PermissionsUpdaterTest, Delegate) {
502 InitializeEmptyExtensionService();
503
504 ListBuilder required_permissions;
505 required_permissions.Append("tabs").Append("management").Append("cookies");
506 scoped_refptr<const Extension> extension =
507 CreateExtensionWithOptionalPermissions(
Jinho Bangb5216cec2018-01-17 19:43:11508 std::make_unique<base::ListValue>(), required_permissions.Build(),
isandrk80e3eb92017-04-12 15:22:14509 "My Extension");
510
Jinho Bangb5216cec2018-01-17 19:43:11511 auto test_delegate = std::make_unique<PermissionsUpdaterTestDelegate>();
isandrk80e3eb92017-04-12 15:22:14512 PermissionsUpdater::SetPlatformDelegate(test_delegate.get());
513 PermissionsUpdater updater(profile());
514 updater.InitializePermissions(extension.get());
515
516 EXPECT_TRUE(extension->permissions_data()->HasAPIPermission(
517 APIPermission::kTab));
518 EXPECT_TRUE(extension->permissions_data()->HasAPIPermission(
519 APIPermission::kManagement));
520 EXPECT_FALSE(extension->permissions_data()->HasAPIPermission(
521 APIPermission::kCookie));
522
523 // Unset the delegate.
524 PermissionsUpdater::SetPlatformDelegate(nullptr);
525}
526
Devlin Cronine90eacf2018-06-07 17:23:45527TEST_F(PermissionsUpdaterTest, UpdatingRuntimeGrantedPermissions) {
528 InitializeEmptyExtensionService();
529
530 scoped_refptr<const Extension> extension =
531 ExtensionBuilder("extension")
532 .SetManifestKey("optional_permissions",
533 extensions::ListBuilder().Append("tabs").Build())
534 .Build();
535
536 PermissionsUpdater updater(profile());
537 updater.InitializePermissions(extension.get());
538
539 ExtensionPrefs* prefs = ExtensionPrefs::Get(profile());
540
541 // Initially, there should be no runtime-granted permissions.
542 EXPECT_TRUE(prefs->GetRuntimeGrantedPermissions(extension->id())->IsEmpty());
543
544 APIPermissionSet apis;
545 apis.insert(APIPermission::kTab);
546 PermissionSet optional_permissions(apis, ManifestPermissionSet(),
547 URLPatternSet(), URLPatternSet());
548
549 // Granting permissions should update runtime-granted permissions.
550 updater.AddPermissions(extension.get(), optional_permissions);
551 EXPECT_EQ(optional_permissions,
552 *prefs->GetRuntimeGrantedPermissions(extension->id()));
553
554 // Removing permissions with REMOVE_SOFT should not remove the permission
555 // from runtime-granted permissions; this happens when the extension opts
556 // into lower privilege.
557 updater.RemovePermissions(extension.get(), optional_permissions,
558 PermissionsUpdater::REMOVE_SOFT);
559 EXPECT_EQ(optional_permissions,
560 *prefs->GetRuntimeGrantedPermissions(extension->id()));
561
562 // Removing permissions with REMOVE_HARD should remove the permission from
563 // runtime granted permissions; this happens when the user chooses to revoke
564 // the permission.
565 // Note: we need to add back the permission first, so it shows up as a
566 // revokable permission.
567 // TODO(devlin): Inactive, but granted, permissions should be revokable.
568 updater.AddPermissions(extension.get(), optional_permissions);
569 updater.RemovePermissions(extension.get(), optional_permissions,
570 PermissionsUpdater::REMOVE_HARD);
571 EXPECT_TRUE(prefs->GetRuntimeGrantedPermissions(extension->id())->IsEmpty());
572}
573
[email protected]c333e792012-01-06 16:57:39574} // namespace extensions