Limit the number of `PermissionObserver` handles open by the Permissions API
This CL ensures that only at most one handle is open per (permission type, execution handle) pair.
It introduces a new class PermissionStatusListener that will hold the actual handle
and the PermissionStatus objects will hold a reference to this class.
This means that the PermissionType enum needs to be accessible in blink
and as such it's been moved from
`content/public/browser/permission_type.h`
to
`third_party/blink/public/common/permissions/permission_utils.h`
Additionally fix bugs uncovered along the way:
* If a PTZ (pan-tilt-zoom capable camera) request is made but it results
in a simple camera one, the Permissions API still tracks the PTZ
permission which would be incorrect.
* The New Tab Page doesn't properly get permission updates on the
PermissionStatus handle because of its weird URL. (`chrome://newtab`)
Fixed: 1122423
AX-Relnotes: n/a
Change-Id: Ieb5e9c7203f7bf3101a41af718a7d211b8bb40f3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3359620
Reviewed-by: Ravjit Uppal <ravjit@chromium.org>
Reviewed-by: Kamila Hasanbega <hkamila@chromium.org>
Reviewed-by: John Abd-El-Malek <jam@chromium.org>
Reviewed-by: Andy Paicu <andypaicu@chromium.org>
Commit-Queue: Andy Paicu <andypaicu@chromium.org>
Cr-Commit-Position: refs/heads/main@{#995106}
diff --git a/components/permissions/permission_manager.cc b/components/permissions/permission_manager.cc
index f4ca147..3aef9c1 100644
--- a/components/permissions/permission_manager.cc
+++ b/components/permissions/permission_manager.cc
@@ -704,6 +704,7 @@
content::RenderFrameHost* rfh = content::RenderFrameHost::FromID(
subscription->render_process_id, subscription->render_frame_id);
GURL embedding_origin;
+ GURL requesting_origin = subscription->requesting_origin;
if (rfh) {
embedding_origin =
GetEmbeddingOrigin(rfh, subscription->requesting_origin);
@@ -711,7 +712,7 @@
embedding_origin = subscription->requesting_origin;
}
- if (!primary_pattern.Matches(subscription->requesting_origin) ||
+ if (!primary_pattern.Matches(requesting_origin) ||
!secondary_pattern.Matches(embedding_origin)) {
continue;
}
diff --git a/components/permissions/permission_util.cc b/components/permissions/permission_util.cc
index 1ea019c..f0446a50 100644
--- a/components/permissions/permission_util.cc
+++ b/components/permissions/permission_util.cc
@@ -10,7 +10,6 @@
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "components/permissions/features.h"
-#include "content/public/browser/permission_type.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "third_party/blink/public/common/web_preferences/web_preferences.h"
diff --git a/components/permissions/permission_util.h b/components/permissions/permission_util.h
index b3a8f816..a55864a 100644
--- a/components/permissions/permission_util.h
+++ b/components/permissions/permission_util.h
@@ -11,9 +11,9 @@
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/permissions/permission_request.h"
+#include "content/public/browser/permission_type.h"
namespace content {
-enum class PermissionType;
class RenderFrameHost;
} // namespace content
diff --git a/content/browser/permissions/permission_service_context.cc b/content/browser/permissions/permission_service_context.cc
index c75a14c..acaa026 100644
--- a/content/browser/permissions/permission_service_context.cc
+++ b/content/browser/permissions/permission_service_context.cc
@@ -17,6 +17,7 @@
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "url/origin.h"
namespace content {
@@ -104,9 +105,11 @@
void PermissionServiceContext::CreateService(
mojo::PendingReceiver<blink::mojom::PermissionService> receiver) {
DCHECK(render_frame_host_);
- services_.Add(std::make_unique<PermissionServiceImpl>(
- this, render_frame_host_->GetLastCommittedOrigin()),
- std::move(receiver));
+ services_.Add(
+ std::make_unique<PermissionServiceImpl>(
+ this, url::Origin::Create(PermissionUtil::GetLastCommittedOriginAsURL(
+ render_frame_host_))),
+ std::move(receiver));
}
void PermissionServiceContext::CreateServiceForWorker(
diff --git a/content/browser/permissions/permission_service_impl.cc b/content/browser/permissions/permission_service_impl.cc
index 21d9ab9..fcf5ec0 100644
--- a/content/browser/permissions/permission_service_impl.cc
+++ b/content/browser/permissions/permission_service_impl.cc
@@ -104,7 +104,7 @@
std::vector<PermissionType> types(permissions.size());
std::set<PermissionType> duplicates_check;
for (size_t i = 0; i < types.size(); ++i) {
- auto type = PermissionDescriptorToPermissionType(permissions[i]);
+ auto type = blink::PermissionDescriptorToPermissionType(permissions[i]);
if (!type) {
ReceivedBadMessage();
return;
@@ -147,7 +147,8 @@
void PermissionServiceImpl::RevokePermission(
PermissionDescriptorPtr permission,
PermissionStatusCallback callback) {
- auto permission_type = PermissionDescriptorToPermissionType(permission);
+ auto permission_type =
+ blink::PermissionDescriptorToPermissionType(permission);
if (!permission_type) {
ReceivedBadMessage();
return;
@@ -170,7 +171,7 @@
PermissionDescriptorPtr permission,
PermissionStatus last_known_status,
mojo::PendingRemote<blink::mojom::PermissionObserver> observer) {
- auto type = PermissionDescriptorToPermissionType(permission);
+ auto type = blink::PermissionDescriptorToPermissionType(permission);
if (!type) {
ReceivedBadMessage();
return;
@@ -182,7 +183,7 @@
PermissionStatus PermissionServiceImpl::GetPermissionStatus(
const PermissionDescriptorPtr& permission) {
- auto type = PermissionDescriptorToPermissionType(permission);
+ auto type = blink::PermissionDescriptorToPermissionType(permission);
if (!type) {
ReceivedBadMessage();
return PermissionStatus::DENIED;
diff --git a/content/browser/permissions/permission_service_impl.h b/content/browser/permissions/permission_service_impl.h
index f47d95a9..21a3350 100644
--- a/content/browser/permissions/permission_service_impl.h
+++ b/content/browser/permissions/permission_service_impl.h
@@ -10,14 +10,13 @@
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/permissions/permission_service_context.h"
+#include "content/public/browser/permission_type.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "third_party/blink/public/mojom/permissions/permission.mojom.h"
#include "url/origin.h"
namespace content {
-enum class PermissionType;
-
// Implements the PermissionService Mojo interface.
// This service can be created from a RenderFrameHost or a RenderProcessHost.
// It is owned by a PermissionServiceContext.
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn
index 4f1b2d3e..847002ec 100644
--- a/content/public/browser/BUILD.gn
+++ b/content/public/browser/BUILD.gn
@@ -284,7 +284,6 @@
"permission_controller.h",
"permission_controller_delegate.cc",
"permission_controller_delegate.h",
- "permission_type.cc",
"permission_type.h",
"picture_in_picture_window_controller.h",
"platform_notification_context.h",
@@ -527,10 +526,6 @@
deps += [ "//ppapi/c" ]
}
- if (is_chromeos || is_android || is_win || is_chromecast || is_fuchsia) {
- defines = [ "ENABLE_PROTECTED_MEDIA_IDENTIFIER_PERMISSION" ]
- }
-
if (is_posix || is_fuchsia) {
sources += [ "posix_file_descriptor_info.h" ]
}
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
index 41d5f73a..29f73d1 100644
--- a/content/public/browser/content_browser_client.h
+++ b/content/public/browser/content_browser_client.h
@@ -32,6 +32,7 @@
#include "content/public/browser/generated_code_cache_settings.h"
#include "content/public/browser/login_delegate.h"
#include "content/public/browser/mojo_binder_policy_map.h"
+#include "content/public/browser/permission_type.h"
#include "content/public/browser/storage_partition_config.h"
#include "content/public/common/alternative_error_page_override_info.mojom-forward.h"
#include "content/public/common/main_function_params.h"
@@ -193,7 +194,6 @@
} // namespace storage
namespace content {
-enum class PermissionType;
enum class SiteIsolationMode;
enum class SmsFetchFailureType;
class AuthenticatorRequestClientDelegate;
diff --git a/content/public/browser/devtools_permission_overrides.cc b/content/public/browser/devtools_permission_overrides.cc
index a2c79c4..090bbbc4 100644
--- a/content/public/browser/devtools_permission_overrides.cc
+++ b/content/public/browser/devtools_permission_overrides.cc
@@ -72,7 +72,7 @@
const absl::optional<url::Origin>& origin,
const std::vector<PermissionType>& permissions) {
const std::vector<PermissionType>& kAllPermissionTypes =
- GetAllPermissionTypes();
+ blink::GetAllPermissionTypes();
PermissionOverrides granted_overrides;
for (const auto& permission : kAllPermissionTypes)
granted_overrides[permission] = PermissionStatus::DENIED;
diff --git a/content/public/browser/permission_controller_delegate.h b/content/public/browser/permission_controller_delegate.h
index 0adaa67..88e7c00 100644
--- a/content/public/browser/permission_controller_delegate.h
+++ b/content/public/browser/permission_controller_delegate.h
@@ -13,7 +13,6 @@
class GURL;
namespace content {
-enum class PermissionType;
class RenderFrameHost;
class RenderProcessHost;
diff --git a/content/public/browser/permission_type.cc b/content/public/browser/permission_type.cc
deleted file mode 100644
index df8afa72..0000000
--- a/content/public/browser/permission_type.cc
+++ /dev/null
@@ -1,113 +0,0 @@
-// 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 "content/public/browser/permission_type.h"
-
-#include "base/no_destructor.h"
-#include "build/build_config.h"
-#include "third_party/blink/public/mojom/permissions/permission.mojom.h"
-
-using blink::mojom::PermissionDescriptorPtr;
-using blink::mojom::PermissionName;
-using blink::mojom::PermissionStatus;
-
-namespace content {
-
-const std::vector<PermissionType>& GetAllPermissionTypes() {
- static const base::NoDestructor<std::vector<PermissionType>>
- kAllPermissionTypes([] {
- const int NUM_TYPES = static_cast<int>(PermissionType::NUM);
- std::vector<PermissionType> all_types;
- // Note: Update this if the set of removed entries changes.
- // This is 6 because it skips 0 as well as the 5 numbers explicitly
- // mentioned below.
- all_types.reserve(NUM_TYPES - 6);
- for (int i = 1; i < NUM_TYPES; ++i) {
- // Skip removed entries.
- if (i == 2 || i == 11 || i == 14 || i == 15 || i == 32)
- continue;
- all_types.push_back(static_cast<PermissionType>(i));
- }
- return all_types;
- }());
- return *kAllPermissionTypes;
-}
-
-absl::optional<PermissionType> PermissionDescriptorToPermissionType(
- const PermissionDescriptorPtr& descriptor) {
- switch (descriptor->name) {
- case PermissionName::GEOLOCATION:
- return PermissionType::GEOLOCATION;
- case PermissionName::NOTIFICATIONS:
- return PermissionType::NOTIFICATIONS;
- case PermissionName::MIDI: {
- if (descriptor->extension && descriptor->extension->is_midi() &&
- descriptor->extension->get_midi()->sysex) {
- return PermissionType::MIDI_SYSEX;
- }
- return PermissionType::MIDI;
- }
- case PermissionName::PROTECTED_MEDIA_IDENTIFIER:
-#if defined(ENABLE_PROTECTED_MEDIA_IDENTIFIER_PERMISSION)
- return PermissionType::PROTECTED_MEDIA_IDENTIFIER;
-#else
- NOTIMPLEMENTED();
- return absl::nullopt;
-#endif // defined(ENABLE_PROTECTED_MEDIA_IDENTIFIER_PERMISSION)
- case PermissionName::DURABLE_STORAGE:
- return PermissionType::DURABLE_STORAGE;
- case PermissionName::AUDIO_CAPTURE:
- return PermissionType::AUDIO_CAPTURE;
- case PermissionName::VIDEO_CAPTURE:
- if (descriptor->extension && descriptor->extension->is_camera_device() &&
- descriptor->extension->get_camera_device()->panTiltZoom) {
- return PermissionType::CAMERA_PAN_TILT_ZOOM;
- } else {
- return PermissionType::VIDEO_CAPTURE;
- }
- case PermissionName::BACKGROUND_SYNC:
- return PermissionType::BACKGROUND_SYNC;
- case PermissionName::SENSORS:
- return PermissionType::SENSORS;
- case PermissionName::ACCESSIBILITY_EVENTS:
- return PermissionType::ACCESSIBILITY_EVENTS;
- case PermissionName::CLIPBOARD_READ:
- return PermissionType::CLIPBOARD_READ_WRITE;
- case PermissionName::CLIPBOARD_WRITE: {
- if (descriptor->extension && descriptor->extension->is_clipboard() &&
- descriptor->extension->get_clipboard()->allowWithoutSanitization) {
- return PermissionType::CLIPBOARD_READ_WRITE;
- } else {
- return PermissionType::CLIPBOARD_SANITIZED_WRITE;
- }
- }
- case PermissionName::PAYMENT_HANDLER:
- return PermissionType::PAYMENT_HANDLER;
- case PermissionName::BACKGROUND_FETCH:
- return PermissionType::BACKGROUND_FETCH;
- case PermissionName::IDLE_DETECTION:
- return PermissionType::IDLE_DETECTION;
- case PermissionName::PERIODIC_BACKGROUND_SYNC:
- return PermissionType::PERIODIC_BACKGROUND_SYNC;
- case PermissionName::SCREEN_WAKE_LOCK:
- return PermissionType::WAKE_LOCK_SCREEN;
- case PermissionName::SYSTEM_WAKE_LOCK:
- return PermissionType::WAKE_LOCK_SYSTEM;
- case PermissionName::NFC:
- return PermissionType::NFC;
- case PermissionName::STORAGE_ACCESS:
- return PermissionType::STORAGE_ACCESS_GRANT;
- case PermissionName::WINDOW_PLACEMENT:
- return PermissionType::WINDOW_PLACEMENT;
- case PermissionName::LOCAL_FONTS:
- return PermissionType::LOCAL_FONTS;
- case PermissionName::DISPLAY_CAPTURE:
- return PermissionType::DISPLAY_CAPTURE;
- }
-
- NOTREACHED();
- return absl::nullopt;
-}
-
-} // namespace content
diff --git a/content/public/browser/permission_type.h b/content/public/browser/permission_type.h
index 260c510d..80ef36a 100644
--- a/content/public/browser/permission_type.h
+++ b/content/public/browser/permission_type.h
@@ -5,64 +5,11 @@
#ifndef CONTENT_PUBLIC_BROWSER_PERMISSION_TYPE_H_
#define CONTENT_PUBLIC_BROWSER_PERMISSION_TYPE_H_
-#include <vector>
-
-#include "content/common/content_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
-#include "third_party/blink/public/mojom/permissions/permission.mojom-forward.h"
+#include "third_party/blink/public/common/permissions/permission_utils.h"
namespace content {
-// This enum is also used for UMA purposes, so it needs to adhere to
-// the UMA guidelines.
-// Make sure you update enums.xml and GetAllPermissionTypes if you add new
-// or deprecate permission types.
-// Never delete or reorder an entry; only add new entries
-// immediately before PermissionType::NUM
-enum class PermissionType {
- MIDI_SYSEX = 1,
- // PUSH_MESSAGING = 2,
- NOTIFICATIONS = 3,
- GEOLOCATION = 4,
- PROTECTED_MEDIA_IDENTIFIER = 5,
- MIDI = 6,
- DURABLE_STORAGE = 7,
- AUDIO_CAPTURE = 8,
- VIDEO_CAPTURE = 9,
- BACKGROUND_SYNC = 10,
- // FLASH = 11,
- SENSORS = 12,
- ACCESSIBILITY_EVENTS = 13,
- // CLIPBOARD_READ = 14, // Replaced by CLIPBOARD_READ_WRITE in M81.
- // CLIPBOARD_WRITE = 15, // Replaced by CLIPBOARD_SANITIZED_WRITE in M81.
- PAYMENT_HANDLER = 16,
- BACKGROUND_FETCH = 17,
- IDLE_DETECTION = 18,
- PERIODIC_BACKGROUND_SYNC = 19,
- WAKE_LOCK_SCREEN = 20,
- WAKE_LOCK_SYSTEM = 21,
- NFC = 22,
- CLIPBOARD_READ_WRITE = 23,
- CLIPBOARD_SANITIZED_WRITE = 24,
- VR = 25,
- AR = 26,
- STORAGE_ACCESS_GRANT = 27,
- CAMERA_PAN_TILT_ZOOM = 28,
- WINDOW_PLACEMENT = 29,
- LOCAL_FONTS = 30,
- DISPLAY_CAPTURE = 31,
- // FILE_HANDLING = 32, // Removed in M98.
-
- // Always keep this at the end.
- NUM,
-};
-
-CONTENT_EXPORT const std::vector<PermissionType>& GetAllPermissionTypes();
-
-// Given |descriptor|, set |permission_type| to a corresponding PermissionType.
-CONTENT_EXPORT absl::optional<PermissionType>
-PermissionDescriptorToPermissionType(
- const blink::mojom::PermissionDescriptorPtr& descriptor);
+using PermissionType = blink::BlinkPermissionType;
} // namespace content
diff --git a/content/public/test/mock_permission_controller.h b/content/public/test/mock_permission_controller.h
index 375fd762..3328ef2 100644
--- a/content/public/test/mock_permission_controller.h
+++ b/content/public/test/mock_permission_controller.h
@@ -6,6 +6,7 @@
#define CONTENT_PUBLIC_TEST_MOCK_PERMISSION_CONTROLLER_H_
#include "content/public/browser/permission_controller.h"
+#include "content/public/browser/permission_type.h"
#include "testing/gmock/include/gmock/gmock.h"
class GURL;
@@ -16,8 +17,6 @@
namespace content {
-enum class PermissionType;
-
// Mock of the permission controller for unit tests.
class MockPermissionController : public PermissionController {
public:
diff --git a/content/public/test/mock_permission_manager.h b/content/public/test/mock_permission_manager.h
index 6cacf2f..7bd2d42b 100644
--- a/content/public/test/mock_permission_manager.h
+++ b/content/public/test/mock_permission_manager.h
@@ -6,13 +6,12 @@
#define CONTENT_PUBLIC_TEST_MOCK_PERMISSION_MANAGER_H_
#include "content/public/browser/permission_controller_delegate.h"
+#include "content/public/browser/permission_type.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "url/gurl.h"
namespace content {
-enum class PermissionType;
-
// Mock of the permission manager for unit tests.
class MockPermissionManager : public PermissionControllerDelegate {
public:
diff --git a/content/public/test/permission_type_unittest.cc b/content/public/test/permission_type_unittest.cc
index ae2c48ce..f0573630 100644
--- a/content/public/test/permission_type_unittest.cc
+++ b/content/public/test/permission_type_unittest.cc
@@ -12,7 +12,7 @@
using testing::Contains;
TEST(PermissionTypeHelpersTest, AllPermissionTypesSmokeTest) {
- const auto all_permission_types = GetAllPermissionTypes();
+ const auto all_permission_types = blink::GetAllPermissionTypes();
// All but PermissionType::NUM should be added.
EXPECT_EQ(all_permission_types.size(),
diff --git a/content/public/test/permissions_test_utils.h b/content/public/test/permissions_test_utils.h
index c5c4c807..1bac2c5 100644
--- a/content/public/test/permissions_test_utils.h
+++ b/content/public/test/permissions_test_utils.h
@@ -5,6 +5,7 @@
#ifndef CONTENT_PUBLIC_TEST_PERMISSIONS_TEST_UTILS_H_
#define CONTENT_PUBLIC_TEST_PERMISSIONS_TEST_UTILS_H_
+#include "content/public/browser/permission_type.h"
#include "third_party/blink/public/mojom/permissions/permission_status.mojom.h"
namespace url {
@@ -14,7 +15,6 @@
namespace content {
class PermissionController;
-enum class PermissionType;
void SetPermissionControllerOverrideForDevTools(
PermissionController* permission_controller,
diff --git a/content/web_test/browser/web_test_permission_manager.cc b/content/web_test/browser/web_test_permission_manager.cc
index 3014378..9800029 100644
--- a/content/web_test/browser/web_test_permission_manager.cc
+++ b/content/web_test/browser/web_test_permission_manager.cc
@@ -250,7 +250,7 @@
const GURL& url,
const GURL& embedding_url,
blink::test::mojom::PermissionAutomation::SetPermissionCallback callback) {
- auto type = PermissionDescriptorToPermissionType(descriptor);
+ auto type = blink::PermissionDescriptorToPermissionType(descriptor);
if (!type) {
std::move(callback).Run(false);
return;
diff --git a/third_party/blink/common/BUILD.gn b/third_party/blink/common/BUILD.gn
index 13f70d4..76e68c1 100644
--- a/third_party/blink/common/BUILD.gn
+++ b/third_party/blink/common/BUILD.gn
@@ -282,6 +282,10 @@
sources += [ "dwrite_rasterizer_support/dwrite_rasterizer_support.cc" ]
deps += [ "//ui/gfx/" ]
}
+
+ if (is_chromeos || is_android || is_win || is_chromecast || is_fuchsia) {
+ defines = [ "ENABLE_PROTECTED_MEDIA_IDENTIFIER_PERMISSION" ]
+ }
}
test("blink_common_unittests") {
diff --git a/third_party/blink/common/permissions/permission_utils.cc b/third_party/blink/common/permissions/permission_utils.cc
index bad6007..e9bf0a2 100644
--- a/third_party/blink/common/permissions/permission_utils.cc
+++ b/third_party/blink/common/permissions/permission_utils.cc
@@ -4,10 +4,16 @@
#include "third_party/blink/public/common/permissions/permission_utils.h"
+#include "base/no_destructor.h"
#include "base/notreached.h"
+#include "third_party/blink/public/mojom/permissions/permission.mojom.h"
namespace blink {
+using mojom::PermissionDescriptorPtr;
+using mojom::PermissionName;
+using mojom::PermissionStatus;
+
mojom::PermissionStatus ToPermissionStatus(const std::string& status) {
if (status == "granted")
return mojom::PermissionStatus::GRANTED;
@@ -19,4 +25,112 @@
return mojom::PermissionStatus::DENIED;
}
+const std::vector<BlinkPermissionType>& GetAllPermissionTypes() {
+ static const base::NoDestructor<std::vector<BlinkPermissionType>>
+ kAllBlinkPermissionTypes([] {
+ const int NUM_TYPES = static_cast<int>(BlinkPermissionType::NUM);
+ std::vector<BlinkPermissionType> all_types;
+ // Note: Update this if the set of removed entries changes.
+ // This is 6 because it skips 0 as well as the 5 numbers explicitly
+ // mentioned below.
+ all_types.reserve(NUM_TYPES - 6);
+ for (int i = 1; i < NUM_TYPES; ++i) {
+ // Skip removed entries.
+ if (i == 2 || i == 11 || i == 14 || i == 15 || i == 32)
+ continue;
+ all_types.push_back(static_cast<BlinkPermissionType>(i));
+ }
+ return all_types;
+ }());
+ return *kAllBlinkPermissionTypes;
+}
+
+absl::optional<BlinkPermissionType> PermissionDescriptorToPermissionType(
+ const PermissionDescriptorPtr& descriptor) {
+ return PermissionDescriptorInfoToPermissionType(
+ descriptor->name,
+ descriptor->extension && descriptor->extension->is_midi() &&
+ descriptor->extension->get_midi()->sysex,
+ descriptor->extension && descriptor->extension->is_camera_device() &&
+ descriptor->extension->get_camera_device()->panTiltZoom,
+ descriptor->extension && descriptor->extension->is_clipboard() &&
+ descriptor->extension->get_clipboard()->allowWithoutSanitization);
+}
+
+absl::optional<BlinkPermissionType> PermissionDescriptorInfoToPermissionType(
+ mojom::PermissionName name,
+ bool midi_sysex,
+ bool camera_ptz,
+ bool clipboard_allow_without_sanitization) {
+ switch (name) {
+ case PermissionName::GEOLOCATION:
+ return BlinkPermissionType::GEOLOCATION;
+ case PermissionName::NOTIFICATIONS:
+ return BlinkPermissionType::NOTIFICATIONS;
+ case PermissionName::MIDI: {
+ if (midi_sysex) {
+ return BlinkPermissionType::MIDI_SYSEX;
+ }
+ return BlinkPermissionType::MIDI;
+ }
+ case PermissionName::PROTECTED_MEDIA_IDENTIFIER:
+#if defined(ENABLE_PROTECTED_MEDIA_IDENTIFIER_PERMISSION)
+ return BlinkPermissionType::PROTECTED_MEDIA_IDENTIFIER;
+#else
+ NOTIMPLEMENTED();
+ return absl::nullopt;
+#endif // defined(ENABLE_PROTECTED_MEDIA_IDENTIFIER_PERMISSION)
+ case PermissionName::DURABLE_STORAGE:
+ return BlinkPermissionType::DURABLE_STORAGE;
+ case PermissionName::AUDIO_CAPTURE:
+ return BlinkPermissionType::AUDIO_CAPTURE;
+ case PermissionName::VIDEO_CAPTURE:
+ if (camera_ptz) {
+ return BlinkPermissionType::CAMERA_PAN_TILT_ZOOM;
+ } else {
+ return BlinkPermissionType::VIDEO_CAPTURE;
+ }
+ case PermissionName::BACKGROUND_SYNC:
+ return BlinkPermissionType::BACKGROUND_SYNC;
+ case PermissionName::SENSORS:
+ return BlinkPermissionType::SENSORS;
+ case PermissionName::ACCESSIBILITY_EVENTS:
+ return BlinkPermissionType::ACCESSIBILITY_EVENTS;
+ case PermissionName::CLIPBOARD_READ:
+ return BlinkPermissionType::CLIPBOARD_READ_WRITE;
+ case PermissionName::CLIPBOARD_WRITE: {
+ if (clipboard_allow_without_sanitization) {
+ return BlinkPermissionType::CLIPBOARD_READ_WRITE;
+ } else {
+ return BlinkPermissionType::CLIPBOARD_SANITIZED_WRITE;
+ }
+ }
+ case PermissionName::PAYMENT_HANDLER:
+ return BlinkPermissionType::PAYMENT_HANDLER;
+ case PermissionName::BACKGROUND_FETCH:
+ return BlinkPermissionType::BACKGROUND_FETCH;
+ case PermissionName::IDLE_DETECTION:
+ return BlinkPermissionType::IDLE_DETECTION;
+ case PermissionName::PERIODIC_BACKGROUND_SYNC:
+ return BlinkPermissionType::PERIODIC_BACKGROUND_SYNC;
+ case PermissionName::SCREEN_WAKE_LOCK:
+ return BlinkPermissionType::WAKE_LOCK_SCREEN;
+ case PermissionName::SYSTEM_WAKE_LOCK:
+ return BlinkPermissionType::WAKE_LOCK_SYSTEM;
+ case PermissionName::NFC:
+ return BlinkPermissionType::NFC;
+ case PermissionName::STORAGE_ACCESS:
+ return BlinkPermissionType::STORAGE_ACCESS_GRANT;
+ case PermissionName::WINDOW_PLACEMENT:
+ return BlinkPermissionType::WINDOW_PLACEMENT;
+ case PermissionName::LOCAL_FONTS:
+ return BlinkPermissionType::LOCAL_FONTS;
+ case PermissionName::DISPLAY_CAPTURE:
+ return BlinkPermissionType::DISPLAY_CAPTURE;
+
+ NOTREACHED();
+ return absl::nullopt;
+ }
+}
+
} // namespace blink
diff --git a/third_party/blink/public/common/permissions/permission_utils.h b/third_party/blink/public/common/permissions/permission_utils.h
index d623fc6..2350b84e 100644
--- a/third_party/blink/public/common/permissions/permission_utils.h
+++ b/third_party/blink/public/common/permissions/permission_utils.h
@@ -7,16 +7,85 @@
#include <string>
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/common/common_export.h"
+#include "third_party/blink/public/mojom/permissions/permission.mojom-forward.h"
#include "third_party/blink/public/mojom/permissions/permission_status.mojom-shared.h"
namespace blink {
+// This enum is also used for UMA purposes, so it needs to adhere to
+// the UMA guidelines.
+// Make sure you update enums.xml and GetAllPermissionTypes if you add new
+// or deprecate permission types.
+// Never delete or reorder an entry; only add new entries
+// immediately before PermissionType::NUM
+enum class BlinkPermissionType {
+ MIDI_SYSEX = 1,
+ // PUSH_MESSAGING = 2,
+ NOTIFICATIONS = 3,
+ GEOLOCATION = 4,
+ PROTECTED_MEDIA_IDENTIFIER = 5,
+ MIDI = 6,
+ DURABLE_STORAGE = 7,
+ AUDIO_CAPTURE = 8,
+ VIDEO_CAPTURE = 9,
+ BACKGROUND_SYNC = 10,
+ // FLASH = 11,
+ SENSORS = 12,
+ ACCESSIBILITY_EVENTS = 13,
+ // CLIPBOARD_READ = 14, // Replaced by CLIPBOARD_READ_WRITE in M81.
+ // CLIPBOARD_WRITE = 15, // Replaced by CLIPBOARD_SANITIZED_WRITE in M81.
+ PAYMENT_HANDLER = 16,
+ BACKGROUND_FETCH = 17,
+ IDLE_DETECTION = 18,
+ PERIODIC_BACKGROUND_SYNC = 19,
+ WAKE_LOCK_SCREEN = 20,
+ WAKE_LOCK_SYSTEM = 21,
+ NFC = 22,
+ CLIPBOARD_READ_WRITE = 23,
+ CLIPBOARD_SANITIZED_WRITE = 24,
+ VR = 25,
+ AR = 26,
+ STORAGE_ACCESS_GRANT = 27,
+ CAMERA_PAN_TILT_ZOOM = 28,
+ WINDOW_PLACEMENT = 29,
+ LOCAL_FONTS = 30,
+ DISPLAY_CAPTURE = 31,
+ // FILE_HANDLING = 32, // Removed in M98.
+
+ // Always keep this at the end.
+ NUM,
+};
+
// Converts a permission string ("granted", "denied", "prompt") into a
// PermissionStatus.
BLINK_COMMON_EXPORT mojom::PermissionStatus ToPermissionStatus(
const std::string& status);
+// Get a list of all permission types.
+BLINK_COMMON_EXPORT const std::vector<BlinkPermissionType>&
+GetAllPermissionTypes();
+
+// Given |descriptor|, set |permission_type| to a corresponding PermissionType.
+BLINK_COMMON_EXPORT absl::optional<BlinkPermissionType>
+PermissionDescriptorToPermissionType(
+ const mojom::PermissionDescriptorPtr& descriptor);
+
+// Ideally this would be an equivalent function to
+// |PermissionDescriptorToPermissionType| but for a
+// `mojom::blink::PermissionDescriptorPtr` descriptor. But unfortunately mojo
+// blink headers depend on blink/common so we can't introduce the reverse
+// dependency. Instead we provide this function that requires the relevant
+// information for making the decision and the caller needs to extract it from
+// the descriptor and provide it.
+BLINK_COMMON_EXPORT absl::optional<BlinkPermissionType>
+PermissionDescriptorInfoToPermissionType(
+ mojom::PermissionName name,
+ bool midi_sysex,
+ bool camera_ptz,
+ bool clipboard_allow_without_sanitization);
+
} // namespace blink
#endif // THIRD_PARTY_BLINK_PUBLIC_COMMON_PERMISSIONS_PERMISSION_UTILS_H_
diff --git a/third_party/blink/renderer/modules/permissions/BUILD.gn b/third_party/blink/renderer/modules/permissions/BUILD.gn
index 2f90b5ae..0e54957 100644
--- a/third_party/blink/renderer/modules/permissions/BUILD.gn
+++ b/third_party/blink/renderer/modules/permissions/BUILD.gn
@@ -8,6 +8,8 @@
sources = [
"permission_status.cc",
"permission_status.h",
+ "permission_status_listener.cc",
+ "permission_status_listener.h",
"permission_utils.cc",
"permission_utils.h",
"permissions.cc",
diff --git a/third_party/blink/renderer/modules/permissions/permission_status.cc b/third_party/blink/renderer/modules/permissions/permission_status.cc
index d74aca8..6a5abea 100644
--- a/third_party/blink/renderer/modules/permissions/permission_status.cc
+++ b/third_party/blink/renderer/modules/permissions/permission_status.cc
@@ -4,53 +4,30 @@
#include "third_party/blink/renderer/modules/permissions/permission_status.h"
-#include "mojo/public/cpp/bindings/remote.h"
#include "third_party/blink/public/mojom/frame/lifecycle.mojom-shared.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
-#include "third_party/blink/renderer/core/dom/document.h"
#include "third_party/blink/renderer/core/dom/events/event.h"
#include "third_party/blink/renderer/modules/event_target_modules_names.h"
-#include "third_party/blink/renderer/modules/permissions/permission_utils.h"
-#include "third_party/blink/renderer/modules/permissions/permissions.h"
-#include "third_party/blink/renderer/platform/wtf/functional.h"
+#include "third_party/blink/renderer/modules/permissions/permission_status_listener.h"
namespace blink {
// static
-PermissionStatus* PermissionStatus::Take(
- Permissions& associated_permissions_object,
- ScriptPromiseResolver* resolver,
- MojoPermissionStatus status,
- MojoPermissionDescriptor descriptor) {
- return PermissionStatus::CreateAndListen(associated_permissions_object,
- resolver->GetExecutionContext(),
- status, std::move(descriptor));
-}
-
-PermissionStatus* PermissionStatus::CreateAndListen(
- Permissions& associated_permissions_object,
- ExecutionContext* execution_context,
- MojoPermissionStatus status,
- MojoPermissionDescriptor descriptor) {
- PermissionStatus* permission_status = MakeGarbageCollected<PermissionStatus>(
- associated_permissions_object, execution_context, status,
- std::move(descriptor));
+PermissionStatus* PermissionStatus::Take(PermissionStatusListener* listener,
+ ScriptPromiseResolver* resolver) {
+ ExecutionContext* execution_context = resolver->GetExecutionContext();
+ PermissionStatus* permission_status =
+ MakeGarbageCollected<PermissionStatus>(listener, execution_context);
permission_status->UpdateStateIfNeeded();
permission_status->StartListening();
return permission_status;
}
-PermissionStatus::PermissionStatus(Permissions& associated_permissions_object,
- ExecutionContext* execution_context,
- MojoPermissionStatus status,
- MojoPermissionDescriptor descriptor)
+PermissionStatus::PermissionStatus(PermissionStatusListener* listener,
+ ExecutionContext* execution_context)
: ExecutionContextLifecycleStateObserver(execution_context),
- status_(status),
- descriptor_(std::move(descriptor)),
- receiver_(this, execution_context) {
- associated_permissions_object.PermissionStatusObjectCreated();
-}
+ listener_(listener) {}
PermissionStatus::~PermissionStatus() = default;
@@ -63,7 +40,9 @@
}
bool PermissionStatus::HasPendingActivity() const {
- return receiver_.is_bound();
+ if (!listener_)
+ return false;
+ return listener_->HasPendingActivity();
}
void PermissionStatus::ContextLifecycleStateChanged(
@@ -75,43 +54,38 @@
}
String PermissionStatus::state() const {
- return PermissionStatusToString(status_);
+ if (!listener_)
+ return String();
+ return listener_->state();
}
String PermissionStatus::name() const {
- return PermissionNameToString(descriptor_->name);
+ if (!listener_)
+ return String();
+ return listener_->name();
}
void PermissionStatus::StartListening() {
- DCHECK(!receiver_.is_bound());
- mojo::PendingRemote<mojom::blink::PermissionObserver> observer;
- scoped_refptr<base::SingleThreadTaskRunner> task_runner =
- GetExecutionContext()->GetTaskRunner(TaskType::kPermission);
- receiver_.Bind(observer.InitWithNewPipeAndPassReceiver(), task_runner);
-
- mojo::Remote<mojom::blink::PermissionService> service;
- ConnectToPermissionService(GetExecutionContext(),
- service.BindNewPipeAndPassReceiver(task_runner));
- service->AddPermissionObserver(descriptor_->Clone(), status_,
- std::move(observer));
+ if (!listener_)
+ return;
+ listener_->AddObserver(this);
}
void PermissionStatus::StopListening() {
- receiver_.reset();
+ if (!listener_)
+ return;
+ listener_->RemoveObserver(this);
}
void PermissionStatus::OnPermissionStatusChange(MojoPermissionStatus status) {
- if (status_ == status)
- return;
-
- status_ = status;
DispatchEvent(*Event::Create(event_type_names::kChange));
}
void PermissionStatus::Trace(Visitor* visitor) const {
- visitor->Trace(receiver_);
+ visitor->Trace(listener_);
EventTargetWithInlineData::Trace(visitor);
ExecutionContextLifecycleStateObserver::Trace(visitor);
+ PermissionStatusListener::Observer::Trace(visitor);
}
} // namespace blink
diff --git a/third_party/blink/renderer/modules/permissions/permission_status.h b/third_party/blink/renderer/modules/permissions/permission_status.h
index 12cfa6c8..59f84ab0 100644
--- a/third_party/blink/renderer/modules/permissions/permission_status.h
+++ b/third_party/blink/renderer/modules/permissions/permission_status.h
@@ -5,10 +5,10 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PERMISSIONS_PERMISSION_STATUS_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_PERMISSIONS_PERMISSION_STATUS_H_
-#include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/core/dom/events/event_target.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h"
+#include "third_party/blink/renderer/modules/permissions/permission_status_listener.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
#include "third_party/blink/renderer/platform/wtf/text/atomic_string.h"
@@ -18,34 +18,23 @@
class ExecutionContext;
class ScriptPromiseResolver;
-class Permissions;
// Expose the status of a given permission type for the current
// ExecutionContext.
class PermissionStatus final : public EventTargetWithInlineData,
public ActiveScriptWrappable<PermissionStatus>,
public ExecutionContextLifecycleStateObserver,
- public mojom::blink::PermissionObserver {
+ public PermissionStatusListener::Observer {
DEFINE_WRAPPERTYPEINFO();
using MojoPermissionDescriptor = mojom::blink::PermissionDescriptorPtr;
using MojoPermissionStatus = mojom::blink::PermissionStatus;
public:
- static PermissionStatus* Take(Permissions&,
- ScriptPromiseResolver*,
- MojoPermissionStatus,
- MojoPermissionDescriptor);
+ static PermissionStatus* Take(PermissionStatusListener*,
+ ScriptPromiseResolver*);
- static PermissionStatus* CreateAndListen(Permissions&,
- ExecutionContext*,
- MojoPermissionStatus,
- MojoPermissionDescriptor);
-
- PermissionStatus(Permissions&,
- ExecutionContext*,
- MojoPermissionStatus,
- MojoPermissionDescriptor);
+ PermissionStatus(PermissionStatusListener*, ExecutionContext*);
~PermissionStatus() override;
// EventTarget implementation.
@@ -59,6 +48,9 @@
void ContextLifecycleStateChanged(mojom::FrameLifecycleState) override;
void ContextDestroyed() override {}
+ // PermissionStatusListener::Observer
+ void OnPermissionStatusChange(MojoPermissionStatus) override;
+
String state() const;
String name() const;
@@ -71,12 +63,7 @@
void StartListening();
void StopListening();
- void OnPermissionStatusChange(MojoPermissionStatus) override;
-
- MojoPermissionStatus status_;
- MojoPermissionDescriptor descriptor_;
- HeapMojoReceiver<mojom::blink::PermissionObserver, PermissionStatus>
- receiver_;
+ WeakMember<PermissionStatusListener> listener_;
};
} // namespace blink
diff --git a/third_party/blink/renderer/modules/permissions/permission_status_listener.cc b/third_party/blink/renderer/modules/permissions/permission_status_listener.cc
new file mode 100644
index 0000000..424314c
--- /dev/null
+++ b/third_party/blink/renderer/modules/permissions/permission_status_listener.cc
@@ -0,0 +1,105 @@
+// Copyright 2021 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 "third_party/blink/renderer/modules/permissions/permission_status_listener.h"
+
+#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
+#include "third_party/blink/renderer/modules/permissions/permission_utils.h"
+#include "third_party/blink/renderer/modules/permissions/permissions.h"
+
+namespace blink {
+
+PermissionStatusListener* PermissionStatusListener::Create(
+ Permissions& associated_permissions_object,
+ ExecutionContext* execution_context,
+ MojoPermissionStatus status,
+ MojoPermissionDescriptor descriptor) {
+ PermissionStatusListener* permission_status =
+ MakeGarbageCollected<PermissionStatusListener>(
+ associated_permissions_object, execution_context, status,
+ std::move(descriptor));
+ return permission_status;
+}
+
+PermissionStatusListener::PermissionStatusListener(
+ Permissions& associated_permissions_object,
+ ExecutionContext* execution_context,
+ MojoPermissionStatus status,
+ MojoPermissionDescriptor descriptor)
+ : ExecutionContextClient(execution_context),
+ status_(status),
+ descriptor_(std::move(descriptor)),
+ receiver_(this, execution_context) {
+ associated_permissions_object.PermissionStatusObjectCreated();
+}
+
+PermissionStatusListener::~PermissionStatusListener() = default;
+
+void PermissionStatusListener::StartListening() {
+ DCHECK(!receiver_.is_bound());
+ mojo::PendingRemote<mojom::blink::PermissionObserver> observer;
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+ GetExecutionContext()->GetTaskRunner(TaskType::kPermission);
+ receiver_.Bind(observer.InitWithNewPipeAndPassReceiver(), task_runner);
+
+ mojo::Remote<mojom::blink::PermissionService> service;
+ ConnectToPermissionService(GetExecutionContext(),
+ service.BindNewPipeAndPassReceiver(task_runner));
+ service->AddPermissionObserver(descriptor_->Clone(), status_,
+ std::move(observer));
+}
+
+void PermissionStatusListener::StopListening() {
+ receiver_.reset();
+}
+
+void PermissionStatusListener::OnPermissionStatusChange(
+ MojoPermissionStatus status) {
+ if (status_ == status)
+ return;
+
+ status_ = status;
+
+ for (const auto& observer : observers_) {
+ if (observer)
+ observer->OnPermissionStatusChange(status);
+ else
+ RemoveObserver(observer);
+ }
+}
+
+void PermissionStatusListener::AddObserver(Observer* observer) {
+ if (observers_.IsEmpty())
+ StartListening();
+
+ observers_.insert(observer);
+}
+
+void PermissionStatusListener::RemoveObserver(Observer* observer) {
+ observers_.erase(observer);
+
+ if (observers_.IsEmpty())
+ StopListening();
+}
+
+bool PermissionStatusListener::HasPendingActivity() {
+ return receiver_.is_bound();
+}
+
+String PermissionStatusListener::state() const {
+ return PermissionStatusToString(status_);
+}
+
+String PermissionStatusListener::name() const {
+ return PermissionNameToString(descriptor_->name);
+}
+
+void PermissionStatusListener::Trace(Visitor* visitor) const {
+ visitor->Trace(observers_);
+ visitor->Trace(receiver_);
+ ExecutionContextClient::Trace(visitor);
+}
+
+} // namespace blink
diff --git a/third_party/blink/renderer/modules/permissions/permission_status_listener.h b/third_party/blink/renderer/modules/permissions/permission_status_listener.h
new file mode 100644
index 0000000..2b906cab
--- /dev/null
+++ b/third_party/blink/renderer/modules/permissions/permission_status_listener.h
@@ -0,0 +1,79 @@
+// Copyright 2021 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 THIRD_PARTY_BLINK_RENDERER_MODULES_PERMISSIONS_PERMISSION_STATUS_LISTENER_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_PERMISSIONS_PERMISSION_STATUS_LISTENER_H_
+
+#include "base/memory/weak_ptr.h"
+#include "third_party/blink/public/mojom/permissions/permission.mojom-blink.h"
+#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
+#include "third_party/blink/renderer/platform/heap/collection_support/heap_hash_set.h"
+#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
+#include "third_party/blink/renderer/platform/heap/member.h"
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
+
+namespace blink {
+
+class ExecutionContext;
+class Permissions;
+
+class PermissionStatusListener final
+ : public GarbageCollected<PermissionStatusListener>,
+ public ExecutionContextClient,
+ public mojom::blink::PermissionObserver {
+ using MojoPermissionDescriptor = mojom::blink::PermissionDescriptorPtr;
+ using MojoPermissionStatus = mojom::blink::PermissionStatus;
+
+ public:
+ class Observer : public GarbageCollectedMixin {
+ public:
+ virtual ~Observer() = default;
+
+ virtual void OnPermissionStatusChange(MojoPermissionStatus) = 0;
+
+ void Trace(Visitor* visitor) const override {}
+ };
+
+ static PermissionStatusListener* Create(Permissions&,
+ ExecutionContext*,
+ MojoPermissionStatus,
+ MojoPermissionDescriptor);
+
+ PermissionStatusListener(Permissions&,
+ ExecutionContext*,
+ MojoPermissionStatus,
+ MojoPermissionDescriptor);
+ ~PermissionStatusListener() override;
+
+ PermissionStatusListener(const PermissionStatusListener&) = delete;
+ PermissionStatusListener& operator=(const PermissionStatusListener&) = delete;
+
+ void AddObserver(Observer* observer);
+ void RemoveObserver(Observer* observer);
+
+ bool HasPendingActivity();
+ void SetStatus(MojoPermissionStatus status) { status_ = status; }
+
+ String state() const;
+ String name() const;
+
+ void Trace(Visitor*) const override;
+
+ private:
+ void StartListening();
+ void StopListening();
+
+ // mojom::blink::PermissionObserver
+ void OnPermissionStatusChange(MojoPermissionStatus) override;
+
+ MojoPermissionStatus status_;
+ MojoPermissionDescriptor descriptor_;
+ HeapHashSet<WeakMember<Observer>> observers_;
+ HeapMojoReceiver<mojom::blink::PermissionObserver, PermissionStatusListener>
+ receiver_;
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PERMISSIONS_PERMISSION_STATUS_LISTENER_H_
diff --git a/third_party/blink/renderer/modules/permissions/permissions.cc b/third_party/blink/renderer/modules/permissions/permissions.cc
index 6a29853..5b14c7acd 100644
--- a/third_party/blink/renderer/modules/permissions/permissions.cc
+++ b/third_party/blink/renderer/modules/permissions/permissions.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/metrics/histogram_functions.h"
+#include "third_party/blink/public/common/permissions/permission_utils.h"
#include "third_party/blink/public/platform/platform.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
@@ -90,10 +91,12 @@
PermissionDescriptorPtr descriptor_copy = descriptor->Clone();
LocalDOMWindow* window = DynamicTo<LocalDOMWindow>(context);
LocalFrame* frame = window ? window->GetFrame() : nullptr;
+
GetService(context)->RequestPermission(
std::move(descriptor), LocalFrame::HasTransientUserActivation(frame),
- WTF::Bind(&Permissions::TaskComplete, WrapPersistent(this),
- WrapPersistent(resolver), std::move(descriptor_copy)));
+ WTF::Bind(&Permissions::VerifyPermissionAndReturnStatus,
+ WrapPersistent(this), WrapPersistent(resolver),
+ std::move(descriptor_copy)));
return promise;
}
@@ -160,12 +163,15 @@
LocalDOMWindow* window = DynamicTo<LocalDOMWindow>(context);
LocalFrame* frame = window ? window->GetFrame() : nullptr;
+
GetService(context)->RequestPermissions(
std::move(internal_permissions),
LocalFrame::HasTransientUserActivation(frame),
- WTF::Bind(&Permissions::BatchTaskComplete, WrapPersistent(this),
- WrapPersistent(resolver), std::move(internal_permissions_copy),
- std::move(caller_index_to_internal_index)));
+ WTF::Bind(
+ &Permissions::VerifyPermissionsAndReturnStatus, WrapPersistent(this),
+ WrapPersistent(resolver), std::move(internal_permissions_copy),
+ std::move(caller_index_to_internal_index),
+ -1 /* last_verified_permission_index */, true /* is_bulk_request */));
return promise;
}
@@ -176,6 +182,7 @@
void Permissions::Trace(Visitor* visitor) const {
visitor->Trace(service_);
+ visitor->Trace(listeners_);
ScriptWrappable::Trace(visitor);
Supplement<NavigatorBase>::Trace(visitor);
ExecutionContextLifecycleObserver::Trace(visitor);
@@ -204,15 +211,41 @@
if (!resolver->GetExecutionContext() ||
resolver->GetExecutionContext()->IsContextDestroyed())
return;
- resolver->Resolve(
- PermissionStatus::Take(*this, resolver, result, std::move(descriptor)));
+
+ PermissionStatusListener* listener =
+ GetOrCreatePermissionStatusListener(result, std::move(descriptor));
+ if (listener)
+ resolver->Resolve(PermissionStatus::Take(listener, resolver));
}
-void Permissions::BatchTaskComplete(
+void Permissions::VerifyPermissionAndReturnStatus(
+ ScriptPromiseResolver* resolver,
+ mojom::blink::PermissionDescriptorPtr descriptor,
+ mojom::blink::PermissionStatus result) {
+ Vector<int> caller_index_to_internal_index;
+ caller_index_to_internal_index.push_back(0);
+ Vector<mojom::blink::PermissionStatus> results;
+ results.push_back(std::move(result));
+ Vector<mojom::blink::PermissionDescriptorPtr> descriptors;
+ descriptors.push_back(std::move(descriptor));
+
+ VerifyPermissionsAndReturnStatus(resolver, std::move(descriptors),
+ std::move(caller_index_to_internal_index),
+ -1 /* last_verified_permission_index */,
+ false /* is_bulk_request */,
+ std::move(results));
+}
+
+void Permissions::VerifyPermissionsAndReturnStatus(
ScriptPromiseResolver* resolver,
Vector<mojom::blink::PermissionDescriptorPtr> descriptors,
Vector<int> caller_index_to_internal_index,
+ int last_verified_permission_index,
+ bool is_bulk_request,
const Vector<mojom::blink::PermissionStatus>& results) {
+ DCHECK(caller_index_to_internal_index.size() == 1u || is_bulk_request);
+ DCHECK_EQ(descriptors.size(), caller_index_to_internal_index.size());
+
if (!resolver->GetExecutionContext() ||
resolver->GetExecutionContext()->IsContextDestroyed())
return;
@@ -223,11 +256,102 @@
HeapVector<Member<PermissionStatus>> result;
result.ReserveInitialCapacity(caller_index_to_internal_index.size());
for (int internal_index : caller_index_to_internal_index) {
- result.push_back(PermissionStatus::CreateAndListen(
- *this, resolver->GetExecutionContext(), results[internal_index],
- descriptors[internal_index]->Clone()));
+ // If there is a chance that this permission result came from a different
+ // permission type (e.g. a PTZ request could be replaced with a camera
+ // request internally), then re-check the actual permission type to ensure
+ // that it it indeed that permission type. If it's not, replace the
+ // descriptor with the verification descriptor.
+ auto verification_descriptor = CreatePermissionVerificationDescriptor(
+ *GetPermissionType(*descriptors[internal_index]));
+ if (last_verified_permission_index == -1 && verification_descriptor) {
+ auto descriptor_copy = descriptors[internal_index]->Clone();
+ service_->HasPermission(
+ std::move(descriptor_copy),
+ WTF::Bind(&Permissions::PermissionVerificationComplete,
+ WrapPersistent(this), WrapPersistent(resolver),
+ std::move(descriptors),
+ std::move(caller_index_to_internal_index),
+ std::move(results), std::move(verification_descriptor),
+ internal_index, is_bulk_request));
+ return;
+ }
+
+ // This is the last permission that was verified.
+ if (internal_index == last_verified_permission_index)
+ last_verified_permission_index = -1;
+
+ PermissionStatusListener* listener = GetOrCreatePermissionStatusListener(
+ results[internal_index], descriptors[internal_index]->Clone());
+ if (listener) {
+ // If it's not a bulk request, return the first (and only) result.
+ if (!is_bulk_request) {
+ resolver->Resolve(PermissionStatus::Take(listener, resolver));
+ return;
+ }
+ result.push_back(PermissionStatus::Take(listener, resolver));
+ }
}
resolver->Resolve(result);
}
+void Permissions::PermissionVerificationComplete(
+ ScriptPromiseResolver* resolver,
+ Vector<mojom::blink::PermissionDescriptorPtr> descriptors,
+ Vector<int> caller_index_to_internal_index,
+ const Vector<mojom::blink::PermissionStatus>& results,
+ mojom::blink::PermissionDescriptorPtr verification_descriptor,
+ int internal_index_to_verify,
+ bool is_bulk_request,
+ mojom::blink::PermissionStatus verification_result) {
+ if (verification_result != results[internal_index_to_verify]) {
+ // The permission actually came from the verification descriptor, so use
+ // that descriptor when returning the permission status.
+ descriptors[internal_index_to_verify] = std::move(verification_descriptor);
+ }
+
+ VerifyPermissionsAndReturnStatus(resolver, std::move(descriptors),
+ std::move(caller_index_to_internal_index),
+ internal_index_to_verify, is_bulk_request,
+ std::move(results));
+}
+
+PermissionStatusListener* Permissions::GetOrCreatePermissionStatusListener(
+ mojom::blink::PermissionStatus status,
+ mojom::blink::PermissionDescriptorPtr descriptor) {
+ auto type = GetPermissionType(*descriptor);
+ if (!type)
+ return nullptr;
+
+ if (!listeners_.Contains(*type)) {
+ listeners_.insert(
+ *type, PermissionStatusListener::Create(*this, GetExecutionContext(),
+ status, std::move(descriptor)));
+ } else {
+ listeners_.at(*type)->SetStatus(status);
+ }
+
+ return listeners_.at(*type);
+}
+
+absl::optional<BlinkPermissionType> Permissions::GetPermissionType(
+ const mojom::blink::PermissionDescriptor& descriptor) {
+ return PermissionDescriptorInfoToPermissionType(
+ descriptor.name,
+ descriptor.extension && descriptor.extension->is_midi() &&
+ descriptor.extension->get_midi()->sysex,
+ descriptor.extension && descriptor.extension->is_camera_device() &&
+ descriptor.extension->get_camera_device()->panTiltZoom,
+ descriptor.extension && descriptor.extension->is_clipboard() &&
+ descriptor.extension->get_clipboard()->allowWithoutSanitization);
+}
+
+mojom::blink::PermissionDescriptorPtr
+Permissions::CreatePermissionVerificationDescriptor(
+ BlinkPermissionType descriptor_type) {
+ if (descriptor_type == BlinkPermissionType::CAMERA_PAN_TILT_ZOOM) {
+ return CreateVideoCapturePermissionDescriptor(false /* pan_tilt_zoom */);
+ }
+ return nullptr;
+}
+
} // namespace blink
diff --git a/third_party/blink/renderer/modules/permissions/permissions.h b/third_party/blink/renderer/modules/permissions/permissions.h
index 2898e75..4e46c1d 100644
--- a/third_party/blink/renderer/modules/permissions/permissions.h
+++ b/third_party/blink/renderer/modules/permissions/permissions.h
@@ -9,11 +9,13 @@
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
+#include "third_party/blink/renderer/modules/permissions/permission_status_listener.h"
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
#include "third_party/blink/renderer/platform/heap/garbage_collected.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_remote.h"
#include "third_party/blink/renderer/platform/mojo/heap_mojo_wrapper_mode.h"
#include "third_party/blink/renderer/platform/supplementable.h"
+#include "third_party/blink/renderer/platform/wtf/hash_map.h"
namespace blink {
@@ -22,6 +24,7 @@
class ScriptPromiseResolver;
class ScriptState;
class ScriptValue;
+enum class BlinkPermissionType;
class Permissions final : public ScriptWrappable,
public Supplement<NavigatorBase>,
@@ -53,16 +56,45 @@
private:
mojom::blink::PermissionService* GetService(ExecutionContext*);
void ServiceConnectionError();
- void TaskComplete(ScriptPromiseResolver*,
- mojom::blink::PermissionDescriptorPtr,
- mojom::blink::PermissionStatus);
- void BatchTaskComplete(ScriptPromiseResolver*,
- Vector<mojom::blink::PermissionDescriptorPtr>,
- Vector<int>,
- const Vector<mojom::blink::PermissionStatus>&);
+
+ void TaskComplete(ScriptPromiseResolver* resolver,
+ mojom::blink::PermissionDescriptorPtr descriptor,
+ mojom::blink::PermissionStatus result);
+
+ void VerifyPermissionAndReturnStatus(
+ ScriptPromiseResolver* resolver,
+ mojom::blink::PermissionDescriptorPtr descriptor,
+ mojom::blink::PermissionStatus result);
+ void VerifyPermissionsAndReturnStatus(
+ ScriptPromiseResolver* resolver,
+ Vector<mojom::blink::PermissionDescriptorPtr> descriptors,
+ Vector<int> caller_index_to_internal_index,
+ int last_verified_permission_index,
+ bool is_bulk_request,
+ const Vector<mojom::blink::PermissionStatus>& results);
+
+ void PermissionVerificationComplete(
+ ScriptPromiseResolver* resolver,
+ Vector<mojom::blink::PermissionDescriptorPtr> descriptors,
+ Vector<int> caller_index_to_internal_index,
+ const Vector<mojom::blink::PermissionStatus>& results,
+ mojom::blink::PermissionDescriptorPtr verification_descriptor,
+ int internal_index_to_verify,
+ bool is_bulk_request,
+ mojom::blink::PermissionStatus verification_result);
+
+ PermissionStatusListener* GetOrCreatePermissionStatusListener(
+ mojom::blink::PermissionStatus status,
+ mojom::blink::PermissionDescriptorPtr descriptor);
+ absl::optional<BlinkPermissionType> GetPermissionType(
+ const mojom::blink::PermissionDescriptor& descriptor);
+ mojom::blink::PermissionDescriptorPtr CreatePermissionVerificationDescriptor(
+ BlinkPermissionType descriptor_type);
int created_permission_status_objects_ = 0;
+ HeapHashMap<BlinkPermissionType, Member<PermissionStatusListener>> listeners_;
+
HeapMojoRemote<mojom::blink::PermissionService> service_;
};
diff --git a/weblayer/browser/permissions/permission_manager_factory.cc b/weblayer/browser/permissions/permission_manager_factory.cc
index 13726db..950e3245 100644
--- a/weblayer/browser/permissions/permission_manager_factory.cc
+++ b/weblayer/browser/permissions/permission_manager_factory.cc
@@ -119,7 +119,7 @@
// For now, all requests are denied. As features are added, their permission
// contexts can be added here instead of DeniedPermissionContext.
- for (content::PermissionType type : content::GetAllPermissionTypes()) {
+ for (content::PermissionType type : blink::GetAllPermissionTypes()) {
#if !BUILDFLAG(IS_ANDROID)
// PROTECTED_MEDIA_IDENTIFIER is only supported on Android.
if (type == content::PermissionType::PROTECTED_MEDIA_IDENTIFIER)