0

[MSC] Porting GenerateStreams clients to handle stream vectors.

The getDisplayMedia implementation currently only handles single
streams. This CL ports several GenerateStreams clients to handle
multiple streams.

Bug: 1300883
Change-Id: I764cb74b9a6fd66929ee7ebc741800968d0be503
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3560567
Reviewed-by: Sergey Ulanov <sergeyu@chromium.org>
Reviewed-by: Henrik Boström <hbos@chromium.org>
Reviewed-by: Sean Topping <seantopping@chromium.org>
Reviewed-by: Evan Stade <estade@chromium.org>
Reviewed-by: Finnur Thorarinsson <finnur@chromium.org>
Reviewed-by: Michael Bai <michaelbai@chromium.org>
Reviewed-by: Alex Moshchuk <alexmos@chromium.org>
Reviewed-by: Vasilii Sukhanov <vasilii@chromium.org>
Commit-Queue: Simon Hangl <simonha@google.com>
Reviewed-by: Elad Alon <eladalon@chromium.org>
Reviewed-by: Carlos Knippschild <carlosk@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1012407}
This commit is contained in:
Simon Hangl
2022-06-09 09:36:54 +00:00
committed by Chromium LUCI CQ
parent 0f379849f0
commit fd537997df
47 changed files with 746 additions and 373 deletions
android_webview/browser
chrome/browser
chromecast/browser
components
content
extensions/browser
fuchsia_web/webengine/browser
third_party/blink
common
public
common
renderer
modules
weblayer/browser

@@ -257,7 +257,7 @@ void AwWebContentsDelegate::RequestMediaAccessPermission(
AwContents* aw_contents = AwContents::FromWebContents(web_contents); AwContents* aw_contents = AwContents::FromWebContents(web_contents);
if (!aw_contents) { if (!aw_contents) {
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN, blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN,
nullptr); nullptr);
return; return;

@@ -4,6 +4,7 @@
#include "android_webview/browser/permission/media_access_permission_request.h" #include "android_webview/browser/permission/media_access_permission_request.h"
#include <algorithm>
#include <utility> #include <utility>
#include "android_webview/browser/permission/aw_permission_request.h" #include "android_webview/browser/permission/aw_permission_request.h"
@@ -48,14 +49,18 @@ MediaAccessPermissionRequest::~MediaAccessPermissionRequest() {}
void MediaAccessPermissionRequest::NotifyRequestResult(bool allowed) { void MediaAccessPermissionRequest::NotifyRequestResult(bool allowed) {
std::unique_ptr<content::MediaStreamUI> ui; std::unique_ptr<content::MediaStreamUI> ui;
blink::mojom::StreamDevices devices;
if (!allowed) { if (!allowed) {
std::move(callback_).Run( std::move(callback_).Run(
devices, blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
std::move(ui)); std::move(ui));
return; return;
} }
blink::mojom::StreamDevicesSet stream_devices_set;
stream_devices_set.stream_devices.emplace_back(
blink::mojom::StreamDevices::New());
blink::mojom::StreamDevices& devices = *stream_devices_set.stream_devices[0];
if (request_.audio_type == if (request_.audio_type ==
blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) { blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) {
const MediaStreamDevices& audio_devices = const MediaStreamDevices& audio_devices =
@@ -79,11 +84,16 @@ void MediaAccessPermissionRequest::NotifyRequestResult(bool allowed) {
if (device) if (device)
devices.video_device = *device; devices.video_device = *device;
} }
const bool has_no_hardware =
!devices.audio_device.has_value() && !devices.video_device.has_value();
if (has_no_hardware) {
stream_devices_set.stream_devices.clear();
}
std::move(callback_).Run( std::move(callback_).Run(
devices, stream_devices_set,
(!devices.audio_device.has_value() && !devices.video_device.has_value()) has_no_hardware ? blink::mojom::MediaStreamRequestResult::NO_HARDWARE
? blink::mojom::MediaStreamRequestResult::NO_HARDWARE : blink::mojom::MediaStreamRequestResult::OK,
: blink::mojom::MediaStreamRequestResult::OK,
std::move(ui)); std::move(ui));
} }

@@ -80,10 +80,10 @@ class MediaAccessPermissionRequestTest : public testing::Test {
blink::mojom::MediaStreamRequestResult result_; blink::mojom::MediaStreamRequestResult result_;
private: private:
void Callback(const blink::mojom::StreamDevices& devices, void Callback(const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result, blink::mojom::MediaStreamRequestResult result,
std::unique_ptr<content::MediaStreamUI> ui) { std::unique_ptr<content::MediaStreamUI> ui) {
devices_ = blink::StreamDevicesToMediaStreamDevicesList(devices); devices_ = blink::ToMediaStreamDevicesList(stream_devices_set);
result_ = result; result_ = result;
} }
}; };

@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include "base/test/bind.h"
#include "chrome/browser/ash/policy/dlp/dlp_content_manager_ash.h" #include "chrome/browser/ash/policy/dlp/dlp_content_manager_ash.h"
#include <functional> #include <functional>
@@ -54,6 +55,7 @@
#include "content/public/test/browser_test.h" #include "content/public/test/browser_test.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-forward.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h" #include "third_party/blink/public/mojom/mediastream/media_stream.mojom-shared.h"
#include "ui/aura/window.h" #include "ui/aura/window.h"
#include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/rect.h"
@@ -874,23 +876,27 @@ class DlpContentManagerAshScreenShareBrowserTest
bool expect_warning) { bool expect_warning) {
// First check for the permission to start screen sharing. // First check for the permission to start screen sharing.
// It should call DlpContentManager::CheckScreenShareRestriction(). // It should call DlpContentManager::CheckScreenShareRestriction().
base::test::TestFuture<const blink::mojom::StreamDevices&, blink::mojom::MediaStreamRequestResult received_result =
blink::mojom::MediaStreamRequestResult, blink::mojom::MediaStreamRequestResult::NUM_MEDIA_REQUEST_RESULTS;
std::unique_ptr<content::MediaStreamUI>> base::RunLoop run_loop;
test_future;
handler->HandleRequest( handler->HandleRequest(
web_contents, request, web_contents, request,
test_future.GetCallback<const blink::mojom::StreamDevices&, base::BindLambdaForTesting(
blink::mojom::MediaStreamRequestResult, [&received_result, &run_loop](
std::unique_ptr<content::MediaStreamUI>>(), const blink::mojom::StreamDevicesSet&,
blink::mojom::MediaStreamRequestResult result,
std::unique_ptr<content::MediaStreamUI>) {
received_result = result;
run_loop.Quit();
}),
/*extension=*/nullptr); /*extension=*/nullptr);
if (expect_warning) if (expect_warning)
DismissDialog(expect_allowed); DismissDialog(expect_allowed);
ASSERT_TRUE(test_future.Wait()) << "MediaResponseCallback timed out."; run_loop.Run();
EXPECT_EQ( EXPECT_EQ(
test_future.Get<1>(), received_result,
(expect_allowed (expect_allowed
? blink::mojom::MediaStreamRequestResult::OK ? blink::mojom::MediaStreamRequestResult::OK
: blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED)); : blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED));

@@ -30,7 +30,12 @@ void MediaAccessHandler::CheckDevicesAndRunCallback(
bool get_default_audio_device = audio_allowed; bool get_default_audio_device = audio_allowed;
bool get_default_video_device = video_allowed; bool get_default_video_device = video_allowed;
blink::mojom::StreamDevices stream_devices; // TOOD(crbug.com/1300883): Generalize to multiple streams.
blink::mojom::StreamDevicesSet stream_devices_set;
stream_devices_set.stream_devices.emplace_back(
blink::mojom::StreamDevices::New());
blink::mojom::StreamDevices& stream_devices =
*stream_devices_set.stream_devices[0];
// Set an initial error result. If neither audio or video is allowed, we'll // Set an initial error result. If neither audio or video is allowed, we'll
// never try to get any device below but will just create |ui| and return an // never try to get any device below but will just create |ui| and return an
@@ -85,5 +90,10 @@ void MediaAccessHandler::CheckDevicesAndRunCallback(
->RegisterMediaStream(web_contents, stream_devices); ->RegisterMediaStream(web_contents, stream_devices);
} }
std::move(callback).Run(stream_devices, result, std::move(ui)); if (!stream_devices.audio_device.has_value() &&
!stream_devices.video_device.has_value()) {
stream_devices_set.stream_devices.clear();
}
std::move(callback).Run(stream_devices_set, result, std::move(ui));
} }

@@ -334,7 +334,7 @@ void OffscreenTab::RequestMediaAccessPermission(
WebContents* contents, WebContents* contents,
const content::MediaStreamRequest& request, const content::MediaStreamRequest& request,
content::MediaResponseCallback callback) { content::MediaResponseCallback callback) {
std::move(callback).Run(blink::mojom::StreamDevices(), std::move(callback).Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED,
nullptr); nullptr);
} }

