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 "content/browser/renderer_host/media/media_stream_manager.h" | 5 #include "content/browser/renderer_host/media/media_stream_manager.h" |
6 | 6 |
7 #include <list> | 7 #include <list> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/rand_util.h" | 12 #include "base/rand_util.h" |
13 #include "content/browser/renderer_host/media/audio_input_device_manager.h" | 13 #include "content/browser/renderer_host/media/audio_input_device_manager.h" |
14 #include "content/browser/renderer_host/media/media_stream_device_settings.h" | 14 #include "content/browser/renderer_host/media/media_stream_device_settings.h" |
15 #include "content/browser/renderer_host/media/media_stream_requester.h" | 15 #include "content/browser/renderer_host/media/media_stream_requester.h" |
16 #include "content/browser/renderer_host/media/video_capture_manager.h" | 16 #include "content/browser/renderer_host/media/video_capture_manager.h" |
17 #include "content/browser/resource_context_impl.h" | 17 #include "content/browser/resource_context_impl.h" |
18 #include "content/common/media/media_stream_options.h" | 18 #include "content/common/media/media_stream_options.h" |
19 #include "content/public/browser/browser_thread.h" | 19 #include "content/public/browser/browser_thread.h" |
| 20 #include "content/public/browser/content_browser_client.h" |
| 21 #include "content/public/browser/media_observer.h" |
20 #include "media/audio/audio_manager.h" | 22 #include "media/audio/audio_manager.h" |
21 | 23 |
22 using content::BrowserThread; | 24 using content::BrowserThread; |
23 | 25 |
24 static const char* kMediaStreamManagerKeyName = "content_media_stream_manager"; | 26 static const char* kMediaStreamManagerKeyName = "content_media_stream_manager"; |
25 | 27 |
26 namespace media_stream { | 28 namespace media_stream { |
27 | 29 |
28 // Creates a random label used to identify requests. | 30 // Creates a random label used to identify requests. |
29 static std::string RandomLabel() { | 31 static std::string RandomLabel() { |
(...skipping 17 matching lines...) Expand all Loading... |
47 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE && | 49 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE && |
48 options.video) { | 50 options.video) { |
49 return true; | 51 return true; |
50 } else if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE && | 52 } else if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE && |
51 options.audio) { | 53 options.audio) { |
52 return true; | 54 return true; |
53 } | 55 } |
54 return false; | 56 return false; |
55 } | 57 } |
56 | 58 |
| 59 // TODO(xians): Merge DeviceRequest with MediaStreamRequest. |
57 struct MediaStreamManager::DeviceRequest { | 60 struct MediaStreamManager::DeviceRequest { |
58 enum RequestState { | 61 enum RequestState { |
59 kNotRequested = 0, | 62 kNotRequested = 0, |
60 kRequested, | 63 kRequested, |
61 kPendingApproval, | 64 kPendingApproval, |
62 kOpening, | 65 kOpening, |
63 kDone, | 66 kDone, |
64 kError | 67 kError |
65 }; | 68 }; |
66 | 69 |
67 enum RequestType { | 70 enum RequestType { |
68 kGenerateStream = 0, | 71 kGenerateStream = 0, |
69 kEnumerateDevices, | 72 kEnumerateDevices, |
70 kOpenDevice | 73 kOpenDevice |
71 }; | 74 }; |
72 | 75 |
73 DeviceRequest() | 76 DeviceRequest() |
74 : requester(NULL), | 77 : requester(NULL), |
75 state(content::NUM_MEDIA_STREAM_DEVICE_TYPES, kNotRequested), | 78 state(content::NUM_MEDIA_STREAM_DEVICE_TYPES, kNotRequested), |
76 type(kGenerateStream) { | 79 type(kGenerateStream), |
| 80 render_process_id(-1), |
| 81 render_view_id(-1) { |
77 options.audio = false; | 82 options.audio = false; |
78 options.video = false; | 83 options.video = false; |
79 } | 84 } |
80 | 85 |
81 DeviceRequest(MediaStreamRequester* requester, | 86 DeviceRequest(MediaStreamRequester* requester, |
82 const StreamOptions& request_options) | 87 const StreamOptions& request_options, |
| 88 int render_process_id, |
| 89 int render_view_id, |
| 90 const std::string& request_security_origin) |
83 : requester(requester), | 91 : requester(requester), |
84 options(request_options), | 92 options(request_options), |
85 state(content::NUM_MEDIA_STREAM_DEVICE_TYPES, kNotRequested), | 93 state(content::NUM_MEDIA_STREAM_DEVICE_TYPES, kNotRequested), |
86 type(kGenerateStream) { | 94 type(kGenerateStream), |
| 95 render_process_id(render_process_id), |
| 96 render_view_id(render_view_id), |
| 97 security_origin(request_security_origin) { |
87 DCHECK(requester); | 98 DCHECK(requester); |
88 } | 99 } |
89 | 100 |
90 ~DeviceRequest() {} | 101 ~DeviceRequest() {} |
91 | 102 |
92 MediaStreamRequester* requester; | 103 MediaStreamRequester* requester; |
93 StreamOptions options; | 104 StreamOptions options; |
94 std::vector<RequestState> state; | 105 std::vector<RequestState> state; |
95 RequestType type; | 106 RequestType type; |
| 107 int render_process_id; |
| 108 int render_view_id; |
| 109 std::string security_origin; |
96 std::string requested_device_id; | 110 std::string requested_device_id; |
97 StreamDeviceInfoArray audio_devices; | 111 StreamDeviceInfoArray audio_devices; |
98 StreamDeviceInfoArray video_devices; | 112 StreamDeviceInfoArray video_devices; |
99 }; | 113 }; |
100 | 114 |
101 // static | 115 // static |
102 MediaStreamManager* MediaStreamManager::GetForResourceContext( | 116 MediaStreamManager* MediaStreamManager::GetForResourceContext( |
103 content::ResourceContext* resource_context, | 117 content::ResourceContext* resource_context, |
104 media::AudioManager* audio_manager) { | 118 media::AudioManager* audio_manager) { |
105 MediaStreamManager* rv = static_cast<MediaStreamManager*>( | 119 MediaStreamManager* rv = static_cast<MediaStreamManager*>( |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 | 161 |
148 void MediaStreamManager::GenerateStream(MediaStreamRequester* requester, | 162 void MediaStreamManager::GenerateStream(MediaStreamRequester* requester, |
149 int render_process_id, | 163 int render_process_id, |
150 int render_view_id, | 164 int render_view_id, |
151 const StreamOptions& options, | 165 const StreamOptions& options, |
152 const std::string& security_origin, | 166 const std::string& security_origin, |
153 std::string* label) { | 167 std::string* label) { |
154 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 168 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
155 | 169 |
156 // Create a new request based on options. | 170 // Create a new request based on options. |
157 DeviceRequest new_request = DeviceRequest(requester, options); | 171 DeviceRequest new_request(requester, options, |
158 StartEnumeration(&new_request, render_process_id, render_view_id, | 172 render_process_id, |
159 security_origin, label); | 173 render_view_id, |
| 174 security_origin); |
| 175 StartEnumeration(&new_request, label); |
160 } | 176 } |
161 | 177 |
162 void MediaStreamManager::CancelRequests(MediaStreamRequester* requester) { | 178 void MediaStreamManager::CancelRequests(MediaStreamRequester* requester) { |
163 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 179 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
164 DeviceRequests::iterator it = requests_.begin(); | 180 DeviceRequests::iterator it = requests_.begin(); |
165 while (it != requests_.end()) { | 181 while (it != requests_.end()) { |
166 if (it->second.requester == requester && !RequestDone(it->second)) { | 182 if (it->second.requester == requester && !RequestDone(it->second)) { |
167 // The request isn't complete, but there might be some devices already | 183 // The request isn't complete, but there might be some devices already |
168 // opened -> close them. | 184 // opened -> close them. |
169 DeviceRequest* request = &(it->second); | 185 DeviceRequest* request = &(it->second); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
202 for (StreamDeviceInfoArray::iterator audio_it = | 218 for (StreamDeviceInfoArray::iterator audio_it = |
203 it->second.audio_devices.begin(); | 219 it->second.audio_devices.begin(); |
204 audio_it != it->second.audio_devices.end(); ++audio_it) { | 220 audio_it != it->second.audio_devices.end(); ++audio_it) { |
205 audio_input_device_manager()->Close(audio_it->session_id); | 221 audio_input_device_manager()->Close(audio_it->session_id); |
206 } | 222 } |
207 for (StreamDeviceInfoArray::iterator video_it = | 223 for (StreamDeviceInfoArray::iterator video_it = |
208 it->second.video_devices.begin(); | 224 it->second.video_devices.begin(); |
209 video_it != it->second.video_devices.end(); ++video_it) { | 225 video_it != it->second.video_devices.end(); ++video_it) { |
210 video_capture_manager()->Close(video_it->session_id); | 226 video_capture_manager()->Close(video_it->session_id); |
211 } | 227 } |
| 228 if (it->second.type == DeviceRequest::kGenerateStream) { |
| 229 NotifyObserverDevicesClosed(&(it->second)); |
| 230 } |
212 requests_.erase(it); | 231 requests_.erase(it); |
213 return; | 232 return; |
214 } | 233 } |
215 } | 234 } |
216 | 235 |
217 void MediaStreamManager::EnumerateDevices( | 236 void MediaStreamManager::EnumerateDevices( |
218 MediaStreamRequester* requester, | 237 MediaStreamRequester* requester, |
219 int render_process_id, | 238 int render_process_id, |
220 int render_view_id, | 239 int render_view_id, |
221 MediaStreamType type, | 240 MediaStreamType type, |
222 const std::string& security_origin, | 241 const std::string& security_origin, |
223 std::string* label) { | 242 std::string* label) { |
224 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 243 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
225 | 244 |
226 // Create a new request. | 245 // Create a new request. |
227 StreamOptions options; | 246 StreamOptions options; |
228 if (type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) | 247 if (type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) |
229 options.audio = true; | 248 options.audio = true; |
230 else | 249 else |
231 options.video = true; | 250 options.video = true; |
232 | 251 |
233 DeviceRequest new_request = DeviceRequest(requester, options); | 252 DeviceRequest new_request(requester, options, |
| 253 render_process_id, |
| 254 render_view_id, |
| 255 security_origin); |
234 new_request.type = DeviceRequest::kEnumerateDevices; | 256 new_request.type = DeviceRequest::kEnumerateDevices; |
235 | 257 |
236 StartEnumeration(&new_request, render_process_id, render_view_id, | 258 StartEnumeration(&new_request, label); |
237 security_origin, label); | |
238 } | 259 } |
239 | 260 |
240 void MediaStreamManager::OpenDevice( | 261 void MediaStreamManager::OpenDevice( |
241 MediaStreamRequester* requester, | 262 MediaStreamRequester* requester, |
242 int render_process_id, | 263 int render_process_id, |
243 int render_view_id, | 264 int render_view_id, |
244 const std::string& device_id, | 265 const std::string& device_id, |
245 MediaStreamType type, | 266 MediaStreamType type, |
246 const std::string& security_origin, | 267 const std::string& security_origin, |
247 std::string* label) { | 268 std::string* label) { |
248 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 269 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
249 | 270 |
250 // Create a new request. | 271 // Create a new request. |
251 StreamOptions options; | 272 StreamOptions options; |
252 if (type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) | 273 if (type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) |
253 options.audio = true; | 274 options.audio = true; |
254 else | 275 else |
255 options.video = true; | 276 options.video = true; |
256 | 277 |
257 DeviceRequest new_request = DeviceRequest(requester, options); | 278 DeviceRequest new_request(requester, options, |
| 279 render_process_id, |
| 280 render_view_id, |
| 281 security_origin); |
258 new_request.type = DeviceRequest::kOpenDevice; | 282 new_request.type = DeviceRequest::kOpenDevice; |
259 new_request.requested_device_id = device_id; | 283 new_request.requested_device_id = device_id; |
260 | 284 |
261 StartEnumeration(&new_request, render_process_id, render_view_id, | 285 StartEnumeration(&new_request, label); |
262 security_origin, label); | |
263 } | 286 } |
264 | 287 |
265 void MediaStreamManager::StartEnumeration( | 288 void MediaStreamManager::StartEnumeration( |
266 DeviceRequest* new_request, | 289 DeviceRequest* new_request, |
267 int render_process_id, | |
268 int render_view_id, | |
269 const std::string& security_origin, | |
270 std::string* label) { | 290 std::string* label) { |
271 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 291 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
272 | 292 |
273 MediaStreamType stream_type = content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE; | 293 MediaStreamType stream_type = content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE; |
274 if (Requested(new_request->options, stream_type)) { | 294 if (Requested(new_request->options, stream_type)) { |
275 new_request->state[stream_type] = DeviceRequest::kRequested; | 295 new_request->state[stream_type] = DeviceRequest::kRequested; |
276 if (!enumeration_in_progress_[stream_type]) { | 296 if (!enumeration_in_progress_[stream_type]) { |
277 enumeration_in_progress_[stream_type] = true; | 297 enumeration_in_progress_[stream_type] = true; |
278 GetDeviceManager(stream_type)->EnumerateDevices(); | 298 GetDeviceManager(stream_type)->EnumerateDevices(); |
279 } | 299 } |
(...skipping 16 matching lines...) Expand all Loading... |
296 requests_.insert(std::make_pair(request_label, *new_request)); | 316 requests_.insert(std::make_pair(request_label, *new_request)); |
297 | 317 |
298 // Get user confirmation to use capture devices. | 318 // Get user confirmation to use capture devices. |
299 // Need to make an asynchronous call to make sure the |requester| gets the | 319 // Need to make an asynchronous call to make sure the |requester| gets the |
300 // |label| before it would receive any event. | 320 // |label| before it would receive any event. |
301 if (new_request->type == DeviceRequest::kGenerateStream) { | 321 if (new_request->type == DeviceRequest::kGenerateStream) { |
302 BrowserThread::PostTask(BrowserThread::IO, | 322 BrowserThread::PostTask(BrowserThread::IO, |
303 FROM_HERE, | 323 FROM_HERE, |
304 base::Bind(&MediaStreamDeviceSettings::RequestCaptureDeviceUsage, | 324 base::Bind(&MediaStreamDeviceSettings::RequestCaptureDeviceUsage, |
305 base::Unretained(device_settings_.get()), | 325 base::Unretained(device_settings_.get()), |
306 request_label, render_process_id, | 326 request_label, new_request->render_process_id, |
307 render_view_id, new_request->options, | 327 new_request->render_view_id, new_request->options, |
308 security_origin)); | 328 new_request->security_origin)); |
309 } | 329 } |
310 | 330 |
311 (*label) = request_label; | 331 (*label) = request_label; |
312 } | 332 } |
313 | 333 |
314 void MediaStreamManager::Opened(MediaStreamType stream_type, | 334 void MediaStreamManager::Opened(MediaStreamType stream_type, |
315 int capture_session_id) { | 335 int capture_session_id) { |
316 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 336 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
317 | 337 |
318 // Find the request containing this device and mark it as used. | 338 // Find the request containing this device and mark it as used. |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
363 return; | 383 return; |
364 } | 384 } |
365 | 385 |
366 switch (request->type) { | 386 switch (request->type) { |
367 case DeviceRequest::kOpenDevice: | 387 case DeviceRequest::kOpenDevice: |
368 request->requester->DeviceOpened(label, (*devices)[0]); | 388 request->requester->DeviceOpened(label, (*devices)[0]); |
369 break; | 389 break; |
370 case DeviceRequest::kGenerateStream: | 390 case DeviceRequest::kGenerateStream: |
371 request->requester->StreamGenerated(label, request->audio_devices, | 391 request->requester->StreamGenerated(label, request->audio_devices, |
372 request->video_devices); | 392 request->video_devices); |
| 393 NotifyObserverDevicesOpened(request); |
373 break; | 394 break; |
374 default: | 395 default: |
375 NOTREACHED(); | 396 NOTREACHED(); |
376 } | 397 } |
377 } | 398 } |
378 | 399 |
379 void MediaStreamManager::Closed(MediaStreamType stream_type, | 400 void MediaStreamManager::Closed(MediaStreamType stream_type, |
380 int capture_session_id) { | 401 int capture_session_id) { |
381 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 402 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
382 } | 403 } |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
549 return; | 570 return; |
550 } | 571 } |
551 } | 572 } |
552 | 573 |
553 void MediaStreamManager::UseFakeDevice() { | 574 void MediaStreamManager::UseFakeDevice() { |
554 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 575 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
555 video_capture_manager()->UseFakeDevice(); | 576 video_capture_manager()->UseFakeDevice(); |
556 device_settings_->UseFakeUI(); | 577 device_settings_->UseFakeUI(); |
557 } | 578 } |
558 | 579 |
| 580 void MediaStreamManager::NotifyObserverDevicesOpened(DeviceRequest* request) { |
| 581 content::MediaObserver* media_observer = |
| 582 content::GetContentClient()->browser()->GetMediaObserver(); |
| 583 content::MediaStreamDevices opened_devices; |
| 584 DevicesFromRequest(request, &opened_devices); |
| 585 DCHECK(!opened_devices.empty()); |
| 586 media_observer->OnCaptureDevicesOpened(request->render_process_id, |
| 587 request->render_view_id, |
| 588 opened_devices); |
| 589 } |
| 590 |
| 591 void MediaStreamManager::NotifyObserverDevicesClosed(DeviceRequest* request) { |
| 592 content::MediaObserver* media_observer = |
| 593 content::GetContentClient()->browser()->GetMediaObserver(); |
| 594 content::MediaStreamDevices closed_devices; |
| 595 DevicesFromRequest(request, &closed_devices); |
| 596 if (closed_devices.empty()) |
| 597 return; |
| 598 media_observer->OnCaptureDevicesClosed(request->render_process_id, |
| 599 request->render_view_id, |
| 600 closed_devices); |
| 601 } |
| 602 |
| 603 void MediaStreamManager::DevicesFromRequest( |
| 604 DeviceRequest* request, content::MediaStreamDevices* devices) { |
| 605 StreamDeviceInfoArray::const_iterator it = request->audio_devices.begin(); |
| 606 for (; it != request->audio_devices.end(); ++it) { |
| 607 devices->push_back( |
| 608 content::MediaStreamDevice( |
| 609 content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE, |
| 610 it->device_id, |
| 611 it->name)); |
| 612 } |
| 613 for (it = request->video_devices.begin(); it != request->video_devices.end(); |
| 614 ++it) { |
| 615 devices->push_back( |
| 616 content::MediaStreamDevice( |
| 617 content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE, |
| 618 it->device_id, |
| 619 it->name)); |
| 620 } |
| 621 } |
| 622 |
559 bool MediaStreamManager::RequestDone(const DeviceRequest& request) const { | 623 bool MediaStreamManager::RequestDone(const DeviceRequest& request) const { |
560 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 624 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
561 // Check if all devices are opened. | 625 // Check if all devices are opened. |
562 if (Requested(request.options, | 626 if (Requested(request.options, |
563 content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE)) { | 627 content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE)) { |
564 for (StreamDeviceInfoArray::const_iterator it = | 628 for (StreamDeviceInfoArray::const_iterator it = |
565 request.audio_devices.begin(); it != request.audio_devices.end(); | 629 request.audio_devices.begin(); it != request.audio_devices.end(); |
566 ++it) { | 630 ++it) { |
567 if (it->in_use == false) { | 631 if (it->in_use == false) { |
568 return false; | 632 return false; |
(...skipping 19 matching lines...) Expand all Loading... |
588 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) { | 652 if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) { |
589 return video_capture_manager(); | 653 return video_capture_manager(); |
590 } else if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { | 654 } else if (stream_type == content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) { |
591 return audio_input_device_manager(); | 655 return audio_input_device_manager(); |
592 } | 656 } |
593 NOTREACHED(); | 657 NOTREACHED(); |
594 return NULL; | 658 return NULL; |
595 } | 659 } |
596 | 660 |
597 } // namespace media_stream | 661 } // namespace media_stream |
OLD | NEW |