summaryrefslogtreecommitdiff
path: root/chromium/components/permissions
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/components/permissions')
-rw-r--r--chromium/components/permissions/BUILD.gn4
-rw-r--r--chromium/components/permissions/android/BUILD.gn3
-rw-r--r--chromium/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogController.java10
-rw-r--r--chromium/components/permissions/chooser_context_base.cc2
-rw-r--r--chromium/components/permissions/chooser_context_base.h4
-rw-r--r--chromium/components/permissions/contexts/OWNERS6
-rw-r--r--chromium/components/permissions/contexts/geolocation_permission_context.cc5
-rw-r--r--chromium/components/permissions/contexts/geolocation_permission_context.h5
-rw-r--r--chromium/components/permissions/contexts/geolocation_permission_context_unittest.cc57
-rw-r--r--chromium/components/permissions/contexts/webxr_permission_context.cc136
-rw-r--r--chromium/components/permissions/contexts/webxr_permission_context.h59
-rw-r--r--chromium/components/permissions/notification_permission_ui_selector.h2
-rw-r--r--chromium/components/permissions/permission_context_base.cc15
-rw-r--r--chromium/components/permissions/permission_request.cc6
-rw-r--r--chromium/components/permissions/permission_request.h5
-rw-r--r--chromium/components/permissions/permission_request_impl.cc42
-rw-r--r--chromium/components/permissions/permission_request_impl.h3
-rw-r--r--chromium/components/permissions/permission_request_manager.cc45
-rw-r--r--chromium/components/permissions/permission_request_manager.h8
-rw-r--r--chromium/components/permissions/permission_result.h4
-rw-r--r--chromium/components/permissions/permission_uma_util.cc83
-rw-r--r--chromium/components/permissions/permission_uma_util.h9
-rw-r--r--chromium/components/permissions/permissions_client.cc6
-rw-r--r--chromium/components/permissions/permissions_client.h15
-rw-r--r--chromium/components/permissions/quota_permission_context_impl.cc9
25 files changed, 422 insertions, 121 deletions
diff --git a/chromium/components/permissions/BUILD.gn b/chromium/components/permissions/BUILD.gn
index 7265a29a466..055fa84b5ee 100644
--- a/chromium/components/permissions/BUILD.gn
+++ b/chromium/components/permissions/BUILD.gn
@@ -8,6 +8,8 @@ source_set("permissions") {
"chooser_context_base.h",
"contexts/geolocation_permission_context.cc",
"contexts/geolocation_permission_context.h",
+ "contexts/webxr_permission_context.cc",
+ "contexts/webxr_permission_context.h",
"contexts/window_placement_permission_context.cc",
"contexts/window_placement_permission_context.h",
"features.cc",
@@ -103,6 +105,7 @@ source_set("test_support") {
deps = [
":permissions",
"//base",
+ "//components/content_settings/core/browser",
"//components/sync_preferences:test_support",
"//components/ukm/content",
"//components/vector_icons",
@@ -134,6 +137,7 @@ source_set("unit_tests") {
"//base",
"//base/test:test_support",
"//components/content_settings/browser",
+ "//components/content_settings/browser:test_support",
"//components/content_settings/core/browser",
"//components/keyed_service/content",
"//components/prefs:test_support",
diff --git a/chromium/components/permissions/android/BUILD.gn b/chromium/components/permissions/android/BUILD.gn
index 6e409eec28d..9c226bae1cb 100644
--- a/chromium/components/permissions/android/BUILD.gn
+++ b/chromium/components/permissions/android/BUILD.gn
@@ -140,6 +140,9 @@ java_library("components_permissions_junit_tests") {
":java",
"//base:base_java_test_support",
"//base:base_junit_test_support",
+ "//third_party/android_deps:robolectric_all_java",
+ "//third_party/junit",
+ "//third_party/mockito:mockito_java",
"//ui/android:ui_java",
]
}
diff --git a/chromium/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogController.java b/chromium/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogController.java
index b1d120e721a..2b05abc83ea 100644
--- a/chromium/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogController.java
+++ b/chromium/components/permissions/android/java/src/org/chromium/components/permissions/PermissionDialogController.java
@@ -5,7 +5,6 @@
package org.chromium.components.permissions;
import android.annotation.SuppressLint;
-import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
@@ -15,6 +14,7 @@ import androidx.annotation.IntDef;
import androidx.annotation.VisibleForTesting;
import org.chromium.base.BuildInfo;
+import org.chromium.base.ContextUtils;
import org.chromium.base.annotations.CalledByNative;
import org.chromium.ui.modaldialog.DialogDismissalCause;
import org.chromium.ui.modaldialog.ModalDialogManager;
@@ -144,12 +144,14 @@ public class PermissionDialogController
assert mState == State.NOT_SHOWING;
mDialogDelegate = mRequestQueue.remove(0);
- Activity activity = mDialogDelegate.getWindow().getActivity().get();
+ // Use the context to access resources instead of the activity because the activity may not
+ // have the correct resources in some cases (e.g. WebLayer).
+ Context context = mDialogDelegate.getWindow().getContext().get();
// It's possible for the activity to be null if we reach here just after the user
// backgrounds the browser and cleanup has happened. In that case, we can't show a prompt,
// so act as though the user dismissed it.
- if (activity == null) {
+ if (ContextUtils.activityFromContext(context) == null) {
// TODO(timloh): This probably doesn't work, as this happens synchronously when creating
// the PermissionPromptAndroid, so the PermissionRequestManager won't be ready yet.
mDialogDelegate.onDismiss();
@@ -167,7 +169,7 @@ public class PermissionDialogController
mModalDialogManager = mDialogDelegate.getWindow().getModalDialogManager();
mDialogModel = PermissionDialogModel.getModel(
- this, mDialogDelegate, () -> showFilteredTouchEventDialog(activity));
+ this, mDialogDelegate, () -> showFilteredTouchEventDialog(context));
mModalDialogManager.showDialog(mDialogModel, ModalDialogManager.ModalDialogType.TAB);
mState = State.PROMPT_OPEN;
}
diff --git a/chromium/components/permissions/chooser_context_base.cc b/chromium/components/permissions/chooser_context_base.cc
index b3ba00c9bea..5be013f2d77 100644
--- a/chromium/components/permissions/chooser_context_base.cc
+++ b/chromium/components/permissions/chooser_context_base.cc
@@ -156,7 +156,7 @@ void ChooserContextBase::GrantObjectPermission(
void ChooserContextBase::UpdateObjectPermission(
const url::Origin& requesting_origin,
const url::Origin& embedding_origin,
- base::Value& old_object,
+ const base::Value& old_object,
base::Value new_object) {
base::Value setting =
GetWebsiteSetting(requesting_origin, embedding_origin, /*info=*/nullptr);
diff --git a/chromium/components/permissions/chooser_context_base.h b/chromium/components/permissions/chooser_context_base.h
index e32535cd80b..e82b8be8fbc 100644
--- a/chromium/components/permissions/chooser_context_base.h
+++ b/chromium/components/permissions/chooser_context_base.h
@@ -105,14 +105,14 @@ class ChooserContextBase : public KeyedService {
// |host_content_settings_map_|.
void UpdateObjectPermission(const url::Origin& requesting_origin,
const url::Origin& embedding_origin,
- base::Value& old_object,
+ const base::Value& old_object,
base::Value new_object);
// Revokes |requesting_origin|'s permission to access |object| when embedded
// within |embedding_origin|.
//
// This method may be extended by a subclass to revoke permission to access
- // objects returned by GetPreviouslyChosenObjects but not stored in
+ // objects returned by GetGrantedObjects but not stored in
// |host_content_settings_map_|.
virtual void RevokeObjectPermission(const url::Origin& requesting_origin,
const url::Origin& embedding_origin,
diff --git a/chromium/components/permissions/contexts/OWNERS b/chromium/components/permissions/contexts/OWNERS
new file mode 100644
index 00000000000..4862047cfa4
--- /dev/null
+++ b/chromium/components/permissions/contexts/OWNERS
@@ -0,0 +1,6 @@
+file://components/permissions/PERMISSIONS_OWNERS
+
+per-file *webxr_permission_context*=file://content/browser/xr/OWNERS
+
+# COMPONENT: Internals>Permissions
+# TEAM: permissions-dev@chromium.org
diff --git a/chromium/components/permissions/contexts/geolocation_permission_context.cc b/chromium/components/permissions/contexts/geolocation_permission_context.cc
index ece50351c21..b62512c32ad 100644
--- a/chromium/components/permissions/contexts/geolocation_permission_context.cc
+++ b/chromium/components/permissions/contexts/geolocation_permission_context.cc
@@ -43,6 +43,11 @@ void GeolocationPermissionContext::DecidePermission(
}
}
+base::WeakPtr<GeolocationPermissionContext>
+GeolocationPermissionContext::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
void GeolocationPermissionContext::UpdateTabContext(
const PermissionRequestID& id,
const GURL& requesting_frame,
diff --git a/chromium/components/permissions/contexts/geolocation_permission_context.h b/chromium/components/permissions/contexts/geolocation_permission_context.h
index 6e86b9c215b..bbe8af336ce 100644
--- a/chromium/components/permissions/contexts/geolocation_permission_context.h
+++ b/chromium/components/permissions/contexts/geolocation_permission_context.h
@@ -7,6 +7,7 @@
#include "base/callback.h"
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "build/build_config.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/permissions/permission_context_base.h"
@@ -69,6 +70,8 @@ class GeolocationPermissionContext : public PermissionContextBase {
bool user_gesture,
BrowserPermissionCallback callback) override;
+ base::WeakPtr<GeolocationPermissionContext> GetWeakPtr();
+
// Make this public for use by the delegate implementation.
using PermissionContextBase::NotifyPermissionSet;
@@ -85,6 +88,8 @@ class GeolocationPermissionContext : public PermissionContextBase {
mojo::Remote<device::mojom::GeolocationControl> geolocation_control_;
+ base::WeakPtrFactory<GeolocationPermissionContext> weak_factory_{this};
+
DISALLOW_COPY_AND_ASSIGN(GeolocationPermissionContext);
};
diff --git a/chromium/components/permissions/contexts/geolocation_permission_context_unittest.cc b/chromium/components/permissions/contexts/geolocation_permission_context_unittest.cc
index f1102df0a98..8aec360f714 100644
--- a/chromium/components/permissions/contexts/geolocation_permission_context_unittest.cc
+++ b/chromium/components/permissions/contexts/geolocation_permission_context_unittest.cc
@@ -29,6 +29,7 @@
#include "build/build_config.h"
#include "components/content_settings/browser/content_settings_usages_state.h"
#include "components/content_settings/browser/tab_specific_content_settings.h"
+#include "components/content_settings/browser/test_tab_specific_content_settings_delegate.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/permissions/features.h"
#include "components/permissions/permission_context_base.h"
@@ -115,55 +116,6 @@ class TestGeolocationPermissionContextDelegate
TestingPrefServiceSimple prefs_;
base::Optional<url::Origin> dse_origin_;
};
-
-class TestTabSpecificContentSettingsDelegate
- : public content_settings::TabSpecificContentSettings::Delegate {
- public:
- explicit TestTabSpecificContentSettingsDelegate(
- content::BrowserContext* browser_context)
- : browser_context_(browser_context) {}
-
- // content_settings::TabSpecificContentSettings::Delegate:
- void UpdateLocationBar() override {}
-
- void SetContentSettingRules(
- content::RenderProcessHost* process,
- const RendererContentSettingRules& rules) override {}
-
- PrefService* GetPrefs() override { return nullptr; }
-
- HostContentSettingsMap* GetSettingsMap() override {
- return PermissionsClient::Get()->GetSettingsMap(browser_context_);
- }
-
- std::vector<storage::FileSystemType> GetAdditionalFileSystemTypes() override {
- return {};
- }
-
- browsing_data::CookieHelper::IsDeletionDisabledCallback
- GetIsDeletionDisabledCallback() override {
- return base::NullCallback();
- }
-
- bool IsMicrophoneCameraStateChanged(
- content_settings::TabSpecificContentSettings::MicrophoneCameraState
- microphone_camera_state,
- const std::string& media_stream_selected_audio_device,
- const std::string& media_stream_selected_video_device) override {
- return false;
- }
-
- content_settings::TabSpecificContentSettings::MicrophoneCameraState
- GetMicrophoneCameraState() override {
- return content_settings::TabSpecificContentSettings::
- MICROPHONE_CAMERA_NOT_ACCESSED;
- }
-
- void OnContentBlocked(ContentSettingsType type) override {}
-
- private:
- content::BrowserContext* browser_context_;
-};
} // namespace
// GeolocationPermissionContextTests ------------------------------------------
@@ -317,8 +269,11 @@ void GeolocationPermissionContextTests::SetUp() {
RenderViewHostTestHarness::SetUp();
content_settings::TabSpecificContentSettings::CreateForWebContents(
- web_contents(), std::make_unique<TestTabSpecificContentSettingsDelegate>(
- browser_context()));
+ web_contents(),
+ std::make_unique<
+ content_settings::TestTabSpecificContentSettingsDelegate>(
+ /*prefs=*/nullptr,
+ PermissionsClient::Get()->GetSettingsMap(browser_context())));
auto delegate = std::make_unique<TestGeolocationPermissionContextDelegate>(
browser_context());
diff --git a/chromium/components/permissions/contexts/webxr_permission_context.cc b/chromium/components/permissions/contexts/webxr_permission_context.cc
new file mode 100644
index 00000000000..82227fa9f66
--- /dev/null
+++ b/chromium/components/permissions/contexts/webxr_permission_context.cc
@@ -0,0 +1,136 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/permissions/contexts/webxr_permission_context.h"
+
+#include "base/check.h"
+#include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom.h"
+
+#if defined(OS_ANDROID)
+#include "components/permissions/android/android_permission_util.h"
+#include "components/permissions/permission_request_id.h"
+#include "components/permissions/permissions_client.h"
+#include "content/public/browser/web_contents.h"
+#endif
+
+namespace permissions {
+WebXrPermissionContext::WebXrPermissionContext(
+ content::BrowserContext* browser_context,
+ ContentSettingsType content_settings_type)
+ : PermissionContextBase(browser_context,
+ content_settings_type,
+ blink::mojom::FeaturePolicyFeature::kWebXr),
+ content_settings_type_(content_settings_type) {
+ DCHECK(content_settings_type_ == ContentSettingsType::VR ||
+ content_settings_type_ == ContentSettingsType::AR);
+}
+
+WebXrPermissionContext::~WebXrPermissionContext() = default;
+
+bool WebXrPermissionContext::IsRestrictedToSecureOrigins() const {
+ return true;
+}
+
+#if defined(OS_ANDROID)
+// There are two other permissions that need to check corresponding OS-level
+// permissions, and they take two different approaches to this. Geolocation only
+// stores the permission ContentSetting if both requests are granted (or if the
+// site permission is "Block"). The media permissions follow something more
+// similar to this approach, first querying and storing the site-specific
+// ContentSetting and then querying for the additional OS permissions as needed.
+// However, this is done in MediaStreamDevicesController, not their permission
+// context. By persisting and then running additional code as needed, we thus
+// mimic that flow, but keep all logic contained into the permission context
+// class.
+void WebXrPermissionContext::NotifyPermissionSet(
+ const PermissionRequestID& id,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin,
+ BrowserPermissionCallback callback,
+ bool persist,
+ ContentSetting content_setting) {
+ // Only AR needs to check for additional permissions, and then only if it was
+ // actually allowed.
+ if (!(content_settings_type_ == ContentSettingsType::AR &&
+ content_setting == ContentSetting::CONTENT_SETTING_ALLOW)) {
+ PermissionContextBase::NotifyPermissionSet(
+ id, requesting_origin, embedding_origin, std::move(callback), persist,
+ content_setting);
+ return;
+ }
+
+ // Whether or not the user will ultimately accept the OS permissions, we want
+ // to save the content_setting here if we should.
+ if (persist) {
+ PermissionContextBase::UpdateContentSetting(
+ requesting_origin, embedding_origin, content_setting);
+ }
+
+ content::WebContents* web_contents =
+ content::WebContents::FromRenderFrameHost(
+ content::RenderFrameHost::FromID(id.render_process_id(),
+ id.render_frame_id()));
+ if (!web_contents) {
+ // If we can't get the web contents, we don't know the state of the OS
+ // permission, so assume we don't have it.
+ OnAndroidPermissionDecided(id, requesting_origin, embedding_origin,
+ std::move(callback),
+ false /*permission_granted*/);
+ return;
+ }
+
+ // Otherwise, the user granted permission to use AR, so now we need to check
+ // if we need to prompt for android system permissions.
+ std::vector<ContentSettingsType> permission_type = {content_settings_type_};
+ PermissionRepromptState reprompt_state =
+ ShouldRepromptUserForPermissions(web_contents, permission_type);
+ switch (reprompt_state) {
+ case PermissionRepromptState::kNoNeed:
+ // We have already returned if permission was denied by the user, and this
+ // indicates that we have all the OS permissions we need.
+ OnAndroidPermissionDecided(id, requesting_origin, embedding_origin,
+ std::move(callback),
+ true /*permission_granted*/);
+ return;
+
+ case PermissionRepromptState::kCannotShow:
+ // If we cannot show the info bar, then we have to assume we don't have
+ // the permissions we need.
+ OnAndroidPermissionDecided(id, requesting_origin, embedding_origin,
+ std::move(callback),
+ false /*permission_granted*/);
+ return;
+
+ case PermissionRepromptState::kShow:
+ // Otherwise, prompt the user that we need additional permissions.
+ PermissionsClient::Get()->RepromptForAndroidPermissions(
+ web_contents, permission_type,
+ base::BindOnce(&WebXrPermissionContext::OnAndroidPermissionDecided,
+ weak_ptr_factory_.GetWeakPtr(), id, requesting_origin,
+ embedding_origin, std::move(callback)));
+ return;
+ }
+}
+
+void WebXrPermissionContext::OnAndroidPermissionDecided(
+ const PermissionRequestID& id,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin,
+ BrowserPermissionCallback callback,
+ bool permission_granted) {
+ // If we were supposed to persist the setting we've already done so in the
+ // initial override of |NotifyPermissionSet|. At this point, if the user
+ // has denied the OS level permission, we want to notify the requestor that
+ // the permission has been blocked.
+ // TODO(https://crbug.com/1060163): Ensure that this is taken into account
+ // when returning navigator.permissions results.
+ ContentSetting setting = permission_granted
+ ? ContentSetting::CONTENT_SETTING_ALLOW
+ : ContentSetting::CONTENT_SETTING_BLOCK;
+ PermissionContextBase::NotifyPermissionSet(
+ id, requesting_origin, embedding_origin, std::move(callback),
+ false /*persist*/, setting);
+}
+#endif // defined(OS_ANDROID)
+} // namespace permissions
diff --git a/chromium/components/permissions/contexts/webxr_permission_context.h b/chromium/components/permissions/contexts/webxr_permission_context.h
new file mode 100644
index 00000000000..467a6404413
--- /dev/null
+++ b/chromium/components/permissions/contexts/webxr_permission_context.h
@@ -0,0 +1,59 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_PERMISSIONS_CONTEXTS_WEBXR_PERMISSION_CONTEXT_H_
+#define COMPONENTS_PERMISSIONS_CONTEXTS_WEBXR_PERMISSION_CONTEXT_H_
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "build/build_config.h"
+#include "components/content_settings/core/common/content_settings_types.h"
+#include "components/permissions/permission_context_base.h"
+
+namespace permissions {
+class WebXrPermissionContext : public PermissionContextBase {
+ public:
+ WebXrPermissionContext(content::BrowserContext* browser_context,
+ ContentSettingsType content_settings_type);
+ ~WebXrPermissionContext() override;
+ WebXrPermissionContext(const WebXrPermissionContext&) = delete;
+ WebXrPermissionContext& operator=(const WebXrPermissionContext&) = delete;
+
+ private:
+ // PermissionContextBase:
+ bool IsRestrictedToSecureOrigins() const override;
+
+#if defined(OS_ANDROID)
+ // On Android we need to do some additional checking for OS level permissions,
+ // which do not need to happen on Desktop. Note that NotifyPermissionSet is
+ // only called after a "RequestPermission" call (and not if we are just
+ // checking the state of the permission), however, the requestSession flow
+ // requires checking the permission as one of it's steps: (5.6 as of 03/10/20)
+ // https://immersive-web.github.io/webxr/#dom-xrsystem-requestsession
+ // When implementing navigator.xr.permission methods, we should ensure that
+ // GetPermissionStatus is also updated to check these permissions.
+ void NotifyPermissionSet(const PermissionRequestID& id,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin,
+ BrowserPermissionCallback callback,
+ bool persist,
+ ContentSetting content_setting) override;
+
+ void OnAndroidPermissionDecided(const PermissionRequestID& id,
+ const GURL& requesting_origin,
+ const GURL& embedding_origin,
+ BrowserPermissionCallback callback,
+ bool permission_granted);
+#endif
+
+ ContentSettingsType content_settings_type_;
+
+ // Must be the last member, to ensure that it will be
+ // destroyed first, which will invalidate weak pointers
+ base::WeakPtrFactory<WebXrPermissionContext> weak_ptr_factory_{this};
+};
+
+} // namespace permissions
+
+#endif // COMPONENTS_PERMISSIONS_CONTEXTS_WEBXR_PERMISSION_CONTEXT_H_
diff --git a/chromium/components/permissions/notification_permission_ui_selector.h b/chromium/components/permissions/notification_permission_ui_selector.h
index 4300fc17c17..444dec57b20 100644
--- a/chromium/components/permissions/notification_permission_ui_selector.h
+++ b/chromium/components/permissions/notification_permission_ui_selector.h
@@ -23,10 +23,12 @@ class NotificationPermissionUiSelector {
kEnabledInPrefs,
kTriggeredByCrowdDeny,
kTriggeredDueToAbusiveRequests,
+ kTriggeredDueToAbusiveContent,
};
enum class WarningReason {
kAbusiveRequests,
+ kAbusiveContent,
};
struct Decision {
diff --git a/chromium/components/permissions/permission_context_base.cc b/chromium/components/permissions/permission_context_base.cc
index 0d55900ad8e..0308b2e3ffc 100644
--- a/chromium/components/permissions/permission_context_base.cc
+++ b/chromium/components/permissions/permission_context_base.cc
@@ -75,6 +75,10 @@ const char kPermissionBlockedFeaturePolicyMessage[] =
"%s permission has been blocked because of a Feature Policy applied to the "
"current document. See https://goo.gl/EuHzyv for more details.";
+const char kPermissionBlockedPortalsMessage[] =
+ "%s permission has been blocked because it was requested inside a portal. "
+ "Portals don't currently support permission requests.";
+
void LogPermissionBlockedMessage(content::WebContents* web_contents,
const char* message,
ContentSettingsType type) {
@@ -164,6 +168,11 @@ void PermissionContextBase::RequestPermission(
kPermissionBlockedFeaturePolicyMessage,
content_settings_type_);
break;
+ case PermissionStatusSource::PORTAL:
+ LogPermissionBlockedMessage(web_contents,
+ kPermissionBlockedPortalsMessage,
+ content_settings_type_);
+ break;
case PermissionStatusSource::INSECURE_ORIGIN:
case PermissionStatusSource::UNSPECIFIED:
case PermissionStatusSource::VIRTUAL_URL_DIFFERENT_ORIGIN:
@@ -231,6 +240,12 @@ PermissionResult PermissionContextBase::GetPermissionStatus(
content::WebContents* web_contents =
content::WebContents::FromRenderFrameHost(render_frame_host);
+ // Permissions are denied for portals.
+ if (web_contents && web_contents->IsPortal()) {
+ return PermissionResult(CONTENT_SETTING_BLOCK,
+ PermissionStatusSource::PORTAL);
+ }
+
// Automatically deny all HTTP or HTTPS requests where the virtual URL and
// the loaded URL are for different origins. The loaded URL is the one
// actually in the renderer, but the virtual URL is the one
diff --git a/chromium/components/permissions/permission_request.cc b/chromium/components/permissions/permission_request.cc
index 7ba80986e6f..4032a226ec5 100644
--- a/chromium/components/permissions/permission_request.cc
+++ b/chromium/components/permissions/permission_request.cc
@@ -18,6 +18,12 @@ ContentSettingsType PermissionRequest::GetContentSettingsType() const {
return ContentSettingsType::DEFAULT;
}
+#if !defined(OS_ANDROID)
+base::string16 PermissionRequest::GetChipText() const {
+ return base::string16();
+}
+#endif
+
base::string16 PermissionRequest::GetMessageTextWarningFragment() const {
return base::string16();
}
diff --git a/chromium/components/permissions/permission_request.h b/chromium/components/permissions/permission_request.h
index 3dcfc3a51dd..f05dc7c82aa 100644
--- a/chromium/components/permissions/permission_request.h
+++ b/chromium/components/permissions/permission_request.h
@@ -111,6 +111,11 @@ class PermissionRequest {
virtual base::string16 GetQuietMessageText() const;
#endif
+#if !defined(OS_ANDROID)
+ // Returns the short text for the chip button related to this permission.
+ virtual base::string16 GetChipText() const;
+#endif
+
// Returns the shortened prompt text for this permission. The permission
// bubble may coalesce different requests, and if it does, this text will
// be displayed next to an image and indicate the user grants the permission.
diff --git a/chromium/components/permissions/permission_request_impl.cc b/chromium/components/permissions/permission_request_impl.cc
index 3d1366df87f..e354561025b 100644
--- a/chromium/components/permissions/permission_request_impl.cc
+++ b/chromium/components/permissions/permission_request_impl.cc
@@ -89,6 +89,7 @@ PermissionRequest::IconId PermissionRequestImpl::GetIconId() const {
case ContentSettingsType::MEDIASTREAM_MIC:
return vector_icons::kMicIcon;
case ContentSettingsType::MEDIASTREAM_CAMERA:
+ case ContentSettingsType::CAMERA_PAN_TILT_ZOOM:
return vector_icons::kVideocamIcon;
case ContentSettingsType::ACCESSIBILITY_EVENTS:
return vector_icons::kAccessibilityIcon;
@@ -99,8 +100,6 @@ PermissionRequest::IconId PermissionRequestImpl::GetIconId() const {
return vector_icons::kVrHeadsetIcon;
case ContentSettingsType::STORAGE_ACCESS:
return vector_icons::kCookieIcon;
- case ContentSettingsType::CAMERA_PAN_TILT_ZOOM:
- return vector_icons::kCameraPanTiltZoomIcon;
case ContentSettingsType::WINDOW_PLACEMENT:
return vector_icons::kWindowPlacementIcon;
default:
@@ -218,8 +217,7 @@ base::string16 PermissionRequestImpl::GetMessageTextFragment() const {
message_id = IDS_MEDIA_CAPTURE_VIDEO_ONLY_PERMISSION_FRAGMENT;
break;
case ContentSettingsType::CAMERA_PAN_TILT_ZOOM:
- message_id =
- IDS_MEDIA_CAPTURE_CAMERA_PAN_TILT_ZOOM_ONLY_PERMISSION_FRAGMENT;
+ message_id = IDS_MEDIA_CAPTURE_CAMERA_PAN_TILT_ZOOM_PERMISSION_FRAGMENT;
break;
case ContentSettingsType::ACCESSIBILITY_EVENTS:
message_id = IDS_ACCESSIBILITY_EVENTS_PERMISSION_FRAGMENT;
@@ -254,6 +252,42 @@ base::string16 PermissionRequestImpl::GetMessageTextFragment() const {
return l10n_util::GetStringUTF16(message_id);
}
+#if !defined(OS_ANDROID)
+base::string16 PermissionRequestImpl::GetChipText() const {
+ int message_id;
+ switch (content_settings_type_) {
+ case ContentSettingsType::GEOLOCATION:
+ message_id = IDS_GEOLOCATION_PERMISSION_CHIP;
+ break;
+ case ContentSettingsType::NOTIFICATIONS:
+ message_id = IDS_NOTIFICATION_PERMISSIONS_CHIP;
+ break;
+ case ContentSettingsType::MIDI_SYSEX:
+ message_id = IDS_MIDI_SYSEX_PERMISSION_CHIP;
+ break;
+ case ContentSettingsType::MEDIASTREAM_MIC:
+ message_id = IDS_MEDIA_CAPTURE_AUDIO_ONLY_PERMISSION_CHIP;
+ break;
+ case ContentSettingsType::MEDIASTREAM_CAMERA:
+ message_id = IDS_MEDIA_CAPTURE_VIDEO_ONLY_PERMISSION_CHIP;
+ break;
+ case ContentSettingsType::CLIPBOARD_READ_WRITE:
+ message_id = IDS_CLIPBOARD_PERMISSION_CHIP;
+ break;
+ case ContentSettingsType::VR:
+ message_id = IDS_VR_PERMISSION_CHIP;
+ break;
+ case ContentSettingsType::AR:
+ message_id = IDS_AR_PERMISSION_CHIP;
+ break;
+ default:
+ NOTREACHED();
+ return base::string16();
+ }
+ return l10n_util::GetStringUTF16(message_id);
+}
+#endif
+
base::string16 PermissionRequestImpl::GetMessageTextWarningFragment() const {
if (content_settings_type_ == ContentSettingsType::PLUGINS)
return l10n_util::GetStringUTF16(IDS_FLASH_PERMISSION_WARNING_FRAGMENT);
diff --git a/chromium/components/permissions/permission_request_impl.h b/chromium/components/permissions/permission_request_impl.h
index faa231ef608..70631e4033d 100644
--- a/chromium/components/permissions/permission_request_impl.h
+++ b/chromium/components/permissions/permission_request_impl.h
@@ -41,6 +41,9 @@ class PermissionRequestImpl : public PermissionRequest {
base::string16 GetQuietTitleText() const override;
base::string16 GetQuietMessageText() const override;
#endif
+#if !defined(OS_ANDROID)
+ base::string16 GetChipText() const override;
+#endif
base::string16 GetMessageTextFragment() const override;
base::string16 GetMessageTextWarningFragment() const override;
GURL GetEmbeddingOrigin() const override;
diff --git a/chromium/components/permissions/permission_request_manager.cc b/chromium/components/permissions/permission_request_manager.cc
index b16e1e1a943..60234f3733d 100644
--- a/chromium/components/permissions/permission_request_manager.cc
+++ b/chromium/components/permissions/permission_request_manager.cc
@@ -15,7 +15,6 @@
#include "base/metrics/user_metrics_action.h"
#include "base/stl_util.h"
#include "base/strings/string16.h"
-#include "base/task/post_task.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "build/build_config.h"
#include "components/permissions/features.h"
@@ -48,6 +47,20 @@ const char kAbusiveNotificationRequestsWarningMessage[] =
"fix the issues as soon as possible and submit your site for another "
"review. Learn more at https://support.google.com/webtools/answer/9799048.";
+constexpr char kAbusiveNotificationContentEnforcementMessage[] =
+ "Chrome is blocking notification permission requests on this site because "
+ "the site tends to show notifications with content that mislead or trick "
+ "users. You should fix the issues as soon as possible and submit your site "
+ "for another review. Learn more at "
+ "https://support.google.com/webtools/answer/9799048";
+
+constexpr char kAbusiveNotificationContentWarningMessage[] =
+ "Chrome might start blocking notification permission requests on this site "
+ "in the future because the site tends to show notifications with content "
+ "that mislead or trick users. You should fix the issues as soon as "
+ "possible and submit your site for another review. Learn more at "
+ "https://support.google.com/webtools/answer/9799048";
+
namespace {
bool IsMessageTextEqual(PermissionRequest* a, PermissionRequest* b) {
@@ -358,8 +371,8 @@ PermissionRequestManager::PermissionRequestManager(
void PermissionRequestManager::ScheduleShowBubble() {
base::RecordAction(base::UserMetricsAction("PermissionBubbleRequest"));
- base::PostTask(FROM_HERE, {content::BrowserThread::UI},
- base::BindOnce(&PermissionRequestManager::ShowBubble,
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE, base::BindOnce(&PermissionRequestManager::ShowBubble,
weak_factory_.GetWeakPtr()));
}
@@ -421,18 +434,30 @@ void PermissionRequestManager::ShowBubble() {
PermissionUmaUtil::PermissionPromptShown(requests_);
if (ShouldCurrentRequestUseQuietUI()) {
- if (ReasonForUsingQuietUi() ==
- QuietUiReason::kTriggeredDueToAbusiveRequests) {
- LogWarningToConsole(kAbusiveNotificationRequestsEnforcementMessage);
+ switch (ReasonForUsingQuietUi()) {
+ case QuietUiReason::kEnabledInPrefs:
+ case QuietUiReason::kTriggeredByCrowdDeny:
+ break;
+ case QuietUiReason::kTriggeredDueToAbusiveRequests:
+ LogWarningToConsole(kAbusiveNotificationRequestsEnforcementMessage);
+ break;
+ case QuietUiReason::kTriggeredDueToAbusiveContent:
+ LogWarningToConsole(kAbusiveNotificationContentEnforcementMessage);
+ break;
}
base::RecordAction(base::UserMetricsAction(
"Notifications.Quiet.PermissionRequestShown"));
}
- if (current_request_ui_to_use_->warning_reason &&
- *(current_request_ui_to_use_->warning_reason) ==
- WarningReason::kAbusiveRequests) {
- LogWarningToConsole(kAbusiveNotificationRequestsWarningMessage);
+ if (current_request_ui_to_use_->warning_reason) {
+ switch (*(current_request_ui_to_use_->warning_reason)) {
+ case WarningReason::kAbusiveRequests:
+ LogWarningToConsole(kAbusiveNotificationRequestsWarningMessage);
+ break;
+ case WarningReason::kAbusiveContent:
+ LogWarningToConsole(kAbusiveNotificationContentWarningMessage);
+ break;
+ }
}
}
current_request_view_shown_to_user_ = true;
diff --git a/chromium/components/permissions/permission_request_manager.h b/chromium/components/permissions/permission_request_manager.h
index 839990cd5b5..158214c0d22 100644
--- a/chromium/components/permissions/permission_request_manager.h
+++ b/chromium/components/permissions/permission_request_manager.h
@@ -36,6 +36,14 @@ extern const char kAbusiveNotificationRequestsEnforcementMessage[];
// the warning list for abusive permission request flows.
extern const char kAbusiveNotificationRequestsWarningMessage[];
+// The message to be printed in the Developer Tools console when the site is on
+// the blocking list for showing abusive notification content.
+extern const char kAbusiveNotificationContentEnforcementMessage[];
+
+// The message to be printed in the Developer Tools console when the site is on
+// the warning list for showing abusive notification content.
+extern const char kAbusiveNotificationContentWarningMessage[];
+
// Provides access to permissions bubbles. Allows clients to add a request
// callback interface to the existing permission bubble configuration.
// Depending on the situation and policy, that may add new UI to an existing
diff --git a/chromium/components/permissions/permission_result.h b/chromium/components/permissions/permission_result.h
index 37ff25704d9..3275b5722e0 100644
--- a/chromium/components/permissions/permission_result.h
+++ b/chromium/components/permissions/permission_result.h
@@ -37,6 +37,10 @@ enum class PermissionStatusSource {
// seen by the user. This may be very confusing for a user to see in a
// permissions request.
VIRTUAL_URL_DIFFERENT_ORIGIN,
+
+ // The status is the result of a permissions being requested inside a portal.
+ // Permissions are currently always denied inside a portal.
+ PORTAL
};
struct PermissionResult {
diff --git a/chromium/components/permissions/permission_uma_util.cc b/chromium/components/permissions/permission_uma_util.cc
index e58d8ef5f3b..039722c2c8d 100644
--- a/chromium/components/permissions/permission_uma_util.cc
+++ b/chromium/components/permissions/permission_uma_util.cc
@@ -30,19 +30,6 @@
namespace permissions {
-// UMA keys need to be statically initialized so plain function would not
-// work. Use macros instead.
-#define PERMISSION_ACTION_UMA(secure_origin, permission, permission_secure, \
- permission_insecure, action) \
- base::UmaHistogramEnumeration(permission, action, PermissionAction::NUM); \
- if (secure_origin) { \
- base::UmaHistogramEnumeration(permission_secure, action, \
- PermissionAction::NUM); \
- } else { \
- base::UmaHistogramEnumeration(permission_insecure, action, \
- PermissionAction::NUM); \
- }
-
#define PERMISSION_BUBBLE_TYPE_UMA(metric_name, permission_bubble_type) \
base::UmaHistogramEnumeration(metric_name, permission_bubble_type, \
PermissionRequestType::NUM)
@@ -128,29 +115,41 @@ void RecordEngagementMetric(const std::vector<PermissionRequest*>& requests,
base::UmaHistogramPercentage(name, engagement_score);
}
-void RecordPermissionActionUkm(PermissionAction action,
- PermissionRequestGestureType gesture_type,
- ContentSettingsType permission,
- int dismiss_count,
- int ignore_count,
- PermissionSourceUI source_ui,
- PermissionPromptDisposition ui_disposition,
- base::Optional<ukm::SourceId> source_id) {
+void RecordPermissionActionUkm(
+ PermissionAction action,
+ PermissionRequestGestureType gesture_type,
+ ContentSettingsType permission,
+ int dismiss_count,
+ int ignore_count,
+ PermissionSourceUI source_ui,
+ PermissionPromptDisposition ui_disposition,
+ base::Optional<bool> has_three_consecutive_denies,
+ base::Optional<ukm::SourceId> source_id) {
// Only record the permission change if the origin is in the history.
if (!source_id.has_value())
return;
size_t num_values = 0;
- ukm::builders::Permission(source_id.value())
- .SetAction(static_cast<int64_t>(action))
+
+ ukm::builders::Permission builder(source_id.value());
+ builder.SetAction(static_cast<int64_t>(action))
.SetGesture(static_cast<int64_t>(gesture_type))
.SetPermissionType(static_cast<int64_t>(
ContentSettingTypeToHistogramValue(permission, &num_values)))
.SetPriorDismissals(std::min(kPriorCountCap, dismiss_count))
.SetPriorIgnores(std::min(kPriorCountCap, ignore_count))
.SetSource(static_cast<int64_t>(source_ui))
- .SetPromptDisposition(static_cast<int64_t>(ui_disposition))
- .Record(ukm::UkmRecorder::Get());
+ .SetPromptDisposition(static_cast<int64_t>(ui_disposition));
+
+ if (has_three_consecutive_denies.has_value()) {
+ int64_t satisfied_adaptive_triggers = 0;
+ if (has_three_consecutive_denies.value())
+ satisfied_adaptive_triggers |=
+ static_cast<int64_t>(AdaptiveTriggers::THREE_CONSECUTIVE_DENIES);
+ builder.SetSatisfiedAdaptiveTriggers(satisfied_adaptive_triggers);
+ }
+
+ builder.Record(ukm::UkmRecorder::Get());
}
std::string GetPromptDispositionString(
@@ -265,6 +264,7 @@ void PermissionUmaUtil::RecordEmbargoPromptSuppressionFromSource(
case PermissionStatusSource::INSECURE_ORIGIN:
case PermissionStatusSource::FEATURE_POLICY:
case PermissionStatusSource::VIRTUAL_URL_DIFFERENT_ORIGIN:
+ case PermissionStatusSource::PORTAL:
// The permission wasn't under embargo, so don't record anything. We may
// embargo it later.
break;
@@ -489,35 +489,31 @@ void PermissionUmaUtil::RecordPermissionAction(
PermissionsClient::Get()->GetUkmSourceId(
browser_context, web_contents, requesting_origin,
- base::BindOnce(&RecordPermissionActionUkm, action, gesture_type,
- permission, dismiss_count, ignore_count, source_ui,
- ui_disposition));
-
- bool secure_origin = content::IsOriginSecure(requesting_origin);
+ base::BindOnce(
+ &RecordPermissionActionUkm, action, gesture_type, permission,
+ dismiss_count, ignore_count, source_ui, ui_disposition,
+ permission == ContentSettingsType::NOTIFICATIONS
+ ? PermissionsClient::Get()
+ ->HadThreeConsecutiveNotificationPermissionDenies(
+ browser_context)
+ : base::nullopt));
switch (permission) {
- // Geolocation, MidiSysEx, Push, Media, Clipboard, and AR/VR permissions are
- // disabled on insecure origins, so there's no need to record separate
- // metrics for secure/insecure.
case ContentSettingsType::GEOLOCATION:
base::UmaHistogramEnumeration("Permissions.Action.Geolocation", action,
PermissionAction::NUM);
break;
case ContentSettingsType::NOTIFICATIONS:
- PERMISSION_ACTION_UMA(secure_origin, "Permissions.Action.Notifications",
- "Permissions.Action.SecureOrigin.Notifications",
- "Permissions.Action.InsecureOrigin.Notifications",
- action);
+ base::UmaHistogramEnumeration("Permissions.Action.Notifications", action,
+ PermissionAction::NUM);
break;
case ContentSettingsType::MIDI_SYSEX:
base::UmaHistogramEnumeration("Permissions.Action.MidiSysEx", action,
PermissionAction::NUM);
break;
case ContentSettingsType::PROTECTED_MEDIA_IDENTIFIER:
- PERMISSION_ACTION_UMA(secure_origin, "Permissions.Action.ProtectedMedia",
- "Permissions.Action.SecureOrigin.ProtectedMedia",
- "Permissions.Action.InsecureOrigin.ProtectedMedia",
- action);
+ base::UmaHistogramEnumeration("Permissions.Action.ProtectedMedia", action,
+ PermissionAction::NUM);
break;
case ContentSettingsType::MEDIASTREAM_MIC:
base::UmaHistogramEnumeration("Permissions.Action.AudioCapture", action,
@@ -528,9 +524,8 @@ void PermissionUmaUtil::RecordPermissionAction(
PermissionAction::NUM);
break;
case ContentSettingsType::PLUGINS:
- PERMISSION_ACTION_UMA(secure_origin, "Permissions.Action.Flash",
- "Permissions.Action.SecureOrigin.Flash",
- "Permissions.Action.InsecureOrigin.Flash", action);
+ base::UmaHistogramEnumeration("Permissions.Action.Flash", action,
+ PermissionAction::NUM);
break;
case ContentSettingsType::CLIPBOARD_READ_WRITE:
base::UmaHistogramEnumeration("Permissions.Action.ClipboardReadWrite",
diff --git a/chromium/components/permissions/permission_uma_util.h b/chromium/components/permissions/permission_uma_util.h
index a30c52d828f..ac64a8c7381 100644
--- a/chromium/components/permissions/permission_uma_util.h
+++ b/chromium/components/permissions/permission_uma_util.h
@@ -94,6 +94,15 @@ enum class PermissionPromptDisposition {
MINI_INFOBAR = 5,
};
+enum class AdaptiveTriggers {
+ // None of the adaptive triggers were met. Currently this means two or less
+ // consecutive denies in a row.
+ NONE = 0,
+
+ // User denied permission prompt 3 or more times.
+ THREE_CONSECUTIVE_DENIES = 0x01,
+};
+
// Provides a convenient way of logging UMA for permission related operations.
class PermissionUmaUtil {
public:
diff --git a/chromium/components/permissions/permissions_client.cc b/chromium/components/permissions/permissions_client.cc
index c9714ed6c97..02e9d545528 100644
--- a/chromium/components/permissions/permissions_client.cc
+++ b/chromium/components/permissions/permissions_client.cc
@@ -79,6 +79,12 @@ void PermissionsClient::OnPromptResolved(
PermissionRequestType request_type,
PermissionAction action) {}
+base::Optional<bool>
+PermissionsClient::HadThreeConsecutiveNotificationPermissionDenies(
+ content::BrowserContext* browser_context) {
+ return base::nullopt;
+}
+
base::Optional<url::Origin> PermissionsClient::GetAutoApprovalOrigin() {
return base::nullopt;
}
diff --git a/chromium/components/permissions/permissions_client.h b/chromium/components/permissions/permissions_client.h
index 1becc45542a..96744c3f5a0 100644
--- a/chromium/components/permissions/permissions_client.h
+++ b/chromium/components/permissions/permissions_client.h
@@ -23,6 +23,10 @@ class BrowserContext;
class WebContents;
} // namespace content
+namespace content_settings {
+class CookieSettings;
+}
+
namespace infobars {
class InfoBar;
class InfoBarManager;
@@ -53,6 +57,10 @@ class PermissionsClient {
virtual HostContentSettingsMap* GetSettingsMap(
content::BrowserContext* browser_context) = 0;
+ // Retrieves the CookieSettings for this context.
+ virtual scoped_refptr<content_settings::CookieSettings> GetCookieSettings(
+ content::BrowserContext* browser_context) = 0;
+
// Retrieves the PermissionDecisionAutoBlocker for this context. The returned
// pointer has the same lifetime as |browser_context|.
virtual PermissionDecisionAutoBlocker* GetPermissionDecisionAutoBlocker(
@@ -120,6 +128,13 @@ class PermissionsClient {
PermissionRequestType request_type,
PermissionAction action);
+ // Returns true if user has 3 consecutive notifications permission denies,
+ // returns false otherwise.
+ // Returns base::nullopt if the user is not in the adoptive activation quiet
+ // ui dry run experiment group.
+ virtual base::Optional<bool> HadThreeConsecutiveNotificationPermissionDenies(
+ content::BrowserContext* browser_context);
+
// If the embedder returns an origin here, any requests matching that origin
// will be approved. Requests that do not match the returned origin will
// immediately be finished without granting/denying the permission.
diff --git a/chromium/components/permissions/quota_permission_context_impl.cc b/chromium/components/permissions/quota_permission_context_impl.cc
index fff8d90fc82..a9778e0c829 100644
--- a/chromium/components/permissions/quota_permission_context_impl.cc
+++ b/chromium/components/permissions/quota_permission_context_impl.cc
@@ -11,7 +11,6 @@
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "base/task/post_task.h"
#include "build/build_config.h"
#include "components/permissions/permission_request.h"
#include "components/permissions/permission_request_manager.h"
@@ -171,8 +170,8 @@ void QuotaPermissionContextImpl::RequestQuotaPermission(
}
if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
- base::PostTask(
- FROM_HERE, {content::BrowserThread::UI},
+ content::GetUIThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&QuotaPermissionContextImpl::RequestQuotaPermission,
this, params, render_process_id, std::move(callback)));
return;
@@ -212,8 +211,8 @@ void QuotaPermissionContextImpl::DispatchCallbackOnIOThread(
DCHECK(callback);
if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)) {
- base::PostTask(
- FROM_HERE, {content::BrowserThread::IO},
+ content::GetIOThreadTaskRunner({})->PostTask(
+ FROM_HERE,
base::BindOnce(&QuotaPermissionContextImpl::DispatchCallbackOnIOThread,
this, std::move(callback), response));
return;