@@ -253,7 +253,7 @@ void DesktopCaptureAccessHandler::ProcessScreenCaptureAccessRequest(
if (!screen_capture_enabled || !origin_is_secure) { if (!screen_capture_enabled || !origin_is_secure) {
std::move(pending_request->callback) std::move(pending_request->callback)
.Run(blink::mojom::StreamDevices(), .Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::INVALID_STATE, blink::mojom::MediaStreamRequestResult::INVALID_STATE,
/*ui=*/nullptr); /*ui=*/nullptr);
return; return;
@@ -262,7 +262,7 @@ void DesktopCaptureAccessHandler::ProcessScreenCaptureAccessRequest(
if (!IsRequestApproved(web_contents, pending_request->request, extension, if (!IsRequestApproved(web_contents, pending_request->request, extension,
pending_request->is_allowlisted_extension)) { pending_request->is_allowlisted_extension)) {
std::move(pending_request->callback) std::move(pending_request->callback)
.Run(blink::mojom::StreamDevices(), .Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
/*ui=*/nullptr); /*ui=*/nullptr);
return; return;
@@ -273,7 +273,7 @@ void DesktopCaptureAccessHandler::ProcessScreenCaptureAccessRequest(
pending_request->request.render_process_id, pending_request->request.render_process_id,
pending_request->request.render_frame_id))) { pending_request->request.render_frame_id))) {
std::move(pending_request->callback) std::move(pending_request->callback)
.Run(blink::mojom::StreamDevices(), .Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::INVALID_STATE, blink::mojom::MediaStreamRequestResult::INVALID_STATE,
/*ui=*/nullptr); /*ui=*/nullptr);
return; return;
@@ -351,7 +351,7 @@ void DesktopCaptureAccessHandler::HandleRequest(
if (request.video_type != if (request.video_type !=
blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE) { blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE) {
std::move(pending_request->callback) std::move(pending_request->callback)
.Run(blink::mojom::StreamDevices(), .Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::INVALID_STATE, blink::mojom::MediaStreamRequestResult::INVALID_STATE,
/*ui=*/nullptr); /*ui=*/nullptr);
return; return;
@@ -363,7 +363,7 @@ void DesktopCaptureAccessHandler::HandleRequest(
if (allowed_capture_level == AllowedScreenCaptureLevel::kDisallowed) { if (allowed_capture_level == AllowedScreenCaptureLevel::kDisallowed) {
std::move(pending_request->callback) std::move(pending_request->callback)
.Run(blink::mojom::StreamDevices(), .Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
/*ui=*/nullptr); /*ui=*/nullptr);
return; return;
@@ -379,7 +379,7 @@ void DesktopCaptureAccessHandler::HandleRequest(
if (request.requested_video_device_id.empty()) { if (request.requested_video_device_id.empty()) {
if (allowed_capture_level < AllowedScreenCaptureLevel::kDesktop) { if (allowed_capture_level < AllowedScreenCaptureLevel::kDesktop) {
std::move(pending_request->callback) std::move(pending_request->callback)
.Run(blink::mojom::StreamDevices(), .Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
/*ui=*/nullptr); /*ui=*/nullptr);
return; return;
@@ -388,7 +388,7 @@ void DesktopCaptureAccessHandler::HandleRequest(
if (system_media_permissions::CheckSystemScreenCapturePermission() != if (system_media_permissions::CheckSystemScreenCapturePermission() !=
system_media_permissions::SystemPermission::kAllowed) { system_media_permissions::SystemPermission::kAllowed) {
std::move(pending_request->callback) std::move(pending_request->callback)
.Run(blink::mojom::StreamDevices(), .Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::SYSTEM_PERMISSION_DENIED, blink::mojom::MediaStreamRequestResult::SYSTEM_PERMISSION_DENIED,
/*ui=*/nullptr); /*ui=*/nullptr);
return; return;
@@ -423,7 +423,7 @@ void DesktopCaptureAccessHandler::HandleRequest(
// Received invalid device id. // Received invalid device id.
if (media_id.type == content::DesktopMediaID::TYPE_NONE) { if (media_id.type == content::DesktopMediaID::TYPE_NONE) {
std::move(pending_request->callback) std::move(pending_request->callback)
.Run(blink::mojom::StreamDevices(), .Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::INVALID_STATE, blink::mojom::MediaStreamRequestResult::INVALID_STATE,
/*ui=*/nullptr); /*ui=*/nullptr);
return; return;
@@ -431,7 +431,7 @@ void DesktopCaptureAccessHandler::HandleRequest(
if (!IsMediaTypeAllowed(allowed_capture_level, media_id.type)) { if (!IsMediaTypeAllowed(allowed_capture_level, media_id.type)) {
std::move(pending_request->callback) std::move(pending_request->callback)
.Run(blink::mojom::StreamDevices(), .Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
/*ui=*/nullptr); /*ui=*/nullptr);
return; return;
@@ -441,7 +441,7 @@ void DesktopCaptureAccessHandler::HandleRequest(
system_media_permissions::CheckSystemScreenCapturePermission() != system_media_permissions::CheckSystemScreenCapturePermission() !=
system_media_permissions::SystemPermission::kAllowed) { system_media_permissions::SystemPermission::kAllowed) {
std::move(pending_request->callback) std::move(pending_request->callback)
.Run(blink::mojom::StreamDevices(), .Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::SYSTEM_PERMISSION_DENIED, blink::mojom::MediaStreamRequestResult::SYSTEM_PERMISSION_DENIED,
/*ui=*/nullptr); /*ui=*/nullptr);
return; return;
@@ -454,7 +454,7 @@ void DesktopCaptureAccessHandler::HandleRequest(
media_id.web_contents_id.render_process_id, media_id.web_contents_id.render_process_id,
media_id.web_contents_id.main_render_frame_id))) { media_id.web_contents_id.main_render_frame_id))) {
std::move(pending_request->callback) std::move(pending_request->callback)
.Run(blink::mojom::StreamDevices(), .Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::TAB_CAPTURE_FAILURE, blink::mojom::MediaStreamRequestResult::TAB_CAPTURE_FAILURE,
/*ui=*/nullptr); /*ui=*/nullptr);
return; return;
@@ -489,7 +489,7 @@ void DesktopCaptureAccessHandler::ProcessChangeSourceRequest(
pending_request->picker = picker_factory_->CreatePicker(); pending_request->picker = picker_factory_->CreatePicker();
if (!pending_request->picker) { if (!pending_request->picker) {
std::move(pending_request->callback) std::move(pending_request->callback)
.Run(blink::mojom::StreamDevices(), .Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::INVALID_STATE, blink::mojom::MediaStreamRequestResult::INVALID_STATE,
/*ui=*/nullptr); /*ui=*/nullptr);
return; return;
@@ -614,7 +614,7 @@ void DesktopCaptureAccessHandler::OnPickerDialogResults(
if (media_id.is_null()) { if (media_id.is_null()) {
std::move(pending_request->callback) std::move(pending_request->callback)
.Run(blink::mojom::StreamDevices(), .Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
/*ui=*/nullptr); /*ui=*/nullptr);
} else { } else {
@@ -670,19 +670,26 @@ void DesktopCaptureAccessHandler::AcceptRequest(
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(web_contents); DCHECK(web_contents);
blink::mojom::StreamDevices devices; // TODO(crbug.com/1300883): Generalize to multiple streams.
blink::mojom::StreamDevicesSet stream_devices_set;
stream_devices_set.stream_devices.emplace_back(
blink::mojom::StreamDevices::New());
blink::mojom::StreamDevices& stream_devices =
*stream_devices_set.stream_devices[0];
std::unique_ptr<content::MediaStreamUI> ui = GetDevicesForDesktopCapture( std::unique_ptr<content::MediaStreamUI> ui = GetDevicesForDesktopCapture(
pending_request->request, web_contents, media_id, capture_audio, pending_request->request, web_contents, media_id, capture_audio,
pending_request->request.disable_local_echo, pending_request->request.disable_local_echo,
pending_request->should_display_notification, pending_request->should_display_notification,
pending_request->application_title, devices); pending_request->application_title, stream_devices);
DCHECK(devices.audio_device.has_value() || devices.video_device.has_value()); DCHECK(stream_devices.audio_device.has_value() ||
stream_devices.video_device.has_value());
UpdateExtensionTrusted(pending_request->request, UpdateExtensionTrusted(pending_request->request,
pending_request->is_allowlisted_extension); pending_request->is_allowlisted_extension);
std::move(pending_request->callback) std::move(pending_request->callback)
.Run(devices, blink::mojom::MediaStreamRequestResult::OK, std::move(ui)); .Run(stream_devices_set, blink::mojom::MediaStreamRequestResult::OK,
std::move(ui));
} }
#if BUILDFLAG(IS_CHROMEOS) #if BUILDFLAG(IS_CHROMEOS)
@@ -702,7 +709,7 @@ void DesktopCaptureAccessHandler::OnDlpRestrictionChecked(
if (!is_dlp_allowed) { if (!is_dlp_allowed) {
std::move(pending_request->callback) std::move(pending_request->callback)
.Run(blink::mojom::StreamDevices(), .Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
/*ui=*/nullptr); /*ui=*/nullptr);
return; return;

@@ -86,11 +86,17 @@ class DesktopCaptureAccessHandlerTest : public ChromeRenderViewHostTestHarness {
[](base::RunLoop* wait_loop, bool expect_result, [](base::RunLoop* wait_loop, bool expect_result,
blink::mojom::MediaStreamRequestResult* request_result, blink::mojom::MediaStreamRequestResult* request_result,
blink::mojom::StreamDevices* devices_result, blink::mojom::StreamDevices* devices_result,
const blink::mojom::StreamDevices& devices, const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result, blink::mojom::MediaStreamRequestResult result,
std::unique_ptr<content::MediaStreamUI> ui) { std::unique_ptr<content::MediaStreamUI> ui) {
*request_result = result; *request_result = result;
*devices_result = devices; if (result == blink::mojom::MediaStreamRequestResult::OK) {
ASSERT_EQ(stream_devices_set.stream_devices.size(), 1u);
*devices_result = *stream_devices_set.stream_devices[0];
} else {
ASSERT_TRUE(stream_devices_set.stream_devices.empty());
*devices_result = blink::mojom::StreamDevices();
}
EXPECT_TRUE(expect_result) << "MediaResponseCallback should not be " EXPECT_TRUE(expect_result) << "MediaResponseCallback should not be "
"called when expect_result is false."; "called when expect_result is false.";
wait_loop->Quit(); wait_loop->Quit();
@@ -131,12 +137,16 @@ class DesktopCaptureAccessHandlerTest : public ChromeRenderViewHostTestHarness {
content::MediaResponseCallback callback = base::BindOnce( content::MediaResponseCallback callback = base::BindOnce(
[](base::RunLoop* wait_loop, [](base::RunLoop* wait_loop,
blink::mojom::MediaStreamRequestResult* request_result, blink::mojom::MediaStreamRequestResult* request_result,
blink::mojom::StreamDevices* stream_devices_result, blink::mojom::StreamDevices* devices_result,
const blink::mojom::StreamDevices& devices, const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result, blink::mojom::MediaStreamRequestResult result,
std::unique_ptr<content::MediaStreamUI> ui) { std::unique_ptr<content::MediaStreamUI> ui) {
*request_result = result; *request_result = result;
*stream_devices_result = devices; if (!stream_devices_set.stream_devices.empty()) {
*devices_result = *stream_devices_set.stream_devices[0];
} else {
*devices_result = blink::mojom::StreamDevices();
}
wait_loop->Quit(); wait_loop->Quit();
}, },
&wait_loop, request_result, stream_devices_result); &wait_loop, request_result, stream_devices_result);
@@ -306,12 +316,12 @@ TEST_F(DesktopCaptureAccessHandlerTest, ChangeSourceMultipleRequests) {
[](base::RunLoop* wait_loop, [](base::RunLoop* wait_loop,
blink::mojom::MediaStreamRequestResult* request_result, blink::mojom::MediaStreamRequestResult* request_result,
blink::MediaStreamDevices* devices_result, blink::MediaStreamDevices* devices_result,
const blink::mojom::StreamDevices& devices, const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result, blink::mojom::MediaStreamRequestResult result,
std::unique_ptr<content::MediaStreamUI> ui) { std::unique_ptr<content::MediaStreamUI> ui) {
ASSERT_EQ(stream_devices_set.stream_devices.size(), 1u);
*request_result = result; *request_result = result;
*devices_result = *devices_result = blink::ToMediaStreamDevicesList(stream_devices_set);
blink::StreamDevicesToMediaStreamDevicesList(devices);
wait_loop->Quit(); wait_loop->Quit();
}, },
&loop, &result, &devices); &loop, &result, &devices);

@@ -101,7 +101,7 @@ void DisplayMediaAccessHandler::HandleRequest(
web_contents) == web_contents) ==
AllowedScreenCaptureLevel::kDisallowed) { AllowedScreenCaptureLevel::kDisallowed) {
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
/*ui=*/nullptr); /*ui=*/nullptr);
return; return;
@@ -116,7 +116,7 @@ void DisplayMediaAccessHandler::HandleRequest(
web_contents); web_contents);
if (observer) { if (observer) {
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
/*ui=*/nullptr); /*ui=*/nullptr);
observer->OnDesktopCaptureRequest(); observer->OnDesktopCaptureRequest();
@@ -133,7 +133,7 @@ void DisplayMediaAccessHandler::HandleRequest(
request.request_type != blink::MEDIA_DEVICE_UPDATE) { request.request_type != blink::MEDIA_DEVICE_UPDATE) {
LOG(ERROR) << "Do not allow getDisplayMedia() on a backgrounded page."; LOG(ERROR) << "Do not allow getDisplayMedia() on a backgrounded page.";
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr); blink::mojom::MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr);
return; return;
} }
@@ -159,7 +159,7 @@ void DisplayMediaAccessHandler::HandleRequest(
request.render_process_id, request.render_frame_id); request.render_process_id, request.render_frame_id);
if (!rfh) { if (!rfh) {
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::INVALID_STATE, blink::mojom::MediaStreamRequestResult::INVALID_STATE,
/*ui=*/nullptr); /*ui=*/nullptr);
return; return;
@@ -179,7 +179,7 @@ void DisplayMediaAccessHandler::HandleRequest(
rfh->GetProcess(), bad_message::BadMessageReason:: rfh->GetProcess(), bad_message::BadMessageReason::
RFH_DISPLAY_CAPTURE_PERMISSION_MISSING); RFH_DISPLAY_CAPTURE_PERMISSION_MISSING);
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
/*ui=*/nullptr); /*ui=*/nullptr);
return; return;
@@ -190,7 +190,7 @@ void DisplayMediaAccessHandler::HandleRequest(
std::unique_ptr<DesktopMediaPicker> picker = picker_factory_->CreatePicker(); std::unique_ptr<DesktopMediaPicker> picker = picker_factory_->CreatePicker();
if (!picker) { if (!picker) {
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr); blink::mojom::MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr);
return; return;
} }
@@ -371,7 +371,7 @@ void DisplayMediaAccessHandler::RejectRequest(
return; return;
PendingAccessRequest& mutable_request = *mutable_queue.front(); PendingAccessRequest& mutable_request = *mutable_queue.front();
std::move(mutable_request.callback) std::move(mutable_request.callback)
.Run(blink::mojom::StreamDevices(), result, /*ui=*/nullptr); .Run(blink::mojom::StreamDevicesSet(), result, /*ui=*/nullptr);
mutable_queue.pop_front(); mutable_queue.pop_front();
if (!mutable_queue.empty()) if (!mutable_queue.empty())
ProcessQueuedAccessRequest(mutable_queue, web_contents); ProcessQueuedAccessRequest(mutable_queue, web_contents);
@@ -398,15 +398,20 @@ void DisplayMediaAccessHandler::AcceptRequest(
(media_id.type == content::DesktopMediaID::TYPE_WEB_CONTENTS) && (media_id.type == content::DesktopMediaID::TYPE_WEB_CONTENTS) &&
media_id.web_contents_id.disable_local_echo; media_id.web_contents_id.disable_local_echo;
blink::mojom::StreamDevices devices; blink::mojom::StreamDevicesSet stream_devices_set;
stream_devices_set.stream_devices.emplace_back(
blink::mojom::StreamDevices::New());
blink::mojom::StreamDevices& stream_devices =
*stream_devices_set.stream_devices[0];
std::unique_ptr<content::MediaStreamUI> ui = GetDevicesForDesktopCapture( std::unique_ptr<content::MediaStreamUI> ui = GetDevicesForDesktopCapture(
pending_request.request, web_contents, media_id, media_id.audio_share, pending_request.request, web_contents, media_id, media_id.audio_share,
disable_local_echo, display_notification_, disable_local_echo, display_notification_,
GetApplicationTitle(web_contents), devices); GetApplicationTitle(web_contents), stream_devices);
UpdateTarget(pending_request.request, media_id); UpdateTarget(pending_request.request, media_id);
std::move(pending_request.callback) std::move(pending_request.callback)
.Run(devices, blink::mojom::MediaStreamRequestResult::OK, std::move(ui)); .Run(stream_devices_set, blink::mojom::MediaStreamRequestResult::OK,
std::move(ui));
queue.pop_front(); queue.pop_front();
if (!queue.empty()) if (!queue.empty())

@@ -97,11 +97,17 @@ class DisplayMediaAccessHandlerTest : public ChromeRenderViewHostTestHarness {
[](base::RunLoop* wait_loop, [](base::RunLoop* wait_loop,
blink::mojom::MediaStreamRequestResult* request_result, blink::mojom::MediaStreamRequestResult* request_result,
blink::mojom::StreamDevices* devices_result, blink::mojom::StreamDevices* devices_result,
const blink::mojom::StreamDevices& devices, const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result, blink::mojom::MediaStreamRequestResult result,
std::unique_ptr<content::MediaStreamUI> ui) { std::unique_ptr<content::MediaStreamUI> ui) {
*request_result = result; *request_result = result;
*devices_result = devices; if (result == blink::mojom::MediaStreamRequestResult::OK) {
ASSERT_EQ(stream_devices_set.stream_devices.size(), 1u);
*devices_result = *stream_devices_set.stream_devices[0];
} else {
ASSERT_TRUE(stream_devices_set.stream_devices.empty());
*devices_result = blink::mojom::StreamDevices();
}
wait_loop->Quit(); wait_loop->Quit();
}, },
wait_loop, request_result, &devices_result); wait_loop, request_result, &devices_result);
@@ -508,12 +514,17 @@ TEST_F(DisplayMediaAccessHandlerTest, MultipleRequests) {
[](base::RunLoop* wait_loop, [](base::RunLoop* wait_loop,
blink::mojom::MediaStreamRequestResult* request_result, blink::mojom::MediaStreamRequestResult* request_result,
blink::MediaStreamDevices* devices_result, blink::MediaStreamDevices* devices_result,
const blink::mojom::StreamDevices& devices, const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result, blink::mojom::MediaStreamRequestResult result,
std::unique_ptr<content::MediaStreamUI> ui) { std::unique_ptr<content::MediaStreamUI> ui) {
*request_result = result; *request_result = result;
*devices_result = if (result == blink::mojom::MediaStreamRequestResult::OK) {
blink::StreamDevicesToMediaStreamDevicesList(devices); ASSERT_EQ(stream_devices_set.stream_devices.size(), 1u);
*devices_result =
blink::ToMediaStreamDevicesList(stream_devices_set);
} else {
ASSERT_TRUE(stream_devices_set.stream_devices.empty());
}
wait_loop->Quit(); wait_loop->Quit();
}, },
&wait_loop[i], &result, &devices); &wait_loop[i], &result, &devices);

@@ -150,7 +150,7 @@ void MediaCaptureDevicesDispatcher::ProcessMediaAccessRequest(
blink::mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE && blink::mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE &&
!base::FeatureList::IsEnabled(features::kUserMediaScreenCapturing)) { !base::FeatureList::IsEnabled(features::kUserMediaScreenCapturing)) {
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, nullptr); blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, nullptr);
return; return;
} }
@@ -166,7 +166,7 @@ void MediaCaptureDevicesDispatcher::ProcessMediaAccessRequest(
return; return;
} }
} }
std::move(callback).Run(blink::mojom::StreamDevices(), std::move(callback).Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED,
nullptr); nullptr);
} }

@@ -40,6 +40,7 @@
#include "content/public/test/mock_render_process_host.h" #include "content/public/test/mock_render_process_host.h"
#include "extensions/common/constants.h" #include "extensions/common/constants.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/mediastream/media_stream_request.h"
#include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h" #include "third_party/blink/public/mojom/mediastream/media_stream.mojom.h"
using content_settings::PageSpecificContentSettings; using content_settings::PageSpecificContentSettings;
@@ -53,11 +54,12 @@ class MediaStreamDevicesControllerTest : public WebRtcTestBase {
blink::mojom::MediaStreamRequestResult::NUM_MEDIA_REQUEST_RESULTS) { blink::mojom::MediaStreamRequestResult::NUM_MEDIA_REQUEST_RESULTS) {
} }
void OnMediaStreamResponse(const blink::mojom::StreamDevices& devices, void OnMediaStreamResponse(
blink::mojom::MediaStreamRequestResult result, const blink::mojom::StreamDevicesSet& stream_devices_set,
std::unique_ptr<content::MediaStreamUI> ui) { blink::mojom::MediaStreamRequestResult result,
std::unique_ptr<content::MediaStreamUI> ui) {
blink::MediaStreamDevices devices_list = blink::MediaStreamDevices devices_list =
blink::StreamDevicesToMediaStreamDevicesList(devices); blink::ToMediaStreamDevicesList(stream_devices_set);
EXPECT_EQ(devices_list.empty(), !ui); EXPECT_EQ(devices_list.empty(), !ui);
media_stream_devices_ = devices_list; media_stream_devices_ = devices_list;
media_stream_result_ = result; media_stream_result_ = result;
@@ -960,14 +962,16 @@ IN_PROC_BROWSER_TEST_F(MediaStreamDevicesControllerTest,
permission_bubble_media_access_handler_->HandleRequest( permission_bubble_media_access_handler_->HandleRequest(
prompt_contents, prompt_contents,
CreateRequest(example_audio_id(), example_video_id(), false), CreateRequest(example_audio_id(), example_video_id(), false),
base::BindOnce([](const blink::mojom::StreamDevices& devices, base::BindOnce(
blink::mojom::MediaStreamRequestResult result, [](const blink::mojom::StreamDevicesSet& stream_devices_set,
std::unique_ptr<content::MediaStreamUI> ui) { blink::mojom::MediaStreamRequestResult result,
// The permission may be dismissed before we have a chance to delete the std::unique_ptr<content::MediaStreamUI> ui) {
// request. // The permission may be dismissed before we have a chance to delete
EXPECT_EQ(blink::mojom::MediaStreamRequestResult::PERMISSION_DISMISSED, // the request.
result); EXPECT_EQ(
}), blink::mojom::MediaStreamRequestResult::PERMISSION_DISMISSED,
result);
}),
nullptr); nullptr);
// Since the mock prompt factory holds a reference to the // Since the mock prompt factory holds a reference to the
// PermissionRequestManager for the WebContents and uses that reference in its // PermissionRequestManager for the WebContents and uses that reference in its

@@ -54,7 +54,7 @@
using content::BrowserThread; using content::BrowserThread;
using MediaResponseCallback = using MediaResponseCallback =
base::OnceCallback<void(const blink::mojom::StreamDevices& devices, base::OnceCallback<void(const blink::mojom::StreamDevicesSet& devices,
blink::mojom::MediaStreamRequestResult result, blink::mojom::MediaStreamRequestResult result,
std::unique_ptr<content::MediaStreamUI> ui)>; std::unique_ptr<content::MediaStreamUI> ui)>;
@@ -214,7 +214,7 @@ void PermissionBubbleMediaAccessHandler::HandleRequest(
// If screen capturing isn't enabled on Android, we'll use "invalid state" // If screen capturing isn't enabled on Android, we'll use "invalid state"
// as result, same as on desktop. // as result, same as on desktop.
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::INVALID_STATE, nullptr); blink::mojom::MediaStreamRequestResult::INVALID_STATE, nullptr);
return; return;
} }
@@ -310,7 +310,7 @@ void PermissionBubbleMediaAccessHandler::OnMediaStreamRequestResponse(
content::WebContents* web_contents, content::WebContents* web_contents,
int64_t request_id, int64_t request_id,
content::MediaStreamRequest request, content::MediaStreamRequest request,
const blink::mojom::StreamDevices& devices, const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result, blink::mojom::MediaStreamRequestResult result,
bool blocked_by_permissions_policy, bool blocked_by_permissions_policy,
ContentSetting audio_setting, ContentSetting audio_setting,
@@ -328,20 +328,40 @@ void PermissionBubbleMediaAccessHandler::OnMediaStreamRequestResponse(
video_setting); video_setting);
} }
// At most one stream is expected as this function is not used with the
// getDisplayMediaSet API (only used with getUserMedia).
DCHECK_LE(stream_devices_set.stream_devices.size(), 1u);
blink::mojom::StreamDevices devices;
if (!stream_devices_set.stream_devices.empty()) {
devices = *stream_devices_set.stream_devices[0];
}
std::unique_ptr<content::MediaStreamUI> ui; std::unique_ptr<content::MediaStreamUI> ui;
if (devices.audio_device.has_value() || devices.video_device.has_value()) { if (devices.audio_device.has_value() || devices.video_device.has_value()) {
ui = MediaCaptureDevicesDispatcher::GetInstance() ui = MediaCaptureDevicesDispatcher::GetInstance()
->GetMediaStreamCaptureIndicator() ->GetMediaStreamCaptureIndicator()
->RegisterMediaStream(web_contents, devices); ->RegisterMediaStream(web_contents, devices);
} }
OnAccessRequestResponse(web_contents, request_id, devices, result, OnAccessRequestResponse(web_contents, request_id, stream_devices_set, result,
std::move(ui));
}
void PermissionBubbleMediaAccessHandler::OnAccessRequestResponseForBinding(
content::WebContents* web_contents,
int64_t request_id,
blink::mojom::StreamDevicesSetPtr stream_devices_set,
blink::mojom::MediaStreamRequestResult result,
std::unique_ptr<content::MediaStreamUI> ui) {
DCHECK(stream_devices_set);
DCHECK(ui);
OnAccessRequestResponse(web_contents, request_id, *stream_devices_set, result,
std::move(ui)); std::move(ui));
} }
void PermissionBubbleMediaAccessHandler::OnAccessRequestResponse( void PermissionBubbleMediaAccessHandler::OnAccessRequestResponse(
content::WebContents* web_contents, content::WebContents* web_contents,
int64_t request_id, int64_t request_id,
const blink::mojom::StreamDevices& devices, const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result, blink::mojom::MediaStreamRequestResult result,
std::unique_ptr<content::MediaStreamUI> ui) { std::unique_ptr<content::MediaStreamUI> ui) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
@@ -379,10 +399,10 @@ void PermissionBubbleMediaAccessHandler::OnAccessRequestResponse(
// Using WeakPtr since callback can come at any time and we might be // Using WeakPtr since callback can come at any time and we might be
// destroyed. // destroyed.
system_media_permissions::RequestSystemAudioCapturePermisson( system_media_permissions::RequestSystemAudioCapturePermisson(
base::BindOnce( base::BindOnce(&PermissionBubbleMediaAccessHandler::
&PermissionBubbleMediaAccessHandler::OnAccessRequestResponse, OnAccessRequestResponseForBinding,
weak_factory_.GetWeakPtr(), web_contents, request_id, devices, weak_factory_.GetWeakPtr(), web_contents, request_id,
result, std::move(ui))); stream_devices_set.Clone(), result, std::move(ui)));
return; return;
} else if (system_audio_permission == SystemPermission::kRestricted || } else if (system_audio_permission == SystemPermission::kRestricted ||
system_audio_permission == SystemPermission::kDenied) { system_audio_permission == SystemPermission::kDenied) {
@@ -406,10 +426,10 @@ void PermissionBubbleMediaAccessHandler::OnAccessRequestResponse(
// Using WeakPtr since callback can come at any time and we might be // Using WeakPtr since callback can come at any time and we might be
// destroyed. // destroyed.
system_media_permissions::RequestSystemVideoCapturePermisson( system_media_permissions::RequestSystemVideoCapturePermisson(
base::BindOnce( base::BindOnce(&PermissionBubbleMediaAccessHandler::
&PermissionBubbleMediaAccessHandler::OnAccessRequestResponse, OnAccessRequestResponseForBinding,
weak_factory_.GetWeakPtr(), web_contents, request_id, devices, weak_factory_.GetWeakPtr(), web_contents, request_id,
result, std::move(ui))); stream_devices_set.Clone(), result, std::move(ui)));
return; return;
} else if (system_video_permission == SystemPermission::kRestricted || } else if (system_video_permission == SystemPermission::kRestricted ||
system_video_permission == SystemPermission::kDenied) { system_video_permission == SystemPermission::kDenied) {
@@ -439,7 +459,7 @@ void PermissionBubbleMediaAccessHandler::OnAccessRequestResponse(
base::Unretained(this), web_contents)); base::Unretained(this), web_contents));
} }
std::move(callback).Run(devices, final_result, std::move(ui)); std::move(callback).Run(stream_devices_set, final_result, std::move(ui));
} }
void PermissionBubbleMediaAccessHandler::WebContentsDestroyed( void PermissionBubbleMediaAccessHandler::WebContentsDestroyed(

@@ -60,16 +60,27 @@ class PermissionBubbleMediaAccessHandler
content::WebContents* web_contents, content::WebContents* web_contents,
int64_t request_id, int64_t request_id,
content::MediaStreamRequest request, content::MediaStreamRequest request,
const blink::mojom::StreamDevices& devices, const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result, blink::mojom::MediaStreamRequestResult result,
bool blocked_by_permissions_policy, bool blocked_by_permissions_policy,
ContentSetting audio_setting, ContentSetting audio_setting,
ContentSetting video_setting); ContentSetting video_setting);
void OnAccessRequestResponse(content::WebContents* web_contents, void OnAccessRequestResponse(
int64_t request_id, content::WebContents* web_contents,
const blink::mojom::StreamDevices& devices, int64_t request_id,
blink::mojom::MediaStreamRequestResult result, const blink::mojom::StreamDevicesSet& stream_devices_set,
std::unique_ptr<content::MediaStreamUI> ui); blink::mojom::MediaStreamRequestResult result,
std::unique_ptr<content::MediaStreamUI> ui);
// OnAccessRequestResponse cannot be used together with base::BindOnce as
// StreamDevicesSet& cannot be captured (neither copyable nor movable).
// This method uses StreamDevicesSetPtr (movable) and forwards the data
// to OnAccessRequestResponse when calling the callback.
void OnAccessRequestResponseForBinding(
content::WebContents* web_contents,
int64_t request_id,
blink::mojom::StreamDevicesSetPtr stream_devices_set,
blink::mojom::MediaStreamRequestResult result,
std::unique_ptr<content::MediaStreamUI> ui);
// WebContentsCollection::Observer: // WebContentsCollection::Observer:
void WebContentsDestroyed(content::WebContents* web_contents) override; void WebContentsDestroyed(content::WebContents* web_contents) override;

