Commit b236ad48 authored by Devlin Cronin's avatar Devlin Cronin Committed by Commit Bot

[Extensions Click-to-Script] Adjust permissions API for withheld permissions

Adjust the chrome.permissions API for use with withheld permissions as
a result of the RuntimeHostPermissions feature. This patch allows the
permissions API to be used to request withheld or optional host
permissions, rather than just optional host permissions.

This is important for extensions that want to be able to request
permissions at runtime using the chrome.permissions API as a workaround
to having required permisssions withheld.

Additionally, move requesting optional permissions to looking at the
runtime granted permission set, rather than the granted permission set.
This greatly simplifies the logic, as now all permission requests are
compared to the same permissions set, and we don't need to isolate host
permission requests versus API permission requests. This also ensures
we avoid granting a permission that was explicitly revoked by the user
(as could happen if we just checked granted permissions).

As of Chrome 70, all permissions granted through the permissions API
are added to the runtime granted set. However, this does mean that
optional permissions that were granted prior to M70, and then later
removed via permissions.remove(), will re-prompt the user. In practice,
this is very rare. This also means that optional permissions will not be
granted automatically for permissions that were used by previous versions
of the extension (similarly, very rare in practice).

This does *not* address the issue of scriptable hosts in requested
permissions; that is still an issue.

Bug: 889654

Change-Id: I8c20f03ec7b402cd61ae1db04b782447dc39414e
Reviewed-on: https://chromium-review.googlesource.com/c/1301851
Commit-Queue: Devlin <rdevlin.cronin@chromium.org>
Reviewed-by: default avatarKaran Bhatia <karandeepb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#607474}
parent 2687587b
...@@ -60,8 +60,12 @@ class PermissionsRequestFunction : public UIThreadExtensionFunction { ...@@ -60,8 +60,12 @@ class PermissionsRequestFunction : public UIThreadExtensionFunction {
// FOR TESTS ONLY to bypass the confirmation UI. // FOR TESTS ONLY to bypass the confirmation UI.
static void SetAutoConfirmForTests(bool should_proceed); static void SetAutoConfirmForTests(bool should_proceed);
static void ResetAutoConfirmForTests();
static void SetIgnoreUserGestureForTests(bool ignore); static void SetIgnoreUserGestureForTests(bool ignore);
// Returns the set of permissions that the user was prompted for, if any.
std::unique_ptr<const PermissionSet> TakePromptedPermissionsForTesting();
protected: protected:
~PermissionsRequestFunction() override; ~PermissionsRequestFunction() override;
...@@ -72,7 +76,16 @@ class PermissionsRequestFunction : public UIThreadExtensionFunction { ...@@ -72,7 +76,16 @@ class PermissionsRequestFunction : public UIThreadExtensionFunction {
void OnInstallPromptDone(ExtensionInstallPrompt::Result result); void OnInstallPromptDone(ExtensionInstallPrompt::Result result);
std::unique_ptr<ExtensionInstallPrompt> install_ui_; std::unique_ptr<ExtensionInstallPrompt> install_ui_;
std::unique_ptr<const PermissionSet> requested_permissions_;
// Requested permissions that are currently withheld.
std::unique_ptr<const PermissionSet> requested_withheld_;
// Requested permissions that are currently optional, and not granted.
std::unique_ptr<const PermissionSet> requested_optional_;
// The permissions, if any, that Chrome would prompt the user for. This will
// be recorded if and only if the prompt is being bypassed for a test (see
// also SetAutoConfirmForTests()).
std::unique_ptr<const PermissionSet> prompted_permissions_for_testing_;
DISALLOW_COPY_AND_ASSIGN(PermissionsRequestFunction); DISALLOW_COPY_AND_ASSIGN(PermissionsRequestFunction);
}; };
......
...@@ -87,9 +87,10 @@ IN_PROC_BROWSER_TEST_F(PermissionsApiTest, OptionalPermissionsGranted) { ...@@ -87,9 +87,10 @@ IN_PROC_BROWSER_TEST_F(PermissionsApiTest, OptionalPermissionsGranted) {
AddPattern(&explicit_hosts, "http://*.c.com/*"); AddPattern(&explicit_hosts, "http://*.c.com/*");
ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile()); ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile());
prefs->AddGrantedPermissions("kjmkgkdkpedkejedfhmfcenooemhbpbo", prefs->AddRuntimeGrantedPermissions(
PermissionSet(apis, manifest_permissions, "kjmkgkdkpedkejedfhmfcenooemhbpbo",
explicit_hosts, URLPatternSet())); PermissionSet(apis, manifest_permissions, explicit_hosts,
URLPatternSet()));
PermissionsRequestFunction::SetIgnoreUserGestureForTests(true); PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
ASSERT_TRUE(StartEmbeddedTestServer()); ASSERT_TRUE(StartEmbeddedTestServer());
...@@ -114,9 +115,10 @@ IN_PROC_BROWSER_TEST_F(PermissionsApiTest, OptionalPermissionsDeny) { ...@@ -114,9 +115,10 @@ IN_PROC_BROWSER_TEST_F(PermissionsApiTest, OptionalPermissionsDeny) {
apis.insert(APIPermission::kManagement); apis.insert(APIPermission::kManagement);
ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile()); ExtensionPrefs* prefs = ExtensionPrefs::Get(browser()->profile());
prefs->AddGrantedPermissions("kjmkgkdkpedkejedfhmfcenooemhbpbo", prefs->AddRuntimeGrantedPermissions(
PermissionSet(apis, ManifestPermissionSet(), "kjmkgkdkpedkejedfhmfcenooemhbpbo",
URLPatternSet(), URLPatternSet())); PermissionSet(apis, ManifestPermissionSet(), URLPatternSet(),
URLPatternSet()));
PermissionsRequestFunction::SetAutoConfirmForTests(false); PermissionsRequestFunction::SetAutoConfirmForTests(false);
PermissionsRequestFunction::SetIgnoreUserGestureForTests(true); PermissionsRequestFunction::SetIgnoreUserGestureForTests(true);
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
var ERROR = 'Optional permissions must be listed in extension manifest.'; var ERROR = 'Only permissions specified in the manifest may be requested.';
var test = chrome.test; var test = chrome.test;
// The URL patterns that we've supposedly been granted access to so far. Use // The URL patterns that we've supposedly been granted access to so far. Use
......
...@@ -11,7 +11,7 @@ var pass = chrome.test.callbackPass; ...@@ -11,7 +11,7 @@ var pass = chrome.test.callbackPass;
var listenOnce = chrome.test.listenOnce; var listenOnce = chrome.test.listenOnce;
var NOT_OPTIONAL_ERROR = var NOT_OPTIONAL_ERROR =
"Optional permissions must be listed in extension manifest."; "Only permissions specified in the manifest may be requested.";
var REQUIRED_ERROR = var REQUIRED_ERROR =
"You cannot remove required permissions."; "You cannot remove required permissions.";
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment