| OLD | NEW |
| 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/sha1.h" | 10 #include "base/sha1.h" |
| 11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
| 12 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
| 13 #include "chrome/browser/extensions/api/tab_capture/tab_capture_registry.h" | 13 #include "chrome/browser/extensions/api/tab_capture/tab_capture_registry.h" |
| 14 #include "chrome/browser/extensions/api/tab_capture/tab_capture_registry_factory
.h" | 14 #include "chrome/browser/extensions/api/tab_capture/tab_capture_registry_factory
.h" |
| 15 #include "chrome/browser/media/audio_stream_indicator.h" | 15 #include "chrome/browser/media/audio_stream_indicator.h" |
| 16 #include "chrome/browser/media/media_stream_capture_indicator.h" | 16 #include "chrome/browser/media/media_stream_capture_indicator.h" |
| 17 #include "chrome/browser/media/media_stream_infobar_delegate.h" | 17 #include "chrome/browser/media/media_stream_infobar_delegate.h" |
| 18 #include "chrome/browser/prefs/scoped_user_pref_update.h" | 18 #include "chrome/browser/prefs/scoped_user_pref_update.h" |
| 19 #include "chrome/browser/profiles/profile.h" | 19 #include "chrome/browser/profiles/profile.h" |
| 20 #include "chrome/browser/ui/simple_message_box.h" | 20 #include "chrome/browser/ui/simple_message_box.h" |
| 21 #include "chrome/common/chrome_switches.h" | 21 #include "chrome/common/chrome_switches.h" |
| 22 #include "chrome/common/extensions/extension.h" | 22 #include "chrome/common/extensions/extension.h" |
| 23 #include "chrome/common/extensions/feature_switch.h" | 23 #include "chrome/common/extensions/feature_switch.h" |
| 24 #include "chrome/common/pref_names.h" | 24 #include "chrome/common/pref_names.h" |
| 25 #include "components/user_prefs/pref_registry_syncable.h" | 25 #include "components/user_prefs/pref_registry_syncable.h" |
| 26 #include "content/public/browser/browser_thread.h" | 26 #include "content/public/browser/browser_thread.h" |
| 27 #include "content/public/browser/media_devices_monitor.h" | 27 #include "content/public/browser/media_devices_monitor.h" |
| 28 #include "content/public/browser/notification_service.h" |
| 29 #include "content/public/browser/notification_source.h" |
| 30 #include "content/public/browser/notification_types.h" |
| 28 #include "content/public/browser/web_contents.h" | 31 #include "content/public/browser/web_contents.h" |
| 29 #include "content/public/common/media_stream_request.h" | 32 #include "content/public/common/media_stream_request.h" |
| 30 #include "extensions/common/constants.h" | 33 #include "extensions/common/constants.h" |
| 31 #include "grit/generated_resources.h" | 34 #include "grit/generated_resources.h" |
| 32 #include "ui/base/l10n/l10n_util.h" | 35 #include "ui/base/l10n/l10n_util.h" |
| 33 | 36 |
| 34 using content::BrowserThread; | 37 using content::BrowserThread; |
| 35 using content::MediaStreamDevices; | 38 using content::MediaStreamDevices; |
| 36 | 39 |
| 37 namespace { | 40 namespace { |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 73 return | 76 return |
| 74 hexencoded_origin_hash == "3C2705BC432E7C51CA8553FDC5BEE873FF2468EE" || | 77 hexencoded_origin_hash == "3C2705BC432E7C51CA8553FDC5BEE873FF2468EE" || |
| 75 hexencoded_origin_hash == "50F02B8A668CAB274527D58356F07C2143080FCC"; | 78 hexencoded_origin_hash == "50F02B8A668CAB274527D58356F07C2143080FCC"; |
| 76 #else | 79 #else |
| 77 return false; | 80 return false; |
| 78 #endif | 81 #endif |
| 79 } | 82 } |
| 80 | 83 |
| 81 } // namespace | 84 } // namespace |
| 82 | 85 |
| 86 MediaCaptureDevicesDispatcher::PendingAccessRequest::PendingAccessRequest( |
| 87 const content::MediaStreamRequest& request, |
| 88 const content::MediaResponseCallback& callback) |
| 89 : request(request), |
| 90 callback(callback) { |
| 91 } |
| 92 |
| 93 MediaCaptureDevicesDispatcher::PendingAccessRequest::~PendingAccessRequest() {} |
| 94 |
| 83 MediaCaptureDevicesDispatcher* MediaCaptureDevicesDispatcher::GetInstance() { | 95 MediaCaptureDevicesDispatcher* MediaCaptureDevicesDispatcher::GetInstance() { |
| 84 return Singleton<MediaCaptureDevicesDispatcher>::get(); | 96 return Singleton<MediaCaptureDevicesDispatcher>::get(); |
| 85 } | 97 } |
| 86 | 98 |
| 87 MediaCaptureDevicesDispatcher::MediaCaptureDevicesDispatcher() | 99 MediaCaptureDevicesDispatcher::MediaCaptureDevicesDispatcher() |
| 88 : devices_enumerated_(false), | 100 : devices_enumerated_(false), |
| 89 media_stream_capture_indicator_(new MediaStreamCaptureIndicator()), | 101 media_stream_capture_indicator_(new MediaStreamCaptureIndicator()), |
| 90 audio_stream_indicator_(new AudioStreamIndicator()) {} | 102 audio_stream_indicator_(new AudioStreamIndicator()) { |
| 103 notifications_registrar_.Add( |
| 104 this, content::NOTIFICATION_WEB_CONTENTS_DESTROYED, |
| 105 content::NotificationService::AllSources()); |
| 106 } |
| 91 | 107 |
| 92 MediaCaptureDevicesDispatcher::~MediaCaptureDevicesDispatcher() {} | 108 MediaCaptureDevicesDispatcher::~MediaCaptureDevicesDispatcher() {} |
| 93 | 109 |
| 94 void MediaCaptureDevicesDispatcher::RegisterUserPrefs( | 110 void MediaCaptureDevicesDispatcher::RegisterUserPrefs( |
| 95 user_prefs::PrefRegistrySyncable* registry) { | 111 user_prefs::PrefRegistrySyncable* registry) { |
| 96 registry->RegisterStringPref( | 112 registry->RegisterStringPref( |
| 97 prefs::kDefaultAudioCaptureDevice, | 113 prefs::kDefaultAudioCaptureDevice, |
| 98 std::string(), | 114 std::string(), |
| 99 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); | 115 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); |
| 100 registry->RegisterStringPref( | 116 registry->RegisterStringPref( |
| (...skipping 30 matching lines...) Expand all Loading... |
| 131 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 147 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 132 if (!devices_enumerated_) { | 148 if (!devices_enumerated_) { |
| 133 BrowserThread::PostTask( | 149 BrowserThread::PostTask( |
| 134 BrowserThread::IO, FROM_HERE, | 150 BrowserThread::IO, FROM_HERE, |
| 135 base::Bind(&content::EnsureMonitorCaptureDevices)); | 151 base::Bind(&content::EnsureMonitorCaptureDevices)); |
| 136 devices_enumerated_ = true; | 152 devices_enumerated_ = true; |
| 137 } | 153 } |
| 138 return video_devices_; | 154 return video_devices_; |
| 139 } | 155 } |
| 140 | 156 |
| 157 void MediaCaptureDevicesDispatcher::Observe( |
| 158 int type, |
| 159 const content::NotificationSource& source, |
| 160 const content::NotificationDetails& details) { |
| 161 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 162 if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { |
| 163 content::WebContents* web_contents = |
| 164 content::Source<content::WebContents>(source).ptr(); |
| 165 pending_requests_.erase(web_contents); |
| 166 } |
| 167 } |
| 168 |
| 141 void MediaCaptureDevicesDispatcher::ProcessMediaAccessRequest( | 169 void MediaCaptureDevicesDispatcher::ProcessMediaAccessRequest( |
| 142 content::WebContents* web_contents, | 170 content::WebContents* web_contents, |
| 143 const content::MediaStreamRequest& request, | 171 const content::MediaStreamRequest& request, |
| 144 const content::MediaResponseCallback& callback, | 172 const content::MediaResponseCallback& callback, |
| 145 const extensions::Extension* extension) { | 173 const extensions::Extension* extension) { |
| 146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 174 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 147 | 175 |
| 148 if (request.video_type == content::MEDIA_SCREEN_VIDEO_CAPTURE) { | 176 if (request.video_type == content::MEDIA_SCREEN_VIDEO_CAPTURE) { |
| 149 ProcessScreenCaptureAccessRequest(web_contents, request, callback); | 177 ProcessScreenCaptureAccessRequest(web_contents, request, callback); |
| 150 } else if (extension) { | 178 } else if (extension) { |
| 151 // For extensions access is approved based on extension permissions. | 179 // For extensions access is approved based on extension permissions. |
| 152 ProcessMediaAccessRequestFromExtension( | 180 ProcessMediaAccessRequestFromExtension( |
| 153 web_contents, request, callback, extension); | 181 web_contents, request, callback, extension); |
| 154 } else { | 182 } else { |
| 155 // For all regular media requests show infobar. | 183 ProcessRegularMediaAccessRequest(web_contents, request, callback); |
| 156 MediaStreamInfoBarDelegate::Create(web_contents, request, callback); | |
| 157 } | 184 } |
| 158 } | 185 } |
| 159 | 186 |
| 160 void MediaCaptureDevicesDispatcher::ProcessScreenCaptureAccessRequest( | 187 void MediaCaptureDevicesDispatcher::ProcessScreenCaptureAccessRequest( |
| 161 content::WebContents* web_contents, | 188 content::WebContents* web_contents, |
| 162 const content::MediaStreamRequest& request, | 189 const content::MediaStreamRequest& request, |
| 163 const content::MediaResponseCallback& callback) { | 190 const content::MediaResponseCallback& callback) { |
| 164 content::MediaStreamDevices devices; | 191 content::MediaStreamDevices devices; |
| 165 | 192 |
| 166 bool screen_capture_enabled = | 193 bool screen_capture_enabled = |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 252 } | 279 } |
| 253 | 280 |
| 254 scoped_ptr<content::MediaStreamUI> ui; | 281 scoped_ptr<content::MediaStreamUI> ui; |
| 255 if (!devices.empty()) { | 282 if (!devices.empty()) { |
| 256 ui = media_stream_capture_indicator_->RegisterMediaStream( | 283 ui = media_stream_capture_indicator_->RegisterMediaStream( |
| 257 web_contents, devices); | 284 web_contents, devices); |
| 258 } | 285 } |
| 259 callback.Run(devices, ui.Pass()); | 286 callback.Run(devices, ui.Pass()); |
| 260 } | 287 } |
| 261 | 288 |
| 289 void MediaCaptureDevicesDispatcher::ProcessRegularMediaAccessRequest( |
| 290 content::WebContents* web_contents, |
| 291 const content::MediaStreamRequest& request, |
| 292 const content::MediaResponseCallback& callback) { |
| 293 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 294 |
| 295 RequestsQueue& queue = pending_requests_[web_contents]; |
| 296 queue.push(PendingAccessRequest(request, callback)); |
| 297 |
| 298 // If this is the only request then show the infobar. |
| 299 if (queue.size() == 1) |
| 300 ProcessQueuedAccessRequest(web_contents); |
| 301 } |
| 302 |
| 303 void MediaCaptureDevicesDispatcher::ProcessQueuedAccessRequest( |
| 304 content::WebContents* web_contents) { |
| 305 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 306 |
| 307 std::map<content::WebContents*, RequestsQueue>::iterator it = |
| 308 pending_requests_.find(web_contents); |
| 309 |
| 310 if (it == pending_requests_.end() || it->second.empty()) { |
| 311 // Don't do anything if the tab was was closed. |
| 312 return; |
| 313 } |
| 314 |
| 315 DCHECK(!it->second.empty()); |
| 316 |
| 317 MediaStreamInfoBarDelegate::Create( |
| 318 web_contents, it->second.front().request, |
| 319 base::Bind(&MediaCaptureDevicesDispatcher::OnAccessRequestResponse, |
| 320 base::Unretained(this), web_contents)); |
| 321 } |
| 322 |
| 323 void MediaCaptureDevicesDispatcher::OnAccessRequestResponse( |
| 324 content::WebContents* web_contents, |
| 325 const content::MediaStreamDevices& devices, |
| 326 scoped_ptr<content::MediaStreamUI> ui) { |
| 327 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 328 |
| 329 std::map<content::WebContents*, RequestsQueue>::iterator it = |
| 330 pending_requests_.find(web_contents); |
| 331 DCHECK(it != pending_requests_.end()); |
| 332 RequestsQueue& queue(it->second); |
| 333 content::MediaResponseCallback callback = queue.front().callback; |
| 334 queue.pop(); |
| 335 |
| 336 if (!queue.empty()) { |
| 337 // Post a task to process next queued request. It has to be done |
| 338 // asynchronously to make sure that calling infobar is not destroyed until |
| 339 // after this function returns. |
| 340 BrowserThread::PostTask( |
| 341 BrowserThread::UI, FROM_HERE, |
| 342 base::Bind(&MediaCaptureDevicesDispatcher::ProcessQueuedAccessRequest, |
| 343 base::Unretained(this), web_contents)); |
| 344 } |
| 345 |
| 346 callback.Run(devices, ui.Pass()); |
| 347 } |
| 348 |
| 262 void MediaCaptureDevicesDispatcher::GetDefaultDevicesForProfile( | 349 void MediaCaptureDevicesDispatcher::GetDefaultDevicesForProfile( |
| 263 Profile* profile, | 350 Profile* profile, |
| 264 bool audio, | 351 bool audio, |
| 265 bool video, | 352 bool video, |
| 266 content::MediaStreamDevices* devices) { | 353 content::MediaStreamDevices* devices) { |
| 267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 354 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 268 DCHECK(audio || video); | 355 DCHECK(audio || video); |
| 269 | 356 |
| 270 PrefService* prefs = profile->GetPrefs(); | 357 PrefService* prefs = profile->GetPrefs(); |
| 271 std::string default_device; | 358 std::string default_device; |
| (...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 378 int render_process_id, | 465 int render_process_id, |
| 379 int render_view_id, | 466 int render_view_id, |
| 380 const content::MediaStreamDevice& device, | 467 const content::MediaStreamDevice& device, |
| 381 content::MediaRequestState state) { | 468 content::MediaRequestState state) { |
| 382 FOR_EACH_OBSERVER(Observer, observers_, | 469 FOR_EACH_OBSERVER(Observer, observers_, |
| 383 OnRequestUpdate(render_process_id, | 470 OnRequestUpdate(render_process_id, |
| 384 render_view_id, | 471 render_view_id, |
| 385 device, | 472 device, |
| 386 state)); | 473 state)); |
| 387 } | 474 } |
| OLD | NEW |