@@ -31,7 +31,12 @@ void GetScreenCapturePermissionAndroid(
? blink::mojom::MediaStreamRequestResult::OK ? blink::mojom::MediaStreamRequestResult::OK
: blink::mojom::MediaStreamRequestResult::INVALID_STATE; : blink::mojom::MediaStreamRequestResult::INVALID_STATE;
blink::mojom::StreamDevices devices; // TODO(crbug.com/1300883): Generalize to multiple streams.
blink::mojom::StreamDevicesSet stream_devices_set;
stream_devices_set.stream_devices.emplace_back(
blink::mojom::StreamDevices::New());
blink::mojom::StreamDevices& stream_devices =
*stream_devices_set.stream_devices[0];
std::unique_ptr<content::MediaStreamUI> ui; std::unique_ptr<content::MediaStreamUI> ui;
if (result == blink::mojom::MediaStreamRequestResult::OK) { if (result == blink::mojom::MediaStreamRequestResult::OK) {
if (request.video_type == if (request.video_type ==
@@ -40,20 +45,20 @@ void GetScreenCapturePermissionAndroid(
screen_id.type = content::DesktopMediaID::TYPE_WEB_CONTENTS; screen_id.type = content::DesktopMediaID::TYPE_WEB_CONTENTS;
screen_id.web_contents_id = content::WebContentsMediaCaptureId( screen_id.web_contents_id = content::WebContentsMediaCaptureId(
request.render_process_id, request.render_frame_id); request.render_process_id, request.render_frame_id);
devices.video_device = blink::MediaStreamDevice( stream_devices.video_device = blink::MediaStreamDevice(
request.video_type, screen_id.ToString(), "Current Tab"); request.video_type, screen_id.ToString(), "Current Tab");
} else { } else {
content::DesktopMediaID screen_id = content::DesktopMediaID( content::DesktopMediaID screen_id = content::DesktopMediaID(
content::DesktopMediaID::TYPE_SCREEN, webrtc::kFullDesktopScreenId); content::DesktopMediaID::TYPE_SCREEN, webrtc::kFullDesktopScreenId);
devices.video_device = blink::MediaStreamDevice( stream_devices.video_device = blink::MediaStreamDevice(
request.video_type, screen_id.ToString(), "Screen"); request.video_type, screen_id.ToString(), "Screen");
} }
ui = MediaCaptureDevicesDispatcher::GetInstance() ui = MediaCaptureDevicesDispatcher::GetInstance()
->GetMediaStreamCaptureIndicator() ->GetMediaStreamCaptureIndicator()
->RegisterMediaStream(web_contents, devices); ->RegisterMediaStream(web_contents, stream_devices);
} }
std::move(callback).Run(devices, result, std::move(ui)); std::move(callback).Run(stream_devices_set, result, std::move(ui));
} }
} // namespace screen_capture } // namespace screen_capture

@@ -128,7 +128,7 @@ void TabCaptureAccessHandler::HandleRequest(
if (!tab_capture_registry) { if (!tab_capture_registry) {
NOTREACHED(); NOTREACHED();
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr); blink::mojom::MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr);
return; return;
} }
@@ -146,7 +146,7 @@ void TabCaptureAccessHandler::HandleRequest(
request.render_frame_id)); request.render_frame_id));
if (!can_show_web_contents.Run(target_web_contents)) { if (!can_show_web_contents.Run(target_web_contents)) {
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
/*ui=*/nullptr); /*ui=*/nullptr);
return; return;
@@ -159,7 +159,7 @@ void TabCaptureAccessHandler::HandleRequest(
if (!tab_capture_registry->VerifyRequest( if (!tab_capture_registry->VerifyRequest(
request.render_process_id, request.render_frame_id, extension_id)) { request.render_process_id, request.render_frame_id, extension_id)) {
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr); blink::mojom::MediaStreamRequestResult::INVALID_STATE, /*ui=*/nullptr);
return; return;
} }
@@ -217,13 +217,20 @@ void TabCaptureAccessHandler::AcceptRequest(
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
DCHECK(web_contents); DCHECK(web_contents);
blink::mojom::StreamDevices devices; // TOOD(crbug.com/1300883): Generalize to multiple streams.
std::unique_ptr<content::MediaStreamUI> ui = blink::mojom::StreamDevicesSet stream_devices_set;
GetMediaStreamUI(request, web_contents, std::move(media_ui), devices); stream_devices_set.stream_devices.emplace_back(
DCHECK(devices.audio_device.has_value() || devices.video_device.has_value()); blink::mojom::StreamDevices::New());
blink::mojom::StreamDevices& stream_devices =
*stream_devices_set.stream_devices[0];
std::unique_ptr<content::MediaStreamUI> ui = GetMediaStreamUI(
request, web_contents, std::move(media_ui), stream_devices);
DCHECK(stream_devices.audio_device.has_value() ||
stream_devices.video_device.has_value());
UpdateExtensionTrusted(request, is_allowlisted_extension); UpdateExtensionTrusted(request, is_allowlisted_extension);
std::move(callback).Run(devices, blink::mojom::MediaStreamRequestResult::OK, std::move(callback).Run(stream_devices_set,
blink::mojom::MediaStreamRequestResult::OK,
std::move(ui)); std::move(ui));
} }
@@ -246,7 +253,7 @@ void TabCaptureAccessHandler::OnDlpRestrictionChecked(
std::move(media_ui)); std::move(media_ui));
} else { } else {
std::move(pending_request->callback) std::move(pending_request->callback)
.Run(blink::mojom::StreamDevices(), .Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
/*ui=*/nullptr); /*ui=*/nullptr);
} }

@@ -66,11 +66,19 @@ class TabCaptureAccessHandlerTest : public ChromeRenderViewHostTestHarness {
[](base::RunLoop* wait_loop, bool expect_result, [](base::RunLoop* wait_loop, bool expect_result,
blink::mojom::MediaStreamRequestResult* request_result, blink::mojom::MediaStreamRequestResult* request_result,
blink::mojom::StreamDevices* devices_result, blink::mojom::StreamDevices* devices_result,
const blink::mojom::StreamDevices& devices, const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result, blink::mojom::MediaStreamRequestResult result,
std::unique_ptr<content::MediaStreamUI> ui) { std::unique_ptr<content::MediaStreamUI> ui) {
DCHECK(!devices_result->audio_device);
DCHECK(!devices_result->video_device);
*request_result = result; *request_result = result;
*devices_result = devices; if (result == blink::mojom::MediaStreamRequestResult::OK) {
ASSERT_EQ(stream_devices_set.stream_devices.size(), 1u);
*devices_result = *stream_devices_set.stream_devices[0];
} else {
ASSERT_TRUE(stream_devices_set.stream_devices.empty());
*devices_result = blink::mojom::StreamDevices();
}
if (!expect_result) { if (!expect_result) {
FAIL() << "MediaResponseCallback should not be called."; FAIL() << "MediaResponseCallback should not be called.";
} }
@@ -212,4 +220,5 @@ TEST_F(TabCaptureAccessHandlerTest, DlpWebContentsDestroyed) {
EXPECT_FALSE(devices.video_device.has_value()); EXPECT_FALSE(devices.video_device.has_value());
EXPECT_FALSE(devices.audio_device.has_value()); EXPECT_FALSE(devices.audio_device.has_value());
} }
#endif // BUILDFLAG(IS_CHROMEOS) #endif // BUILDFLAG(IS_CHROMEOS)

@@ -108,22 +108,29 @@ class MediaStreamDevicesControllerBrowserTest
} }
} }
void Accept(const blink::mojom::StreamDevices& devices, void Accept(const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result, blink::mojom::MediaStreamRequestResult result,
bool blocked_by_permissions_policy, bool blocked_by_permissions_policy,
ContentSetting audio_setting, ContentSetting audio_setting,
ContentSetting video_setting) { ContentSetting video_setting) {
if (policy_value_ || request_url_allowed_via_allowlist_) { if (result == blink::mojom::MediaStreamRequestResult::OK) {
ASSERT_EQ(1, devices.audio_device.has_value() + ASSERT_EQ(stream_devices_set.stream_devices.size(), 1u);
devices.video_device.has_value()); const blink::mojom::StreamDevices& devices =
if (devices.audio_device.has_value()) { *stream_devices_set.stream_devices[0];
ASSERT_EQ("fake_dev", devices.audio_device.value().id); if (policy_value_ || request_url_allowed_via_allowlist_) {
} else if (devices.video_device.has_value()) { ASSERT_EQ(1, devices.audio_device.has_value() +
ASSERT_EQ("fake_dev", devices.video_device.value().id); devices.video_device.has_value());
if (devices.audio_device.has_value()) {
ASSERT_EQ("fake_dev", devices.audio_device.value().id);
} else if (devices.video_device.has_value()) {
ASSERT_EQ("fake_dev", devices.video_device.value().id);
}
} else {
ASSERT_FALSE(devices.audio_device.has_value());
ASSERT_FALSE(devices.video_device.has_value());
} }
} else { } else {
ASSERT_FALSE(devices.audio_device.has_value()); ASSERT_EQ(0u, stream_devices_set.stream_devices.size());
ASSERT_FALSE(devices.video_device.has_value());
} }
} }

@@ -136,7 +136,7 @@ void AshWebViewImpl::RequestMediaAccessPermission(
content::MediaResponseCallback callback) { content::MediaResponseCallback callback) {
if (!params_.can_record_media) { if (!params_.can_record_media) {
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED,
std::unique_ptr<content::MediaStreamUI>()); std::unique_ptr<content::MediaStreamUI>());
return; return;

@@ -245,7 +245,7 @@ void CastWebViewDefault::RequestMediaAccessPermission(
!params_->allow_media_access) { !params_->allow_media_access) {
LOG(WARNING) << __func__ << ": media access is disabled."; LOG(WARNING) << __func__ << ": media access is disabled.";
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED,
std::unique_ptr<content::MediaStreamUI>()); std::unique_ptr<content::MediaStreamUI>());
return; return;
@@ -258,7 +258,10 @@ void CastWebViewDefault::RequestMediaAccessPermission(
DVLOG(2) << __func__ << " audio_devices=" << audio_devices.size() DVLOG(2) << __func__ << " audio_devices=" << audio_devices.size()
<< " video_devices=" << video_devices.size(); << " video_devices=" << video_devices.size();
blink::mojom::StreamDevices devices; blink::mojom::StreamDevicesSet stream_devices_set;
stream_devices_set.stream_devices.emplace_back(
blink::mojom::StreamDevices::New());
blink::mojom::StreamDevices& devices = *stream_devices_set.stream_devices[0];
if (request.audio_type == if (request.audio_type ==
blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) { blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) {
const blink::MediaStreamDevice* device = GetRequestedDeviceOrDefault( const blink::MediaStreamDevice* device = GetRequestedDeviceOrDefault(
@@ -281,7 +284,8 @@ void CastWebViewDefault::RequestMediaAccessPermission(
} }
} }
std::move(callback).Run(devices, blink::mojom::MediaStreamRequestResult::OK, std::move(callback).Run(stream_devices_set,
blink::mojom::MediaStreamRequestResult::OK,
std::unique_ptr<content::MediaStreamUI>()); std::unique_ptr<content::MediaStreamUI>());
} }

@@ -116,7 +116,7 @@ void BackgroundLoaderContents::RequestMediaAccessPermission(
content::MediaResponseCallback callback) { content::MediaResponseCallback callback) {
// No permissions granted, act as if dismissed. // No permissions granted, act as if dismissed.
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::PERMISSION_DISMISSED, blink::mojom::MediaStreamRequestResult::PERMISSION_DISMISSED,
std::unique_ptr<content::MediaStreamUI>()); std::unique_ptr<content::MediaStreamUI>());
} }

