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/prefs/scoped_user_pref_update.h" | 17 #include "chrome/browser/prefs/scoped_user_pref_update.h" |
18 #include "chrome/browser/profiles/profile.h" | 18 #include "chrome/browser/profiles/profile.h" |
19 #include "chrome/browser/ui/media_stream_infobar_delegate.h" | 19 #include "chrome/browser/ui/media_stream_infobar_delegate.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 content::MediaStreamRequest request, |
| 88 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 PrefRegistrySyncable* registry) { | 111 PrefRegistrySyncable* registry) { |
96 registry->RegisterStringPref(prefs::kDefaultAudioCaptureDevice, | 112 registry->RegisterStringPref(prefs::kDefaultAudioCaptureDevice, |
97 std::string(), | 113 std::string(), |
98 PrefRegistrySyncable::UNSYNCABLE_PREF); | 114 PrefRegistrySyncable::UNSYNCABLE_PREF); |
99 registry->RegisterStringPref(prefs::kDefaultVideoCaptureDevice, | 115 registry->RegisterStringPref(prefs::kDefaultVideoCaptureDevice, |
100 std::string(), | 116 std::string(), |
(...skipping 28 matching lines...) Expand all Loading... |
129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 145 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
130 if (!devices_enumerated_) { | 146 if (!devices_enumerated_) { |
131 BrowserThread::PostTask( | 147 BrowserThread::PostTask( |
132 BrowserThread::IO, FROM_HERE, | 148 BrowserThread::IO, FROM_HERE, |
133 base::Bind(&content::EnsureMonitorCaptureDevices)); | 149 base::Bind(&content::EnsureMonitorCaptureDevices)); |
134 devices_enumerated_ = true; | 150 devices_enumerated_ = true; |
135 } | 151 } |
136 return video_devices_; | 152 return video_devices_; |
137 } | 153 } |
138 | 154 |
| 155 void MediaCaptureDevicesDispatcher::Observe( |
| 156 int type, |
| 157 const content::NotificationSource& source, |
| 158 const content::NotificationDetails& details) { |
| 159 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 160 if (type == content::NOTIFICATION_WEB_CONTENTS_DESTROYED) { |
| 161 content::WebContents* web_contents = |
| 162 content::Source<content::WebContents>(source).ptr(); |
| 163 pending_requests_.erase(web_contents); |
| 164 } |
| 165 } |
| 166 |
139 void MediaCaptureDevicesDispatcher::ProcessMediaAccessRequest( | 167 void MediaCaptureDevicesDispatcher::ProcessMediaAccessRequest( |
140 content::WebContents* web_contents, | 168 content::WebContents* web_contents, |
141 const content::MediaStreamRequest& request, | 169 const content::MediaStreamRequest& request, |
142 const content::MediaResponseCallback& callback, | 170 const content::MediaResponseCallback& callback, |
143 const extensions::Extension* extension) { | 171 const extensions::Extension* extension) { |
144 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 172 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
145 | 173 |
146 if (request.video_type == content::MEDIA_SCREEN_VIDEO_CAPTURE) { | 174 if (request.video_type == content::MEDIA_SCREEN_VIDEO_CAPTURE) { |
147 ProcessScreenCaptureAccessRequest(web_contents, request, callback); | 175 ProcessScreenCaptureAccessRequest(web_contents, request, callback); |
148 } else if (extension) { | 176 } else if (extension) { |
149 // For extensions access is approved based on extension permissions. | 177 // For extensions access is approved based on extension permissions. |
150 ProcessMediaAccessRequestFromExtension( | 178 ProcessMediaAccessRequestFromExtension( |
151 web_contents, request, callback, extension); | 179 web_contents, request, callback, extension); |
152 } else { | 180 } else { |
153 // For all regular media requests show infobar. | 181 ProcessRegularMediaAccessRequest(web_contents, request, callback); |
154 MediaStreamInfoBarDelegate::Create(web_contents, request, callback); | |
155 } | 182 } |
156 } | 183 } |
157 | 184 |
158 void MediaCaptureDevicesDispatcher::ProcessScreenCaptureAccessRequest( | 185 void MediaCaptureDevicesDispatcher::ProcessScreenCaptureAccessRequest( |
159 content::WebContents* web_contents, | 186 content::WebContents* web_contents, |
160 const content::MediaStreamRequest& request, | 187 const content::MediaStreamRequest& request, |
161 const content::MediaResponseCallback& callback) { | 188 const content::MediaResponseCallback& callback) { |
162 content::MediaStreamDevices devices; | 189 content::MediaStreamDevices devices; |
163 | 190 |
164 bool screen_capture_enabled = | 191 bool screen_capture_enabled = |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
245 } | 272 } |
246 | 273 |
247 scoped_ptr<content::MediaStreamUI> ui; | 274 scoped_ptr<content::MediaStreamUI> ui; |
248 if (!devices.empty()) { | 275 if (!devices.empty()) { |
249 ui = media_stream_capture_indicator_->RegisterMediaStream( | 276 ui = media_stream_capture_indicator_->RegisterMediaStream( |
250 web_contents, devices); | 277 web_contents, devices); |
251 } | 278 } |
252 callback.Run(devices, ui.Pass()); | 279 callback.Run(devices, ui.Pass()); |
253 } | 280 } |
254 | 281 |
| 282 void MediaCaptureDevicesDispatcher::ProcessRegularMediaAccessRequest( |
| 283 content::WebContents* web_contents, |
| 284 const content::MediaStreamRequest& request, |
| 285 const content::MediaResponseCallback& callback) { |
| 286 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 287 |
| 288 RequestsQueue& queue = pending_requests_[web_contents]; |
| 289 queue.push(PendingAccessRequest(request, callback)); |
| 290 |
| 291 // If this is the only request then show the infobar. |
| 292 if (queue.size() == 1) |
| 293 ProcessQueuedAccessRequest(web_contents, queue.front()); |
| 294 } |
| 295 |
| 296 void MediaCaptureDevicesDispatcher::ProcessQueuedAccessRequest( |
| 297 content::WebContents* web_contents, |
| 298 PendingAccessRequest& request) { |
| 299 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 300 |
| 301 MediaStreamInfoBarDelegate::Create( |
| 302 web_contents, request.request, |
| 303 base::Bind(&MediaCaptureDevicesDispatcher::OnAccessRequestResponse, |
| 304 base::Unretained(this), web_contents)); |
| 305 } |
| 306 |
| 307 void MediaCaptureDevicesDispatcher::OnAccessRequestResponse( |
| 308 content::WebContents* web_contents, |
| 309 const content::MediaStreamDevices& devices, |
| 310 scoped_ptr<content::MediaStreamUI> ui) { |
| 311 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 312 |
| 313 std::map<content::WebContents*, RequestsQueue>::iterator it = |
| 314 pending_requests_.find(web_contents); |
| 315 DCHECK(it != pending_requests_.end()); |
| 316 RequestsQueue& queue(it->second); |
| 317 content::MediaResponseCallback callback = queue.front().callback; |
| 318 queue.pop(); |
| 319 if (!queue.empty()) |
| 320 ProcessQueuedAccessRequest(web_contents, queue.front()); |
| 321 |
| 322 callback.Run(devices, ui.Pass()); |
| 323 } |
| 324 |
255 void MediaCaptureDevicesDispatcher::GetDefaultDevicesForProfile( | 325 void MediaCaptureDevicesDispatcher::GetDefaultDevicesForProfile( |
256 Profile* profile, | 326 Profile* profile, |
257 bool audio, | 327 bool audio, |
258 bool video, | 328 bool video, |
259 content::MediaStreamDevices* devices) { | 329 content::MediaStreamDevices* devices) { |
260 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 330 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
261 DCHECK(audio || video); | 331 DCHECK(audio || video); |
262 | 332 |
263 PrefService* prefs = profile->GetPrefs(); | 333 PrefService* prefs = profile->GetPrefs(); |
264 std::string default_device; | 334 std::string default_device; |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 int render_process_id, | 441 int render_process_id, |
372 int render_view_id, | 442 int render_view_id, |
373 const content::MediaStreamDevice& device, | 443 const content::MediaStreamDevice& device, |
374 content::MediaRequestState state) { | 444 content::MediaRequestState state) { |
375 FOR_EACH_OBSERVER(Observer, observers_, | 445 FOR_EACH_OBSERVER(Observer, observers_, |
376 OnRequestUpdate(render_process_id, | 446 OnRequestUpdate(render_process_id, |
377 render_view_id, | 447 render_view_id, |
378 device, | 448 device, |
379 state)); | 449 state)); |
380 } | 450 } |
OLD | NEW |