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 |