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

Side by Side Diff: chrome/browser/media/media_capture_devices_dispatcher.cc

Issue 98233009: Fix crash in MediaCaptureDevicesDispatcher::ProcessScreenCaptureAccessRequest. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Invalid the |web_contents| pointer just to be safe. Created 7 years 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/media/media_capture_devices_dispatcher.h" 5 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/logging.h" 8 #include "base/logging.h"
9 #include "base/prefs/pref_service.h" 9 #include "base/prefs/pref_service.h"
10 #include "base/prefs/scoped_user_pref_update.h" 10 #include "base/prefs/scoped_user_pref_update.h"
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
104 // Use extension name as title for extensions and origin for drive-by web. 104 // Use extension name as title for extensions and origin for drive-by web.
105 std::string title; 105 std::string title;
106 if (extension) { 106 if (extension) {
107 title = extension->name(); 107 title = extension->name();
108 } else { 108 } else {
109 title = web_contents->GetURL().GetOrigin().spec(); 109 title = web_contents->GetURL().GetOrigin().spec();
110 } 110 }
111 return UTF8ToUTF16(title); 111 return UTF8ToUTF16(title);
112 } 112 }
113 113
114 // Helper to get list of media stream devices for desktop capture in |devices|.
115 // Registers to display notification if |display_notification| is true.
116 // Returns an instance of MediaStreamUI to be passed to content layer.
117 scoped_ptr<content::MediaStreamUI> GetDevicesForDesktopCapture(
118 content::MediaStreamDevices& devices,
119 content::DesktopMediaID media_id,
120 bool capture_audio,
121 bool display_notification,
122 base::string16 application_title) {
123 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
124 scoped_ptr<content::MediaStreamUI> ui;
125
126 // Add selected desktop source to the list.
127 devices.push_back(content::MediaStreamDevice(
128 content::MEDIA_DESKTOP_VIDEO_CAPTURE, media_id.ToString(), "Screen"));
129 if (capture_audio) {
130 // Use the special loopback device ID for system audio capture.
131 devices.push_back(content::MediaStreamDevice(
132 content::MEDIA_LOOPBACK_AUDIO_CAPTURE,
133 media::AudioManagerBase::kLoopbackInputDeviceId, "System Audio"));
134 }
135
136 // If required, register to display the notification for stream capture.
137 if (display_notification) {
138 ui = ScreenCaptureNotificationUI::Create(l10n_util::GetStringFUTF16(
139 IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TEXT,
140 application_title));
141 }
142
143 return ui.Pass();
144 }
145
114 } // namespace 146 } // namespace
115 147
116 MediaCaptureDevicesDispatcher::PendingAccessRequest::PendingAccessRequest( 148 MediaCaptureDevicesDispatcher::PendingAccessRequest::PendingAccessRequest(
117 const content::MediaStreamRequest& request, 149 const content::MediaStreamRequest& request,
118 const content::MediaResponseCallback& callback) 150 const content::MediaResponseCallback& callback)
119 : request(request), 151 : request(request),
120 callback(callback) { 152 callback(callback) {
121 } 153 }
122 154
123 MediaCaptureDevicesDispatcher::PendingAccessRequest::~PendingAccessRequest() {} 155 MediaCaptureDevicesDispatcher::PendingAccessRequest::~PendingAccessRequest() {}
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
244 request.render_view_id, request.security_origin); 276 request.render_view_id, request.security_origin);
245 277
246 // If the id wasn't generated using Desktop Capture API then process it as a 278 // If the id wasn't generated using Desktop Capture API then process it as a
247 // screen capture request. 279 // screen capture request.
248 if (media_id.type == content::DesktopMediaID::TYPE_NONE) { 280 if (media_id.type == content::DesktopMediaID::TYPE_NONE) {
249 ProcessScreenCaptureAccessRequest( 281 ProcessScreenCaptureAccessRequest(
250 web_contents, request, callback, extension); 282 web_contents, request, callback, extension);
251 return; 283 return;
252 } 284 }
253 285
254 // Add selected desktop source to the list.
255 devices.push_back(content::MediaStreamDevice(
256 content::MEDIA_DESKTOP_VIDEO_CAPTURE, media_id.ToString(),
257 std::string()));
258
259 bool loopback_audio_supported = false; 286 bool loopback_audio_supported = false;
260 #if defined(USE_CRAS) || defined(OS_WIN) 287 #if defined(USE_CRAS) || defined(OS_WIN)
261 // Currently loopback audio capture is supported only on Windows and ChromeOS. 288 // Currently loopback audio capture is supported only on Windows and ChromeOS.
262 loopback_audio_supported = true; 289 loopback_audio_supported = true;
263 #endif 290 #endif
264 291
265 // Audio is only supported for screen capture streams. 292 // Audio is only supported for screen capture streams.
266 if (media_id.type == content::DesktopMediaID::TYPE_SCREEN && 293 bool capture_audio =
267 request.audio_type == content::MEDIA_LOOPBACK_AUDIO_CAPTURE && 294 (media_id.type == content::DesktopMediaID::TYPE_SCREEN &&
268 loopback_audio_supported) { 295 request.audio_type == content::MEDIA_LOOPBACK_AUDIO_CAPTURE &&
269 devices.push_back(content::MediaStreamDevice( 296 loopback_audio_supported);
270 content::MEDIA_LOOPBACK_AUDIO_CAPTURE,
271 media::AudioManagerBase::kLoopbackInputDeviceId, "System Audio"));
272 }
273 297
274 ui = ScreenCaptureNotificationUI::Create(l10n_util::GetStringFUTF16( 298 ui = GetDevicesForDesktopCapture(
275 IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TEXT, 299 devices, media_id, capture_audio, true,
276 GetApplicationTitle(web_contents, extension))); 300 GetApplicationTitle(web_contents, extension));
277 301
278 callback.Run(devices, ui.Pass()); 302 callback.Run(devices, ui.Pass());
279 } 303 }
280 304
281 void MediaCaptureDevicesDispatcher::ProcessScreenCaptureAccessRequest( 305 void MediaCaptureDevicesDispatcher::ProcessScreenCaptureAccessRequest(
282 content::WebContents* web_contents, 306 content::WebContents* web_contents,
283 const content::MediaStreamRequest& request, 307 const content::MediaStreamRequest& request,
284 const content::MediaResponseCallback& callback, 308 const content::MediaResponseCallback& callback,
285 const extensions::Extension* extension) { 309 const extensions::Extension* extension) {
286 content::MediaStreamDevices devices; 310 content::MediaStreamDevices devices;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
323 request.security_origin.SchemeIsSecure() || 347 request.security_origin.SchemeIsSecure() ||
324 request.security_origin.SchemeIs(extensions::kExtensionScheme) || 348 request.security_origin.SchemeIs(extensions::kExtensionScheme) ||
325 CommandLine::ForCurrentProcess()->HasSwitch( 349 CommandLine::ForCurrentProcess()->HasSwitch(
326 switches::kAllowHttpScreenCapture); 350 switches::kAllowHttpScreenCapture);
327 351
328 // Approve request only when the following conditions are met: 352 // Approve request only when the following conditions are met:
329 // 1. Screen capturing is enabled via command line switch or white-listed for 353 // 1. Screen capturing is enabled via command line switch or white-listed for
330 // the given origin. 354 // the given origin.
331 // 2. Request comes from a page with a secure origin or from an extension. 355 // 2. Request comes from a page with a secure origin or from an extension.
332 if (screen_capture_enabled && origin_is_secure) { 356 if (screen_capture_enabled && origin_is_secure) {
357 // Get title of the calling application prior to showing the message box.
358 // chrome::ShowMessageBox() starts a nested message loop which may allow
359 // |web_contents| to be destroyed on the UI thread before the message box
360 // is closed. See http://crbug.com/326690.
361 base::string16 application_title =
362 GetApplicationTitle(web_contents, extension);
363 web_contents = NULL;
364
333 // For component extensions, bypass message box. 365 // For component extensions, bypass message box.
334 bool user_approved = false; 366 bool user_approved = false;
335 if (!component_extension) { 367 if (!component_extension) {
336 base::string16 application_name = UTF8ToUTF16( 368 base::string16 application_name = UTF8ToUTF16(
337 extension ? extension->name() : request.security_origin.spec()); 369 extension ? extension->name() : request.security_origin.spec());
338 base::string16 confirmation_text = l10n_util::GetStringFUTF16( 370 base::string16 confirmation_text = l10n_util::GetStringFUTF16(
339 request.audio_type == content::MEDIA_NO_SERVICE ? 371 request.audio_type == content::MEDIA_NO_SERVICE ?
340 IDS_MEDIA_SCREEN_CAPTURE_CONFIRMATION_TEXT : 372 IDS_MEDIA_SCREEN_CAPTURE_CONFIRMATION_TEXT :
341 IDS_MEDIA_SCREEN_AND_AUDIO_CAPTURE_CONFIRMATION_TEXT, 373 IDS_MEDIA_SCREEN_AND_AUDIO_CAPTURE_CONFIRMATION_TEXT,
342 application_name); 374 application_name);
343 chrome::MessageBoxResult result = chrome::ShowMessageBox( 375 chrome::MessageBoxResult result = chrome::ShowMessageBox(
344 NULL, 376 NULL,
345 l10n_util::GetStringFUTF16( 377 l10n_util::GetStringFUTF16(
346 IDS_MEDIA_SCREEN_CAPTURE_CONFIRMATION_TITLE, application_name), 378 IDS_MEDIA_SCREEN_CAPTURE_CONFIRMATION_TITLE, application_name),
347 confirmation_text, 379 confirmation_text,
348 chrome::MESSAGE_BOX_TYPE_QUESTION); 380 chrome::MESSAGE_BOX_TYPE_QUESTION);
349 user_approved = (result == chrome::MESSAGE_BOX_RESULT_YES); 381 user_approved = (result == chrome::MESSAGE_BOX_RESULT_YES);
350 } 382 }
351 383
352 if (user_approved || component_extension) { 384 if (user_approved || component_extension) {
353 devices.push_back(content::MediaStreamDevice( 385 bool capture_audio =
354 content::MEDIA_DESKTOP_VIDEO_CAPTURE, media_id.ToString(), "Screen")); 386 (request.audio_type == content::MEDIA_LOOPBACK_AUDIO_CAPTURE &&
355 if (request.audio_type == content::MEDIA_LOOPBACK_AUDIO_CAPTURE && 387 loopback_audio_supported);
356 loopback_audio_supported) { 388
357 // Use the special loopback device ID for system audio capture. 389 // Unless we're being invoked from a component extension, register to
358 devices.push_back(content::MediaStreamDevice( 390 // display the notification for stream capture.
359 content::MEDIA_LOOPBACK_AUDIO_CAPTURE, 391 bool display_notification = !component_extension;
360 media::AudioManagerBase::kLoopbackInputDeviceId, "System Audio")); 392
361 } 393 ui = GetDevicesForDesktopCapture(devices, media_id, capture_audio,
394 display_notification, application_title);
362 } 395 }
363 } 396 }
364 397
365 // Unless we're being invoked from a component extension, register to display
366 // the notification for stream capture.
367 if (!devices.empty() && !component_extension) {
368 ui = ScreenCaptureNotificationUI::Create(l10n_util::GetStringFUTF16(
369 IDS_MEDIA_SCREEN_CAPTURE_NOTIFICATION_TEXT,
370 GetApplicationTitle(web_contents, extension)));
371 }
372
373 callback.Run(devices, ui.Pass()); 398 callback.Run(devices, ui.Pass());
374 } 399 }
375 400
376 void MediaCaptureDevicesDispatcher::ProcessTabCaptureAccessRequest( 401 void MediaCaptureDevicesDispatcher::ProcessTabCaptureAccessRequest(
377 content::WebContents* web_contents, 402 content::WebContents* web_contents,
378 const content::MediaStreamRequest& request, 403 const content::MediaStreamRequest& request,
379 const content::MediaResponseCallback& callback, 404 const content::MediaResponseCallback& callback,
380 const extensions::Extension* extension) { 405 const extensions::Extension* extension) {
381 content::MediaStreamDevices devices; 406 content::MediaStreamDevices devices;
382 scoped_ptr<content::MediaStreamUI> ui; 407 scoped_ptr<content::MediaStreamUI> ui;
(...skipping 354 matching lines...) Expand 10 before | Expand all | Expand 10 after
737 int render_view_id) { 762 int render_view_id) {
738 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 763 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
739 FOR_EACH_OBSERVER(Observer, observers_, 764 FOR_EACH_OBSERVER(Observer, observers_,
740 OnCreatingAudioStream(render_process_id, render_view_id)); 765 OnCreatingAudioStream(render_process_id, render_view_id));
741 } 766 }
742 767
743 bool MediaCaptureDevicesDispatcher::IsDesktopCaptureInProgress() { 768 bool MediaCaptureDevicesDispatcher::IsDesktopCaptureInProgress() {
744 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 769 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
745 return desktop_capture_sessions_.size() > 0; 770 return desktop_capture_sessions_.size() > 0;
746 } 771 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698