0

[MPArch Guest View] Support Media Access permissions

- Create Guest variants of the Media Access queries on the
GuestPageHolder::Delegate.
- Pass RenderFrameHost into SupportsStreamType.
- Look up the RenderFrameHost from the request object.

Bug: 40202416
Change-Id: Iac31b817892d7222c041b1a78a3e905de2a2f9b2
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6157121
Reviewed-by: Mark Foltz <mfoltz@chromium.org>
Reviewed-by: Robbie McElrath <rmcelrath@chromium.org>
Reviewed-by: Kevin McNee <mcnee@chromium.org>
Commit-Queue: Dave Tapuska <dtapuska@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1405643}
This commit is contained in:
Dave Tapuska
2025-01-13 11:39:36 -08:00
committed by Chromium LUCI CQ
parent 6572dc4750
commit ddcf18f3b0
33 changed files with 149 additions and 99 deletions

@ -3340,16 +3340,12 @@ IN_PROC_BROWSER_TEST_P(WebViewTest,
IN_PROC_BROWSER_TEST_P(WebViewTest, IN_PROC_BROWSER_TEST_P(WebViewTest,
PermissionsAPIEmbedderHasAccessAllowCamera) { PermissionsAPIEmbedderHasAccessAllowCamera) {
SKIP_FOR_MPARCH(); // TODO(crbug.com/40202416): Enable test for MPArch.
TestHelper("testAllowCamera", TestHelper("testAllowCamera",
"web_view/permissions_test/embedder_has_permission", "web_view/permissions_test/embedder_has_permission",
NEEDS_TEST_SERVER); NEEDS_TEST_SERVER);
} }
IN_PROC_BROWSER_TEST_P(WebViewTest, PermissionsAPIEmbedderHasAccessDenyCamera) { IN_PROC_BROWSER_TEST_P(WebViewTest, PermissionsAPIEmbedderHasAccessDenyCamera) {
SKIP_FOR_MPARCH(); // TODO(crbug.com/40202416): Enable test for MPArch.
TestHelper("testDenyCamera", TestHelper("testDenyCamera",
"web_view/permissions_test/embedder_has_permission", "web_view/permissions_test/embedder_has_permission",
NEEDS_TEST_SERVER); NEEDS_TEST_SERVER);
@ -3357,8 +3353,6 @@ IN_PROC_BROWSER_TEST_P(WebViewTest, PermissionsAPIEmbedderHasAccessDenyCamera) {
IN_PROC_BROWSER_TEST_P(WebViewTest, IN_PROC_BROWSER_TEST_P(WebViewTest,
PermissionsAPIEmbedderHasAccessAllowMicrophone) { PermissionsAPIEmbedderHasAccessAllowMicrophone) {
SKIP_FOR_MPARCH(); // TODO(crbug.com/40202416): Enable test for MPArch.
TestHelper("testAllowMicrophone", TestHelper("testAllowMicrophone",
"web_view/permissions_test/embedder_has_permission", "web_view/permissions_test/embedder_has_permission",
NEEDS_TEST_SERVER); NEEDS_TEST_SERVER);
@ -3366,24 +3360,18 @@ IN_PROC_BROWSER_TEST_P(WebViewTest,
IN_PROC_BROWSER_TEST_P(WebViewTest, IN_PROC_BROWSER_TEST_P(WebViewTest,
PermissionsAPIEmbedderHasAccessDenyMicrophone) { PermissionsAPIEmbedderHasAccessDenyMicrophone) {
SKIP_FOR_MPARCH(); // TODO(crbug.com/40202416): Enable test for MPArch.
TestHelper("testDenyMicrophone", TestHelper("testDenyMicrophone",
"web_view/permissions_test/embedder_has_permission", "web_view/permissions_test/embedder_has_permission",
NEEDS_TEST_SERVER); NEEDS_TEST_SERVER);
} }
IN_PROC_BROWSER_TEST_P(WebViewTest, PermissionsAPIEmbedderHasAccessAllowMedia) { IN_PROC_BROWSER_TEST_P(WebViewTest, PermissionsAPIEmbedderHasAccessAllowMedia) {
SKIP_FOR_MPARCH(); // TODO(crbug.com/40202416): Enable test for MPArch.
TestHelper("testAllowMedia", TestHelper("testAllowMedia",
"web_view/permissions_test/embedder_has_permission", "web_view/permissions_test/embedder_has_permission",
NEEDS_TEST_SERVER); NEEDS_TEST_SERVER);
} }
IN_PROC_BROWSER_TEST_P(WebViewTest, PermissionsAPIEmbedderHasAccessDenyMedia) { IN_PROC_BROWSER_TEST_P(WebViewTest, PermissionsAPIEmbedderHasAccessDenyMedia) {
SKIP_FOR_MPARCH(); // TODO(crbug.com/40202416): Enable test for MPArch.
TestHelper("testDenyMedia", TestHelper("testDenyMedia",
"web_view/permissions_test/embedder_has_permission", "web_view/permissions_test/embedder_has_permission",
NEEDS_TEST_SERVER); NEEDS_TEST_SERVER);
@ -3556,8 +3544,6 @@ IN_PROC_BROWSER_TEST_P(WebViewTest,
IN_PROC_BROWSER_TEST_P(WebViewTest, IN_PROC_BROWSER_TEST_P(WebViewTest,
PermissionsAPIEmbedderHasNoAccessAllowCamera) { PermissionsAPIEmbedderHasNoAccessAllowCamera) {
SKIP_FOR_MPARCH(); // TODO(crbug.com/40202416): Enable test for MPArch.
TestHelper("testAllowCamera", TestHelper("testAllowCamera",
"web_view/permissions_test/embedder_has_no_permission", "web_view/permissions_test/embedder_has_no_permission",
NEEDS_TEST_SERVER); NEEDS_TEST_SERVER);
@ -3565,8 +3551,6 @@ IN_PROC_BROWSER_TEST_P(WebViewTest,
IN_PROC_BROWSER_TEST_P(WebViewTest, IN_PROC_BROWSER_TEST_P(WebViewTest,
PermissionsAPIEmbedderHasNoAccessDenyCamera) { PermissionsAPIEmbedderHasNoAccessDenyCamera) {
SKIP_FOR_MPARCH(); // TODO(crbug.com/40202416): Enable test for MPArch.
TestHelper("testDenyCamera", TestHelper("testDenyCamera",
"web_view/permissions_test/embedder_has_no_permission", "web_view/permissions_test/embedder_has_no_permission",
NEEDS_TEST_SERVER); NEEDS_TEST_SERVER);
@ -3574,8 +3558,6 @@ IN_PROC_BROWSER_TEST_P(WebViewTest,
IN_PROC_BROWSER_TEST_P(WebViewTest, IN_PROC_BROWSER_TEST_P(WebViewTest,
PermissionsAPIEmbedderHasNoAccessAllowMicrophone) { PermissionsAPIEmbedderHasNoAccessAllowMicrophone) {
SKIP_FOR_MPARCH(); // TODO(crbug.com/40202416): Enable test for MPArch.
TestHelper("testAllowMicrophone", TestHelper("testAllowMicrophone",
"web_view/permissions_test/embedder_has_no_permission", "web_view/permissions_test/embedder_has_no_permission",
NEEDS_TEST_SERVER); NEEDS_TEST_SERVER);
@ -3583,8 +3565,6 @@ IN_PROC_BROWSER_TEST_P(WebViewTest,
IN_PROC_BROWSER_TEST_P(WebViewTest, IN_PROC_BROWSER_TEST_P(WebViewTest,
PermissionsAPIEmbedderHasNoAccessDenyMicrophone) { PermissionsAPIEmbedderHasNoAccessDenyMicrophone) {
SKIP_FOR_MPARCH(); // TODO(crbug.com/40202416): Enable test for MPArch.
TestHelper("testDenyMicrophone", TestHelper("testDenyMicrophone",
"web_view/permissions_test/embedder_has_no_permission", "web_view/permissions_test/embedder_has_no_permission",
NEEDS_TEST_SERVER); NEEDS_TEST_SERVER);
@ -3592,8 +3572,6 @@ IN_PROC_BROWSER_TEST_P(WebViewTest,
IN_PROC_BROWSER_TEST_P(WebViewTest, IN_PROC_BROWSER_TEST_P(WebViewTest,
PermissionsAPIEmbedderHasNoAccessAllowMedia) { PermissionsAPIEmbedderHasNoAccessAllowMedia) {
SKIP_FOR_MPARCH(); // TODO(crbug.com/40202416): Enable test for MPArch.
TestHelper("testAllowMedia", TestHelper("testAllowMedia",
"web_view/permissions_test/embedder_has_no_permission", "web_view/permissions_test/embedder_has_no_permission",
NEEDS_TEST_SERVER); NEEDS_TEST_SERVER);
@ -3601,8 +3579,6 @@ IN_PROC_BROWSER_TEST_P(WebViewTest,
IN_PROC_BROWSER_TEST_P(WebViewTest, IN_PROC_BROWSER_TEST_P(WebViewTest,
PermissionsAPIEmbedderHasNoAccessDenyMedia) { PermissionsAPIEmbedderHasNoAccessDenyMedia) {
SKIP_FOR_MPARCH(); // TODO(crbug.com/40202416): Enable test for MPArch.
TestHelper("testDenyMedia", TestHelper("testDenyMedia",
"web_view/permissions_test/embedder_has_no_permission", "web_view/permissions_test/embedder_has_no_permission",
NEEDS_TEST_SERVER); NEEDS_TEST_SERVER);

@ -54,18 +54,14 @@ ControlledFrameMediaAccessHandler::~ControlledFrameMediaAccessHandler() =
default; default;
bool ControlledFrameMediaAccessHandler::SupportsStreamType( bool ControlledFrameMediaAccessHandler::SupportsStreamType(
content::WebContents* web_contents, content::RenderFrameHost* render_frame_host,
const blink::mojom::MediaStreamType type, const blink::mojom::MediaStreamType type,
const extensions::Extension* extension) { const extensions::Extension* extension) {
if (!web_contents || extension) { if (!render_frame_host || extension) {
return false; return false;
} }
// TODO(b/40238394): |GuestView| should be looked up from |RenderFrameHost|
// instead of |WebContents|. To fix this, |SupportsStreamType| could pass
// |RenderFrameHost| instead of |WebContents|.
extensions::WebViewGuest* web_view = extensions::WebViewGuest* web_view =
extensions::WebViewGuest::FromWebContents(web_contents); extensions::WebViewGuest::FromRenderFrameHost(render_frame_host);
bool is_controlled_frame = web_view && web_view->attached() && bool is_controlled_frame = web_view && web_view->attached() &&
web_view->IsOwnedByControlledFrameEmbedder(); web_view->IsOwnedByControlledFrameEmbedder();

@ -42,7 +42,7 @@ class ControlledFrameMediaAccessHandler : public MediaAccessHandler {
~ControlledFrameMediaAccessHandler() override; ~ControlledFrameMediaAccessHandler() override;
// MediaAccessHandler implementation: // MediaAccessHandler implementation:
bool SupportsStreamType(content::WebContents* web_contents, bool SupportsStreamType(content::RenderFrameHost* render_frame_host,
const blink::mojom::MediaStreamType type, const blink::mojom::MediaStreamType type,
const extensions::Extension* extension) override; const extensions::Extension* extension) override;
bool CheckMediaAccessPermission( bool CheckMediaAccessPermission(

@ -13,7 +13,9 @@
#include "chromeos/ash/components/settings/cros_settings.h" #include "chromeos/ash/components/settings/cros_settings.h"
#include "chromeos/ash/components/settings/cros_settings_names.h" #include "chromeos/ash/components/settings/cros_settings_names.h"
#include "components/content_settings/core/common/content_settings_pattern.h" #include "components/content_settings/core/common/content_settings_pattern.h"
#include "components/guest_view/browser/guest_view_base.h"
#include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_frame_host.h"
#include "content/public/browser/web_contents.h"
#include "url/gurl.h" #include "url/gurl.h"
ChromeOSLoginAndLockMediaAccessHandler:: ChromeOSLoginAndLockMediaAccessHandler::
@ -23,9 +25,12 @@ ChromeOSLoginAndLockMediaAccessHandler::
~ChromeOSLoginAndLockMediaAccessHandler() = default; ~ChromeOSLoginAndLockMediaAccessHandler() = default;
bool ChromeOSLoginAndLockMediaAccessHandler::SupportsStreamType( bool ChromeOSLoginAndLockMediaAccessHandler::SupportsStreamType(
content::WebContents* web_contents, content::RenderFrameHost* render_frame_host,
const blink::mojom::MediaStreamType type, const blink::mojom::MediaStreamType type,
const extensions::Extension* extension) { const extensions::Extension* extension) {
auto* web_contents = guest_view::GuestViewBase::GetTopLevelWebContents(
content::WebContents::FromRenderFrameHost(render_frame_host));
if (!web_contents) if (!web_contents)
return false; return false;
// Check if the `web_contents` corresponds to the login screen. // Check if the `web_contents` corresponds to the login screen.

@ -15,7 +15,7 @@ class ChromeOSLoginAndLockMediaAccessHandler : public MediaAccessHandler {
~ChromeOSLoginAndLockMediaAccessHandler() override; ~ChromeOSLoginAndLockMediaAccessHandler() override;
// MediaAccessHandler implementation. // MediaAccessHandler implementation.
bool SupportsStreamType(content::WebContents* web_contents, bool SupportsStreamType(content::RenderFrameHost* render_frame_host,
const blink::mojom::MediaStreamType type, const blink::mojom::MediaStreamType type,
const extensions::Extension* extension) override; const extensions::Extension* extension) override;
bool CheckMediaAccessPermission( bool CheckMediaAccessPermission(

@ -47,7 +47,7 @@ ExtensionMediaAccessHandler::ExtensionMediaAccessHandler() = default;
ExtensionMediaAccessHandler::~ExtensionMediaAccessHandler() = default; ExtensionMediaAccessHandler::~ExtensionMediaAccessHandler() = default;
bool ExtensionMediaAccessHandler::SupportsStreamType( bool ExtensionMediaAccessHandler::SupportsStreamType(
content::WebContents* web_contents, content::RenderFrameHost* render_frame_host,
const blink::mojom::MediaStreamType type, const blink::mojom::MediaStreamType type,
const extensions::Extension* extension) { const extensions::Extension* extension) {
return extension && return extension &&

@ -14,7 +14,7 @@ class ExtensionMediaAccessHandler : public MediaAccessHandler {
~ExtensionMediaAccessHandler() override; ~ExtensionMediaAccessHandler() override;
// MediaAccessHandler implementation. // MediaAccessHandler implementation.
bool SupportsStreamType(content::WebContents* web_contents, bool SupportsStreamType(content::RenderFrameHost* render_frame_host,
const blink::mojom::MediaStreamType type, const blink::mojom::MediaStreamType type,
const extensions::Extension* extension) override; const extensions::Extension* extension) override;
bool CheckMediaAccessPermission( bool CheckMediaAccessPermission(

@ -27,7 +27,7 @@ class MediaAccessHandler {
virtual ~MediaAccessHandler() = default; virtual ~MediaAccessHandler() = default;
// Check if the media stream type is supported by MediaAccessHandler. // Check if the media stream type is supported by MediaAccessHandler.
virtual bool SupportsStreamType(content::WebContents* web_contents, virtual bool SupportsStreamType(content::RenderFrameHost* render_frame_host,
const blink::mojom::MediaStreamType type, const blink::mojom::MediaStreamType type,
const extensions::Extension* extension) = 0; const extensions::Extension* extension) = 0;

@ -310,7 +310,7 @@ void DesktopCaptureAccessHandler::ProcessScreenCaptureAccessRequest(
} }
bool DesktopCaptureAccessHandler::SupportsStreamType( bool DesktopCaptureAccessHandler::SupportsStreamType(
content::WebContents* web_contents, content::RenderFrameHost* render_frame_host,
const blink::mojom::MediaStreamType type, const blink::mojom::MediaStreamType type,
const extensions::Extension* extension) { const extensions::Extension* extension) {
return type == blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE || return type == blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE ||

@ -50,7 +50,7 @@ class DesktopCaptureAccessHandler : public CaptureAccessHandlerBase,
~DesktopCaptureAccessHandler() override; ~DesktopCaptureAccessHandler() override;
// MediaAccessHandler implementation. // MediaAccessHandler implementation.
bool SupportsStreamType(content::WebContents* web_contents, bool SupportsStreamType(content::RenderFrameHost* render_frame_host,
const blink::mojom::MediaStreamType type, const blink::mojom::MediaStreamType type,
const extensions::Extension* extension) override; const extensions::Extension* extension) override;
bool CheckMediaAccessPermission( bool CheckMediaAccessPermission(

@ -99,7 +99,7 @@ DisplayMediaAccessHandler::DisplayMediaAccessHandler(
DisplayMediaAccessHandler::~DisplayMediaAccessHandler() = default; DisplayMediaAccessHandler::~DisplayMediaAccessHandler() = default;
bool DisplayMediaAccessHandler::SupportsStreamType( bool DisplayMediaAccessHandler::SupportsStreamType(
content::WebContents* web_contents, content::RenderFrameHost* render_frame_host,
const blink::mojom::MediaStreamType stream_type, const blink::mojom::MediaStreamType stream_type,
const extensions::Extension* extension) { const extensions::Extension* extension) {
return stream_type == blink::mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE || return stream_type == blink::mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE ||

@ -41,7 +41,7 @@ class DisplayMediaAccessHandler : public CaptureAccessHandlerBase,
~DisplayMediaAccessHandler() override; ~DisplayMediaAccessHandler() override;
// MediaAccessHandler implementation. // MediaAccessHandler implementation.
bool SupportsStreamType(content::WebContents* web_contents, bool SupportsStreamType(content::RenderFrameHost* render_frame_host,
const blink::mojom::MediaStreamType stream_type, const blink::mojom::MediaStreamType stream_type,
const extensions::Extension* extension) override; const extensions::Extension* extension) override;
bool CheckMediaAccessPermission( bool CheckMediaAccessPermission(

@ -68,18 +68,6 @@ using blink::MediaStreamDevices;
using content::BrowserThread; using content::BrowserThread;
using content::MediaCaptureDevices; using content::MediaCaptureDevices;
namespace {
content::WebContents* WebContentsFromIds(int render_process_id,
int render_frame_id) {
content::WebContents* web_contents =
content::WebContents::FromRenderFrameHost(
content::RenderFrameHost::FromID(render_process_id, render_frame_id));
return web_contents;
}
} // namespace
MediaCaptureDevicesDispatcher* MediaCaptureDevicesDispatcher::GetInstance() { MediaCaptureDevicesDispatcher* MediaCaptureDevicesDispatcher::GetInstance() {
return base::Singleton<MediaCaptureDevicesDispatcher>::get(); return base::Singleton<MediaCaptureDevicesDispatcher>::get();
} }
@ -158,10 +146,13 @@ void MediaCaptureDevicesDispatcher::ProcessMediaAccessRequest(
} }
#endif #endif
auto* render_frame_host = content::RenderFrameHost::FromID(
request.render_process_id, request.render_frame_id);
for (const auto& handler : media_access_handlers_) { for (const auto& handler : media_access_handlers_) {
if (handler->SupportsStreamType(web_contents, request.video_type, if (handler->SupportsStreamType(render_frame_host, request.video_type,
extension) || extension) ||
handler->SupportsStreamType(web_contents, request.audio_type, handler->SupportsStreamType(render_frame_host, request.audio_type,
extension)) { extension)) {
handler->HandleRequest(web_contents, request, std::move(callback), handler->HandleRequest(web_contents, request, std::move(callback),
extension); extension);
@ -200,9 +191,7 @@ bool MediaCaptureDevicesDispatcher::CheckMediaAccessPermission(
const extensions::Extension* extension) { const extensions::Extension* extension) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
for (const auto& handler : media_access_handlers_) { for (const auto& handler : media_access_handlers_) {
if (handler->SupportsStreamType( if (handler->SupportsStreamType(render_frame_host, type, extension)) {
content::WebContents::FromRenderFrameHost(render_frame_host), type,
extension)) {
return handler->CheckMediaAccessPermission( return handler->CheckMediaAccessPermission(
render_frame_host, security_origin, type, extension); render_frame_host, security_origin, type, extension);
} }
@ -349,9 +338,9 @@ void MediaCaptureDevicesDispatcher::UpdateMediaRequestStateOnUIThread(
content::MediaRequestState state) { content::MediaRequestState state) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
for (const auto& handler : media_access_handlers_) { for (const auto& handler : media_access_handlers_) {
if (handler->SupportsStreamType( if (handler->SupportsStreamType(content::RenderFrameHost::FromID(
WebContentsFromIds(render_process_id, render_frame_id), stream_type, render_process_id, render_frame_id),
nullptr)) { stream_type, nullptr)) {
handler->UpdateMediaRequestState(render_process_id, render_frame_id, handler->UpdateMediaRequestState(render_process_id, render_frame_id,
page_request_id, stream_type, state); page_request_id, stream_type, state);
break; break;
@ -424,9 +413,9 @@ void MediaCaptureDevicesDispatcher::UpdateVideoScreenCaptureStatus(
DCHECK(blink::IsVideoScreenCaptureMediaType(stream_type)); DCHECK(blink::IsVideoScreenCaptureMediaType(stream_type));
for (const auto& handler : media_access_handlers_) { for (const auto& handler : media_access_handlers_) {
if (handler->SupportsStreamType( if (handler->SupportsStreamType(content::RenderFrameHost::FromID(
WebContentsFromIds(render_process_id, render_frame_id), stream_type, render_process_id, render_frame_id),
nullptr)) { stream_type, nullptr)) {
handler->UpdateVideoScreenCaptureStatus( handler->UpdateVideoScreenCaptureStatus(
render_process_id, render_frame_id, page_request_id, is_secure); render_process_id, render_frame_id, page_request_id, is_secure);
break; break;

@ -25,7 +25,7 @@ class MockMediaAccessHandler : public MediaAccessHandler {
const blink::mojom::MediaStreamType supported_type) const blink::mojom::MediaStreamType supported_type)
: supported_type_(supported_type) {} : supported_type_(supported_type) {}
bool SupportsStreamType(content::WebContents* web_contents, bool SupportsStreamType(content::RenderFrameHost* render_frame_host,
const blink::mojom::MediaStreamType type, const blink::mojom::MediaStreamType type,
const extensions::Extension* extension) override { const extensions::Extension* extension) override {
return supported_type_ == type; return supported_type_ == type;

@ -131,7 +131,7 @@ PermissionBubbleMediaAccessHandler::~PermissionBubbleMediaAccessHandler() =
default; default;
bool PermissionBubbleMediaAccessHandler::SupportsStreamType( bool PermissionBubbleMediaAccessHandler::SupportsStreamType(
content::WebContents* web_contents, content::RenderFrameHost* render_frame_host,
const blink::mojom::MediaStreamType type, const blink::mojom::MediaStreamType type,
const extensions::Extension* extension) { const extensions::Extension* extension) {
return type == blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE || return type == blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE ||

@ -29,7 +29,7 @@ class PermissionBubbleMediaAccessHandler
~PermissionBubbleMediaAccessHandler() override; ~PermissionBubbleMediaAccessHandler() override;
// MediaAccessHandler implementation. // MediaAccessHandler implementation.
bool SupportsStreamType(content::WebContents* web_contents, bool SupportsStreamType(content::RenderFrameHost* render_frame_host,
const blink::mojom::MediaStreamType type, const blink::mojom::MediaStreamType type,
const extensions::Extension* extension) override; const extensions::Extension* extension) override;
bool CheckMediaAccessPermission( bool CheckMediaAccessPermission(

@ -99,7 +99,7 @@ TabCaptureAccessHandler::TabCaptureAccessHandler() = default;
TabCaptureAccessHandler::~TabCaptureAccessHandler() = default; TabCaptureAccessHandler::~TabCaptureAccessHandler() = default;
bool TabCaptureAccessHandler::SupportsStreamType( bool TabCaptureAccessHandler::SupportsStreamType(
content::WebContents* web_contents, content::RenderFrameHost* render_frame_host,
const blink::mojom::MediaStreamType type, const blink::mojom::MediaStreamType type,
const extensions::Extension* extension) { const extensions::Extension* extension) {
return type == blink::mojom::MediaStreamType::GUM_TAB_VIDEO_CAPTURE || return type == blink::mojom::MediaStreamType::GUM_TAB_VIDEO_CAPTURE ||

@ -20,7 +20,7 @@ class TabCaptureAccessHandler : public CaptureAccessHandlerBase {
~TabCaptureAccessHandler() override; ~TabCaptureAccessHandler() override;
// MediaAccessHandler implementation. // MediaAccessHandler implementation.
bool SupportsStreamType(content::WebContents* web_contents, bool SupportsStreamType(content::RenderFrameHost* render_frame_host,
const blink::mojom::MediaStreamType type, const blink::mojom::MediaStreamType type,
const extensions::Extension* extension) override; const extensions::Extension* extension) override;
bool CheckMediaAccessPermission( bool CheckMediaAccessPermission(

@ -8,6 +8,7 @@ include_rules = [
"+third_party/blink/public/common/page/page_zoom.h", "+third_party/blink/public/common/page/page_zoom.h",
"+third_party/blink/public/common/input/web_gesture_event.h", "+third_party/blink/public/common/input/web_gesture_event.h",
"+third_party/blink/public/common/input/web_input_event.h", "+third_party/blink/public/common/input/web_input_event.h",
"+third_party/blink/public/mojom/mediastream/media_stream.mojom.h",
] ]
specific_include_rules = { specific_include_rules = {

@ -30,6 +30,7 @@
#include "content/public/common/content_features.h" #include "content/public/common/content_features.h"
#include "third_party/blink/public/common/input/web_gesture_event.h" #include "third_party/blink/public/common/input/web_gesture_event.h"
#include "third_party/blink/public/common/page/page_zoom.h" #include "third_party/blink/public/common/page/page_zoom.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
using content::WebContents; using content::WebContents;
@ -720,6 +721,21 @@ void GuestViewBase::GuestOpenURL(
void GuestViewBase::GuestClose() {} void GuestViewBase::GuestClose() {}
void GuestViewBase::GuestRequestMediaAccessPermission(
const content::MediaStreamRequest& request,
content::MediaResponseCallback callback) {
std::move(callback).Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED,
std::unique_ptr<content::MediaStreamUI>());
}
bool GuestViewBase::GuestCheckMediaAccessPermission(
content::RenderFrameHost* render_frame_host,
const url::Origin& security_origin,
blink::mojom::MediaStreamType type) {
return false;
}
void GuestViewBase::LoadProgressChanged(double progress) { void GuestViewBase::LoadProgressChanged(double progress) {
if (base::FeatureList::IsEnabled(features::kGuestViewMPArch)) { if (base::FeatureList::IsEnabled(features::kGuestViewMPArch)) {
// The load state of the embedder does not affect the load state of the // The load state of the embedder does not affect the load state of the

@ -468,6 +468,13 @@ class GuestViewBase : public content::BrowserPluginGuestDelegate,
base::OnceCallback<void(content::NavigationHandle&)> base::OnceCallback<void(content::NavigationHandle&)>
navigation_handle_callback) override; navigation_handle_callback) override;
void GuestClose() override; void GuestClose() override;
void GuestRequestMediaAccessPermission(
const content::MediaStreamRequest& request,
content::MediaResponseCallback callback) override;
bool GuestCheckMediaAccessPermission(
content::RenderFrameHost* render_frame_host,
const url::Origin& security_origin,
blink::mojom::MediaStreamType type) override;
// WebContentsDelegate implementation. // WebContentsDelegate implementation.
void ActivateContents(content::WebContents* contents) final; void ActivateContents(content::WebContents* contents) final;

@ -159,8 +159,11 @@ void MediaStreamUIProxy::Core::RequestAccess(
return; return;
} }
RenderFrameHostImpl* host = RenderFrameHostImpl::FromID(
request->render_process_id, request->render_frame_id);
render_delegate->RequestMediaAccessPermission( render_delegate->RequestMediaAccessPermission(
*request, host, *request,
base::BindOnce(&Core::ProcessAccessRequestResponse, weak_this_, base::BindOnce(&Core::ProcessAccessRequestResponse, weak_this_,
request->render_process_id, request->render_frame_id)); request->render_process_id, request->render_frame_id));
} }

@ -38,7 +38,8 @@ namespace content {
namespace { namespace {
class MockRenderFrameHostDelegate : public RenderFrameHostDelegate { class MockRenderFrameHostDelegate : public RenderFrameHostDelegate {
public: public:
void RequestMediaAccessPermission(const MediaStreamRequest& request, void RequestMediaAccessPermission(RenderFrameHostImpl* render_frame_host,
const MediaStreamRequest& request,
MediaResponseCallback callback) override { MediaResponseCallback callback) override {
return RequestMediaAccessPermission(request, &callback); return RequestMediaAccessPermission(request, &callback);
} }
@ -632,7 +633,8 @@ class MediaStreamUIProxyPermissionsPolicyTest
private: private:
class TestRFHDelegate : public RenderFrameHostDelegate { class TestRFHDelegate : public RenderFrameHostDelegate {
public: public:
void RequestMediaAccessPermission(const MediaStreamRequest& request, void RequestMediaAccessPermission(RenderFrameHostImpl* render_frame_host,
const MediaStreamRequest& request,
MediaResponseCallback callback) override { MediaResponseCallback callback) override {
blink::mojom::StreamDevicesSet stream_devices_set; blink::mojom::StreamDevicesSet stream_devices_set;
stream_devices_set.stream_devices.emplace_back( stream_devices_set.stream_devices.emplace_back(

@ -49,6 +49,7 @@ bool RenderFrameHostDelegate::DidAddMessageToConsole(
} }
void RenderFrameHostDelegate::RequestMediaAccessPermission( void RenderFrameHostDelegate::RequestMediaAccessPermission(
RenderFrameHostImpl* render_frame_host,
const MediaStreamRequest& request, const MediaStreamRequest& request,
MediaResponseCallback callback) { MediaResponseCallback callback) {
LOG(ERROR) << "RenderFrameHostDelegate::RequestMediaAccessPermission: " LOG(ERROR) << "RenderFrameHostDelegate::RequestMediaAccessPermission: "

@ -289,8 +289,10 @@ class CONTENT_EXPORT RenderFrameHostDelegate {
// The render frame has requested access to media devices listed in // The render frame has requested access to media devices listed in
// |request|, and the client should grant or deny that permission by // |request|, and the client should grant or deny that permission by
// calling |callback|. // calling |callback|.
virtual void RequestMediaAccessPermission(const MediaStreamRequest& request, virtual void RequestMediaAccessPermission(
MediaResponseCallback callback); RenderFrameHostImpl* render_frame_host,
const MediaStreamRequest& request,
MediaResponseCallback callback);
// Called when a renderer requests to select an audio output device. // Called when a renderer requests to select an audio output device.
// |request| contains parameters for audio output device selection. // |request| contains parameters for audio output device selection.

@ -5385,6 +5385,7 @@ void WebContentsImpl::CreateMediaPlayerHostForRenderFrameHost(
} }
void WebContentsImpl::RequestMediaAccessPermission( void WebContentsImpl::RequestMediaAccessPermission(
RenderFrameHostImpl* render_frame_host,
const MediaStreamRequest& request, const MediaStreamRequest& request,
MediaResponseCallback callback) { MediaResponseCallback callback) {
OPTIONAL_TRACE_EVENT2("content", OPTIONAL_TRACE_EVENT2("content",
@ -5392,14 +5393,22 @@ void WebContentsImpl::RequestMediaAccessPermission(
"render_process_id", request.render_process_id, "render_process_id", request.render_process_id,
"render_frame_id", request.render_frame_id); "render_frame_id", request.render_frame_id);
if (delegate_) { if (GuestPageHolderImpl* guest =
render_frame_host
? GuestPageHolderImpl::FromRenderFrameHost(*render_frame_host)
: nullptr) {
if (auto* delegate = guest->delegate()) {
delegate->GuestRequestMediaAccessPermission(request, std::move(callback));
return;
}
} else if (delegate_) {
delegate_->RequestMediaAccessPermission(this, request, std::move(callback)); delegate_->RequestMediaAccessPermission(this, request, std::move(callback));
} else { return;
std::move(callback).Run(
blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN,
std::unique_ptr<MediaStreamUI>());
} }
std::move(callback).Run(
blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN,
std::unique_ptr<MediaStreamUI>());
} }
void WebContentsImpl::ProcessSelectAudioOutput( void WebContentsImpl::ProcessSelectAudioOutput(
@ -5426,6 +5435,15 @@ bool WebContentsImpl::CheckMediaAccessPermission(
DCHECK(type == blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE || DCHECK(type == blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE ||
type == blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); type == blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE);
if (auto* guest =
GuestPageHolderImpl::FromRenderFrameHost(*render_frame_host)) {
if (auto* delegate = guest->delegate()) {
return delegate->GuestCheckMediaAccessPermission(render_frame_host,
security_origin, type);
}
return false;
}
return delegate_ && delegate_->CheckMediaAccessPermission( return delegate_ && delegate_->CheckMediaAccessPermission(
render_frame_host, security_origin, type); render_frame_host, security_origin, type);
} }

@ -959,7 +959,8 @@ class CONTENT_EXPORT WebContentsImpl
RenderFrameHostImpl* frame_host, RenderFrameHostImpl* frame_host,
mojo::PendingAssociatedReceiver<media::mojom::MediaPlayerHost> receiver) mojo::PendingAssociatedReceiver<media::mojom::MediaPlayerHost> receiver)
override; override;
void RequestMediaAccessPermission(const MediaStreamRequest& request, void RequestMediaAccessPermission(RenderFrameHostImpl* render_frame_host,
const MediaStreamRequest& request,
MediaResponseCallback callback) override; MediaResponseCallback callback) override;
void ProcessSelectAudioOutput(const SelectAudioOutputRequest& request, void ProcessSelectAudioOutput(const SelectAudioOutputRequest& request,

@ -3383,7 +3383,7 @@ TEST_F(WebContentsImplTest, RequestMediaAccessPermissionNoDelegate) {
/*captured_surface_control_active=*/false); /*captured_surface_control_active=*/false);
bool callback_run = false; bool callback_run = false;
contents()->RequestMediaAccessPermission( contents()->RequestMediaAccessPermission(
dummy_request, contents()->GetPrimaryMainFrame(), dummy_request,
base::BindLambdaForTesting( base::BindLambdaForTesting(
[&callback_run]( [&callback_run](
const blink::mojom::StreamDevicesSet& stream_devices_set, const blink::mojom::StreamDevicesSet& stream_devices_set,

@ -12,6 +12,7 @@
#include "base/process/kill.h" #include "base/process/kill.h"
#include "base/supports_user_data.h" #include "base/supports_user_data.h"
#include "content/common/content_export.h" #include "content/common/content_export.h"
#include "content/public/browser/media_stream_request.h"
#include "ui/base/window_open_disposition.h" #include "ui/base/window_open_disposition.h"
#include "url/gurl.h" #include "url/gurl.h"
@ -101,6 +102,19 @@ class GuestPageHolder : public base::SupportsUserData {
// Close the current window. // Close the current window.
virtual void GuestClose() = 0; virtual void GuestClose() = 0;
// Asks permission to use the camera and/or microphone.
// See `WebContentsDelegate::RequestMediaAccessPermission`
virtual void GuestRequestMediaAccessPermission(
const MediaStreamRequest& request,
MediaResponseCallback callback) = 0;
// Checks if we have permission to access the microphone or camera.
// See `WebContentsDelegate::CheckMediaAccessPermission`
virtual bool GuestCheckMediaAccessPermission(
RenderFrameHost* render_frame_host,
const url::Origin& security_origin,
blink::mojom::MediaStreamType type) = 0;
// TODO(40202416): Guest implementations need to be informed of several // TODO(40202416): Guest implementations need to be informed of several
// other events that they currently get through primary main frame specific // other events that they currently get through primary main frame specific
// WebContentsObserver methods (e.g. // WebContentsObserver methods (e.g.

@ -878,6 +878,31 @@ void WebViewGuest::GuestClose() {
std::make_unique<GuestViewEvent>(webview::kEventClose, std::move(args))); std::make_unique<GuestViewEvent>(webview::kEventClose, std::move(args)));
} }
void WebViewGuest::GuestRequestMediaAccessPermission(
const content::MediaStreamRequest& request,
content::MediaResponseCallback callback) {
if (IsOwnedByControlledFrameEmbedder()) {
web_view_permission_helper_->RequestMediaAccessPermissionForControlledFrame(
web_contents(), request, std::move(callback));
return;
}
web_view_permission_helper_->RequestMediaAccessPermission(
request, std::move(callback));
}
bool WebViewGuest::GuestCheckMediaAccessPermission(
content::RenderFrameHost* render_frame_host,
const url::Origin& security_origin,
blink::mojom::MediaStreamType type) {
if (IsOwnedByControlledFrameEmbedder()) {
return web_view_permission_helper_
->CheckMediaAccessPermissionForControlledFrame(render_frame_host,
security_origin, type);
}
return web_view_permission_helper_->CheckMediaAccessPermission(
render_frame_host, security_origin, type);
}
void WebViewGuest::CreateNewGuestWebViewWindow( void WebViewGuest::CreateNewGuestWebViewWindow(
const content::OpenURLParams& params) { const content::OpenURLParams& params) {
GuestViewManager* guest_manager = GuestViewManager* guest_manager =
@ -1493,13 +1518,7 @@ void WebViewGuest::RequestMediaAccessPermission(
content::MediaResponseCallback callback) { content::MediaResponseCallback callback) {
CHECK(!base::FeatureList::IsEnabled(features::kGuestViewMPArch)); CHECK(!base::FeatureList::IsEnabled(features::kGuestViewMPArch));
if (IsOwnedByControlledFrameEmbedder()) { GuestRequestMediaAccessPermission(request, std::move(callback));
web_view_permission_helper_->RequestMediaAccessPermissionForControlledFrame(
source, request, std::move(callback));
return;
}
web_view_permission_helper_->RequestMediaAccessPermission(
source, request, std::move(callback));
} }
bool WebViewGuest::CheckMediaAccessPermission( bool WebViewGuest::CheckMediaAccessPermission(
@ -1508,13 +1527,8 @@ bool WebViewGuest::CheckMediaAccessPermission(
blink::mojom::MediaStreamType type) { blink::mojom::MediaStreamType type) {
CHECK(!base::FeatureList::IsEnabled(features::kGuestViewMPArch)); CHECK(!base::FeatureList::IsEnabled(features::kGuestViewMPArch));
if (IsOwnedByControlledFrameEmbedder()) { return GuestCheckMediaAccessPermission(render_frame_host, security_origin,
return web_view_permission_helper_ type);
->CheckMediaAccessPermissionForControlledFrame(render_frame_host,
security_origin, type);
}
return web_view_permission_helper_->CheckMediaAccessPermission(
render_frame_host, security_origin, type);
} }
void WebViewGuest::CanDownload(const GURL& url, void WebViewGuest::CanDownload(const GURL& url,

@ -236,6 +236,13 @@ class WebViewGuest : public guest_view::GuestView<WebViewGuest> {
base::OnceCallback<void(content::NavigationHandle&)> base::OnceCallback<void(content::NavigationHandle&)>
navigation_handle_callback) final; navigation_handle_callback) final;
void GuestClose() final; void GuestClose() final;
void GuestRequestMediaAccessPermission(
const content::MediaStreamRequest& request,
content::MediaResponseCallback callback) final;
bool GuestCheckMediaAccessPermission(
content::RenderFrameHost* render_frame_host,
const url::Origin& security_origin,
blink::mojom::MediaStreamType type) final;
// GuestpageHolder::Delegate implementation. // GuestpageHolder::Delegate implementation.
bool GuestHandleContextMenu(content::RenderFrameHost& render_frame_host, bool GuestHandleContextMenu(content::RenderFrameHost& render_frame_host,

@ -189,7 +189,6 @@ WebViewPermissionHelper* WebViewPermissionHelper::FromRenderFrameHostId(
} }
void WebViewPermissionHelper::RequestMediaAccessPermission( void WebViewPermissionHelper::RequestMediaAccessPermission(
content::WebContents* source,
const content::MediaStreamRequest& request, const content::MediaStreamRequest& request,
content::MediaResponseCallback callback) { content::MediaResponseCallback callback) {
base::Value::Dict request_info; base::Value::Dict request_info;

@ -68,8 +68,7 @@ class WebViewPermissionHelper {
static WebViewPermissionHelper* FromRenderFrameHostId( static WebViewPermissionHelper* FromRenderFrameHostId(
const content::GlobalRenderFrameHostId& render_frame_host_id); const content::GlobalRenderFrameHostId& render_frame_host_id);
void RequestMediaAccessPermission(content::WebContents* source, void RequestMediaAccessPermission(const content::MediaStreamRequest& request,
const content::MediaStreamRequest& request,
content::MediaResponseCallback callback); content::MediaResponseCallback callback);
void RequestMediaAccessPermissionForControlledFrame( void RequestMediaAccessPermissionForControlledFrame(