Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1481)

Unified Diff: chrome/browser/media/media_capture_devices_dispatcher.cc

Issue 1095393004: Refactor: Make MediaCaptureDevicesDispatcher have pluggable handlers. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/media/media_capture_devices_dispatcher.cc
diff --git a/chrome/browser/media/media_capture_devices_dispatcher.cc b/chrome/browser/media/media_capture_devices_dispatcher.cc
index 4bfb4c9b75e67baa6562e8701bfd2f84fdc736ce..bcaeea3cfc433b7171aa23d1b2d2599073d24861 100644
--- a/chrome/browser/media/media_capture_devices_dispatcher.cc
+++ b/chrome/browser/media/media_capture_devices_dispatcher.cc
@@ -13,21 +13,17 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "chrome/browser/media/desktop_capture_access_handler.h"
#include "chrome/browser/media/desktop_streams_registry.h"
#include "chrome/browser/media/media_stream_capture_indicator.h"
#include "chrome/browser/media/media_stream_device_permissions.h"
-#include "chrome/browser/media/media_stream_infobar_delegate.h"
-#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/media/regular_media_access_handler.h"
+#include "chrome/browser/media/tab_capture_access_handler.h"
#include "chrome/browser/ui/browser.h"
-#include "chrome/browser/ui/browser_finder.h"
#include "chrome/browser/ui/browser_window.h"
-#include "chrome/browser/ui/screen_capture_notification_ui.h"
-#include "chrome/browser/ui/simple_message_box.h"
-#include "chrome/browser/ui/website_settings/permission_bubble_manager.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/pref_names.h"
-#include "chrome/grit/generated_resources.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/pref_registry/pref_registry_syncable.h"
#include "content/public/browser/browser_thread.h"
@@ -41,20 +37,15 @@
#include "content/public/browser/web_contents.h"
#include "content/public/common/media_stream_request.h"
#include "extensions/common/constants.h"
-#include "media/audio/audio_manager_base.h"
#include "media/base/media_switches.h"
#include "net/base/net_util.h"
-#include "third_party/webrtc/modules/desktop_capture/desktop_capture_types.h"
-#include "ui/base/l10n/l10n_util.h"
#if defined(OS_CHROMEOS)
#include "ash/shell.h"
#endif // defined(OS_CHROMEOS)
#if defined(ENABLE_EXTENSIONS)
-#include "chrome/browser/extensions/api/tab_capture/tab_capture_registry.h"
-#include "extensions/browser/app_window/app_window.h"
-#include "extensions/browser/app_window/app_window_registry.h"
+#include "chrome/browser/media/extension_media_access_handler.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/common/extension.h"
#include "extensions/common/permissions/permissions_data.h"
@@ -66,16 +57,6 @@ using content::MediaStreamDevices;
namespace {
-// A finch experiment to enable the permission bubble for media requests only.
-bool MediaStreamPermissionBubbleExperimentEnabled() {
- const std::string group =
- base::FieldTrialList::FindFullName("MediaStreamPermissionBubble");
- if (group == "enabled")
- return true;
-
- return false;
-}
-
// Finds a device in |devices| that has |device_id|, or NULL if not found.
const content::MediaStreamDevice* FindDeviceWithId(
const content::MediaStreamDevices& devices,
@@ -110,130 +91,8 @@ bool IsMediaRequestWhitelistedForExtension(
extension->id() == "jkghodnilhceideoidjikpgommlajknk" ||
extension->id() == "gjaehgfemfahhmlgpdfknkhdnemmolop";
}
-
-bool IsBuiltInExtension(const GURL& origin) {
- return
- // Feedback Extension.
- origin.spec() == "chrome-extension://gfdkimpbcpahaombhbimeihdjnejgicl/";
-}
-
-// Returns true of the security origin is associated with casting.
-bool IsOriginForCasting(const GURL& origin) {
- // Whitelisted tab casting extensions.
- return
- // Dev
- origin.spec() == "chrome-extension://enhhojjnijigcajfphajepfemndkmdlo/" ||
- // Canary
- origin.spec() == "chrome-extension://hfaagokkkhdbgiakmmlclaapfelnkoah/" ||
- // Beta (internal)
- origin.spec() == "chrome-extension://fmfcbgogabcbclcofgocippekhfcmgfj/" ||
- // Google Cast Beta
- origin.spec() == "chrome-extension://dliochdbjfkdbacpmhlcpmleaejidimm/" ||
- // Google Cast Stable
- origin.spec() == "chrome-extension://boadgeojelhgndaghljhdicfkmllpafd/" ||
- // http://crbug.com/457908
- origin.spec() == "chrome-extension://ekpaaapppgpmolpcldedioblbkmijaca/" ||
- origin.spec() == "chrome-extension://fjhoaacokmgbjemoflkofnenfaiekifl/";
-}
-
-bool IsExtensionWhitelistedForScreenCapture(
- const extensions::Extension* extension) {
-#if defined(OS_CHROMEOS)
- std::string hash = base::SHA1HashString(extension->id());
- std::string hex_hash = base::HexEncode(hash.c_str(), hash.length());
-
- // crbug.com/446688
- return hex_hash == "4F25792AF1AA7483936DE29C07806F203C7170A0" ||
- hex_hash == "BD8781D757D830FC2E85470A1B6E8A718B7EE0D9" ||
- hex_hash == "4AC2B6C63C6480D150DFDA13E4A5956EB1D0DDBB" ||
- hex_hash == "81986D4F846CEDDDB962643FA501D1780DD441BB";
-#else
- return false;
-#endif // defined(OS_CHROMEOS)
-}
#endif // defined(ENABLE_EXTENSIONS)
-// Helper to get title of the calling application shown in the screen capture
-// notification.
-base::string16 GetApplicationTitle(content::WebContents* web_contents,
- const extensions::Extension* extension) {
- // Use extension name as title for extensions and host/origin for drive-by
- // web.
- std::string title;
-#if defined(ENABLE_EXTENSIONS)
- if (extension) {
- title = extension->name();
- return base::UTF8ToUTF16(title);
- }
-#endif
- GURL url = web_contents->GetURL();
- title = url.SchemeIsSecure() ? net::GetHostAndOptionalPort(url)
- : url.GetOrigin().spec();
- return base::UTF8ToUTF16(title);
-}
-
-// Helper to get list of media stream devices for desktop capture in |devices|.
-// Registers to display notification if |display_notification| is true.
-// Returns an instance of MediaStreamUI to be passed to content layer.
-scoped_ptr<content::MediaStreamUI> GetDevicesForDesktopCapture(
- content::MediaStreamDevices* devices,
- content::DesktopMediaID media_id,
- bool capture_audio,
- bool display_notification,
- const base::string16& application_title,
- const base::string16& registered_extension_name) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
- scoped_ptr<content::MediaStreamUI> ui;
-
- // Add selected desktop source to the list.
- devices->push_back(content::MediaStreamDevice(
- content::MEDIA_DESKTOP_VIDEO_CAPTURE, media_id.ToString(), "Screen"));
- if (capture_audio) {
- // Use the special loopback device ID for system audio capture.
- devices->push_back(content::MediaStreamDevice(
- content::MEDIA_DESKTOP_AUDIO_CAPTURE,
- media::AudioManagerBase::kLoopbackInputDeviceId, "System Audio"));
- }
-
- // If required, register to display the notification for stream capture.
- if (display_notification) {
- if (application_title == registered_extension_name) {
- ui = ScreenCaptureNotificationUI::Create(l10n_util::GetStringFUTF16(
- IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TEXT,
- application_title));
- } else {
- ui = ScreenCaptureNotificationUI::Create(l10n_util::GetStringFUTF16(
- IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TEXT_DELEGATED,
- registered_extension_name,
- application_title));
- }
- }
-
- return ui.Pass();
-}
-
-#if !defined(OS_ANDROID)
-// Find browser or app window from a given |web_contents|.
-gfx::NativeWindow FindParentWindowForWebContents(
- content::WebContents* web_contents) {
- Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
- if (browser && browser->window())
- return browser->window()->GetNativeWindow();
-
- const extensions::AppWindowRegistry::AppWindowList& window_list =
- extensions::AppWindowRegistry::Get(
- web_contents->GetBrowserContext())->app_windows();
- for (extensions::AppWindowRegistry::AppWindowList::const_iterator iter =
- window_list.begin();
- iter != window_list.end(); ++iter) {
- if ((*iter)->web_contents() == web_contents)
- return (*iter)->GetNativeWindow();
- }
-
- return NULL;
-}
-#endif
-
#if defined(ENABLE_EXTENSIONS)
const extensions::Extension* GetExtensionForOrigin(
Profile* profile,
@@ -251,15 +110,6 @@ const extensions::Extension* GetExtensionForOrigin(
} // namespace
-MediaCaptureDevicesDispatcher::PendingAccessRequest::PendingAccessRequest(
- const content::MediaStreamRequest& request,
- const content::MediaResponseCallback& callback)
- : request(request),
- callback(callback) {
-}
-
-MediaCaptureDevicesDispatcher::PendingAccessRequest::~PendingAccessRequest() {}
-
MediaCaptureDevicesDispatcher* MediaCaptureDevicesDispatcher::GetInstance() {
return Singleton<MediaCaptureDevicesDispatcher>::get();
}
@@ -350,26 +200,28 @@ void MediaCaptureDevicesDispatcher::ProcessMediaAccessRequest(
if (request.video_type == content::MEDIA_DESKTOP_VIDEO_CAPTURE ||
Sergey Ulanov 2015/04/24 22:43:51 This code shouldn't need to know or care about typ
changbin 2015/04/29 05:24:34 This sounds better;) Use list of MediaAccessHandl
request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE) {
- ProcessDesktopCaptureAccessRequest(
- web_contents, request, callback, extension);
+ media_access_handler_.reset(
+ new DesktopCaptureAccessHandler(GetDesktopStreamsRegistry()));
} else if (request.video_type == content::MEDIA_TAB_VIDEO_CAPTURE ||
request.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE) {
- ProcessTabCaptureAccessRequest(
- web_contents, request, callback, extension);
+ media_access_handler_.reset(
+ new TabCaptureAccessHandler(media_stream_capture_indicator_));
} else {
+ media_access_handler_.reset(
Sergey Ulanov 2015/04/24 22:43:51 RegularMediaAccessHandler keeps queue of pending r
changbin 2015/04/29 05:24:34 That means it should pass pointer of RequestsQueue
Sergey Ulanov 2015/05/07 01:05:48 No. It means you shouldn't be reset handler for ev
+ new RegularMediaAccessHandler(pending_requests_));
#if defined(ENABLE_EXTENSIONS)
bool is_whitelisted =
extension && (extension->is_platform_app() ||
IsMediaRequestWhitelistedForExtension(extension));
if (is_whitelisted) {
// For extensions access is approved based on extension permissions.
- ProcessMediaAccessRequestFromPlatformAppOrExtension(
- web_contents, request, callback, extension);
- return;
+ media_access_handler_.reset(
+ new ExtensionMediaAccessHandler(media_stream_capture_indicator_));
}
#endif
- ProcessRegularMediaAccessRequest(web_contents, request, callback);
}
+ media_access_handler_->HandleRequest(web_contents, request, callback,
+ extension);
}
bool MediaCaptureDevicesDispatcher::CheckMediaAccessPermission(
@@ -497,426 +349,6 @@ bool MediaCaptureDevicesDispatcher::CheckMediaAccessPermission(
}
#endif
-void MediaCaptureDevicesDispatcher::ProcessDesktopCaptureAccessRequest(
- content::WebContents* web_contents,
- const content::MediaStreamRequest& request,
- const content::MediaResponseCallback& callback,
- const extensions::Extension* extension) {
- content::MediaStreamDevices devices;
- scoped_ptr<content::MediaStreamUI> ui;
-
- if (request.video_type != content::MEDIA_DESKTOP_VIDEO_CAPTURE) {
- callback.Run(devices, content::MEDIA_DEVICE_INVALID_STATE, ui.Pass());
- return;
- }
-
- // If the device id wasn't specified then this is a screen capture request
- // (i.e. chooseDesktopMedia() API wasn't used to generate device id).
- if (request.requested_video_device_id.empty()) {
- ProcessScreenCaptureAccessRequest(
- web_contents, request, callback, extension);
- return;
- }
-
- // The extension name that the stream is registered with.
- std::string original_extension_name;
- // Resolve DesktopMediaID for the specified device id.
- content::DesktopMediaID media_id;
- // TODO(miu): Replace "main RenderFrame" IDs with the request's actual
- // RenderFrame IDs once the desktop capture extension API implementation is
- // fixed. http://crbug.com/304341
- content::WebContents* const web_contents_for_stream =
- content::WebContents::FromRenderFrameHost(
- content::RenderFrameHost::FromID(request.render_process_id,
- request.render_frame_id));
- content::RenderFrameHost* const main_frame = web_contents_for_stream ?
- web_contents_for_stream->GetMainFrame() : NULL;
- if (main_frame) {
- media_id = GetDesktopStreamsRegistry()->RequestMediaForStreamId(
- request.requested_video_device_id,
- main_frame->GetProcess()->GetID(),
- main_frame->GetRoutingID(),
- request.security_origin,
- &original_extension_name);
- }
-
- // Received invalid device id.
- if (media_id.type == content::DesktopMediaID::TYPE_NONE) {
- callback.Run(devices, content::MEDIA_DEVICE_INVALID_STATE, ui.Pass());
- return;
- }
-
- bool loopback_audio_supported = false;
-#if defined(USE_CRAS) || defined(OS_WIN)
- // Currently loopback audio capture is supported only on Windows and ChromeOS.
- loopback_audio_supported = true;
-#endif
-
- // Audio is only supported for screen capture streams.
- bool capture_audio =
- (media_id.type == content::DesktopMediaID::TYPE_SCREEN &&
- request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE &&
- loopback_audio_supported);
-
- ui = GetDevicesForDesktopCapture(
- &devices, media_id, capture_audio, true,
- GetApplicationTitle(web_contents, extension),
- base::UTF8ToUTF16(original_extension_name));
-
- callback.Run(devices, content::MEDIA_DEVICE_OK, ui.Pass());
-}
-
-void MediaCaptureDevicesDispatcher::ProcessScreenCaptureAccessRequest(
- content::WebContents* web_contents,
- const content::MediaStreamRequest& request,
- const content::MediaResponseCallback& callback,
- const extensions::Extension* extension) {
- content::MediaStreamDevices devices;
- scoped_ptr<content::MediaStreamUI> ui;
-
- DCHECK_EQ(request.video_type, content::MEDIA_DESKTOP_VIDEO_CAPTURE);
-
- bool loopback_audio_supported = false;
-#if defined(USE_CRAS) || defined(OS_WIN)
- // Currently loopback audio capture is supported only on Windows and ChromeOS.
- loopback_audio_supported = true;
-#endif
-
- bool component_extension = false;
-#if defined(ENABLE_EXTENSIONS)
- component_extension =
- extension && extension->location() == extensions::Manifest::COMPONENT;
-#endif
-
- bool screen_capture_enabled =
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableUserMediaScreenCapturing);
-#if defined(ENABLE_EXTENSIONS)
- screen_capture_enabled |=
- IsOriginForCasting(request.security_origin) ||
- IsExtensionWhitelistedForScreenCapture(extension) ||
- IsBuiltInExtension(request.security_origin);
-#endif
-
- const bool origin_is_secure =
- request.security_origin.SchemeIsSecure() ||
- request.security_origin.SchemeIs(extensions::kExtensionScheme) ||
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kAllowHttpScreenCapture);
-
- // If basic conditions (screen capturing is enabled and origin is secure)
- // aren't fulfilled, we'll use "invalid state" as result. Otherwise, we set
- // it after checking permission.
- // TODO(grunell): It would be good to change this result for something else,
- // probably a new one.
- content::MediaStreamRequestResult result =
- content::MEDIA_DEVICE_INVALID_STATE;
-
- // Approve request only when the following conditions are met:
- // 1. Screen capturing is enabled via command line switch or white-listed for
- // the given origin.
- // 2. Request comes from a page with a secure origin or from an extension.
- if (screen_capture_enabled && origin_is_secure) {
- // Get title of the calling application prior to showing the message box.
- // chrome::ShowMessageBox() starts a nested message loop which may allow
- // |web_contents| to be destroyed on the UI thread before the message box
- // is closed. See http://crbug.com/326690.
- base::string16 application_title =
- GetApplicationTitle(web_contents, extension);
-#if !defined(OS_ANDROID)
- gfx::NativeWindow parent_window =
- FindParentWindowForWebContents(web_contents);
-#else
- gfx::NativeWindow parent_window = NULL;
-#endif
- web_contents = NULL;
-
- bool whitelisted_extension = false;
-#if defined(ENABLE_EXTENSIONS)
- whitelisted_extension = IsExtensionWhitelistedForScreenCapture(
- extension);
-#endif
-
- // For whitelisted or component extensions, bypass message box.
- bool user_approved = false;
- if (!whitelisted_extension && !component_extension) {
- base::string16 application_name =
- base::UTF8ToUTF16(request.security_origin.spec());
-#if defined(ENABLE_EXTENSIONS)
- if (extension)
- application_name = base::UTF8ToUTF16(extension->name());
-#endif
- base::string16 confirmation_text = l10n_util::GetStringFUTF16(
- request.audio_type == content::MEDIA_NO_SERVICE ?
- IDS_MEDIA_SCREEN_CAPTURE_CONFIRMATION_TEXT :
- IDS_MEDIA_SCREEN_AND_AUDIO_CAPTURE_CONFIRMATION_TEXT,
- application_name);
- chrome::MessageBoxResult result = chrome::ShowMessageBox(
- parent_window,
- l10n_util::GetStringFUTF16(
- IDS_MEDIA_SCREEN_CAPTURE_CONFIRMATION_TITLE, application_name),
- confirmation_text,
- chrome::MESSAGE_BOX_TYPE_QUESTION);
- user_approved = (result == chrome::MESSAGE_BOX_RESULT_YES);
- }
-
- if (user_approved || component_extension || whitelisted_extension) {
- content::DesktopMediaID screen_id;
-#if defined(OS_CHROMEOS)
- screen_id = content::DesktopMediaID::RegisterAuraWindow(
- ash::Shell::GetInstance()->GetPrimaryRootWindow());
-#else // defined(OS_CHROMEOS)
- screen_id =
- content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN,
- webrtc::kFullDesktopScreenId);
-#endif // !defined(OS_CHROMEOS)
-
- bool capture_audio =
- (request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE &&
- loopback_audio_supported);
-
- // Unless we're being invoked from a component extension, register to
- // display the notification for stream capture.
- bool display_notification = !component_extension;
-
- ui = GetDevicesForDesktopCapture(&devices, screen_id, capture_audio,
- display_notification, application_title,
- application_title);
- DCHECK(!devices.empty());
- }
-
- // The only case when devices can be empty is if the user has denied
- // permission.
- result = devices.empty() ? content::MEDIA_DEVICE_PERMISSION_DENIED
- : content::MEDIA_DEVICE_OK;
- }
-
- callback.Run(devices, result, ui.Pass());
-}
-
-void MediaCaptureDevicesDispatcher::ProcessTabCaptureAccessRequest(
- content::WebContents* web_contents,
- const content::MediaStreamRequest& request,
- const content::MediaResponseCallback& callback,
- const extensions::Extension* extension) {
- content::MediaStreamDevices devices;
- scoped_ptr<content::MediaStreamUI> ui;
-
-#if defined(ENABLE_EXTENSIONS)
- Profile* profile =
- Profile::FromBrowserContext(web_contents->GetBrowserContext());
- extensions::TabCaptureRegistry* tab_capture_registry =
- extensions::TabCaptureRegistry::Get(profile);
- if (!tab_capture_registry) {
- NOTREACHED();
- callback.Run(devices, content::MEDIA_DEVICE_INVALID_STATE, ui.Pass());
- return;
- }
- const bool tab_capture_allowed = tab_capture_registry->VerifyRequest(
- request.render_process_id, request.render_frame_id, extension->id());
-
- if (request.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE &&
- tab_capture_allowed &&
- extension->permissions_data()->HasAPIPermission(
- extensions::APIPermission::kTabCapture)) {
- devices.push_back(content::MediaStreamDevice(
- content::MEDIA_TAB_AUDIO_CAPTURE, std::string(), std::string()));
- }
-
- if (request.video_type == content::MEDIA_TAB_VIDEO_CAPTURE &&
- tab_capture_allowed &&
- extension->permissions_data()->HasAPIPermission(
- extensions::APIPermission::kTabCapture)) {
- devices.push_back(content::MediaStreamDevice(
- content::MEDIA_TAB_VIDEO_CAPTURE, std::string(), std::string()));
- }
-
- if (!devices.empty()) {
- ui = media_stream_capture_indicator_->RegisterMediaStream(
- web_contents, devices);
- }
- callback.Run(
- devices,
- devices.empty() ? content::MEDIA_DEVICE_INVALID_STATE :
- content::MEDIA_DEVICE_OK,
- ui.Pass());
-#else // defined(ENABLE_EXTENSIONS)
- callback.Run(devices, content::MEDIA_DEVICE_TAB_CAPTURE_FAILURE, ui.Pass());
-#endif // defined(ENABLE_EXTENSIONS)
-}
-
-#if defined(ENABLE_EXTENSIONS)
-void MediaCaptureDevicesDispatcher::
- ProcessMediaAccessRequestFromPlatformAppOrExtension(
- content::WebContents* web_contents,
- const content::MediaStreamRequest& request,
- const content::MediaResponseCallback& callback,
- const extensions::Extension* extension) {
- // TODO(vrk): This code is largely duplicated in
- // MediaStreamDevicesController::Accept(). Move this code into a shared method
- // between the two classes.
-
- Profile* profile =
- Profile::FromBrowserContext(web_contents->GetBrowserContext());
-
- bool audio_allowed =
- request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE &&
- extension->permissions_data()->HasAPIPermission(
- extensions::APIPermission::kAudioCapture) &&
- GetDevicePolicy(profile, extension->url(),
- prefs::kAudioCaptureAllowed,
- prefs::kAudioCaptureAllowedUrls) != ALWAYS_DENY;
- bool video_allowed =
- request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE &&
- extension->permissions_data()->HasAPIPermission(
- extensions::APIPermission::kVideoCapture) &&
- GetDevicePolicy(profile, extension->url(),
- prefs::kVideoCaptureAllowed,
- prefs::kVideoCaptureAllowedUrls) != ALWAYS_DENY;
-
- bool get_default_audio_device = audio_allowed;
- bool get_default_video_device = video_allowed;
-
- content::MediaStreamDevices devices;
-
- // 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
- // empty list with "invalid state" result. If at least one is allowed, we'll
- // try to get device(s), and if failure, we want to return "no hardware"
- // result.
- // TODO(grunell): The invalid state result should be changed to a new denied
- // result + a dcheck to ensure at least one of audio or video types is
- // capture.
- content::MediaStreamRequestResult result =
- (audio_allowed || video_allowed) ? content::MEDIA_DEVICE_NO_HARDWARE
- : content::MEDIA_DEVICE_INVALID_STATE;
-
- // Get the exact audio or video device if an id is specified.
- // We only set any error result here and before running the callback change
- // it to OK if we have any device.
- if (audio_allowed && !request.requested_audio_device_id.empty()) {
- const content::MediaStreamDevice* audio_device =
- GetRequestedAudioDevice(request.requested_audio_device_id);
- if (audio_device) {
- devices.push_back(*audio_device);
- get_default_audio_device = false;
- }
- }
- if (video_allowed && !request.requested_video_device_id.empty()) {
- const content::MediaStreamDevice* video_device =
- GetRequestedVideoDevice(request.requested_video_device_id);
- if (video_device) {
- devices.push_back(*video_device);
- get_default_video_device = false;
- }
- }
-
- // If either or both audio and video devices were requested but not
- // specified by id, get the default devices.
- if (get_default_audio_device || get_default_video_device) {
- GetDefaultDevicesForProfile(profile,
- get_default_audio_device,
- get_default_video_device,
- &devices);
- }
-
- scoped_ptr<content::MediaStreamUI> ui;
- if (!devices.empty()) {
- result = content::MEDIA_DEVICE_OK;
- ui = media_stream_capture_indicator_->RegisterMediaStream(
- web_contents, devices);
- }
-
- callback.Run(devices, result, ui.Pass());
-}
-#endif
-
-void MediaCaptureDevicesDispatcher::ProcessRegularMediaAccessRequest(
- content::WebContents* web_contents,
- const content::MediaStreamRequest& request,
- const content::MediaResponseCallback& callback) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- RequestsQueue& queue = pending_requests_[web_contents];
- queue.push_back(PendingAccessRequest(request, callback));
-
- // If this is the only request then show the infobar.
- if (queue.size() == 1)
- ProcessQueuedAccessRequest(web_contents);
-}
-
-void MediaCaptureDevicesDispatcher::ProcessQueuedAccessRequest(
- content::WebContents* web_contents) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- std::map<content::WebContents*, RequestsQueue>::iterator it =
- pending_requests_.find(web_contents);
-
- if (it == pending_requests_.end() || it->second.empty()) {
- // Don't do anything if the tab was closed.
- return;
- }
-
- DCHECK(!it->second.empty());
-
- if (PermissionBubbleManager::Enabled() ||
- MediaStreamPermissionBubbleExperimentEnabled()) {
- scoped_ptr<MediaStreamDevicesController> controller(
- new MediaStreamDevicesController(web_contents,
- it->second.front().request,
- base::Bind(&MediaCaptureDevicesDispatcher::OnAccessRequestResponse,
- base::Unretained(this), web_contents)));
- if (controller->DismissInfoBarAndTakeActionOnSettings())
- return;
- PermissionBubbleManager* bubble_manager =
- PermissionBubbleManager::FromWebContents(web_contents);
- if (bubble_manager)
- bubble_manager->AddRequest(controller.release());
- return;
- }
-
- // TODO(gbillock): delete this block and the MediaStreamInfoBarDelegate
- // when we've transitioned to bubbles. (crbug/337458)
- MediaStreamInfoBarDelegate::Create(
- web_contents, it->second.front().request,
- base::Bind(&MediaCaptureDevicesDispatcher::OnAccessRequestResponse,
- base::Unretained(this), web_contents));
-}
-
-void MediaCaptureDevicesDispatcher::OnAccessRequestResponse(
- content::WebContents* web_contents,
- const content::MediaStreamDevices& devices,
- content::MediaStreamRequestResult result,
- scoped_ptr<content::MediaStreamUI> ui) {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
-
- std::map<content::WebContents*, RequestsQueue>::iterator it =
- pending_requests_.find(web_contents);
- if (it == pending_requests_.end()) {
- // WebContents has been destroyed. Don't need to do anything.
- return;
- }
-
- RequestsQueue& queue(it->second);
- if (queue.empty())
- return;
-
- content::MediaResponseCallback callback = queue.front().callback;
- queue.pop_front();
-
- if (!queue.empty()) {
- // Post a task to process next queued request. It has to be done
- // asynchronously to make sure that calling infobar is not destroyed until
- // after this function returns.
- BrowserThread::PostTask(
- BrowserThread::UI, FROM_HERE,
- base::Bind(&MediaCaptureDevicesDispatcher::ProcessQueuedAccessRequest,
- base::Unretained(this), web_contents));
- }
-
- callback.Run(devices, result, ui.Pass());
-}
-
void MediaCaptureDevicesDispatcher::GetDefaultDevicesForProfile(
Profile* profile,
bool audio,

Powered by Google App Engine
This is Rietveld 408576698