1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/media/webrtc/desktop_capture_devices_util.h"
6
7 #include <string>
8 #include <utility>
9
10 #include "base/strings/string_util.h"
11 #include "build/build_config.h"
12 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h"
13 #include "chrome/browser/ui/screen_capture_notification_ui.h"
14 #include "chrome/browser/ui/tab_sharing/tab_sharing_ui.h"
15 #include "chrome/common/chrome_features.h"
16 #include "chrome/grit/generated_resources.h"
17 #include "content/public/browser/browser_thread.h"
18 #include "media/audio/audio_device_description.h"
19 #include "media/mojo/mojom/display_media_information.mojom.h"
20 #include "ui/base/l10n/l10n_util.h"
21
22 namespace {
23
24 media::mojom::DisplayMediaInformationPtr
DesktopMediaIDToDisplayMediaInformation(const content::DesktopMediaID & media_id)25 DesktopMediaIDToDisplayMediaInformation(
26 const content::DesktopMediaID& media_id) {
27 media::mojom::DisplayCaptureSurfaceType display_surface =
28 media::mojom::DisplayCaptureSurfaceType::MONITOR;
29 bool logical_surface = true;
30 media::mojom::CursorCaptureType cursor =
31 media::mojom::CursorCaptureType::NEVER;
32 #if defined(USE_AURA)
33 const bool uses_aura =
34 media_id.window_id != content::DesktopMediaID::kNullId ? true : false;
35 #else
36 const bool uses_aura = false;
37 #endif // defined(USE_AURA)
38 switch (media_id.type) {
39 case content::DesktopMediaID::TYPE_SCREEN:
40 display_surface = media::mojom::DisplayCaptureSurfaceType::MONITOR;
41 cursor = uses_aura ? media::mojom::CursorCaptureType::MOTION
42 : media::mojom::CursorCaptureType::ALWAYS;
43 break;
44 case content::DesktopMediaID::TYPE_WINDOW:
45 display_surface = media::mojom::DisplayCaptureSurfaceType::WINDOW;
46 cursor = uses_aura ? media::mojom::CursorCaptureType::MOTION
47 : media::mojom::CursorCaptureType::ALWAYS;
48 break;
49 case content::DesktopMediaID::TYPE_WEB_CONTENTS:
50 display_surface = media::mojom::DisplayCaptureSurfaceType::BROWSER;
51 cursor = media::mojom::CursorCaptureType::MOTION;
52 break;
53 case content::DesktopMediaID::TYPE_NONE:
54 break;
55 }
56
57 return media::mojom::DisplayMediaInformation::New(display_surface,
58 logical_surface, cursor);
59 }
60
GetStopSharingUIString(const base::string16 & application_title,const base::string16 & registered_extension_name,bool capture_audio,content::DesktopMediaID::Type capture_type)61 base::string16 GetStopSharingUIString(
62 const base::string16& application_title,
63 const base::string16& registered_extension_name,
64 bool capture_audio,
65 content::DesktopMediaID::Type capture_type) {
66 if (!capture_audio) {
67 if (application_title == registered_extension_name) {
68 switch (capture_type) {
69 case content::DesktopMediaID::TYPE_SCREEN:
70 return l10n_util::GetStringFUTF16(
71 IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TEXT, application_title);
72 case content::DesktopMediaID::TYPE_WINDOW:
73 return l10n_util::GetStringFUTF16(
74 IDS_MEDIA_WINDOW_CAPTURE_NOTIFICATION_TEXT, application_title);
75 case content::DesktopMediaID::TYPE_WEB_CONTENTS:
76 return l10n_util::GetStringFUTF16(
77 IDS_MEDIA_TAB_CAPTURE_NOTIFICATION_TEXT, application_title);
78 case content::DesktopMediaID::TYPE_NONE:
79 NOTREACHED();
80 }
81 } else {
82 switch (capture_type) {
83 case content::DesktopMediaID::TYPE_SCREEN:
84 return l10n_util::GetStringFUTF16(
85 IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TEXT_DELEGATED,
86 registered_extension_name, application_title);
87 case content::DesktopMediaID::TYPE_WINDOW:
88 return l10n_util::GetStringFUTF16(
89 IDS_MEDIA_WINDOW_CAPTURE_NOTIFICATION_TEXT_DELEGATED,
90 registered_extension_name, application_title);
91 case content::DesktopMediaID::TYPE_WEB_CONTENTS:
92 return l10n_util::GetStringFUTF16(
93 IDS_MEDIA_TAB_CAPTURE_NOTIFICATION_TEXT_DELEGATED,
94 registered_extension_name, application_title);
95 case content::DesktopMediaID::TYPE_NONE:
96 NOTREACHED();
97 }
98 }
99 } else { // The case with audio
100 if (application_title == registered_extension_name) {
101 switch (capture_type) {
102 case content::DesktopMediaID::TYPE_SCREEN:
103 return l10n_util::GetStringFUTF16(
104 IDS_MEDIA_SCREEN_CAPTURE_WITH_AUDIO_NOTIFICATION_TEXT,
105 application_title);
106 case content::DesktopMediaID::TYPE_WEB_CONTENTS:
107 return l10n_util::GetStringFUTF16(
108 IDS_MEDIA_TAB_CAPTURE_WITH_AUDIO_NOTIFICATION_TEXT,
109 application_title);
110 case content::DesktopMediaID::TYPE_NONE:
111 case content::DesktopMediaID::TYPE_WINDOW:
112 NOTREACHED();
113 }
114 } else {
115 switch (capture_type) {
116 case content::DesktopMediaID::TYPE_SCREEN:
117 return l10n_util::GetStringFUTF16(
118 IDS_MEDIA_SCREEN_CAPTURE_WITH_AUDIO_NOTIFICATION_TEXT_DELEGATED,
119 registered_extension_name, application_title);
120 case content::DesktopMediaID::TYPE_WEB_CONTENTS:
121 return l10n_util::GetStringFUTF16(
122 IDS_MEDIA_TAB_CAPTURE_WITH_AUDIO_NOTIFICATION_TEXT_DELEGATED,
123 registered_extension_name, application_title);
124 case content::DesktopMediaID::TYPE_NONE:
125 case content::DesktopMediaID::TYPE_WINDOW:
126 NOTREACHED();
127 }
128 }
129 }
130 return base::string16();
131 }
132
133 } // namespace
134
GetDevicesForDesktopCapture(content::WebContents * web_contents,blink::MediaStreamDevices * devices,const content::DesktopMediaID & media_id,blink::mojom::MediaStreamType devices_video_type,blink::mojom::MediaStreamType devices_audio_type,bool capture_audio,bool disable_local_echo,bool display_notification,const base::string16 & application_title,const base::string16 & registered_extension_name)135 std::unique_ptr<content::MediaStreamUI> GetDevicesForDesktopCapture(
136 content::WebContents* web_contents,
137 blink::MediaStreamDevices* devices,
138 const content::DesktopMediaID& media_id,
139 blink::mojom::MediaStreamType devices_video_type,
140 blink::mojom::MediaStreamType devices_audio_type,
141 bool capture_audio,
142 bool disable_local_echo,
143 bool display_notification,
144 const base::string16& application_title,
145 const base::string16& registered_extension_name) {
146 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
147
148 DVLOG(2) << __func__ << ": media_id " << media_id.ToString()
149 << ", capture_audio " << capture_audio << ", disable_local_echo "
150 << disable_local_echo << ", display_notification "
151 << display_notification << ", application_title "
152 << application_title << ", extension_name "
153 << registered_extension_name;
154
155 // Add selected desktop source to the list.
156 auto device = blink::MediaStreamDevice(
157 devices_video_type, media_id.ToString(), media_id.ToString());
158 device.display_media_info = DesktopMediaIDToDisplayMediaInformation(media_id);
159 devices->push_back(device);
160 if (capture_audio) {
161 if (media_id.type == content::DesktopMediaID::TYPE_WEB_CONTENTS) {
162 content::WebContentsMediaCaptureId web_id = media_id.web_contents_id;
163 web_id.disable_local_echo = disable_local_echo;
164 devices->push_back(blink::MediaStreamDevice(
165 devices_audio_type, web_id.ToString(), "Tab audio"));
166 } else if (disable_local_echo) {
167 // Use the special loopback device ID for system audio capture.
168 devices->push_back(blink::MediaStreamDevice(
169 devices_audio_type,
170 media::AudioDeviceDescription::kLoopbackWithMuteDeviceId,
171 "System Audio"));
172 } else {
173 // Use the special loopback device ID for system audio capture.
174 devices->push_back(blink::MediaStreamDevice(
175 devices_audio_type,
176 media::AudioDeviceDescription::kLoopbackInputDeviceId,
177 "System Audio"));
178 }
179 }
180
181 // If required, register to display the notification for stream capture.
182 std::unique_ptr<MediaStreamUI> notification_ui;
183 if (display_notification) {
184 if (media_id.type == content::DesktopMediaID::TYPE_WEB_CONTENTS &&
185 base::FeatureList::IsEnabled(
186 features::kDesktopCaptureTabSharingInfobar)) {
187 notification_ui = TabSharingUI::Create(media_id, application_title);
188 } else {
189 notification_ui = ScreenCaptureNotificationUI::Create(
190 GetStopSharingUIString(application_title, registered_extension_name,
191 capture_audio, media_id.type));
192 }
193 }
194
195 return MediaCaptureDevicesDispatcher::GetInstance()
196 ->GetMediaStreamCaptureIndicator()
197 ->RegisterMediaStream(web_contents, *devices, std::move(notification_ui));
198 }
199