@@ -37,9 +37,10 @@ class BackgroundLoaderContentsTest : public testing::Test,
bool download() { return download_; } bool download() { return download_; }
bool can_download_delegate_called() { return delegate_called_; } bool can_download_delegate_called() { return delegate_called_; }
void MediaAccessCallback(const blink::mojom::StreamDevices& devices, void MediaAccessCallback(
blink::mojom::MediaStreamRequestResult result, const blink::mojom::StreamDevicesSet& stream_devices_set,
std::unique_ptr<content::MediaStreamUI> ui); blink::mojom::MediaStreamRequestResult result,
std::unique_ptr<content::MediaStreamUI> ui);
blink::mojom::StreamDevices& devices() { return devices_; } blink::mojom::StreamDevices& devices() { return devices_; }
blink::mojom::MediaStreamRequestResult request_result() { blink::mojom::MediaStreamRequestResult request_result() {
return request_result_; return request_result_;
@@ -91,10 +92,15 @@ void BackgroundLoaderContentsTest::SetDelegate() {
} }
void BackgroundLoaderContentsTest::MediaAccessCallback( void BackgroundLoaderContentsTest::MediaAccessCallback(
const blink::mojom::StreamDevices& devices, const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result, blink::mojom::MediaStreamRequestResult result,
std::unique_ptr<content::MediaStreamUI> ui) { std::unique_ptr<content::MediaStreamUI> ui) {
devices_ = devices; if (result == blink::mojom::MediaStreamRequestResult::OK) {
ASSERT_FALSE(stream_devices_set.stream_devices.empty());
devices_ = *stream_devices_set.stream_devices[0];
} else {
ASSERT_TRUE(stream_devices_set.stream_devices.empty());
}
request_result_ = result; request_result_ = result;
media_stream_ui_.reset(ui.get()); media_stream_ui_.reset(ui.get());
waiter_.Signal(); waiter_.Signal();

@@ -63,7 +63,7 @@ void MediaStreamDevicesController::RequestPermissions(
// The RFH may have been destroyed by the time the request is processed. // The RFH may have been destroyed by the time the request is processed.
if (!rfh) { if (!rfh) {
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN, false, blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN, false,
{}, {}); {}, {});
return; return;
@@ -71,7 +71,7 @@ void MediaStreamDevicesController::RequestPermissions(
if (rfh->GetLastCommittedOrigin().GetURL().is_empty()) { if (rfh->GetLastCommittedOrigin().GetURL().is_empty()) {
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, false, {}, blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, false, {},
{}); {});
return; return;
@@ -79,7 +79,7 @@ void MediaStreamDevicesController::RequestPermissions(
if (rfh->GetLastCommittedOrigin().GetURL() != request.security_origin) { if (rfh->GetLastCommittedOrigin().GetURL() != request.security_origin) {
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::INVALID_SECURITY_ORIGIN, false, blink::mojom::MediaStreamRequestResult::INVALID_SECURITY_ORIGIN, false,
{}, {}); {}, {});
return; return;
@@ -166,7 +166,7 @@ void MediaStreamDevicesController::RequestPermissions(
MediaStreamDevicesController::~MediaStreamDevicesController() { MediaStreamDevicesController::~MediaStreamDevicesController() {
if (!callback_.is_null()) { if (!callback_.is_null()) {
std::move(callback_).Run( std::move(callback_).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN, false, blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN, false,
{}, {}); {}, {});
} }
@@ -202,16 +202,21 @@ bool MediaStreamDevicesController::ShouldRequestVideo() const {
return video_setting_ == CONTENT_SETTING_ASK; return video_setting_ == CONTENT_SETTING_ASK;
} }
blink::mojom::StreamDevices MediaStreamDevicesController::GetDevices( blink::mojom::StreamDevicesSetPtr MediaStreamDevicesController::GetDevices(
ContentSetting audio_setting, ContentSetting audio_setting,
ContentSetting video_setting) { ContentSetting video_setting) {
bool audio_allowed = audio_setting == CONTENT_SETTING_ALLOW; bool audio_allowed = audio_setting == CONTENT_SETTING_ALLOW;
bool video_allowed = video_setting == CONTENT_SETTING_ALLOW; bool video_allowed = video_setting == CONTENT_SETTING_ALLOW;
blink::mojom::StreamDevicesSetPtr stream_devices_set =
blink::mojom::StreamDevicesSet::New();
if (!audio_allowed && !video_allowed) if (!audio_allowed && !video_allowed)
return blink::mojom::StreamDevices(); return nullptr;
blink::mojom::StreamDevices devices; // TODO(crbug.com/1300883): Generalize to multiple streams.
stream_devices_set->stream_devices.emplace_back(
blink::mojom::StreamDevices::New());
blink::mojom::StreamDevices& devices = *stream_devices_set->stream_devices[0];
switch (request_.request_type) { switch (request_.request_type) {
case blink::MEDIA_OPEN_DEVICE_PEPPER_ONLY: { case blink::MEDIA_OPEN_DEVICE_PEPPER_ONLY: {
// For open device request, when requested device_id is empty, pick // For open device request, when requested device_id is empty, pick
@@ -303,14 +308,14 @@ blink::mojom::StreamDevices MediaStreamDevicesController::GetDevices(
} }
} // switch } // switch
return devices; return stream_devices_set;
} }
void MediaStreamDevicesController::RunCallback( void MediaStreamDevicesController::RunCallback(
bool blocked_by_permissions_policy) { bool blocked_by_permissions_policy) {
CHECK(callback_); CHECK(callback_);
blink::mojom::StreamDevices devices; blink::mojom::StreamDevicesSetPtr stream_devices_set;
// If all requested permissions are allowed then the callback should report // If all requested permissions are allowed then the callback should report
// success, otherwise we report |denial_reason_|. // success, otherwise we report |denial_reason_|.
blink::mojom::MediaStreamRequestResult request_result = blink::mojom::MediaStreamRequestResult request_result =
@@ -319,7 +324,14 @@ void MediaStreamDevicesController::RunCallback(
audio_setting_ == CONTENT_SETTING_DEFAULT) && audio_setting_ == CONTENT_SETTING_DEFAULT) &&
(video_setting_ == CONTENT_SETTING_ALLOW || (video_setting_ == CONTENT_SETTING_ALLOW ||
video_setting_ == CONTENT_SETTING_DEFAULT)) { video_setting_ == CONTENT_SETTING_DEFAULT)) {
devices = GetDevices(audio_setting_, video_setting_); stream_devices_set = GetDevices(audio_setting_, video_setting_);
DCHECK(!stream_devices_set ||
stream_devices_set->stream_devices.size() <= 1u);
blink::mojom::StreamDevices devices;
if (stream_devices_set && !stream_devices_set->stream_devices.empty()) {
devices = *stream_devices_set->stream_devices[0];
}
if (!devices.audio_device.has_value() && if (!devices.audio_device.has_value() &&
!devices.video_device.has_value()) { !devices.video_device.has_value()) {
// Even if all requested permissions are allowed, if there are no devices // Even if all requested permissions are allowed, if there are no devices
@@ -329,9 +341,10 @@ void MediaStreamDevicesController::RunCallback(
} else { } else {
DCHECK_NE(blink::mojom::MediaStreamRequestResult::OK, denial_reason_); DCHECK_NE(blink::mojom::MediaStreamRequestResult::OK, denial_reason_);
request_result = denial_reason_; request_result = denial_reason_;
stream_devices_set = blink::mojom::StreamDevicesSet::New();
} }
std::move(callback_).Run(devices, request_result, std::move(callback_).Run(*stream_devices_set, request_result,
blocked_by_permissions_policy, audio_setting_, blocked_by_permissions_policy, audio_setting_,
video_setting_); video_setting_);
} }

@@ -34,11 +34,12 @@ class MediaStreamDeviceEnumerator;
// renderer. // renderer.
class MediaStreamDevicesController { class MediaStreamDevicesController {
public: public:
typedef base::OnceCallback<void(const blink::mojom::StreamDevices& devices, typedef base::OnceCallback<void(
blink::mojom::MediaStreamRequestResult result, const blink::mojom::StreamDevicesSet& stream_devices_set,
bool blocked_by_permissions_policy, blink::mojom::MediaStreamRequestResult result,
ContentSetting audio_setting, bool blocked_by_permissions_policy,
ContentSetting video_setting)> ContentSetting audio_setting,
ContentSetting video_setting)>
ResultCallback; ResultCallback;
// Requests the mic/camera permissions described in |request|, using // Requests the mic/camera permissions described in |request|, using
@@ -74,8 +75,8 @@ class MediaStreamDevicesController {
// Returns a list of devices available for the request for the given // Returns a list of devices available for the request for the given
// audio/video permission settings. // audio/video permission settings.
blink::mojom::StreamDevices GetDevices(ContentSetting audio_setting, blink::mojom::StreamDevicesSetPtr GetDevices(ContentSetting audio_setting,
ContentSetting video_setting); ContentSetting video_setting);
// Runs |callback_| with the current audio/video permission settings. // Runs |callback_| with the current audio/video permission settings.
void RunCallback(bool blocked_by_permissions_policy); void RunCallback(bool blocked_by_permissions_policy);

@@ -253,10 +253,12 @@ void CaptureHandleManager::OnTabCaptureStopped(
void CaptureHandleManager::OnTabCaptureDevicesUpdated( void CaptureHandleManager::OnTabCaptureDevicesUpdated(
const std::string& label, const std::string& label,
const blink::mojom::StreamDevices& new_devices, blink::mojom::StreamDevicesSetPtr new_stream_devices_set,
GlobalRenderFrameHostId capturer, GlobalRenderFrameHostId capturer,
DeviceCaptureHandleChangeCallback handle_change_callback) { DeviceCaptureHandleChangeCallback handle_change_callback) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(new_stream_devices_set);
DCHECK_EQ(1u, new_stream_devices_set->stream_devices.size());
// Pause tracking of all old devices. // Pause tracking of all old devices.
for (auto& capture : captures_) { for (auto& capture : captures_) {
@@ -266,6 +268,8 @@ void CaptureHandleManager::OnTabCaptureDevicesUpdated(
} }
// Start tracking any new devices; resume tracking of changed devices. // Start tracking any new devices; resume tracking of changed devices.
const blink::mojom::StreamDevices& new_devices =
*new_stream_devices_set->stream_devices[0];
if (new_devices.audio_device.has_value()) { if (new_devices.audio_device.has_value()) {
OnTabCaptureStarted(label, new_devices.audio_device.value(), capturer, OnTabCaptureStarted(label, new_devices.audio_device.value(), capturer,
handle_change_callback); handle_change_callback);

@@ -50,7 +50,7 @@ class CONTENT_EXPORT CaptureHandleManager {
// then calling OnTabCaptureStarted() on all |new_devices|. // then calling OnTabCaptureStarted() on all |new_devices|.
void OnTabCaptureDevicesUpdated( void OnTabCaptureDevicesUpdated(
const std::string& label, const std::string& label,
const blink::mojom::StreamDevices& new_devices, blink::mojom::StreamDevicesSetPtr new_stream_devices,
GlobalRenderFrameHostId capturer, GlobalRenderFrameHostId capturer,
DeviceCaptureHandleChangeCallback handle_change_callback); DeviceCaptureHandleChangeCallback handle_change_callback);

@@ -70,11 +70,42 @@ constexpr int kProcessId = 5;
constexpr int kRenderId = 6; constexpr int kRenderId = 6;
constexpr int kRequesterId = 7; constexpr int kRequesterId = 7;
constexpr int kPageRequestId = 8; constexpr int kPageRequestId = 8;
constexpr const char* kRegularVideoDeviceId = "stub_device_0"; constexpr const char* kRegularVideoDeviceId1 = "stub_device_1";
constexpr const char* kRegularVideoDeviceId2 = "stub_device_2";
constexpr const char* kDepthVideoDeviceId = "stub_device_1 (depth)"; constexpr const char* kDepthVideoDeviceId = "stub_device_1 (depth)";
constexpr media::VideoCaptureApi kStubCaptureApi = constexpr media::VideoCaptureApi kStubCaptureApi =
media::VideoCaptureApi::LINUX_V4L2_SINGLE_PLANE; media::VideoCaptureApi::LINUX_V4L2_SINGLE_PLANE;
bool DoStreamDevicesHaveSameTypes(const blink::mojom::StreamDevices& lhs,
const blink::mojom::StreamDevices& rhs) {
return lhs.audio_device.has_value() == rhs.audio_device.has_value() &&
lhs.video_device.has_value() == rhs.video_device.has_value();
}
MATCHER_P(SameTypesAs,
expected_stream_devices_set_ref,
"Compares if two StreamDevices objects contain the same number and "
"type of MediaStreamDevice objects.") {
const blink::mojom::StreamDevicesSet& stream_devices_set = arg;
const blink::mojom::StreamDevicesSet& expected_stream_devices_set =
expected_stream_devices_set_ref.get();
if (stream_devices_set.stream_devices.size() !=
expected_stream_devices_set.stream_devices.size()) {
return false;
}
for (size_t i = 0; i < stream_devices_set.stream_devices.size(); ++i) {
if (!DoStreamDevicesHaveSameTypes(
*stream_devices_set.stream_devices[i],
*expected_stream_devices_set.stream_devices[i])) {
return false;
}
}
return true;
}
void AudioInputDevicesEnumerated(base::OnceClosure quit_closure, void AudioInputDevicesEnumerated(base::OnceClosure quit_closure,
media::AudioDeviceDescriptions* out, media::AudioDeviceDescriptions* out,
const MediaDeviceEnumeration& enumeration) { const MediaDeviceEnumeration& enumeration) {
@@ -99,10 +130,9 @@ class MockMediaStreamDispatcherHost
~MockMediaStreamDispatcherHost() override {} ~MockMediaStreamDispatcherHost() override {}
// A list of mock methods. // A list of mock methods.
MOCK_METHOD3(OnStreamGenerationSuccess, MOCK_METHOD2(OnStreamGenerationSuccess,
void(int request_id, void(int request_id,
int audio_array_size, const blink::mojom::StreamDevicesSet& stream_devices_set));
int video_array_size));
MOCK_METHOD2(OnStreamGenerationFailure, MOCK_METHOD2(OnStreamGenerationFailure,
void(int request_id, void(int request_id,
blink::mojom::MediaStreamRequestResult result)); blink::mojom::MediaStreamRequestResult result));
@@ -193,21 +223,7 @@ class MockMediaStreamDispatcherHost
return; return;
} }
DCHECK(stream_devices_set); OnStreamGenerationSuccess(request_id, *stream_devices_set);
size_t audio_devices_count = base::ranges::count_if(
stream_devices_set->stream_devices,
[](const blink::mojom::StreamDevicesPtr& devices) {
return devices->audio_device.has_value();
});
size_t video_devices_count = base::ranges::count_if(
stream_devices_set->stream_devices,
[](const blink::mojom::StreamDevicesPtr& devices) {
return devices->video_device.has_value();
});
OnStreamGenerationSuccess(request_id, audio_devices_count,
video_devices_count);
// Simulate the stream started event back to host for UI testing. // Simulate the stream started event back to host for UI testing.
OnStreamStarted(label); OnStreamStarted(label);
@@ -327,7 +343,7 @@ class MediaStreamDispatcherHostTest : public testing::Test {
} }
void SetUp() override { void SetUp() override {
stub_video_device_ids_.emplace_back(kRegularVideoDeviceId); stub_video_device_ids_.emplace_back(kRegularVideoDeviceId1);
stub_video_device_ids_.emplace_back(kDepthVideoDeviceId); stub_video_device_ids_.emplace_back(kDepthVideoDeviceId);
ON_CALL(*mock_video_capture_provider_, GetDeviceInfosAsync(_)) ON_CALL(*mock_video_capture_provider_, GetDeviceInfosAsync(_))
.WillByDefault(Invoke( .WillByDefault(Invoke(
@@ -380,31 +396,34 @@ class MediaStreamDispatcherHostTest : public testing::Test {
return fake_ui; return fake_ui;
} }
virtual void SetupFakeUI(bool expect_started) { virtual void SetupFakeUI(
bool expect_started,
const std::vector<std::pair<std::string, std::string>>&
devices_ids_to_select = {}) {
media_stream_manager_->UseFakeUIFactoryForTests( media_stream_manager_->UseFakeUIFactoryForTests(
base::BindRepeating(&MediaStreamDispatcherHostTest::CreateMockUI, base::BindRepeating(&MediaStreamDispatcherHostTest::CreateMockUI,
base::Unretained(this), expect_started)); base::Unretained(this), expect_started));
} }
void GenerateStreamAndWaitForResult(int page_request_id, void GenerateStreamAndWaitForResult(
const blink::StreamControls& controls) { int page_request_id,
const blink::StreamControls& controls,
const blink::mojom::StreamDevicesSet& expectation) {
base::RunLoop run_loop; base::RunLoop run_loop;
int expected_audio_array_size = EXPECT_CALL(*host_,
(controls.audio.requested && !audio_device_descriptions_.empty()) ? 1 OnStreamGenerationSuccess(page_request_id,
: 0; SameTypesAs(std::ref(expectation))));
int expected_video_array_size =
(controls.video.requested && !stub_video_device_ids_.empty()) ? 1 : 0;
EXPECT_CALL(*host_, OnStreamGenerationSuccess(page_request_id,
expected_audio_array_size,
expected_video_array_size));
host_->OnGenerateStreams(page_request_id, controls, run_loop.QuitClosure()); host_->OnGenerateStreams(page_request_id, controls, run_loop.QuitClosure());
run_loop.Run(); run_loop.Run();
EXPECT_FALSE(DoesContainRawIds(audio_device(/*stream_index=*/0u))); for (const blink::mojom::StreamDevicesPtr& stream_devices :
EXPECT_FALSE(DoesContainRawIds(video_device(/*stream_index=*/0u))); host_->stream_devices_set_->stream_devices) {
EXPECT_TRUE( EXPECT_FALSE(DoesContainRawIds(stream_devices->audio_device));
DoesEveryDeviceMapToRawId(audio_device(/*stream_index=*/0u), origin_)); EXPECT_FALSE(DoesContainRawIds(stream_devices->video_device));
EXPECT_TRUE( EXPECT_TRUE(
DoesEveryDeviceMapToRawId(video_device(/*stream_index=*/0u), origin_)); DoesEveryDeviceMapToRawId(stream_devices->audio_device, origin_));
EXPECT_TRUE(
DoesEveryDeviceMapToRawId(stream_devices->video_device, origin_));
}
} }
void GenerateStreamAndWaitForFailure( void GenerateStreamAndWaitForFailure(
@@ -526,10 +545,14 @@ class MediaStreamDispatcherHostTest : public testing::Test {
}; };
TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithVideoOnly) { TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithVideoOnly) {
stub_video_device_ids_.emplace_back(kRegularVideoDeviceId2);
blink::StreamControls controls(false, true); blink::StreamControls controls(false, true);
blink::mojom::StreamDevicesSet expectation;
expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New(
absl::nullopt, blink::MediaStreamDevice()));
SetupFakeUI(true); SetupFakeUI(true);
GenerateStreamAndWaitForResult(kPageRequestId, controls); GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation);
EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value());
EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value());
@@ -539,7 +562,11 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithAudioOnly) {
blink::StreamControls controls(true, false); blink::StreamControls controls(true, false);
SetupFakeUI(true); SetupFakeUI(true);
GenerateStreamAndWaitForResult(kPageRequestId, controls);
blink::mojom::StreamDevicesSet expectation;
expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New(
blink::MediaStreamDevice(), absl::nullopt));
GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation);
EXPECT_TRUE(audio_device(/*stream_index=*/0u).has_value()); EXPECT_TRUE(audio_device(/*stream_index=*/0u).has_value());
EXPECT_FALSE(video_device(/*stream_index=*/0u).has_value()); EXPECT_FALSE(video_device(/*stream_index=*/0u).has_value());
@@ -612,8 +639,11 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithNothing) {
TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithAudioAndVideo) { TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithAudioAndVideo) {
blink::StreamControls controls(true, true); blink::StreamControls controls(true, true);
blink::mojom::StreamDevicesSet expectation;
expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New(
blink::MediaStreamDevice(), blink::MediaStreamDevice()));
SetupFakeUI(true); SetupFakeUI(true);
GenerateStreamAndWaitForResult(kPageRequestId, controls); GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation);
EXPECT_TRUE(audio_device(/*stream_index=*/0u).has_value()); EXPECT_TRUE(audio_device(/*stream_index=*/0u).has_value());
EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value());
@@ -630,8 +660,11 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamWithDepthVideo) {
// See also MediaStreamManager::GenerateStream and other tests here. // See also MediaStreamManager::GenerateStream and other tests here.
controls.video.device_id = source_id; controls.video.device_id = source_id;
blink::mojom::StreamDevicesSet expectation;
expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New(
blink::MediaStreamDevice(), blink::MediaStreamDevice()));
SetupFakeUI(true); SetupFakeUI(true);
GenerateStreamAndWaitForResult(kPageRequestId, controls); GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation);
// We specified the generation and expect to get // We specified the generation and expect to get
// one audio and one depth video stream. // one audio and one depth video stream.
@@ -646,8 +679,11 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsFromSameRenderId) {
blink::StreamControls controls(false, true); blink::StreamControls controls(false, true);
// Generate first stream. // Generate first stream.
blink::mojom::StreamDevicesSet expectation;
expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New(
absl::nullopt, blink::MediaStreamDevice()));
SetupFakeUI(true); SetupFakeUI(true);
GenerateStreamAndWaitForResult(kPageRequestId, controls); GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation);
// Check the latest generated stream. // Check the latest generated stream.
EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value());
@@ -660,7 +696,7 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsFromSameRenderId) {
.session_id(); .session_id();
// Generate second stream. // Generate second stream.
GenerateStreamAndWaitForResult(kPageRequestId + 1, controls); GenerateStreamAndWaitForResult(kPageRequestId + 1, controls, expectation);
// Check the latest generated stream. // Check the latest generated stream.
EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value());
@@ -682,7 +718,10 @@ TEST_F(MediaStreamDispatcherHostTest,
blink::StreamControls controls(false, true); blink::StreamControls controls(false, true);
// Generate first stream. // Generate first stream.
GenerateStreamAndWaitForResult(kPageRequestId, controls); blink::mojom::StreamDevicesSet expectation;
expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New(
absl::nullopt, blink::MediaStreamDevice()));
GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation);
EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value());
EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value());
@@ -711,8 +750,11 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsDifferentRenderId) {
blink::StreamControls controls(false, true); blink::StreamControls controls(false, true);
// Generate first stream. // Generate first stream.
blink::mojom::StreamDevicesSet expectation;
expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New(
absl::nullopt, blink::MediaStreamDevice()));
SetupFakeUI(true); SetupFakeUI(true);
GenerateStreamAndWaitForResult(kPageRequestId, controls); GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation);
// Check the latest generated stream. // Check the latest generated stream.
EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value());
@@ -720,9 +762,7 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsDifferentRenderId) {
const std::string label1 = host_->label_; const std::string label1 = host_->label_;
const std::string device_id1 = video_device(/*stream_index=*/0u).value().id; const std::string device_id1 = video_device(/*stream_index=*/0u).value().id;
const base::UnguessableToken session_id1 = const base::UnguessableToken session_id1 =
host_->stream_devices_set_->stream_devices[0] video_device(/*stream_index=*/0u).value().session_id();
->video_device.value()
.session_id();
// Generate second stream from another render frame. // Generate second stream from another render frame.
host_ = std::make_unique<MockMediaStreamDispatcherHost>( host_ = std::make_unique<MockMediaStreamDispatcherHost>(
@@ -733,7 +773,7 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsDifferentRenderId) {
host_->SetMediaStreamDeviceObserverForTesting( host_->SetMediaStreamDeviceObserverForTesting(
host_->BindNewPipeAndPassRemote()); host_->BindNewPipeAndPassRemote());
GenerateStreamAndWaitForResult(kPageRequestId + 1, controls); GenerateStreamAndWaitForResult(kPageRequestId + 1, controls, expectation);
// Check the latest generated stream. // Check the latest generated stream.
EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value());
@@ -781,13 +821,21 @@ TEST_F(MediaStreamDispatcherHostTest, WebContentsNotFocusedInBackgroundPage) {
base::RunLoop run_loop; base::RunLoop run_loop;
host_->OnGenerateStreams(kPageRequestId, controls, run_loop.QuitClosure()); host_->OnGenerateStreams(kPageRequestId, controls, run_loop.QuitClosure());
int expected_audio_array_size = absl::optional<blink::MediaStreamDevice> expected_audio_device;
(controls.audio.requested && !audio_device_descriptions_.empty()) ? 1 : 0; if (controls.audio.requested && !audio_device_descriptions_.empty()) {
int expected_video_array_size = expected_audio_device = blink::MediaStreamDevice();
(controls.video.requested && !stub_video_device_ids_.empty()) ? 1 : 0; }
EXPECT_CALL(*host_, OnStreamGenerationSuccess(kPageRequestId,
expected_audio_array_size, absl::optional<blink::MediaStreamDevice> expected_video_device;
expected_video_array_size)) if (controls.video.requested && !stub_video_device_ids_.empty()) {
expected_video_device = blink::MediaStreamDevice();
}
blink::mojom::StreamDevicesSet expectation;
expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New(
expected_audio_device, expected_video_device));
EXPECT_CALL(*host_, OnStreamGenerationSuccess(
kPageRequestId, SameTypesAs(std::ref(expectation))))
.Times(1); .Times(1);
run_loop.Run(); run_loop.Run();
@@ -809,13 +857,21 @@ TEST_F(MediaStreamDispatcherHostTest, WebContentsFocused) {
host_->OnGenerateStreams(kPageRequestId, controls, run_loop.QuitClosure()); host_->OnGenerateStreams(kPageRequestId, controls, run_loop.QuitClosure());
run_loop.RunUntilIdle(); run_loop.RunUntilIdle();
int expected_audio_array_size = absl::optional<blink::MediaStreamDevice> expected_audio_device;
(controls.audio.requested && !audio_device_descriptions_.empty()) ? 1 : 0; if (controls.audio.requested && !audio_device_descriptions_.empty()) {
int expected_video_array_size = expected_audio_device = blink::MediaStreamDevice();
(controls.video.requested && !stub_video_device_ids_.empty()) ? 1 : 0; }
EXPECT_CALL(*host_, OnStreamGenerationSuccess(kPageRequestId,
expected_audio_array_size, absl::optional<blink::MediaStreamDevice> expected_video_device;
expected_video_array_size)) if (controls.video.requested && !stub_video_device_ids_.empty()) {
expected_video_device = blink::MediaStreamDevice();
}
blink::mojom::StreamDevicesSet expectation;
expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New(
expected_audio_device, expected_video_device));
EXPECT_CALL(*host_, OnStreamGenerationSuccess(
kPageRequestId, SameTypesAs(std::ref(expectation))))
.Times(1); .Times(1);
focus_ = true; focus_ = true;
@@ -836,13 +892,20 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithoutWaiting) {
blink::StreamControls controls(false, true); blink::StreamControls controls(false, true);
// Generate first stream. // Generate first stream.
blink::mojom::StreamDevicesSet expectation;
expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New(
absl::nullopt, blink::MediaStreamDevice()));
SetupFakeUI(true); SetupFakeUI(true);
{ {
InSequence s; InSequence s;
EXPECT_CALL(*host_, OnStreamGenerationSuccess(kPageRequestId, 0, 1)); EXPECT_CALL(*host_,
OnStreamGenerationSuccess(kPageRequestId,
SameTypesAs(std::ref(expectation))));
// Generate second stream. // Generate second stream.
EXPECT_CALL(*host_, OnStreamGenerationSuccess(kPageRequestId + 1, 0, 1)); EXPECT_CALL(*host_,
OnStreamGenerationSuccess(kPageRequestId + 1,
SameTypesAs(std::ref(expectation))));
} }
base::RunLoop run_loop1; base::RunLoop run_loop1;
base::RunLoop run_loop2; base::RunLoop run_loop2;
@@ -860,6 +923,10 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithSourceId) {
ASSERT_GE(audio_device_descriptions_.size(), 1u); ASSERT_GE(audio_device_descriptions_.size(), 1u);
ASSERT_GE(stub_video_device_ids_.size(), 1u); ASSERT_GE(stub_video_device_ids_.size(), 1u);
blink::mojom::StreamDevicesSet expectation;
expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New(
blink::MediaStreamDevice(), blink::MediaStreamDevice()));
media::AudioDeviceDescriptions::const_iterator audio_it = media::AudioDeviceDescriptions::const_iterator audio_it =
audio_device_descriptions_.begin(); audio_device_descriptions_.begin();
for (; audio_it != audio_device_descriptions_.end(); ++audio_it) { for (; audio_it != audio_device_descriptions_.end(); ++audio_it) {
@@ -870,7 +937,7 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithSourceId) {
controls.audio.device_id = source_id; controls.audio.device_id = source_id;
SetupFakeUI(true); SetupFakeUI(true);
GenerateStreamAndWaitForResult(kPageRequestId, controls); GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation);
EXPECT_EQ(audio_device(/*stream_index=*/0u).value().id, source_id); EXPECT_EQ(audio_device(/*stream_index=*/0u).value().id, source_id);
} }
@@ -881,7 +948,7 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsWithSourceId) {
blink::StreamControls controls(true, true); blink::StreamControls controls(true, true);
controls.video.device_id = source_id; controls.video.device_id = source_id;
GenerateStreamAndWaitForResult(kPageRequestId, controls); GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation);
EXPECT_EQ(video_device(/*stream_index=*/0u).value().id, source_id); EXPECT_EQ(video_device(/*stream_index=*/0u).value().id, source_id);
} }
} }
@@ -922,8 +989,12 @@ TEST_F(MediaStreamDispatcherHostTest, GenerateStreamsNoAvailableVideoDevice) {
TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStream) { TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStream) {
blink::StreamControls controls(false, true); blink::StreamControls controls(false, true);
blink::mojom::StreamDevicesSet expectation;
expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New(
absl::nullopt, blink::MediaStreamDevice()));
SetupFakeUI(true); SetupFakeUI(true);
GenerateStreamAndWaitForResult(kPageRequestId, controls); GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation);
std::string stream_request_label = host_->label_; std::string stream_request_label = host_->label_;
blink::MediaStreamDevice current_video_device = blink::MediaStreamDevice current_video_device =
@@ -951,8 +1022,11 @@ TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStream) {
TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStreamAndRestart) { TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStreamAndRestart) {
blink::StreamControls controls(true, true); blink::StreamControls controls(true, true);
blink::mojom::StreamDevicesSet expectation;
expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New(
blink::MediaStreamDevice(), blink::MediaStreamDevice()));
SetupFakeUI(true); SetupFakeUI(true);
GenerateStreamAndWaitForResult(kPageRequestId, controls); GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation);
std::string request_label1 = host_->label_; std::string request_label1 = host_->label_;
blink::MediaStreamDevice current_video_device = blink::MediaStreamDevice current_video_device =
@@ -968,7 +1042,7 @@ TEST_F(MediaStreamDispatcherHostTest, StopDeviceInStreamAndRestart) {
1u, 1u,
media_stream_manager_->GetDevicesOpenedByRequest(request_label1).size()); media_stream_manager_->GetDevicesOpenedByRequest(request_label1).size());
GenerateStreamAndWaitForResult(kPageRequestId, controls); GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation);
std::string request_label2 = host_->label_; std::string request_label2 = host_->label_;
blink::MediaStreamDevices request1_devices = blink::MediaStreamDevices request1_devices =
@@ -988,12 +1062,18 @@ TEST_F(MediaStreamDispatcherHostTest,
GenerateTwoStreamsAndStopDeviceWhileWaitingForSecondStream) { GenerateTwoStreamsAndStopDeviceWhileWaitingForSecondStream) {
blink::StreamControls controls(false, true); blink::StreamControls controls(false, true);
blink::mojom::StreamDevicesSet expectation;
expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New(
absl::nullopt, blink::MediaStreamDevice()));
SetupFakeUI(true); SetupFakeUI(true);
GenerateStreamAndWaitForResult(kPageRequestId, controls); GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation);
EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value());
// Generate a second stream. // Generate a second stream.
EXPECT_CALL(*host_, OnStreamGenerationSuccess(kPageRequestId + 1, 0, 1)); EXPECT_CALL(*host_,
OnStreamGenerationSuccess(kPageRequestId + 1,
SameTypesAs(std::ref(expectation))));
base::RunLoop run_loop1; base::RunLoop run_loop1;
host_->OnGenerateStreams(kPageRequestId + 1, controls, host_->OnGenerateStreams(kPageRequestId + 1, controls,
@@ -1029,12 +1109,16 @@ TEST_F(MediaStreamDispatcherHostTest, CancelPendingStreams) {
TEST_F(MediaStreamDispatcherHostTest, StopGeneratedStreams) { TEST_F(MediaStreamDispatcherHostTest, StopGeneratedStreams) {
blink::StreamControls controls(false, true); blink::StreamControls controls(false, true);
blink::mojom::StreamDevicesSet expectation;
expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New(
absl::nullopt, blink::MediaStreamDevice()));
SetupFakeUI(true); SetupFakeUI(true);
// Create first group of streams. // Create first group of streams.
size_t generated_streams = 3; size_t generated_streams = 3;
for (size_t i = 0; i < generated_streams; ++i) for (size_t i = 0; i < generated_streams; ++i)
GenerateStreamAndWaitForResult(kPageRequestId + i, controls); GenerateStreamAndWaitForResult(kPageRequestId + i, controls, expectation);
media_stream_manager_->CancelAllRequests(kProcessId, kRenderId, kRequesterId); media_stream_manager_->CancelAllRequests(kProcessId, kRenderId, kRequesterId);
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
@@ -1043,6 +1127,10 @@ TEST_F(MediaStreamDispatcherHostTest, StopGeneratedStreams) {
TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) { TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) {
blink::StreamControls controls(false, true); blink::StreamControls controls(false, true);
blink::mojom::StreamDevicesSet expectation;
expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New(
absl::nullopt, blink::MediaStreamDevice()));
base::OnceClosure close_callback; base::OnceClosure close_callback;
media_stream_manager_->UseFakeUIFactoryForTests(base::BindRepeating( media_stream_manager_->UseFakeUIFactoryForTests(base::BindRepeating(
[](base::OnceClosure* close_callback) { [](base::OnceClosure* close_callback) {
@@ -1055,7 +1143,7 @@ TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) {
}, },
&close_callback)); &close_callback));
GenerateStreamAndWaitForResult(kPageRequestId, controls); GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation);
EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value());
EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value());
@@ -1070,8 +1158,13 @@ TEST_F(MediaStreamDispatcherHostTest, CloseFromUI) {
// being unplugged. // being unplugged.
TEST_F(MediaStreamDispatcherHostTest, VideoDeviceUnplugged) { TEST_F(MediaStreamDispatcherHostTest, VideoDeviceUnplugged) {
blink::StreamControls controls(true, true); blink::StreamControls controls(true, true);
blink::mojom::StreamDevicesSet expectation;
expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New(
blink::MediaStreamDevice(), blink::MediaStreamDevice()));
SetupFakeUI(true); SetupFakeUI(true);
GenerateStreamAndWaitForResult(kPageRequestId, controls); GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation);
EXPECT_TRUE(audio_device(/*stream_index=*/0u).has_value()); EXPECT_TRUE(audio_device(/*stream_index=*/0u).has_value());
EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value());
@@ -1092,8 +1185,12 @@ TEST_F(MediaStreamDispatcherHostTest, Salt) {
SetupFakeUI(true); SetupFakeUI(true);
blink::StreamControls controls(false, true); blink::StreamControls controls(false, true);
blink::mojom::StreamDevicesSet expectation;
expectation.stream_devices.emplace_back(blink::mojom::StreamDevices::New(
absl::nullopt, blink::MediaStreamDevice()));
// Generate first stream. // Generate first stream.
GenerateStreamAndWaitForResult(kPageRequestId, controls); GenerateStreamAndWaitForResult(kPageRequestId, controls, expectation);
EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value()); EXPECT_FALSE(audio_device(/*stream_index=*/0u).has_value());
EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value()); EXPECT_TRUE(video_device(/*stream_index=*/0u).has_value());
const std::string label1 = host_->label_; const std::string label1 = host_->label_;

