Index: chrome/browser/media/desktop_capture_access_handler.cc |
diff --git a/chrome/browser/media/desktop_capture_access_handler.cc b/chrome/browser/media/desktop_capture_access_handler.cc |
deleted file mode 100644 |
index 19577a2ae691db22f867301feca4faf61a866f3a..0000000000000000000000000000000000000000 |
--- a/chrome/browser/media/desktop_capture_access_handler.cc |
+++ /dev/null |
@@ -1,435 +0,0 @@ |
-// Copyright 2015 The Chromium Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
- |
-#include "chrome/browser/media/desktop_capture_access_handler.h" |
- |
-#include <utility> |
- |
-#include "base/command_line.h" |
-#include "base/strings/string_number_conversions.h" |
-#include "base/strings/string_util.h" |
-#include "base/strings/utf_string_conversions.h" |
-#include "build/build_config.h" |
-#include "chrome/browser/media/desktop_streams_registry.h" |
-#include "chrome/browser/media/media_capture_devices_dispatcher.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/common/chrome_switches.h" |
-#include "chrome/grit/generated_resources.h" |
-#include "content/public/browser/browser_thread.h" |
-#include "content/public/browser/desktop_media_id.h" |
-#include "content/public/browser/render_frame_host.h" |
-#include "content/public/browser/render_process_host.h" |
-#include "content/public/common/content_switches.h" |
-#include "content/public/common/media_stream_request.h" |
-#include "content/public/common/origin_util.h" |
-#include "extensions/browser/app_window/app_window.h" |
-#include "extensions/browser/app_window/app_window_registry.h" |
-#include "extensions/common/constants.h" |
-#include "extensions/common/extension.h" |
-#include "extensions/common/switches.h" |
-#include "media/audio/audio_device_description.h" |
-#include "net/base/url_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) |
- |
-using content::BrowserThread; |
- |
-namespace { |
- |
-// 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 (extension) { |
- title = extension->name(); |
- return base::UTF8ToUTF16(title); |
- } |
- GURL url = web_contents->GetURL(); |
- title = content::IsOriginSecure(url) ? net::GetHostAndOptionalPort(url) |
- : url.GetOrigin().spec(); |
- return base::UTF8ToUTF16(title); |
-} |
- |
-base::string16 GetStopSharingUIString( |
- const base::string16& application_title, |
- const base::string16& registered_extension_name, |
- bool capture_audio, |
- content::DesktopMediaID::Type capture_type) { |
- if (!capture_audio) { |
- if (application_title == registered_extension_name) { |
- switch (capture_type) { |
- case content::DesktopMediaID::TYPE_SCREEN: |
- return l10n_util::GetStringFUTF16( |
- IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TEXT, application_title); |
- case content::DesktopMediaID::TYPE_WINDOW: |
- return l10n_util::GetStringFUTF16( |
- IDS_MEDIA_WINDOW_CAPTURE_NOTIFICATION_TEXT, application_title); |
- case content::DesktopMediaID::TYPE_WEB_CONTENTS: |
- return l10n_util::GetStringFUTF16( |
- IDS_MEDIA_TAB_CAPTURE_NOTIFICATION_TEXT, application_title); |
- case content::DesktopMediaID::TYPE_NONE: |
- NOTREACHED(); |
- } |
- } else { |
- switch (capture_type) { |
- case content::DesktopMediaID::TYPE_SCREEN: |
- return l10n_util::GetStringFUTF16( |
- IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TEXT_DELEGATED, |
- registered_extension_name, application_title); |
- case content::DesktopMediaID::TYPE_WINDOW: |
- return l10n_util::GetStringFUTF16( |
- IDS_MEDIA_WINDOW_CAPTURE_NOTIFICATION_TEXT_DELEGATED, |
- registered_extension_name, application_title); |
- case content::DesktopMediaID::TYPE_WEB_CONTENTS: |
- return l10n_util::GetStringFUTF16( |
- IDS_MEDIA_TAB_CAPTURE_NOTIFICATION_TEXT_DELEGATED, |
- registered_extension_name, application_title); |
- case content::DesktopMediaID::TYPE_NONE: |
- NOTREACHED(); |
- } |
- } |
- } else { // The case with audio |
- if (application_title == registered_extension_name) { |
- switch (capture_type) { |
- case content::DesktopMediaID::TYPE_SCREEN: |
- return l10n_util::GetStringFUTF16( |
- IDS_MEDIA_SCREEN_CAPTURE_WITH_AUDIO_NOTIFICATION_TEXT, |
- application_title); |
- case content::DesktopMediaID::TYPE_WEB_CONTENTS: |
- return l10n_util::GetStringFUTF16( |
- IDS_MEDIA_TAB_CAPTURE_WITH_AUDIO_NOTIFICATION_TEXT, |
- application_title); |
- case content::DesktopMediaID::TYPE_NONE: |
- case content::DesktopMediaID::TYPE_WINDOW: |
- NOTREACHED(); |
- } |
- } else { |
- switch (capture_type) { |
- case content::DesktopMediaID::TYPE_SCREEN: |
- return l10n_util::GetStringFUTF16( |
- IDS_MEDIA_SCREEN_CAPTURE_WITH_AUDIO_NOTIFICATION_TEXT_DELEGATED, |
- registered_extension_name, application_title); |
- case content::DesktopMediaID::TYPE_WEB_CONTENTS: |
- return l10n_util::GetStringFUTF16( |
- IDS_MEDIA_TAB_CAPTURE_WITH_AUDIO_NOTIFICATION_TEXT_DELEGATED, |
- registered_extension_name, application_title); |
- case content::DesktopMediaID::TYPE_NONE: |
- case content::DesktopMediaID::TYPE_WINDOW: |
- NOTREACHED(); |
- } |
- } |
- } |
- return base::string16(); |
-} |
-// 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. |
-std::unique_ptr<content::MediaStreamUI> GetDevicesForDesktopCapture( |
- content::MediaStreamDevices* devices, |
- content::DesktopMediaID media_id, |
- bool capture_audio, |
- bool mute_system_audio, |
- bool display_notification, |
- const base::string16& application_title, |
- const base::string16& registered_extension_name) { |
- DCHECK_CURRENTLY_ON(BrowserThread::UI); |
- std::unique_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) { |
- if (media_id.type == content::DesktopMediaID::TYPE_WEB_CONTENTS) { |
- devices->push_back( |
- content::MediaStreamDevice(content::MEDIA_DESKTOP_AUDIO_CAPTURE, |
- media_id.ToString(), "Tab audio")); |
- } else if (mute_system_audio) { |
- // Use the special loopback device ID for system audio capture. |
- devices->push_back(content::MediaStreamDevice( |
- content::MEDIA_DESKTOP_AUDIO_CAPTURE, |
- media::AudioDeviceDescription::kLoopbackWithMuteDeviceId, |
- "System Audio")); |
- } else { |
- // Use the special loopback device ID for system audio capture. |
- devices->push_back(content::MediaStreamDevice( |
- content::MEDIA_DESKTOP_AUDIO_CAPTURE, |
- media::AudioDeviceDescription::kLoopbackInputDeviceId, |
- "System Audio")); |
- } |
- } |
- |
- // If required, register to display the notification for stream capture. |
- if (!display_notification) { |
- return ui; |
- } |
- |
- ui = ScreenCaptureNotificationUI::Create(GetStopSharingUIString( |
- application_title, registered_extension_name, capture_audio, |
- media_id.type)); |
- |
- return ui; |
-} |
- |
-#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 |
- |
-} // namespace |
- |
-DesktopCaptureAccessHandler::DesktopCaptureAccessHandler() { |
-} |
- |
-DesktopCaptureAccessHandler::~DesktopCaptureAccessHandler() { |
-} |
- |
-void DesktopCaptureAccessHandler::ProcessScreenCaptureAccessRequest( |
- content::WebContents* web_contents, |
- const content::MediaStreamRequest& request, |
- const content::MediaResponseCallback& callback, |
- const extensions::Extension* extension) { |
- content::MediaStreamDevices devices; |
- std::unique_ptr<content::MediaStreamUI> ui; |
- |
- DCHECK_EQ(request.video_type, content::MEDIA_DESKTOP_VIDEO_CAPTURE); |
- |
- UpdateExtensionTrusted(request, extension); |
- |
- 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; |
- component_extension = |
- extension && extension->location() == extensions::Manifest::COMPONENT; |
- |
- bool screen_capture_enabled = |
- base::CommandLine::ForCurrentProcess()->HasSwitch( |
- switches::kEnableUserMediaScreenCapturing) || |
- MediaCaptureDevicesDispatcher::IsOriginForCasting( |
- request.security_origin) || |
- IsExtensionWhitelistedForScreenCapture(extension) || |
- IsBuiltInExtension(request.security_origin); |
- |
- const bool origin_is_secure = |
- content::IsOriginSecure(request.security_origin) || |
- 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::ShowQuestionMessageBox() starts a nested message loop which may |
- // allow |web_contents| to be destroyed on the UI thread before the messag |
- // 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 = |
- IsExtensionWhitelistedForScreenCapture(extension); |
- |
- // 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 (extension) |
- application_name = base::UTF8ToUTF16(extension->name()); |
- 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::ShowQuestionMessageBox( |
- parent_window, |
- l10n_util::GetStringFUTF16( |
- IDS_MEDIA_SCREEN_CAPTURE_CONFIRMATION_TITLE, application_name), |
- confirmation_text); |
- 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( |
- content::DesktopMediaID::TYPE_SCREEN, |
- 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, true, |
- 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, std::move(ui)); |
-} |
- |
-bool DesktopCaptureAccessHandler::SupportsStreamType( |
- const content::MediaStreamType type, |
- const extensions::Extension* extension) { |
- return type == content::MEDIA_DESKTOP_VIDEO_CAPTURE || |
- type == content::MEDIA_DESKTOP_AUDIO_CAPTURE; |
-} |
- |
-bool DesktopCaptureAccessHandler::CheckMediaAccessPermission( |
- content::WebContents* web_contents, |
- const GURL& security_origin, |
- content::MediaStreamType type, |
- const extensions::Extension* extension) { |
- return false; |
-} |
- |
-void DesktopCaptureAccessHandler::HandleRequest( |
- content::WebContents* web_contents, |
- const content::MediaStreamRequest& request, |
- const content::MediaResponseCallback& callback, |
- const extensions::Extension* extension) { |
- content::MediaStreamDevices devices; |
- std::unique_ptr<content::MediaStreamUI> ui; |
- |
- if (request.video_type != content::MEDIA_DESKTOP_VIDEO_CAPTURE) { |
- callback.Run(devices, content::MEDIA_DEVICE_INVALID_STATE, std::move(ui)); |
- 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 = MediaCaptureDevicesDispatcher::GetInstance() |
- ->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, std::move(ui)); |
- 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 |
- |
- // This value essentially from the checkbox on picker window, so it |
- // corresponds to user permission. |
- const bool audio_permitted = media_id.audio_share; |
- |
- // This value essentially from whether getUserMedia requests audio stream. |
- const bool audio_requested = |
- request.audio_type == content::MEDIA_DESKTOP_AUDIO_CAPTURE; |
- |
- // This value shows for a given capture type, whether the system or our code |
- // can support audio sharing. Currently audio is only supported for screen and |
- // tab/webcontents capture streams. |
- const bool audio_supported = |
- (media_id.type == content::DesktopMediaID::TYPE_SCREEN && |
- loopback_audio_supported) || |
- media_id.type == content::DesktopMediaID::TYPE_WEB_CONTENTS; |
- |
- const bool check_audio_permission = |
- !base::CommandLine::ForCurrentProcess()->HasSwitch( |
- extensions::switches::kDisableDesktopCaptureAudio); |
- const bool capture_audio = |
- (check_audio_permission ? audio_permitted : true) && audio_requested && |
- audio_supported; |
- |
- ui = GetDevicesForDesktopCapture(&devices, media_id, capture_audio, false, |
- true, |
- GetApplicationTitle(web_contents, extension), |
- base::UTF8ToUTF16(original_extension_name)); |
- UpdateExtensionTrusted(request, extension); |
- callback.Run(devices, content::MEDIA_DEVICE_OK, std::move(ui)); |
-} |
- |