@@ -2119,7 +2119,7 @@ MediaStreamDevices MediaStreamManager::GetDevicesOpenedByRequest(
DeviceRequest* request = FindRequest(label); DeviceRequest* request = FindRequest(label);
if (!request) if (!request)
return MediaStreamDevices(); return MediaStreamDevices();
return blink::StreamDevicesToMediaStreamDevicesList(request->devices); return blink::ToMediaStreamDevicesList(request->devices);
} }
bool MediaStreamManager::FindExistingRequestedDevice( bool MediaStreamManager::FindExistingRequestedDevice(
@@ -2407,8 +2407,7 @@ void MediaStreamManager::FinalizeOpenDevice(const std::string& label,
if (request->open_device_cb) { if (request->open_device_cb) {
std::move(request->open_device_cb) std::move(request->open_device_cb)
.Run(true /* success */, label, .Run(true /* success */, label,
blink::StreamDevicesToMediaStreamDevicesList(request->devices) blink::ToMediaStreamDevicesList(request->devices).front());
.front());
} }
} }
@@ -2739,9 +2738,19 @@ void MediaStreamManager::AddLogMessageOnIOThread(const std::string& message) {
void MediaStreamManager::HandleAccessRequestResponse( void MediaStreamManager::HandleAccessRequestResponse(
const std::string& label, const std::string& label,
const media::AudioParameters& output_parameters, const media::AudioParameters& output_parameters,
const blink::mojom::StreamDevices& devices, const blink::mojom::StreamDevicesSet& devices_set,
MediaStreamRequestResult result) { MediaStreamRequestResult result) {
DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK((result == MediaStreamRequestResult::OK &&
devices_set.stream_devices.size() == 1u) ||
(result != MediaStreamRequestResult::OK &&
devices_set.stream_devices.empty()));
blink::mojom::StreamDevices devices;
if (result == MediaStreamRequestResult::OK) {
DCHECK_EQ(1u, devices_set.stream_devices.size());
devices = *devices_set.stream_devices[0];
}
DeviceRequest* request = FindRequest(label); DeviceRequest* request = FindRequest(label);
if (!request) { if (!request) {
// The request has been canceled before the UI returned. // The request has been canceled before the UI returned.
@@ -3251,8 +3260,7 @@ void MediaStreamManager::OnStreamStarted(const std::string& label) {
RequestTypeToString(request->request_type()))); RequestTypeToString(request->request_type())));
MediaStreamUI::SourceCallback device_changed_cb; MediaStreamUI::SourceCallback device_changed_cb;
if (EnableChangeSource( if (EnableChangeSource(blink::ToMediaStreamDevicesList(request->devices)) &&
blink::StreamDevicesToMediaStreamDevicesList(request->devices)) &&
base::FeatureList::IsEnabled(features::kDesktopCaptureChangeSource)) { base::FeatureList::IsEnabled(features::kDesktopCaptureChangeSource)) {
device_changed_cb = base::BindRepeating( device_changed_cb = base::BindRepeating(
&MediaStreamManager::ChangeMediaStreamSourceFromBrowser, &MediaStreamManager::ChangeMediaStreamSourceFromBrowser,
@@ -3573,7 +3581,12 @@ void MediaStreamManager::MaybeUpdateTrackedCaptureHandleConfigs(
GlobalRenderFrameHostId capturer) { GlobalRenderFrameHostId capturer) {
DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_CURRENTLY_ON(BrowserThread::IO);
blink::mojom::StreamDevices filtered_new_devices; blink::mojom::StreamDevicesSetPtr filtered_new_devices_set =
blink::mojom::StreamDevicesSet::New();
filtered_new_devices_set->stream_devices.emplace_back(
blink::mojom::StreamDevices::New());
blink::mojom::StreamDevices& filtered_new_devices =
*filtered_new_devices_set->stream_devices[0];
if (new_devices.video_device.has_value() && if (new_devices.video_device.has_value() &&
WebContentsMediaCaptureId::Parse(new_devices.video_device->id, nullptr)) { WebContentsMediaCaptureId::Parse(new_devices.video_device->id, nullptr)) {
filtered_new_devices.video_device = new_devices.video_device.value(); filtered_new_devices.video_device = new_devices.video_device.value();
@@ -3587,7 +3600,7 @@ void MediaStreamManager::MaybeUpdateTrackedCaptureHandleConfigs(
base::BindOnce( base::BindOnce(
&CaptureHandleManager::OnTabCaptureDevicesUpdated, &CaptureHandleManager::OnTabCaptureDevicesUpdated,
base::Unretained(&capture_handle_manager_), label, base::Unretained(&capture_handle_manager_), label,
std::move(filtered_new_devices), capturer, std::move(filtered_new_devices_set), capturer,
base::BindPostTask( base::BindPostTask(
GetIOThreadTaskRunner({}), GetIOThreadTaskRunner({}),
base::BindRepeating(&MediaStreamManager::OnCaptureHandleChange, base::BindRepeating(&MediaStreamManager::OnCaptureHandleChange,

@@ -459,7 +459,7 @@ class CONTENT_EXPORT MediaStreamManager
void HandleAccessRequestResponse( void HandleAccessRequestResponse(
const std::string& label, const std::string& label,
const media::AudioParameters& output_parameters, const media::AudioParameters& output_parameters,
const blink::mojom::StreamDevices& devices, const blink::mojom::StreamDevicesSet& devices_set,
blink::mojom::MediaStreamRequestResult result); blink::mojom::MediaStreamRequestResult result);
void HandleChangeSourceRequestResponse( void HandleChangeSourceRequestResponse(
const std::string& label, const std::string& label,

@@ -72,10 +72,19 @@ class MediaStreamUIProxy::Core {
bool is_from_timer); bool is_from_timer);
#endif #endif
// The type blink::mojom::StreamDevices is not movable, therefore stream
// devices cannot be captured for usage with PostTask.
void ProcessAccessRequestResponseForPostTask(
int render_process_id,
int render_frame_id,
blink::mojom::StreamDevicesSetPtr stream_devices_set_ptr,
blink::mojom::MediaStreamRequestResult result,
std::unique_ptr<MediaStreamUI> stream_ui);
void ProcessAccessRequestResponse( void ProcessAccessRequestResponse(
int render_process_id, int render_process_id,
int render_frame_id, int render_frame_id,
const blink::mojom::StreamDevices& devices, const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result, blink::mojom::MediaStreamRequestResult result,
std::unique_ptr<MediaStreamUI> stream_ui); std::unique_ptr<MediaStreamUI> stream_ui);
@@ -137,7 +146,7 @@ void MediaStreamUIProxy::Core::RequestAccess(
if (!render_delegate) { if (!render_delegate) {
ProcessAccessRequestResponse( ProcessAccessRequestResponse(
request->render_process_id, request->render_frame_id, request->render_process_id, request->render_frame_id,
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN, blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN,
std::unique_ptr<MediaStreamUI>()); std::unique_ptr<MediaStreamUI>());
return; return;
@@ -213,15 +222,40 @@ void MediaStreamUIProxy::Core::SetFocus(const DesktopMediaID& media_id,
} }
#endif #endif
void MediaStreamUIProxy::Core::ProcessAccessRequestResponse( void MediaStreamUIProxy::Core::ProcessAccessRequestResponseForPostTask(
int render_process_id, int render_process_id,
int render_frame_id, int render_frame_id,
const blink::mojom::StreamDevices& devices, blink::mojom::StreamDevicesSetPtr stream_devices_set_ptr,
blink::mojom::MediaStreamRequestResult result, blink::mojom::MediaStreamRequestResult result,
std::unique_ptr<MediaStreamUI> stream_ui) { std::unique_ptr<MediaStreamUI> stream_ui) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK(stream_devices_set_ptr);
ProcessAccessRequestResponse(render_process_id, render_frame_id,
*stream_devices_set_ptr, result,
std::move(stream_ui));
}
void MediaStreamUIProxy::Core::ProcessAccessRequestResponse(
int render_process_id,
int render_frame_id,
const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result,
std::unique_ptr<MediaStreamUI> stream_ui) {
DCHECK_CURRENTLY_ON(BrowserThread::UI);
DCHECK((result != blink::mojom::MediaStreamRequestResult::OK &&
stream_devices_set.stream_devices.empty()) ||
(result == blink::mojom::MediaStreamRequestResult::OK &&
stream_devices_set.stream_devices.size() == 1u));
blink::mojom::StreamDevicesSetPtr filtered_devices_set =
blink::mojom::StreamDevicesSet::New();
blink::mojom::StreamDevices devices;
if (!stream_devices_set.stream_devices.empty()) {
devices = *stream_devices_set.stream_devices[0];
filtered_devices_set->stream_devices.emplace_back(
blink::mojom::StreamDevices::New());
}
blink::mojom::StreamDevices filtered_devices;
auto* host = RenderFrameHostImpl::FromID(render_process_id, render_frame_id); auto* host = RenderFrameHostImpl::FromID(render_process_id, render_frame_id);
if (devices.audio_device.has_value()) { if (devices.audio_device.has_value()) {
const blink::MediaStreamDevice& audio_device = devices.audio_device.value(); const blink::MediaStreamDevice& audio_device = devices.audio_device.value();
@@ -229,7 +263,7 @@ void MediaStreamUIProxy::Core::ProcessAccessRequestResponse(
blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE || blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE ||
IsFeatureEnabled(host, tests_use_fake_render_frame_hosts_, IsFeatureEnabled(host, tests_use_fake_render_frame_hosts_,
blink::mojom::PermissionsPolicyFeature::kMicrophone)) { blink::mojom::PermissionsPolicyFeature::kMicrophone)) {
filtered_devices.audio_device = audio_device; filtered_devices_set->stream_devices[0]->audio_device = audio_device;
} }
} }
@@ -239,14 +273,17 @@ void MediaStreamUIProxy::Core::ProcessAccessRequestResponse(
blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE || blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE ||
IsFeatureEnabled(host, tests_use_fake_render_frame_hosts_, IsFeatureEnabled(host, tests_use_fake_render_frame_hosts_,
blink::mojom::PermissionsPolicyFeature::kCamera)) { blink::mojom::PermissionsPolicyFeature::kCamera)) {
filtered_devices.video_device = video_device; filtered_devices_set->stream_devices[0]->video_device = video_device;
} }
} }
if (!filtered_devices.audio_device.has_value() && if ((filtered_devices_set->stream_devices.empty() ||
!filtered_devices.video_device.has_value() && (!filtered_devices_set->stream_devices[0]->audio_device.has_value() &&
result == blink::mojom::MediaStreamRequestResult::OK) !filtered_devices_set->stream_devices[0]->video_device.has_value())) &&
result == blink::mojom::MediaStreamRequestResult::OK) {
result = blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED; result = blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED;
filtered_devices_set->stream_devices.clear();
}
if (stream_ui) { if (stream_ui) {
// Callbacks that were supplied to the existing `ui_` are no longer // Callbacks that were supplied to the existing `ui_` are no longer
@@ -264,7 +301,7 @@ void MediaStreamUIProxy::Core::ProcessAccessRequestResponse(
GetIOThreadTaskRunner({})->PostTask( GetIOThreadTaskRunner({})->PostTask(
FROM_HERE, FROM_HERE,
base::BindOnce(&MediaStreamUIProxy::ProcessAccessRequestResponse, proxy_, base::BindOnce(&MediaStreamUIProxy::ProcessAccessRequestResponse, proxy_,
std::move(filtered_devices), result)); std::move(filtered_devices_set), result));
} }
void MediaStreamUIProxy::Core::ProcessStopRequestFromUI() { void MediaStreamUIProxy::Core::ProcessStopRequestFromUI() {
@@ -407,11 +444,11 @@ void MediaStreamUIProxy::SetFocus(const DesktopMediaID& media_id,
#endif #endif
void MediaStreamUIProxy::ProcessAccessRequestResponse( void MediaStreamUIProxy::ProcessAccessRequestResponse(
const blink::mojom::StreamDevices& devices, blink::mojom::StreamDevicesSetPtr stream_devices_set,
blink::mojom::MediaStreamRequestResult result) { blink::mojom::MediaStreamRequestResult result) {
DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_CURRENTLY_ON(BrowserThread::IO);
DCHECK(!response_callback_.is_null()); DCHECK(!response_callback_.is_null());
std::move(response_callback_).Run(devices, result); std::move(response_callback_).Run(*stream_devices_set, result);
} }
void MediaStreamUIProxy::ProcessStopRequestFromUI() { void MediaStreamUIProxy::ProcessStopRequestFromUI() {
@@ -482,9 +519,9 @@ void FakeMediaStreamUIProxy::RequestAccess(
GetUIThreadTaskRunner({})->PostTask( GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, FROM_HERE,
base::BindOnce( base::BindOnce(
&MediaStreamUIProxy::Core::ProcessAccessRequestResponse, &MediaStreamUIProxy::Core::ProcessAccessRequestResponseForPostTask,
core_->GetWeakPtr(), request->render_process_id, core_->GetWeakPtr(), request->render_process_id,
request->render_frame_id, blink::mojom::StreamDevices(), request->render_frame_id, blink::mojom::StreamDevicesSet::New(),
blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
std::unique_ptr<MediaStreamUI>())); std::unique_ptr<MediaStreamUI>()));
return; return;
@@ -492,7 +529,12 @@ void FakeMediaStreamUIProxy::RequestAccess(
// Use the first capture device of the same media type in the list for the // Use the first capture device of the same media type in the list for the
// fake UI. // fake UI.
blink::mojom::StreamDevices devices_to_use; blink::mojom::StreamDevicesSetPtr devices_set_to_use =
blink::mojom::StreamDevicesSet::New();
devices_set_to_use->stream_devices.emplace_back(
blink::mojom::StreamDevices::New());
blink::mojom::StreamDevices& devices_to_use =
*devices_set_to_use->stream_devices[0];
for (const blink::MediaStreamDevice& device : devices_) { for (const blink::MediaStreamDevice& device : devices_) {
if (!devices_to_use.audio_device.has_value() && if (!devices_to_use.audio_device.has_value() &&
blink::IsAudioInputMediaType(request->audio_type) && blink::IsAudioInputMediaType(request->audio_type) &&
@@ -519,15 +561,18 @@ void FakeMediaStreamUIProxy::RequestAccess(
const bool is_devices_empty = !devices_to_use.audio_device.has_value() && const bool is_devices_empty = !devices_to_use.audio_device.has_value() &&
!devices_to_use.video_device.has_value(); !devices_to_use.video_device.has_value();
if (is_devices_empty) {
devices_set_to_use->stream_devices.clear();
}
GetUIThreadTaskRunner({})->PostTask( GetUIThreadTaskRunner({})->PostTask(
FROM_HERE, FROM_HERE,
base::BindOnce(&MediaStreamUIProxy::Core::ProcessAccessRequestResponse, base::BindOnce(
core_->GetWeakPtr(), request->render_process_id, &MediaStreamUIProxy::Core::ProcessAccessRequestResponseForPostTask,
request->render_frame_id, devices_to_use, core_->GetWeakPtr(), request->render_process_id,
is_devices_empty request->render_frame_id, std::move(devices_set_to_use),
? blink::mojom::MediaStreamRequestResult::NO_HARDWARE is_devices_empty ? blink::mojom::MediaStreamRequestResult::NO_HARDWARE
: blink::mojom::MediaStreamRequestResult::OK, : blink::mojom::MediaStreamRequestResult::OK,
std::unique_ptr<MediaStreamUI>())); std::unique_ptr<MediaStreamUI>()));
} }
void FakeMediaStreamUIProxy::OnStarted( void FakeMediaStreamUIProxy::OnStarted(

@@ -29,9 +29,9 @@ class RenderFrameHostDelegate;
// be created, used and destroyed on the IO thread. // be created, used and destroyed on the IO thread.
class CONTENT_EXPORT MediaStreamUIProxy { class CONTENT_EXPORT MediaStreamUIProxy {
public: public:
using ResponseCallback = using ResponseCallback = base::OnceCallback<void(
base::OnceCallback<void(const blink::mojom::StreamDevices& devices, const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result)>; blink::mojom::MediaStreamRequestResult result)>;
using WindowIdCallback = using WindowIdCallback =
base::OnceCallback<void(gfx::NativeViewId window_id)>; base::OnceCallback<void(gfx::NativeViewId window_id)>;
@@ -117,7 +117,7 @@ class CONTENT_EXPORT MediaStreamUIProxy {
friend class FakeMediaStreamUIProxy; friend class FakeMediaStreamUIProxy;
void ProcessAccessRequestResponse( void ProcessAccessRequestResponse(
const blink::mojom::StreamDevices& devices, blink::mojom::StreamDevicesSetPtr stream_devices_set,
blink::mojom::MediaStreamRequestResult result); blink::mojom::MediaStreamRequestResult result);
void ProcessStopRequestFromUI(); void ProcessStopRequestFromUI();
void ProcessChangeSourceRequestFromUI(const DesktopMediaID& media_id); void ProcessChangeSourceRequestFromUI(const DesktopMediaID& media_id);

@@ -39,7 +39,7 @@ namespace {
class MockRenderFrameHostDelegate : public RenderFrameHostDelegate { class MockRenderFrameHostDelegate : public RenderFrameHostDelegate {
public: public:
void RequestMediaAccessPermission(const MediaStreamRequest& request, void RequestMediaAccessPermission(const MediaStreamRequest& request,
MediaResponseCallback callback) { MediaResponseCallback callback) override {
return RequestMediaAccessPermission(request, &callback); return RequestMediaAccessPermission(request, &callback);
} }
const blink::web_pref::WebPreferences& GetOrCreateWebPreferences() override { const blink::web_pref::WebPreferences& GetOrCreateWebPreferences() override {
@@ -60,7 +60,7 @@ class MockRenderFrameHostDelegate : public RenderFrameHostDelegate {
class MockResponseCallback { class MockResponseCallback {
public: public:
MOCK_METHOD2(OnAccessRequestResponse, MOCK_METHOD2(OnAccessRequestResponse,
void(const blink::mojom::StreamDevices& devices, void(const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result)); blink::mojom::MediaStreamRequestResult result));
MOCK_METHOD1(OnCheckResponse, void(bool have_access)); MOCK_METHOD1(OnCheckResponse, void(bool have_access));
}; };
@@ -153,19 +153,22 @@ TEST_F(MediaStreamUIProxyTest, Deny) {
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
ASSERT_FALSE(callback.is_null()); ASSERT_FALSE(callback.is_null());
std::move(callback).Run(blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet stream_devices_set;
stream_devices_set.stream_devices.emplace_back(
blink::mojom::StreamDevices::New());
std::move(callback).Run(stream_devices_set,
blink::mojom::MediaStreamRequestResult::OK, blink::mojom::MediaStreamRequestResult::OK,
std::unique_ptr<MediaStreamUI>()); std::unique_ptr<MediaStreamUI>());
blink::mojom::StreamDevices response; blink::mojom::StreamDevicesSetPtr response;
EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _)) EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _))
.WillOnce([&response](const blink::mojom::StreamDevices& arg0, .WillOnce([&response](const blink::mojom::StreamDevicesSet& arg0,
blink::mojom::MediaStreamRequestResult arg1) { blink::mojom::MediaStreamRequestResult arg1) {
response = arg0; response = arg0.Clone();
}); });
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
EXPECT_TRUE(blink::StreamDevicesToMediaStreamDevicesList(response).empty()); EXPECT_TRUE(blink::ToMediaStreamDevicesList(*response).empty());
} }
TEST_F(MediaStreamUIProxyTest, AcceptAndStart) { TEST_F(MediaStreamUIProxyTest, AcceptAndStart) {
@@ -189,28 +192,31 @@ TEST_F(MediaStreamUIProxyTest, AcceptAndStart) {
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
ASSERT_FALSE(callback.is_null()); ASSERT_FALSE(callback.is_null());
blink::mojom::StreamDevices devices; blink::mojom::StreamDevicesSet stream_devices_set;
stream_devices_set.stream_devices.emplace_back(
blink::mojom::StreamDevices::New());
blink::mojom::StreamDevices& devices = *stream_devices_set.stream_devices[0];
devices.audio_device = blink::MediaStreamDevice( devices.audio_device = blink::MediaStreamDevice(
blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE, "Mic", "Mic"); blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE, "Mic", "Mic");
auto ui = std::make_unique<MockMediaStreamUI>(); auto ui = std::make_unique<MockMediaStreamUI>();
EXPECT_CALL(*ui, MockOnStarted(_, _)).WillOnce(Return(0)); EXPECT_CALL(*ui, MockOnStarted(_, _)).WillOnce(Return(0));
std::move(callback).Run(std::move(devices), std::move(callback).Run(stream_devices_set,
blink::mojom::MediaStreamRequestResult::OK, blink::mojom::MediaStreamRequestResult::OK,
std::move(ui)); std::move(ui));
blink::mojom::StreamDevices response; blink::mojom::StreamDevicesSetPtr response;
EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _)) EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _))
.WillOnce([&response](const blink::mojom::StreamDevices& arg0, .WillOnce([&response](const blink::mojom::StreamDevicesSet& arg0,
blink::mojom::MediaStreamRequestResult arg1) { blink::mojom::MediaStreamRequestResult arg1) {
response = arg0; response = arg0.Clone();
}); });
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
EXPECT_FALSE(blink::StreamDevicesToMediaStreamDevicesList(response).empty()); EXPECT_FALSE(blink::ToMediaStreamDevicesList(*response).empty());
proxy_->OnStarted(base::OnceClosure(), MediaStreamUI::SourceCallback(), proxy_->OnStarted(base::OnceClosure(), MediaStreamUI::SourceCallback(),
MediaStreamUIProxy::WindowIdCallback(), MediaStreamUIProxy::WindowIdCallback(),
/*label=*/std::string(), /*screen_capture_ids=*/{}, /*label=*/std::string(), /*screen_share_ids=*/{},
MediaStreamUI::StateChangeCallback()); MediaStreamUI::StateChangeCallback());
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
@@ -240,7 +246,10 @@ TEST_F(MediaStreamUIProxyTest, DeleteBeforeAccepted) {
proxy_.reset(); proxy_.reset();
std::unique_ptr<MediaStreamUI> ui; std::unique_ptr<MediaStreamUI> ui;
std::move(callback).Run(blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet stream_devices_set;
stream_devices_set.stream_devices.emplace_back(
blink::mojom::StreamDevices::New());
std::move(callback).Run(stream_devices_set,
blink::mojom::MediaStreamRequestResult::OK, blink::mojom::MediaStreamRequestResult::OK,
std::move(ui)); std::move(ui));
} }
@@ -268,7 +277,10 @@ TEST_F(MediaStreamUIProxyTest, StopFromUI) {
base::OnceClosure stop_callback; base::OnceClosure stop_callback;
blink::mojom::StreamDevices devices; blink::mojom::StreamDevicesSet stream_devices_set;
stream_devices_set.stream_devices.emplace_back(
blink::mojom::StreamDevices::New());
blink::mojom::StreamDevices& devices = *stream_devices_set.stream_devices[0];
devices.audio_device = blink::MediaStreamDevice( devices.audio_device = blink::MediaStreamDevice(
blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE, "Mic", "Mic"); blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE, "Mic", "Mic");
auto ui = std::make_unique<MockMediaStreamUI>(); auto ui = std::make_unique<MockMediaStreamUI>();
@@ -278,26 +290,26 @@ TEST_F(MediaStreamUIProxyTest, StopFromUI) {
return 0; return 0;
}); });
std::move(callback).Run(std::move(devices), std::move(callback).Run(stream_devices_set,
blink::mojom::MediaStreamRequestResult::OK, blink::mojom::MediaStreamRequestResult::OK,
std::move(ui)); std::move(ui));
blink::mojom::StreamDevices response; blink::mojom::StreamDevicesSetPtr response;
EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _)) EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _))
.WillOnce([&response](const blink::mojom::StreamDevices& arg0, .WillOnce([&response](const blink::mojom::StreamDevicesSet& arg0,
blink::mojom::MediaStreamRequestResult arg1) { blink::mojom::MediaStreamRequestResult arg1) {
response = arg0; response = arg0.Clone();
}); });
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
EXPECT_FALSE(blink::StreamDevicesToMediaStreamDevicesList(response).empty()); EXPECT_FALSE(blink::ToMediaStreamDevicesList(*response).empty());
MockStopStreamHandler stop_handler; MockStopStreamHandler stop_handler;
proxy_->OnStarted(base::BindOnce(&MockStopStreamHandler::OnStop, proxy_->OnStarted(base::BindOnce(&MockStopStreamHandler::OnStop,
base::Unretained(&stop_handler)), base::Unretained(&stop_handler)),
MediaStreamUI::SourceCallback(), MediaStreamUI::SourceCallback(),
MediaStreamUIProxy::WindowIdCallback(), MediaStreamUIProxy::WindowIdCallback(),
/*label=*/std::string(), /*screen_capture_ids=*/{}, /*label=*/std::string(), /*screen_share_ids=*/{},
MediaStreamUI::StateChangeCallback()); MediaStreamUI::StateChangeCallback());
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
@@ -331,7 +343,10 @@ TEST_F(MediaStreamUIProxyTest, WindowIdCallbackCalled) {
auto ui = std::make_unique<MockMediaStreamUI>(); auto ui = std::make_unique<MockMediaStreamUI>();
EXPECT_CALL(*ui, MockOnStarted(_, _)).WillOnce(Return(kWindowId)); EXPECT_CALL(*ui, MockOnStarted(_, _)).WillOnce(Return(kWindowId));
std::move(callback).Run(blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet stream_devices_set;
stream_devices_set.stream_devices.emplace_back(
blink::mojom::StreamDevices::New());
std::move(callback).Run(stream_devices_set,
blink::mojom::MediaStreamRequestResult::OK, blink::mojom::MediaStreamRequestResult::OK,
std::move(ui)); std::move(ui));
EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _)); EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _));
@@ -344,7 +359,7 @@ TEST_F(MediaStreamUIProxyTest, WindowIdCallbackCalled) {
MediaStreamUI::SourceCallback(), MediaStreamUI::SourceCallback(),
base::BindOnce(&MockStopStreamHandler::OnWindowId, base::BindOnce(&MockStopStreamHandler::OnWindowId,
base::Unretained(&handler)), base::Unretained(&handler)),
/*label=*/std::string(), /*screen_capture_ids=*/{}, /*label=*/std::string(), /*screen_share_ids=*/{},
MediaStreamUI::StateChangeCallback()); MediaStreamUI::StateChangeCallback());
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
} }
@@ -372,29 +387,31 @@ TEST_F(MediaStreamUIProxyTest, ChangeSourceFromUI) {
MediaStreamUI::SourceCallback source_callback; MediaStreamUI::SourceCallback source_callback;
blink::mojom::StreamDevices devices; blink::mojom::StreamDevicesSet stream_devices_set;
stream_devices_set.stream_devices.emplace_back(
blink::mojom::StreamDevices::New());
blink::mojom::StreamDevices& devices = *stream_devices_set.stream_devices[0];
devices.video_device = blink::MediaStreamDevice( devices.video_device = blink::MediaStreamDevice(
blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE, blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE,
"fake_desktop_video_device", "Fake Desktop Video Device"); "fake_desktop_video_device", "Fake Desktop Video Device");
auto ui = std::make_unique<MockMediaStreamUI>(); auto ui = std::make_unique<MockMediaStreamUI>();
EXPECT_CALL(*ui, MockOnStarted(_, _)) EXPECT_CALL(*ui, MockOnStarted(_, _)).WillOnce([&](auto, auto callback) {
.WillOnce([&source_callback](auto, auto callback) { source_callback = std::move(callback);
source_callback = std::move(callback); return 0;
return 0; });
}); std::move(callback).Run(stream_devices_set,
std::move(callback).Run(std::move(devices),
blink::mojom::MediaStreamRequestResult::OK, blink::mojom::MediaStreamRequestResult::OK,
std::move(ui)); std::move(ui));
blink::mojom::StreamDevices response; blink::mojom::StreamDevicesSetPtr response;
EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _)) EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _))
.WillOnce([&response](const blink::mojom::StreamDevices& arg0, .WillOnce([&response](const blink::mojom::StreamDevicesSet& arg0,
blink::mojom::MediaStreamRequestResult arg1) { blink::mojom::MediaStreamRequestResult arg1) {
response = arg0; response = arg0.Clone();
}); });
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
EXPECT_FALSE(blink::StreamDevicesToMediaStreamDevicesList(response).empty()); EXPECT_FALSE(blink::ToMediaStreamDevicesList(*response).empty());
MockStopStreamHandler stop_handler; MockStopStreamHandler stop_handler;
MockChangeSourceStreamHandler source_handler; MockChangeSourceStreamHandler source_handler;
@@ -404,7 +421,7 @@ TEST_F(MediaStreamUIProxyTest, ChangeSourceFromUI) {
base::BindRepeating(&MockChangeSourceStreamHandler::OnChangeSource, base::BindRepeating(&MockChangeSourceStreamHandler::OnChangeSource,
base::Unretained(&source_handler)), base::Unretained(&source_handler)),
MediaStreamUIProxy::WindowIdCallback(), /*label=*/std::string(), MediaStreamUIProxy::WindowIdCallback(), /*label=*/std::string(),
/*screen_capture_ids=*/{}, MediaStreamUI::StateChangeCallback()); /*screen_share_ids=*/{}, MediaStreamUI::StateChangeCallback());
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
ASSERT_FALSE(source_callback.is_null()); ASSERT_FALSE(source_callback.is_null());
@@ -436,7 +453,10 @@ TEST_F(MediaStreamUIProxyTest, ChangeTabSourceFromUI) {
MediaStreamUI::SourceCallback source_callback; MediaStreamUI::SourceCallback source_callback;
blink::mojom::StreamDevices devices; blink::mojom::StreamDevicesSet stream_devices_set;
stream_devices_set.stream_devices.emplace_back(
blink::mojom::StreamDevices::New());
blink::mojom::StreamDevices& devices = *stream_devices_set.stream_devices[0];
devices.video_device = blink::MediaStreamDevice( devices.video_device = blink::MediaStreamDevice(
blink::mojom::MediaStreamType::GUM_TAB_VIDEO_CAPTURE, blink::mojom::MediaStreamType::GUM_TAB_VIDEO_CAPTURE,
"fake_tab_video_device", "Fake Tab Video Device"); "fake_tab_video_device", "Fake Tab Video Device");
@@ -448,20 +468,20 @@ TEST_F(MediaStreamUIProxyTest, ChangeTabSourceFromUI) {
stop_callback = std::move(stop); stop_callback = std::move(stop);
return 0; return 0;
}); });
std::move(callback).Run(std::move(devices), std::move(callback).Run(stream_devices_set,
blink::mojom::MediaStreamRequestResult::OK, blink::mojom::MediaStreamRequestResult::OK,
std::move(ui)); std::move(ui));
blink::mojom::StreamDevices response; blink::mojom::StreamDevicesSetPtr response;
EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _)) EXPECT_CALL(response_callback_, OnAccessRequestResponse(_, _))
.Times(2) .Times(2)
.WillRepeatedly([&response](const blink::mojom::StreamDevices& arg0, .WillRepeatedly([&](const blink::mojom::StreamDevicesSet& arg0,
blink::mojom::MediaStreamRequestResult arg1) { blink::mojom::MediaStreamRequestResult arg1) {
response = arg0; response = arg0.Clone();
}); });
base::RunLoop().RunUntilIdle(); base::RunLoop().RunUntilIdle();
EXPECT_FALSE(blink::StreamDevicesToMediaStreamDevicesList(response).empty()); EXPECT_FALSE(blink::ToMediaStreamDevicesList(*response).empty());
MockStopStreamHandler stop_handler; MockStopStreamHandler stop_handler;
// No stop event should be triggered. // No stop event should be triggered.
@@ -505,7 +525,7 @@ TEST_F(MediaStreamUIProxyTest, ChangeTabSourceFromUI) {
blink::mojom::MediaStreamType::GUM_TAB_VIDEO_CAPTURE, blink::mojom::MediaStreamType::GUM_TAB_VIDEO_CAPTURE,
"fake_tab_video_device", "Fake Tab Video Device"); "fake_tab_video_device", "Fake Tab Video Device");
std::move(callback).Run(std::move(devices), std::move(callback).Run(stream_devices_set,
blink::mojom::MediaStreamRequestResult::OK, blink::mojom::MediaStreamRequestResult::OK,
std::make_unique<MockMediaStreamUI>()); std::make_unique<MockMediaStreamUI>());
@@ -571,7 +591,11 @@ class MediaStreamUIProxyPermissionsPolicyTest
public: public:
void RequestMediaAccessPermission(const MediaStreamRequest& request, void RequestMediaAccessPermission(const MediaStreamRequest& request,
MediaResponseCallback callback) override { MediaResponseCallback callback) override {
blink::mojom::StreamDevices devices; blink::mojom::StreamDevicesSet stream_devices_set;
stream_devices_set.stream_devices.emplace_back(
blink::mojom::StreamDevices::New());
blink::mojom::StreamDevices& devices =
*stream_devices_set.stream_devices[0];
if (request.audio_type == if (request.audio_type ==
blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) { blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) {
devices.audio_device = blink::MediaStreamDevice( devices.audio_device = blink::MediaStreamDevice(
@@ -584,7 +608,7 @@ class MediaStreamUIProxyPermissionsPolicyTest
"Camera"); "Camera");
} }
auto ui = std::make_unique<MockMediaStreamUI>(); auto ui = std::make_unique<MockMediaStreamUI>();
std::move(callback).Run(std::move(devices), std::move(callback).Run(stream_devices_set,
blink::mojom::MediaStreamRequestResult::OK, blink::mojom::MediaStreamRequestResult::OK,
std::move(ui)); std::move(ui));
} }
@@ -610,7 +634,7 @@ class MediaStreamUIProxyPermissionsPolicyTest
} }
void FinishedGetResultOnIOThread( void FinishedGetResultOnIOThread(
const blink::mojom::StreamDevices& devices, const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result) { blink::mojom::MediaStreamRequestResult result) {
DCHECK_CURRENTLY_ON(BrowserThread::IO); DCHECK_CURRENTLY_ON(BrowserThread::IO);
proxy_.reset(); proxy_.reset();
@@ -618,13 +642,13 @@ class MediaStreamUIProxyPermissionsPolicyTest
FROM_HERE, FROM_HERE,
base::BindOnce( base::BindOnce(
&MediaStreamUIProxyPermissionsPolicyTest::FinishedGetResult, &MediaStreamUIProxyPermissionsPolicyTest::FinishedGetResult,
base::Unretained(this), devices, result)); base::Unretained(this), stream_devices_set.Clone(), result));
} }
void FinishedGetResult(const blink::mojom::StreamDevices& devices, void FinishedGetResult(blink::mojom::StreamDevicesSetPtr stream_devices_set,
blink::mojom::MediaStreamRequestResult result) { blink::mojom::MediaStreamRequestResult result) {
DCHECK_CURRENTLY_ON(BrowserThread::UI); DCHECK_CURRENTLY_ON(BrowserThread::UI);
devices_ = blink::StreamDevicesToMediaStreamDevicesList(devices); devices_ = blink::ToMediaStreamDevicesList(*stream_devices_set);
result_ = result; result_ = result;
std::move(quit_closure_).Run(); std::move(quit_closure_).Run();
} }

@@ -44,7 +44,7 @@ void RenderFrameHostDelegate::RequestMediaAccessPermission(
MediaResponseCallback callback) { MediaResponseCallback callback) {
LOG(ERROR) << "RenderFrameHostDelegate::RequestMediaAccessPermission: " LOG(ERROR) << "RenderFrameHostDelegate::RequestMediaAccessPermission: "
<< "Not supported."; << "Not supported.";
std::move(callback).Run(blink::mojom::StreamDevices(), std::move(callback).Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED,
std::unique_ptr<MediaStreamUI>()); std::unique_ptr<MediaStreamUI>());
} }

@@ -307,9 +307,9 @@ void SpeechRecognitionManagerImpl::MediaRequestPermissionCallback(
// which is only supported in combination with the getDisplayMediaSet API. // which is only supported in combination with the getDisplayMediaSet API.
DCHECK_EQ(stream_devices_set.stream_devices.size(), 1u); DCHECK_EQ(stream_devices_set.stream_devices.size(), 1u);
DCHECK(stream_devices_set.stream_devices[0]); DCHECK(stream_devices_set.stream_devices[0]);
blink::MediaStreamDevices devices_list = blink::MediaStreamDevices devices_list =
blink::StreamDevicesToMediaStreamDevicesList( blink::ToMediaStreamDevicesList(stream_devices_set);
*stream_devices_set.stream_devices[0]);
const bool is_allowed = !devices_list.empty(); const bool is_allowed = !devices_list.empty();
if (is_allowed) { if (is_allowed) {
// Copy the approved devices array to the context for UI indication. // Copy the approved devices array to the context for UI indication.

@@ -4285,7 +4285,7 @@ void WebContentsImpl::RequestMediaAccessPermission(
delegate_->RequestMediaAccessPermission(this, request, std::move(callback)); delegate_->RequestMediaAccessPermission(this, request, std::move(callback));
} else { } else {
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN, blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN,
std::unique_ptr<MediaStreamUI>()); std::unique_ptr<MediaStreamUI>());
} }

@@ -3214,11 +3214,11 @@ TEST_F(WebContentsImplTest, RequestMediaAccessPermissionNoDelegate) {
contents()->RequestMediaAccessPermission( contents()->RequestMediaAccessPermission(
dummy_request, dummy_request,
base::BindLambdaForTesting( base::BindLambdaForTesting(
[&callback_run](const blink::mojom::StreamDevices& stream_devices, [&callback_run](
blink::mojom::MediaStreamRequestResult result, const blink::mojom::StreamDevicesSet& stream_devices_set,
std::unique_ptr<MediaStreamUI> ui) { blink::mojom::MediaStreamRequestResult result,
EXPECT_FALSE(stream_devices.audio_device.has_value()); std::unique_ptr<MediaStreamUI> ui) {
EXPECT_FALSE(stream_devices.video_device.has_value()); EXPECT_TRUE(stream_devices_set.stream_devices.empty());
EXPECT_EQ( EXPECT_EQ(
result, result,
blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN); blink::mojom::MediaStreamRequestResult::FAILED_DUE_TO_SHUTDOWN);

@@ -152,10 +152,10 @@ class MediaStreamUI {
}; };
// Callback used return results of media access requests. // Callback used return results of media access requests.
using MediaResponseCallback = using MediaResponseCallback = base::OnceCallback<void(
base::OnceCallback<void(const blink::mojom::StreamDevices& stream_devices, const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result, blink::mojom::MediaStreamRequestResult result,
std::unique_ptr<MediaStreamUI> ui)>; std::unique_ptr<MediaStreamUI> ui)>;
} // namespace content } // namespace content
#endif // CONTENT_PUBLIC_BROWSER_MEDIA_STREAM_REQUEST_H_ #endif // CONTENT_PUBLIC_BROWSER_MEDIA_STREAM_REQUEST_H_

@@ -220,7 +220,7 @@ void WebContentsDelegate::RequestMediaAccessPermission(
content::MediaResponseCallback callback) { content::MediaResponseCallback callback) {
LOG(ERROR) << "WebContentsDelegate::RequestMediaAccessPermission: " LOG(ERROR) << "WebContentsDelegate::RequestMediaAccessPermission: "
<< "Not supported."; << "Not supported.";
std::move(callback).Run(blink::mojom::StreamDevices(), std::move(callback).Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED,
std::unique_ptr<content::MediaStreamUI>()); std::unique_ptr<content::MediaStreamUI>());
} }

@@ -214,7 +214,7 @@ void WebViewPermissionHelper::OnMediaPermissionResponse(
const std::string& user_input) { const std::string& user_input) {
if (!allow) { if (!allow) {
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED, blink::mojom::MediaStreamRequestResult::PERMISSION_DENIED,
std::unique_ptr<content::MediaStreamUI>()); std::unique_ptr<content::MediaStreamUI>());
return; return;
@@ -222,7 +222,7 @@ void WebViewPermissionHelper::OnMediaPermissionResponse(
if (!web_view_guest()->attached() || if (!web_view_guest()->attached() ||
!web_view_guest()->embedder_web_contents()->GetDelegate()) { !web_view_guest()->embedder_web_contents()->GetDelegate()) {
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::INVALID_STATE, blink::mojom::MediaStreamRequestResult::INVALID_STATE,
std::unique_ptr<content::MediaStreamUI>()); std::unique_ptr<content::MediaStreamUI>());
return; return;

@@ -59,7 +59,11 @@ void GrantMediaStreamRequest(content::WebContents* web_contents,
request.video_type == request.video_type ==
blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE); blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE);
blink::mojom::StreamDevices devices; // TOOD(crbug.com/1300883): Generalize to multiple streams.
blink::mojom::StreamDevicesSet stream_devices_set;
stream_devices_set.stream_devices.emplace_back(
blink::mojom::StreamDevices::New());
blink::mojom::StreamDevices& devices = *stream_devices_set.stream_devices[0];
if (request.audio_type == if (request.audio_type ==
blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) { blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) {
@@ -84,8 +88,8 @@ void GrantMediaStreamRequest(content::WebContents* web_contents,
// TODO(jamescook): Should we show a recording icon somewhere? If so, where? // TODO(jamescook): Should we show a recording icon somewhere? If so, where?
std::unique_ptr<MediaStreamUI> ui; std::unique_ptr<MediaStreamUI> ui;
std::move(callback).Run( std::move(callback).Run(
devices, stream_devices_set,
devices.audio_device.has_value() || devices.video_device.has_value() (devices.audio_device.has_value() || devices.video_device.has_value())
? blink::mojom::MediaStreamRequestResult::OK ? blink::mojom::MediaStreamRequestResult::OK
: blink::mojom::MediaStreamRequestResult::INVALID_STATE, : blink::mojom::MediaStreamRequestResult::INVALID_STATE,
std::move(ui)); std::move(ui));

@@ -8,6 +8,7 @@
#include <lib/fpromise/result.h> #include <lib/fpromise/result.h>
#include <lib/sys/cpp/component_context.h> #include <lib/sys/cpp/component_context.h>
#include <lib/ui/scenic/cpp/view_ref_pair.h> #include <lib/ui/scenic/cpp/view_ref_pair.h>
#include <algorithm>
#include <limits> #include <limits>
#include "base/bind.h" #include "base/bind.h"
@@ -206,14 +207,15 @@ void HandleMediaPermissionsRequestResult(
const content::MediaStreamRequest& request, const content::MediaStreamRequest& request,
content::MediaResponseCallback callback, content::MediaResponseCallback callback,
const std::vector<blink::mojom::PermissionStatus>& result) { const std::vector<blink::mojom::PermissionStatus>& result) {
blink::mojom::StreamDevices devices; // TODO(crbug.com/1300883): Generalize to multiple streams.
blink::mojom::StreamDevicesPtr devices = blink::mojom::StreamDevices::New();
int result_pos = 0; int result_pos = 0;
if (request.audio_type == if (request.audio_type ==
blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) { blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE) {
if (result[result_pos] == blink::mojom::PermissionStatus::GRANTED) { if (result[result_pos] == blink::mojom::PermissionStatus::GRANTED) {
devices.audio_device = blink::MediaStreamDevice( devices->audio_device = blink::MediaStreamDevice(
request.audio_type, request.requested_audio_device_id, request.audio_type, request.requested_audio_device_id,
/*name=*/""); /*name=*/"");
} }
@@ -223,15 +225,19 @@ void HandleMediaPermissionsRequestResult(
if (request.video_type == if (request.video_type ==
blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE) { blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE) {
if (result[result_pos] == blink::mojom::PermissionStatus::GRANTED) { if (result[result_pos] == blink::mojom::PermissionStatus::GRANTED) {
devices.video_device = blink::MediaStreamDevice( devices->video_device = blink::MediaStreamDevice(
request.video_type, request.requested_video_device_id, request.video_type, request.requested_video_device_id,
/*name=*/""); /*name=*/"");
} }
} }
blink::mojom::StreamDevicesSet stream_devices_set;
if (devices->audio_device.has_value() || devices->video_device.has_value()) {
stream_devices_set.stream_devices.emplace_back(std::move(devices));
}
std::move(callback).Run( std::move(callback).Run(
devices, stream_devices_set,
(!devices.audio_device.has_value() && !devices.video_device.has_value()) stream_devices_set.stream_devices.empty()
? blink::mojom::MediaStreamRequestResult::NO_HARDWARE ? blink::mojom::MediaStreamRequestResult::NO_HARDWARE
: blink::mojom::MediaStreamRequestResult::OK, : blink::mojom::MediaStreamRequestResult::OK,
nullptr); nullptr);
@@ -1245,7 +1251,7 @@ void FrameImpl::RequestMediaAccessPermission(
permissions.push_back(blink::PermissionType::AUDIO_CAPTURE); permissions.push_back(blink::PermissionType::AUDIO_CAPTURE);
} else if (request.audio_type != blink::mojom::MediaStreamType::NO_SERVICE) { } else if (request.audio_type != blink::mojom::MediaStreamType::NO_SERVICE) {
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, nullptr); blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, nullptr);
return; return;
} }
@@ -1255,7 +1261,7 @@ void FrameImpl::RequestMediaAccessPermission(
permissions.push_back(blink::PermissionType::VIDEO_CAPTURE); permissions.push_back(blink::PermissionType::VIDEO_CAPTURE);
} else if (request.video_type != blink::mojom::MediaStreamType::NO_SERVICE) { } else if (request.video_type != blink::mojom::MediaStreamType::NO_SERVICE) {
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, nullptr); blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, nullptr);
return; return;
} }
@@ -1264,7 +1270,7 @@ void FrameImpl::RequestMediaAccessPermission(
request.render_process_id, request.render_frame_id); request.render_process_id, request.render_frame_id);
if (!render_frame_host) { if (!render_frame_host) {
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::INVALID_STATE, nullptr); blink::mojom::MediaStreamRequestResult::INVALID_STATE, nullptr);
return; return;
} }
@@ -1272,7 +1278,7 @@ void FrameImpl::RequestMediaAccessPermission(
if (url::Origin::Create(request.security_origin) != if (url::Origin::Create(request.security_origin) !=
render_frame_host->GetLastCommittedOrigin()) { render_frame_host->GetLastCommittedOrigin()) {
std::move(callback).Run( std::move(callback).Run(
blink::mojom::StreamDevices(), blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::INVALID_SECURITY_ORIGIN, blink::mojom::MediaStreamRequestResult::INVALID_SECURITY_ORIGIN,
nullptr); nullptr);
return; return;

@@ -144,16 +144,31 @@ bool MediaStreamDevice::IsSameDevice(
session_id_ == other_device.session_id_; session_id_ == other_device.session_id_;
} }
// TODO(crbug.com/1313021): Remove this function and use BLINK_COMMON_EXPORT MediaStreamDevices
// blink::mojom::StreaDevices directly everywhere. ToMediaStreamDevicesList(const mojom::StreamDevices& stream_devices) {
blink::MediaStreamDevices StreamDevicesToMediaStreamDevicesList( blink::MediaStreamDevices devices;
const blink::mojom::StreamDevices& devices) { if (stream_devices.audio_device.has_value()) {
blink::MediaStreamDevices all_devices; devices.push_back(stream_devices.audio_device.value());
if (devices.audio_device.has_value()) }
all_devices.push_back(devices.audio_device.value()); if (stream_devices.video_device.has_value()) {
if (devices.video_device.has_value()) devices.push_back(stream_devices.video_device.value());
all_devices.push_back(devices.video_device.value()); }
return all_devices; return devices;
}
blink::MediaStreamDevices ToMediaStreamDevicesList(
const blink::mojom::StreamDevicesSet& stream_devices_set) {
blink::MediaStreamDevices devices;
for (const blink::mojom::StreamDevicesPtr& devices_to_insert :
stream_devices_set.stream_devices) {
if (devices_to_insert->audio_device.has_value()) {
devices.push_back(devices_to_insert->audio_device.value());
}
if (devices_to_insert->video_device.has_value()) {
devices.push_back(devices_to_insert->video_device.value());
}
}
return devices;
} }
size_t CountDevices(const blink::mojom::StreamDevices& devices) { size_t CountDevices(const blink::mojom::StreamDevices& devices) {

@@ -125,8 +125,15 @@ struct BLINK_COMMON_EXPORT MediaStreamDevice {
using MediaStreamDevices = std::vector<MediaStreamDevice>; using MediaStreamDevices = std::vector<MediaStreamDevice>;
// Takes a mojom::StreamDevices and returns all contained MediaStreamDevices.
BLINK_COMMON_EXPORT MediaStreamDevices BLINK_COMMON_EXPORT MediaStreamDevices
StreamDevicesToMediaStreamDevicesList(const mojom::StreamDevices& devices); ToMediaStreamDevicesList(const mojom::StreamDevices& stream_devices);
// TODO(crbug.com/1313021): Remove this function and use
// blink::mojom::StreamDevicesSet directly everywhere.
// Takes a mojom::StreamDevicesSet and returns all contained MediaStreamDevices.
BLINK_COMMON_EXPORT MediaStreamDevices
ToMediaStreamDevicesList(const mojom::StreamDevicesSet& stream_devices_set);
BLINK_COMMON_EXPORT size_t CountDevices(const mojom::StreamDevices& devices); BLINK_COMMON_EXPORT size_t CountDevices(const mojom::StreamDevices& devices);

@@ -155,7 +155,7 @@ class MODULES_EXPORT UserMediaProcessor
void OnStreamGenerated(int32_t request_id, void OnStreamGenerated(int32_t request_id,
blink::mojom::blink::MediaStreamRequestResult result, blink::mojom::blink::MediaStreamRequestResult result,
const String& label, const String& label,
mojom::blink::StreamDevicesSetPtr streams_devices_set, mojom::blink::StreamDevicesSetPtr stream_devices_set,
bool pan_tilt_zoom_allowed); bool pan_tilt_zoom_allowed);
void GotAllVideoInputFormatsForDevice( void GotAllVideoInputFormatsForDevice(

@@ -1130,7 +1130,7 @@ void TabImpl::RequestMediaAccessPermission(
MediaStreamManager::FromWebContents(web_contents) MediaStreamManager::FromWebContents(web_contents)
->RequestMediaAccessPermission(request, std::move(callback)); ->RequestMediaAccessPermission(request, std::move(callback));
#else #else
std::move(callback).Run(blink::mojom::StreamDevices(), std::move(callback).Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED, blink::mojom::MediaStreamRequestResult::NOT_SUPPORTED,
nullptr); nullptr);
#endif #endif

@@ -34,11 +34,14 @@ struct UserData : public base::SupportsUserData::Data {
class MediaStreamManager::StreamUi : public content::MediaStreamUI { class MediaStreamManager::StreamUi : public content::MediaStreamUI {
public: public:
StreamUi(base::WeakPtr<MediaStreamManager> manager, StreamUi(base::WeakPtr<MediaStreamManager> manager,
const blink::mojom::StreamDevices& devices) const blink::mojom::StreamDevicesSet& stream_devices)
: manager_(manager) { : manager_(manager) {
DCHECK(manager_); DCHECK(manager_);
streaming_audio_ = devices.audio_device.has_value(); DCHECK_EQ(1u, stream_devices.stream_devices.size());
streaming_video_ = devices.video_device.has_value(); streaming_audio_ =
stream_devices.stream_devices[0]->audio_device.has_value();
streaming_video_ =
stream_devices.stream_devices[0]->video_device.has_value();
} }
StreamUi(const StreamUi&) = delete; StreamUi(const StreamUi&) = delete;
StreamUi& operator=(const StreamUi&) = delete; StreamUi& operator=(const StreamUi&) = delete;
@@ -122,12 +125,12 @@ void MediaStreamManager::OnClientReadyToStream(JNIEnv* env,
CHECK(request != requests_pending_client_approval_.end()); CHECK(request != requests_pending_client_approval_.end());
if (allowed) { if (allowed) {
std::move(request->second.callback) std::move(request->second.callback)
.Run(request->second.devices, request->second.result, .Run(*request->second.stream_devices_set_, request->second.result,
std::make_unique<StreamUi>(weak_factory_.GetWeakPtr(), std::make_unique<StreamUi>(weak_factory_.GetWeakPtr(),
request->second.devices)); *request->second.stream_devices_set_));
} else { } else {
std::move(request->second.callback) std::move(request->second.callback)
.Run(blink::mojom::StreamDevices(), .Run(blink::mojom::StreamDevicesSet(),
blink::mojom::MediaStreamRequestResult::NO_HARDWARE, {}); blink::mojom::MediaStreamRequestResult::NO_HARDWARE, {});
} }
requests_pending_client_approval_.erase(request); requests_pending_client_approval_.erase(request);
@@ -141,22 +144,28 @@ void MediaStreamManager::StopStreaming(JNIEnv* env) {
void MediaStreamManager::OnMediaAccessPermissionResult( void MediaStreamManager::OnMediaAccessPermissionResult(
content::MediaResponseCallback callback, content::MediaResponseCallback callback,
const blink::mojom::StreamDevices& devices, const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result, blink::mojom::MediaStreamRequestResult result,
bool blocked_by_permissions_policy, bool blocked_by_permissions_policy,
ContentSetting audio_setting, ContentSetting audio_setting,
ContentSetting video_setting) { ContentSetting video_setting) {
// TODO(crbug.com/1300883): Generalize to multiple streams.
DCHECK((result != blink::mojom::MediaStreamRequestResult::OK &&
stream_devices_set.stream_devices.empty()) ||
(result == blink::mojom::MediaStreamRequestResult::OK &&
stream_devices_set.stream_devices.size() == 1u));
if (result != blink::mojom::MediaStreamRequestResult::OK) { if (result != blink::mojom::MediaStreamRequestResult::OK) {
std::move(callback).Run(devices, result, {}); std::move(callback).Run(stream_devices_set, result, {});
return; return;
} }
int request_id = next_request_id_++; int request_id = next_request_id_++;
requests_pending_client_approval_[request_id] = requests_pending_client_approval_[request_id] = RequestPendingClientApproval(
RequestPendingClientApproval(std::move(callback), devices, result); std::move(callback), stream_devices_set, result);
Java_MediaStreamManager_prepareToStream( Java_MediaStreamManager_prepareToStream(
base::android::AttachCurrentThread(), j_object_, base::android::AttachCurrentThread(), j_object_,
devices.audio_device.has_value(), devices.video_device.has_value(), stream_devices_set.stream_devices[0]->audio_device.has_value(),
stream_devices_set.stream_devices[0]->video_device.has_value(),
request_id); request_id);
} }
@@ -199,9 +208,11 @@ MediaStreamManager::RequestPendingClientApproval::
MediaStreamManager::RequestPendingClientApproval::RequestPendingClientApproval( MediaStreamManager::RequestPendingClientApproval::RequestPendingClientApproval(
content::MediaResponseCallback callback, content::MediaResponseCallback callback,
const blink::mojom::StreamDevices& devices, const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result) blink::mojom::MediaStreamRequestResult result)
: callback(std::move(callback)), devices(devices), result(result) {} : callback(std::move(callback)),
stream_devices_set_(stream_devices_set.Clone()),
result(result) {}
MediaStreamManager::RequestPendingClientApproval:: MediaStreamManager::RequestPendingClientApproval::
~RequestPendingClientApproval() = default; ~RequestPendingClientApproval() = default;

@@ -57,7 +57,7 @@ class MediaStreamManager {
void OnMediaAccessPermissionResult( void OnMediaAccessPermissionResult(
content::MediaResponseCallback callback, content::MediaResponseCallback callback,
const blink::mojom::StreamDevices& devices, const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result, blink::mojom::MediaStreamRequestResult result,
bool blocked_by_permissions_policy, bool blocked_by_permissions_policy,
ContentSetting audio_setting, ContentSetting audio_setting,
@@ -73,16 +73,17 @@ class MediaStreamManager {
// approval. // approval.
struct RequestPendingClientApproval { struct RequestPendingClientApproval {
RequestPendingClientApproval(); RequestPendingClientApproval();
RequestPendingClientApproval(content::MediaResponseCallback callback, RequestPendingClientApproval(
const blink::mojom::StreamDevices& devices, content::MediaResponseCallback callback,
blink::mojom::MediaStreamRequestResult result); const blink::mojom::StreamDevicesSet& stream_devices_set,
blink::mojom::MediaStreamRequestResult result);
~RequestPendingClientApproval(); ~RequestPendingClientApproval();
RequestPendingClientApproval& operator=( RequestPendingClientApproval& operator=(
RequestPendingClientApproval&& other); RequestPendingClientApproval&& other);
content::MediaResponseCallback callback; content::MediaResponseCallback callback;
blink::mojom::StreamDevices devices; blink::mojom::StreamDevicesSetPtr stream_devices_set_;
blink::mojom::MediaStreamRequestResult result; blink::mojom::MediaStreamRequestResult result;
}; };
std::map<int, RequestPendingClientApproval> requests_pending_client_approval_; std::map<int, RequestPendingClientApproval> requests_pending_client_approval_;