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

Side by Side Diff: content/browser/renderer_host/media/media_stream_manager.cc

Issue 60193002: Revert 232766 "Refactor MediaStreamManager to never output real ..." (Closed) Base URL: svn://svn.chromium.org/chrome/branches/1700/src/
Patch Set: Created 7 years, 1 month 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
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 "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 #include <vector> 8 #include <vector>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/command_line.h" 11 #include "base/command_line.h"
12 #include "base/compiler_specific.h" 12 #include "base/compiler_specific.h"
13 #include "base/logging.h" 13 #include "base/logging.h"
14 #include "base/rand_util.h" 14 #include "base/rand_util.h"
15 #include "base/run_loop.h"
16 #include "base/threading/thread.h" 15 #include "base/threading/thread.h"
17 #include "content/browser/renderer_host/media/audio_input_device_manager.h" 16 #include "content/browser/renderer_host/media/audio_input_device_manager.h"
18 #include "content/browser/renderer_host/media/device_request_message_filter.h" 17 #include "content/browser/renderer_host/media/device_request_message_filter.h"
19 #include "content/browser/renderer_host/media/media_stream_requester.h" 18 #include "content/browser/renderer_host/media/media_stream_requester.h"
20 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h" 19 #include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
21 #include "content/browser/renderer_host/media/video_capture_manager.h" 20 #include "content/browser/renderer_host/media/video_capture_manager.h"
22 #include "content/browser/renderer_host/media/web_contents_capture_util.h" 21 #include "content/browser/renderer_host/media/web_contents_capture_util.h"
23 #include "content/public/browser/browser_thread.h" 22 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/content_browser_client.h" 23 #include "content/public/browser/content_browser_client.h"
25 #include "content/public/browser/media_device_id.h" 24 #include "content/public/browser/media_device_id.h"
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
175 InitializeDeviceManagersOnIOThread(); 174 InitializeDeviceManagersOnIOThread();
176 } else { 175 } else {
177 BrowserThread::PostTask( 176 BrowserThread::PostTask(
178 BrowserThread::IO, FROM_HERE, 177 BrowserThread::IO, FROM_HERE,
179 base::Bind(&MediaStreamManager::InitializeDeviceManagersOnIOThread, 178 base::Bind(&MediaStreamManager::InitializeDeviceManagersOnIOThread,
180 base::Unretained(this))); 179 base::Unretained(this)));
181 } 180 }
182 } 181 }
183 182
184 MediaStreamManager::~MediaStreamManager() { 183 MediaStreamManager::~MediaStreamManager() {
185 DVLOG(1) << "~MediaStreamManager";
186 DCHECK(requests_.empty()); 184 DCHECK(requests_.empty());
187 DCHECK(!device_thread_.get()); 185 DCHECK(!device_thread_.get());
188 } 186 }
189 187
190 VideoCaptureManager* MediaStreamManager::video_capture_manager() { 188 VideoCaptureManager* MediaStreamManager::video_capture_manager() {
191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 189 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
192 DCHECK(video_capture_manager_.get()); 190 DCHECK(video_capture_manager_.get());
193 return video_capture_manager_.get(); 191 return video_capture_manager_.get();
194 } 192 }
195 193
196 AudioInputDeviceManager* MediaStreamManager::audio_input_device_manager() { 194 AudioInputDeviceManager* MediaStreamManager::audio_input_device_manager() {
197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 195 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
198 DCHECK(audio_input_device_manager_.get()); 196 DCHECK(audio_input_device_manager_.get());
199 return audio_input_device_manager_.get(); 197 return audio_input_device_manager_.get();
200 } 198 }
201 199
202 std::string MediaStreamManager::MakeMediaAccessRequest( 200 std::string MediaStreamManager::MakeMediaAccessRequest(
203 int render_process_id, 201 int render_process_id,
204 int render_view_id, 202 int render_view_id,
205 int page_request_id, 203 int page_request_id,
206 const StreamOptions& options, 204 const StreamOptions& options,
207 const GURL& security_origin, 205 const GURL& security_origin,
208 const MediaRequestResponseCallback& callback) { 206 const MediaRequestResponseCallback& callback) {
209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 207 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
210 // Create a new request based on options. 208 // Create a new request based on options.
211 MediaStreamRequest stream_request( 209 MediaStreamRequest stream_request(
212 render_process_id, render_view_id, page_request_id, 210 render_process_id, render_view_id, page_request_id, std::string(),
213 security_origin, MEDIA_DEVICE_ACCESS, std::string(), std::string(), 211 security_origin, MEDIA_DEVICE_ACCESS, std::string(), std::string(),
214 options.audio_type, options.video_type); 212 options.audio_type, options.video_type);
215 DeviceRequest* request = new DeviceRequest(NULL, stream_request, 213 DeviceRequest* request = new DeviceRequest(NULL, stream_request,
216 render_process_id, render_view_id); 214 render_process_id, render_view_id);
217 const std::string& label = AddRequest(request); 215 const std::string& label = AddRequest(request);
218 216
219 request->callback = callback; 217 request->callback = callback;
220 BrowserThread::PostTask( 218
221 BrowserThread::IO, FROM_HERE, 219 HandleRequest(label);
222 base::Bind(&MediaStreamManager::HandleRequest, 220
223 base::Unretained(this), label));
224 return label; 221 return label;
225 } 222 }
226 223
227 std::string MediaStreamManager::GenerateStream( 224 std::string MediaStreamManager::GenerateStream(
228 MediaStreamRequester* requester, 225 MediaStreamRequester* requester,
229 int render_process_id, 226 int render_process_id,
230 int render_view_id, 227 int render_view_id,
231 int page_request_id, 228 int page_request_id,
232 const StreamOptions& options, 229 const StreamOptions& options,
233 const GURL& security_origin) { 230 const GURL& security_origin) {
234 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 231 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
235 if (CommandLine::ForCurrentProcess()->HasSwitch( 232 if (CommandLine::ForCurrentProcess()->HasSwitch(
236 switches::kUseFakeDeviceForMediaStream)) { 233 switches::kUseFakeDeviceForMediaStream)) {
237 UseFakeDevice(); 234 UseFakeDevice();
238 } 235 }
239 if (CommandLine::ForCurrentProcess()->HasSwitch( 236 if (CommandLine::ForCurrentProcess()->HasSwitch(
240 switches::kUseFakeUIForMediaStream)) { 237 switches::kUseFakeUIForMediaStream)) {
241 UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy>()); 238 UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy>());
242 } 239 }
243 240
241 int target_render_process_id = render_process_id;
242 int target_render_view_id = render_view_id;
243 std::string tab_capture_device_id;
244
245 // Customize options for a WebContents based capture.
246 if (options.audio_type == MEDIA_TAB_AUDIO_CAPTURE ||
247 options.video_type == MEDIA_TAB_VIDEO_CAPTURE) {
248 // TODO(justinlin): Can't plumb audio mirroring using stream type right
249 // now, so plumbing by device_id. Will revisit once it's refactored.
250 // http://crbug.com/163100
251 tab_capture_device_id =
252 WebContentsCaptureUtil::AppendWebContentsDeviceScheme(
253 !options.video_device_id.empty() ?
254 options.video_device_id : options.audio_device_id);
255
256 bool has_valid_device_id = WebContentsCaptureUtil::ExtractTabCaptureTarget(
257 tab_capture_device_id, &target_render_process_id,
258 &target_render_view_id);
259 if (!has_valid_device_id ||
260 (options.audio_type != MEDIA_TAB_AUDIO_CAPTURE &&
261 options.audio_type != MEDIA_NO_SERVICE) ||
262 (options.video_type != MEDIA_TAB_VIDEO_CAPTURE &&
263 options.video_type != MEDIA_NO_SERVICE)) {
264 LOG(ERROR) << "Invalid request.";
265 return std::string();
266 }
267 }
268
269 std::string translated_audio_device_id;
270 std::string translated_video_device_id;
271 if (options.audio_type == MEDIA_DEVICE_AUDIO_CAPTURE) {
272 bool found_match = TranslateGUIDToRawId(
273 MEDIA_DEVICE_AUDIO_CAPTURE, security_origin, options.audio_device_id,
274 &translated_audio_device_id);
275 DCHECK(found_match || translated_audio_device_id.empty());
276 }
277
278 if (options.video_type == MEDIA_DEVICE_VIDEO_CAPTURE) {
279 bool found_match = TranslateGUIDToRawId(
280 MEDIA_DEVICE_VIDEO_CAPTURE, security_origin, options.video_device_id,
281 &translated_video_device_id);
282 DCHECK(found_match || translated_video_device_id.empty());
283 }
284
285 if (options.video_type == MEDIA_DESKTOP_VIDEO_CAPTURE ||
286 options.audio_type == MEDIA_LOOPBACK_AUDIO_CAPTURE) {
287 // For screen capture we only support two valid combinations:
288 // (1) screen video capture only, or
289 // (2) screen video capture with loopback audio capture.
290 if (options.video_type != MEDIA_DESKTOP_VIDEO_CAPTURE ||
291 (options.audio_type != MEDIA_NO_SERVICE &&
292 options.audio_type != MEDIA_LOOPBACK_AUDIO_CAPTURE)) {
293 // TODO(sergeyu): Surface error message to the calling JS code.
294 LOG(ERROR) << "Invalid screen capture request.";
295 return std::string();
296 }
297 translated_video_device_id = options.video_device_id;
298 }
299
244 // Create a new request based on options. 300 // Create a new request based on options.
245 MediaStreamRequest stream_request( 301 MediaStreamRequest stream_request(
246 render_process_id, render_view_id, page_request_id, 302 target_render_process_id, target_render_view_id, page_request_id,
247 security_origin, MEDIA_GENERATE_STREAM, 303 tab_capture_device_id, security_origin, MEDIA_GENERATE_STREAM,
248 options.audio_device_id, options.video_device_id, 304 translated_audio_device_id, translated_video_device_id,
249 options.audio_type, options.video_type); 305 options.audio_type, options.video_type);
250 DeviceRequest* request = new DeviceRequest(requester, stream_request, 306 DeviceRequest* request = new DeviceRequest(requester, stream_request,
251 render_process_id, 307 render_process_id,
252 render_view_id); 308 render_view_id);
253 const std::string& label = AddRequest(request); 309 const std::string& label = AddRequest(request);
254 310 HandleRequest(label);
255 // Need to post a task since the requester won't have label till
256 // this function returns.
257 BrowserThread::PostTask(
258 BrowserThread::IO, FROM_HERE,
259 base::Bind(&MediaStreamManager::HandleRequest,
260 base::Unretained(this), label));
261 return label; 311 return label;
262 } 312 }
263 313
264 void MediaStreamManager::CancelRequest(const std::string& label) { 314 void MediaStreamManager::CancelRequest(const std::string& label) {
265 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 315 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
266 316
267 BrowserThread::PostTask( 317 DeviceRequests::iterator request_it = requests_.find(label);
268 BrowserThread::IO, FROM_HERE, 318 if (request_it == requests_.end()) {
269 base::Bind(&MediaStreamManager::DoCancelRequest, 319 NOTREACHED();
270 base::Unretained(this), label));
271 }
272
273 void MediaStreamManager::DoCancelRequest(const std::string& label) {
274 DVLOG(1) << "DoCancelRequest({label = " << label << "})";
275
276 DeviceRequest* request = FindRequest(label);
277 if (!request) {
278 // This can happen if the request completes before DoCancelRequest is
279 // executed or if a client call cancel request on a stream that has failed.
280 return; 320 return;
281 } 321 }
322 scoped_ptr<DeviceRequest> request(request_it->second);
323 RemoveRequest(request_it);
324
282 if (request->request.request_type == MEDIA_ENUMERATE_DEVICES) { 325 if (request->request.request_type == MEDIA_ENUMERATE_DEVICES) {
283 DeleteRequest(label);
284 return; 326 return;
285 } 327 }
286 328
287 // This is a request for opening one or more devices. 329 // This is a request for opening one or more devices.
288 for (StreamDeviceInfoArray::iterator device_it = request->devices.begin(); 330 for (StreamDeviceInfoArray::iterator device_it = request->devices.begin();
289 device_it != request->devices.end(); ++device_it) { 331 device_it != request->devices.end(); ++device_it) {
290 // If we have not yet requested the device to be opened - just ignore it. 332 // If we have not yet requested the device to be opened - just ignore it.
291 if (request->state(device_it->device.type) != MEDIA_REQUEST_STATE_OPENING 333 if (request->state(device_it->device.type) != MEDIA_REQUEST_STATE_OPENING
292 && 334 &&
293 request->state(device_it->device.type) != MEDIA_REQUEST_STATE_DONE) { 335 request->state(device_it->device.type) != MEDIA_REQUEST_STATE_DONE) {
294 continue; 336 continue;
295 } 337 }
296 // Stop the opening/opened devices of the requests. 338 // Stop the opening/opened devices of the requests.
297 StopDevice(*device_it); 339 StopDevice(*device_it);
298 } 340 }
299 341
300 // Cancel the request if still pending at UI side. 342 // Cancel the request if still pending at UI side.
301 request->SetState(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_CLOSING); 343 request->SetState(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_CLOSING);
302 DeleteRequest(label);
303 } 344 }
304 345
305 void MediaStreamManager::CancelAllRequests(int render_process_id) { 346 void MediaStreamManager::CancelAllRequests(int render_process_id) {
306 DeviceRequests::iterator request_it = requests_.begin(); 347 DeviceRequests::iterator request_it = requests_.begin();
307 while (request_it != requests_.end()) { 348 while (request_it != requests_.end()) {
308 if (request_it->second->requesting_process_id != render_process_id) { 349 if (request_it->second->requesting_process_id != render_process_id) {
309 ++request_it; 350 ++request_it;
310 continue; 351 continue;
311 } 352 }
312 353
313 std::string label = request_it->first; 354 std::string label = request_it->first;
314 ++request_it; 355 ++request_it;
315 BrowserThread::PostTask( 356 CancelRequest(label);
316 BrowserThread::IO, FROM_HERE,
317 base::Bind(&MediaStreamManager::DoCancelRequest,
318 base::Unretained(this), label));
319 } 357 }
320 } 358 }
321 359
322 void MediaStreamManager::StopStreamDevice(int render_process_id, 360 void MediaStreamManager::StopStreamDevice(int render_process_id,
323 int render_view_id, 361 int render_view_id,
324 const std::string& device_id) { 362 const std::string& device_id) {
325 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 363 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
326 DVLOG(1) << "StopStreamDevice({render_view_id = " << render_view_id << "} " 364 DVLOG(1) << "StopStreamDevice({render_view_id = " << render_view_id << "} "
327 << ", {device_id = " << device_id << "})"; 365 << ", {device_id = " << device_id << "})";
328 BrowserThread::PostTask(
329 BrowserThread::IO, FROM_HERE,
330 base::Bind(&MediaStreamManager::DoStopStreamDevice,
331 base::Unretained(this), render_process_id, render_view_id,
332 device_id));
333 }
334 366
335 void MediaStreamManager::DoStopStreamDevice(int render_process_id,
336 int render_view_id,
337 const std::string& device_id) {
338 // Find all requests for this |render_process_id| and |render_view_id| of type 367 // Find all requests for this |render_process_id| and |render_view_id| of type
339 // MEDIA_GENERATE_STREAM that has requested to use |device_id|. 368 // MEDIA_GENERATE_STREAM that has requested to use |device_id|.
340 DeviceRequests::iterator request_it = requests_.begin(); 369 DeviceRequests::iterator request_it = requests_.begin();
341 while (request_it != requests_.end()) { 370 while (request_it != requests_.end()) {
342 DeviceRequest* request = request_it->second; 371 DeviceRequest* request = request_it->second;
343 const MediaStreamRequest& ms_request = request->request; 372 const MediaStreamRequest& ms_request = request->request;
344 if (request->requesting_process_id != render_process_id || 373 if (request->requesting_process_id != render_process_id ||
345 request->requesting_view_id != render_view_id || 374 request->requesting_view_id != render_view_id ||
346 ms_request.request_type != MEDIA_GENERATE_STREAM) { 375 ms_request.request_type != MEDIA_GENERATE_STREAM) {
347 ++request_it; 376 ++request_it;
348 continue; 377 continue;
349 } 378 }
350 379
351 StreamDeviceInfoArray* devices = &request->devices; 380 StreamDeviceInfoArray* devices = &request->devices;
352 StreamDeviceInfoArray::iterator device_it = devices->begin(); 381 StreamDeviceInfoArray::iterator device_it = devices->begin();
353 while (device_it != devices->end()) { 382 while (device_it != devices->end()) {
354 MediaStreamType device_type = device_it->device.type; 383 MediaStreamType device_type = device_it->device.type;
355 if (device_it->device.id == device_id) { 384 if (device_it->device.id == device_id) {
356 if (request->state(device_type) == MEDIA_REQUEST_STATE_DONE) { 385 if (request->state(device_type) == MEDIA_REQUEST_STATE_DONE) {
357 StopDevice(*device_it); 386 StopDevice(*device_it);
358 } 387 }
359 device_it = devices->erase(device_it); 388 device_it = devices->erase(device_it);
360 } else { 389 } else {
361 ++device_it; 390 ++device_it;
362 } 391 }
363 } 392 }
364 393
365 // If this request doesn't have any active devices, remove the request. 394 // If this request doesn't have any active devices, remove the request.
366 if (devices->empty()) { 395 if (devices->empty()) {
367 std::string label = request_it->first; 396 DeviceRequests::iterator del_itor(request_it);
368 ++request_it; 397 ++request_it;
369 DeleteRequest(label); 398 scoped_ptr<DeviceRequest> request(del_itor->second);
399 RemoveRequest(del_itor);
370 } else { 400 } else {
371 ++request_it; 401 ++request_it;
372 } 402 }
373 } 403 }
374 } 404 }
375 405
376 void MediaStreamManager::StopDevice(const StreamDeviceInfo& device_info) { 406 void MediaStreamManager::StopDevice(const StreamDeviceInfo& device_info) {
377 DVLOG(1) << "StopDevice(" 407 DVLOG(1) << "StopDevice("
378 << "{device_info.session_id = " << device_info.session_id << "} " 408 << "{device_info.session_id = " << device_info.session_id << "} "
379 << "{device_id = " << device_info.device.id << "})"; 409 << "{device_id = " << device_info.device.id << "})";
(...skipping 30 matching lines...) Expand all
410 // starts monitoring devices. 440 // starts monitoring devices.
411 if (!requester) { 441 if (!requester) {
412 if (!monitoring_started_) 442 if (!monitoring_started_)
413 StartMonitoring(); 443 StartMonitoring();
414 444
415 return std::string(); 445 return std::string();
416 } 446 }
417 447
418 // Create a new request. 448 // Create a new request.
419 StreamOptions options; 449 StreamOptions options;
450 EnumerationCache* cache = NULL;
420 if (type == MEDIA_DEVICE_AUDIO_CAPTURE) { 451 if (type == MEDIA_DEVICE_AUDIO_CAPTURE) {
421 options.audio_type = type; 452 options.audio_type = type;
453 cache = &audio_enumeration_cache_;
422 } else if (type == MEDIA_DEVICE_VIDEO_CAPTURE) { 454 } else if (type == MEDIA_DEVICE_VIDEO_CAPTURE) {
423 options.video_type = type; 455 options.video_type = type;
456 cache = &video_enumeration_cache_;
424 } else { 457 } else {
425 NOTREACHED(); 458 NOTREACHED();
426 return std::string(); 459 return std::string();
427 } 460 }
428 461
429 MediaStreamRequest stream_request( 462 MediaStreamRequest stream_request(
430 render_process_id, render_view_id, page_request_id, 463 render_process_id, render_view_id, page_request_id, std::string(),
431 security_origin, MEDIA_ENUMERATE_DEVICES, std::string(), std::string(), 464 security_origin, MEDIA_ENUMERATE_DEVICES, std::string(), std::string(),
432 options.audio_type, options.video_type); 465 options.audio_type, options.video_type);
433 DeviceRequest* request = new DeviceRequest(requester, stream_request, 466 DeviceRequest* request = new DeviceRequest(requester, stream_request,
434 render_process_id, 467 render_process_id,
435 render_view_id); 468 render_view_id);
436 const std::string& label = AddRequest(request); 469 const std::string& label = AddRequest(request);
437 BrowserThread::PostTask( 470
438 BrowserThread::IO, FROM_HERE, 471 if (cache->valid) {
439 base::Bind(&MediaStreamManager::DoEnumerateDevices, 472 // Cached device list of this type exists. Just send it out.
440 base::Unretained(this), label)); 473 request->SetState(type, MEDIA_REQUEST_STATE_REQUESTED);
474
475 // Need to post a task since the requester won't have label till
476 // this function returns.
477 BrowserThread::PostTask(
478 BrowserThread::IO, FROM_HERE,
479 base::Bind(&MediaStreamManager::SendCachedDeviceList,
480 base::Unretained(this), cache, label));
481 } else {
482 StartEnumeration(request);
483 }
441 484
442 return label; 485 return label;
443 } 486 }
444 487
445 void MediaStreamManager::DoEnumerateDevices(const std::string& label) {
446 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
447 DeviceRequest* request = FindRequest(label);;
448
449 MediaStreamType type;
450 EnumerationCache* cache;
451 if (request->request.audio_type == MEDIA_DEVICE_AUDIO_CAPTURE) {
452 DCHECK(request->request.video_type == MEDIA_NO_SERVICE);
453 type = MEDIA_DEVICE_AUDIO_CAPTURE;
454 cache = &audio_enumeration_cache_;
455 } else {
456 DCHECK(request->request.video_type == MEDIA_DEVICE_VIDEO_CAPTURE);
457 type = MEDIA_DEVICE_VIDEO_CAPTURE;
458 cache = &video_enumeration_cache_;
459 }
460
461 if (cache->valid) {
462 // Cached device list of this type exists. Just send it out.
463 request->SetState(type, MEDIA_REQUEST_STATE_REQUESTED);
464 request->devices = cache->devices;
465 FinalizeEnumerateDevices(label, request);
466 } else {
467 StartEnumeration(request);
468 }
469 }
470
471 std::string MediaStreamManager::OpenDevice( 488 std::string MediaStreamManager::OpenDevice(
472 MediaStreamRequester* requester, 489 MediaStreamRequester* requester,
473 int render_process_id, 490 int render_process_id,
474 int render_view_id, 491 int render_view_id,
475 int page_request_id, 492 int page_request_id,
476 const std::string& device_id, 493 const std::string& device_id,
477 MediaStreamType type, 494 MediaStreamType type,
478 const GURL& security_origin) { 495 const GURL& security_origin) {
479 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 496 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
480 DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE || 497 DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
481 type == MEDIA_DEVICE_VIDEO_CAPTURE); 498 type == MEDIA_DEVICE_VIDEO_CAPTURE);
482 499
483 // Create a new request. 500 // Create a new request.
484 StreamOptions options; 501 StreamOptions options;
485 if (IsAudioMediaType(type)) { 502 if (IsAudioMediaType(type)) {
486 options.audio_type = type; 503 options.audio_type = type;
487 options.audio_device_id = device_id; 504 options.audio_device_id = device_id;
488 } else if (IsVideoMediaType(type)) { 505 } else if (IsVideoMediaType(type)) {
489 options.video_type = type; 506 options.video_type = type;
490 options.video_device_id = device_id; 507 options.video_device_id = device_id;
491 } else { 508 } else {
492 NOTREACHED(); 509 NOTREACHED();
493 return std::string(); 510 return std::string();
494 } 511 }
495 512
496 MediaStreamRequest stream_request( 513 MediaStreamRequest stream_request(
497 render_process_id, render_view_id, page_request_id, 514 render_process_id, render_view_id, page_request_id, std::string(),
498 security_origin, MEDIA_OPEN_DEVICE, options.audio_device_id, 515 security_origin, MEDIA_OPEN_DEVICE, options.audio_device_id,
499 options.video_device_id, options.audio_type, options.video_type); 516 options.video_device_id, options.audio_type, options.video_type);
500 DeviceRequest* request = new DeviceRequest(requester, stream_request, 517 DeviceRequest* request = new DeviceRequest(requester, stream_request,
501 render_process_id, 518 render_process_id,
502 render_view_id); 519 render_view_id);
503 const std::string& label = AddRequest(request); 520 const std::string& label = AddRequest(request);
504 BrowserThread::PostTask( 521 StartEnumeration(request);
505 BrowserThread::IO, FROM_HERE,
506 base::Bind(&MediaStreamManager::HandleRequest,
507 base::Unretained(this), label));
508 522
509 return label; 523 return label;
510 } 524 }
511 525
526 void MediaStreamManager::SendCachedDeviceList(
527 EnumerationCache* cache,
528 const std::string& label) {
529 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
530 if (cache->valid) {
531 DeviceRequests::iterator it = requests_.find(label);
532 if (it != requests_.end()) {
533 it->second->requester->DevicesEnumerated(label, cache->devices);
534 }
535 }
536 }
537
512 void MediaStreamManager::StartMonitoring() { 538 void MediaStreamManager::StartMonitoring() {
513 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 539 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
514 if (!base::SystemMonitor::Get()) 540 if (!base::SystemMonitor::Get())
515 return; 541 return;
516 542
517 if (!monitoring_started_) { 543 if (!monitoring_started_) {
518 monitoring_started_ = true; 544 monitoring_started_ = true;
519 base::SystemMonitor::Get()->AddDevicesChangedObserver(this); 545 base::SystemMonitor::Get()->AddDevicesChangedObserver(this);
520 546
521 // Enumerate both the audio and video devices to cache the device lists 547 // Enumerate both the audio and video devices to cache the device lists
522 // and send them to media observer. 548 // and send them to media observer.
523 ++active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_CAPTURE]; 549 ++active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_CAPTURE];
524 audio_input_device_manager_->EnumerateDevices(MEDIA_DEVICE_AUDIO_CAPTURE); 550 audio_input_device_manager_->EnumerateDevices(MEDIA_DEVICE_AUDIO_CAPTURE);
525 ++active_enumeration_ref_count_[MEDIA_DEVICE_VIDEO_CAPTURE]; 551 ++active_enumeration_ref_count_[MEDIA_DEVICE_VIDEO_CAPTURE];
526 video_capture_manager_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE); 552 video_capture_manager_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
527 } 553 }
528 } 554 }
529 555
530 void MediaStreamManager::StopMonitoring() { 556 void MediaStreamManager::StopMonitoring() {
531 DCHECK_EQ(base::MessageLoop::current(), io_loop_); 557 DCHECK_EQ(base::MessageLoop::current(), io_loop_);
532 if (monitoring_started_) { 558 if (monitoring_started_) {
533 base::SystemMonitor::Get()->RemoveDevicesChangedObserver(this); 559 base::SystemMonitor::Get()->RemoveDevicesChangedObserver(this);
534 monitoring_started_ = false; 560 monitoring_started_ = false;
535 ClearEnumerationCache(&audio_enumeration_cache_); 561 ClearEnumerationCache(&audio_enumeration_cache_);
536 ClearEnumerationCache(&video_enumeration_cache_); 562 ClearEnumerationCache(&video_enumeration_cache_);
537 } 563 }
538 } 564 }
539 565
540 bool MediaStreamManager::TranslateRequestedSourceIdToDeviceId( 566 bool MediaStreamManager::TranslateGUIDToRawId(MediaStreamType stream_type,
541 MediaStreamRequest* request) { 567 const GURL& security_origin,
542 // If a specific device has been requested we need to find the real device id. 568 const std::string& device_guid,
543 if (request->audio_type == MEDIA_DEVICE_AUDIO_CAPTURE && 569 std::string* raw_device_id) {
544 !request->requested_audio_device_id.empty()) {
545 if (!TranslateSourceIdToDeviceId(MEDIA_DEVICE_AUDIO_CAPTURE,
546 request->security_origin,
547 request->requested_audio_device_id,
548 &request->requested_audio_device_id)) {
549 // TODO(perkj): gUM should support mandatory and optional constraints.
550 // Ie - if the sourceId is optional but it does not match - gUM should
551 // not fail. For now we treat sourceId as a mandatory constraint.
552 LOG(ERROR) << "Requested device does not exist.";
553 return false;
554 }
555 }
556
557 if (request->video_type == MEDIA_DEVICE_VIDEO_CAPTURE &&
558 !request->requested_video_device_id.empty()) {
559 if (!TranslateSourceIdToDeviceId(MEDIA_DEVICE_VIDEO_CAPTURE,
560 request->security_origin,
561 request->requested_video_device_id,
562 &request->requested_video_device_id)) {
563 // TODO(perkj): guM should support mandatory and optional constraints.
564 // Ie - if the sourceId is optional but it does not match - guM should
565 // not fail. For now we treat sourceId as a mandatory constraint.
566 return false;
567 }
568 }
569 DVLOG(3) << "Requested audio device " << request->requested_audio_device_id
570 << "Requested video device " << request->requested_video_device_id;
571 return true;
572 }
573
574 void MediaStreamManager::TranslateDeviceIdToSourceId(
575 const MediaStreamRequest& request,
576 MediaStreamDevice* device) {
577 if (request.audio_type == MEDIA_DEVICE_AUDIO_CAPTURE ||
578 request.video_type == MEDIA_DEVICE_VIDEO_CAPTURE) {
579 device->id = content::GetHMACForMediaDeviceID(
580 request.security_origin,
581 device->id);
582 return;
583 }
584 return;
585 }
586
587 bool MediaStreamManager::TranslateSourceIdToDeviceId(
588 MediaStreamType stream_type,
589 const GURL& security_origin,
590 const std::string& source_id,
591 std::string* device_id) {
592 DCHECK(stream_type == MEDIA_DEVICE_AUDIO_CAPTURE || 570 DCHECK(stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ||
593 stream_type == MEDIA_DEVICE_VIDEO_CAPTURE); 571 stream_type == MEDIA_DEVICE_VIDEO_CAPTURE);
594 DCHECK(!source_id.empty()); 572 if (device_guid.empty())
573 return false;
595 574
596 EnumerationCache* cache = 575 EnumerationCache* cache =
597 stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ? 576 stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ?
598 &audio_enumeration_cache_ : &video_enumeration_cache_; 577 &audio_enumeration_cache_ : &video_enumeration_cache_;
599 578
600 // If device monitoring hasn't started, the |device_guid| is not valid. 579 // If device monitoring hasn't started, the |device_guid| is not valid.
601 if (!cache->valid) 580 if (!cache->valid)
602 return false; 581 return false;
603 582
604 for (StreamDeviceInfoArray::const_iterator it = cache->devices.begin(); 583 for (StreamDeviceInfoArray::const_iterator it = cache->devices.begin();
605 it != cache->devices.end(); 584 it != cache->devices.end();
606 ++it) { 585 ++it) {
607 if (content::DoesMediaDeviceIDMatchHMAC(security_origin, source_id, 586 if (content::DoesMediaDeviceIDMatchHMAC(
608 it->device.id)) { 587 security_origin, device_guid, it->device.id)) {
609 *device_id = it->device.id; 588 *raw_device_id = it->device.id;
610 return true; 589 return true;
611 } 590 }
612 } 591 }
613 return false; 592 return false;
614 } 593 }
615 594
616 void MediaStreamManager::ClearEnumerationCache(EnumerationCache* cache) { 595 void MediaStreamManager::ClearEnumerationCache(EnumerationCache* cache) {
617 DCHECK_EQ(base::MessageLoop::current(), io_loop_); 596 DCHECK_EQ(base::MessageLoop::current(), io_loop_);
618 cache->valid = false; 597 cache->valid = false;
619 } 598 }
(...skipping 27 matching lines...) Expand all
647 std::string unique_label; 626 std::string unique_label;
648 do { 627 do {
649 unique_label = RandomLabel(); 628 unique_label = RandomLabel();
650 } while (requests_.find(unique_label) != requests_.end()); 629 } while (requests_.find(unique_label) != requests_.end());
651 630
652 requests_.insert(std::make_pair(unique_label, request)); 631 requests_.insert(std::make_pair(unique_label, request));
653 632
654 return unique_label; 633 return unique_label;
655 } 634 }
656 635
657 MediaStreamManager::DeviceRequest* 636 void MediaStreamManager::RemoveRequest(DeviceRequests::iterator it) {
658 MediaStreamManager::FindRequest(const std::string& label) {
659 DeviceRequests::iterator request_it = requests_.find(label);
660 return request_it == requests_.end() ? NULL : request_it->second;
661 }
662
663 void MediaStreamManager::DeleteRequest(const std::string& label) {
664 DeviceRequests::iterator it = requests_.find(label);
665 scoped_ptr<DeviceRequest> request(it->second);
666 requests_.erase(it); 637 requests_.erase(it);
667 } 638 }
668 639
669 void MediaStreamManager::PostRequestToUI(const std::string& label) { 640 void MediaStreamManager::PostRequestToUI(const std::string& label) {
670 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 641 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
671 DeviceRequest* request = FindRequest(label); 642 DeviceRequest* request = requests_[label];
672 643
673 if (use_fake_ui_) { 644 if (use_fake_ui_) {
674 if (!fake_ui_) 645 if (!fake_ui_)
675 fake_ui_.reset(new FakeMediaStreamUIProxy()); 646 fake_ui_.reset(new FakeMediaStreamUIProxy());
676 647
677 MediaStreamDevices devices; 648 MediaStreamDevices devices;
678 if (audio_enumeration_cache_.valid) { 649 if (audio_enumeration_cache_.valid) {
679 for (StreamDeviceInfoArray::const_iterator it = 650 for (StreamDeviceInfoArray::const_iterator it =
680 audio_enumeration_cache_.devices.begin(); 651 audio_enumeration_cache_.devices.begin();
681 it != audio_enumeration_cache_.devices.end(); ++it) { 652 it != audio_enumeration_cache_.devices.end(); ++it) {
(...skipping 16 matching lines...) Expand all
698 } 669 }
699 670
700 request->ui_proxy->RequestAccess( 671 request->ui_proxy->RequestAccess(
701 request->request, 672 request->request,
702 base::Bind(&MediaStreamManager::HandleAccessRequestResponse, 673 base::Bind(&MediaStreamManager::HandleAccessRequestResponse,
703 base::Unretained(this), label)); 674 base::Unretained(this), label));
704 } 675 }
705 676
706 void MediaStreamManager::HandleRequest(const std::string& label) { 677 void MediaStreamManager::HandleRequest(const std::string& label) {
707 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 678 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
708 DeviceRequest* request = FindRequest(label); 679 DeviceRequest* request = requests_[label];
709 680
710 const MediaStreamType audio_type = request->request.audio_type; 681 const MediaStreamType audio_type = request->request.audio_type;
711 const MediaStreamType video_type = request->request.video_type; 682 const MediaStreamType video_type = request->request.video_type;
712 683
713 bool is_web_contents_capture = 684 bool is_web_contents_capture =
714 audio_type == MEDIA_TAB_AUDIO_CAPTURE || 685 audio_type == MEDIA_TAB_AUDIO_CAPTURE ||
715 video_type == MEDIA_TAB_VIDEO_CAPTURE; 686 video_type == MEDIA_TAB_VIDEO_CAPTURE;
716 if (is_web_contents_capture && !SetupTabCaptureRequest(request)) {
717 FinalizeRequestFailed(label, request);
718 return;
719 }
720 687
721 bool is_screen_capture = 688 bool is_screen_capture =
722 video_type == MEDIA_DESKTOP_VIDEO_CAPTURE; 689 video_type == MEDIA_DESKTOP_VIDEO_CAPTURE;
723 if (is_screen_capture && !SetupScreenCaptureRequest(request)) {
724 FinalizeRequestFailed(label, request);
725 return;
726 }
727 690
728 if (!is_web_contents_capture && 691 if (!is_web_contents_capture &&
729 !is_screen_capture && 692 !is_screen_capture &&
730 ((IsAudioMediaType(audio_type) && !audio_enumeration_cache_.valid) || 693 ((IsAudioMediaType(audio_type) && !audio_enumeration_cache_.valid) ||
731 (IsVideoMediaType(video_type) && !video_enumeration_cache_.valid))) { 694 (IsVideoMediaType(video_type) && !video_enumeration_cache_.valid))) {
732 // Enumerate the devices if there is no valid device lists to be used. 695 // Enumerate the devices if there is no valid device lists to be used.
733 StartEnumeration(request); 696 StartEnumeration(request);
734 return; 697 return;
735 } 698 }
736 699
737 // If a specific device has been requested we need to find the real device id.
738 if (!TranslateRequestedSourceIdToDeviceId(&request->request)) {
739 FinalizeRequestFailed(label, request);
740 return;
741 }
742
743 // No need to do new device enumerations, post the request to UI 700 // No need to do new device enumerations, post the request to UI
744 // immediately. 701 // immediately.
745 if (IsAudioMediaType(audio_type)) 702 if (IsAudioMediaType(audio_type))
746 request->SetState(audio_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL); 703 request->SetState(audio_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
747 if (IsVideoMediaType(video_type)) 704 if (IsVideoMediaType(video_type))
748 request->SetState(video_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL); 705 request->SetState(video_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
749 706
750 PostRequestToUI(label); 707 PostRequestToUI(label);
751 } 708 }
752 709
753 bool MediaStreamManager::SetupTabCaptureRequest(DeviceRequest* request) {
754 DCHECK(request->request.audio_type == MEDIA_TAB_AUDIO_CAPTURE ||
755 request->request.video_type == MEDIA_TAB_VIDEO_CAPTURE);
756
757 MediaStreamRequest* ms_request = &request->request;
758 // Customize options for a WebContents based capture.
759 int target_render_process_id = 0;
760 int target_render_view_id = 0;
761
762 // TODO(justinlin): Can't plumb audio mirroring using stream type right
763 // now, so plumbing by device_id. Will revisit once it's refactored.
764 // http://crbug.com/163100
765 std::string tab_capture_device_id =
766 WebContentsCaptureUtil::AppendWebContentsDeviceScheme(
767 !ms_request->requested_video_device_id.empty() ?
768 ms_request->requested_video_device_id :
769 ms_request->requested_audio_device_id);
770
771 bool has_valid_device_id = WebContentsCaptureUtil::ExtractTabCaptureTarget(
772 tab_capture_device_id, &target_render_process_id,
773 &target_render_view_id);
774 if (!has_valid_device_id ||
775 (ms_request->audio_type != MEDIA_TAB_AUDIO_CAPTURE &&
776 ms_request->audio_type != MEDIA_NO_SERVICE) ||
777 (ms_request->video_type != MEDIA_TAB_VIDEO_CAPTURE &&
778 ms_request->video_type != MEDIA_NO_SERVICE)) {
779 return false;
780 }
781 ms_request->tab_capture_device_id = tab_capture_device_id;
782 ms_request->render_process_id = target_render_process_id;
783 ms_request->render_view_id = target_render_view_id;
784 DVLOG(3) << "SetupTabCaptureRequest "
785 << ", {tab_capture_device_id = " << tab_capture_device_id << "}"
786 << ", {target_render_process_id = " << target_render_process_id
787 << "}"
788 << ", {target_render_view_id = " << target_render_view_id << "}";
789 return true;
790 }
791
792 bool MediaStreamManager::SetupScreenCaptureRequest(DeviceRequest* request) {
793 DCHECK(request->request.audio_type == MEDIA_LOOPBACK_AUDIO_CAPTURE ||
794 request->request.video_type == MEDIA_DESKTOP_VIDEO_CAPTURE);
795 const MediaStreamRequest& ms_request = request->request;
796
797 // For screen capture we only support two valid combinations:
798 // (1) screen video capture only, or
799 // (2) screen video capture with loopback audio capture.
800 if (ms_request.video_type != MEDIA_DESKTOP_VIDEO_CAPTURE ||
801 (ms_request.audio_type != MEDIA_NO_SERVICE &&
802 ms_request.audio_type != MEDIA_LOOPBACK_AUDIO_CAPTURE)) {
803 // TODO(sergeyu): Surface error message to the calling JS code.
804 LOG(ERROR) << "Invalid screen capture request.";
805 return false;
806 }
807 return true;
808 }
809
810 const StreamDeviceInfo* MediaStreamManager::FindRequestedDeviceInfoForTest(
811 const std::string& source_id,
812 int render_process_id,
813 int render_view_id,
814 MediaStreamRequestType type) {
815 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
816 for (DeviceRequests::const_iterator it = requests_.begin();
817 it != requests_.end() ; ++it) {
818 const DeviceRequest* request = it->second;
819 if (request->request.render_process_id == render_process_id &&
820 request->request.render_view_id == render_view_id &&
821 request->request.request_type == type) {
822 for (StreamDeviceInfoArray::const_iterator device_it =
823 request->devices.begin();
824 device_it != request->devices.end(); ++device_it) {
825 if (source_id == device_it->device.id) {
826 return &*device_it;
827 }
828 }
829 }
830 }
831 return NULL;
832 }
833
834 bool MediaStreamManager::FindExistingRequestedDeviceInfo( 710 bool MediaStreamManager::FindExistingRequestedDeviceInfo(
835 int render_process_id, 711 int render_process_id,
836 int render_view_id, 712 int render_view_id,
837 const GURL& security_origin,
838 MediaStreamRequestType type, 713 MediaStreamRequestType type,
839 const std::string& device_id, 714 const std::string& device_id,
840 MediaStreamType device_type,
841 StreamDeviceInfo* device_info, 715 StreamDeviceInfo* device_info,
842 MediaRequestState* request_state) const { 716 MediaRequestState* request_state) const {
843 DCHECK(device_info); 717 DCHECK(device_info);
844 DCHECK(request_state); 718 DCHECK(request_state);
845
846 std::string source_id = content::GetHMACForMediaDeviceID(
847 security_origin,
848 device_id);
849
850 for (DeviceRequests::const_iterator it = requests_.begin(); 719 for (DeviceRequests::const_iterator it = requests_.begin();
851 it != requests_.end() ; ++it) { 720 it != requests_.end() ; ++it) {
852 const DeviceRequest* request = it->second; 721 const DeviceRequest* request = it->second;
853 if (request->requesting_process_id == render_process_id && 722 if (request->requesting_process_id ==render_process_id &&
854 request->requesting_view_id == render_view_id && 723 request->requesting_view_id == render_view_id &&
855 request->request.request_type == type) { 724 request->request.request_type == type) {
856 for (StreamDeviceInfoArray::const_iterator device_it = 725 for (StreamDeviceInfoArray::const_iterator device_it =
857 request->devices.begin(); 726 request->devices.begin();
858 device_it != request->devices.end(); ++device_it) { 727 device_it != request->devices.end(); ++device_it) {
859 if (device_it->device.id == source_id && 728 if (device_it->device.id == device_id) {
860 device_it->device.type == device_type) {
861 *device_info = *device_it; 729 *device_info = *device_it;
862 *request_state = request->state(device_it->device.type); 730 *request_state = request->state(device_it->device.type);
863 return true; 731 return true;
864 } 732 }
865 } 733 }
866 } 734 }
867 } 735 }
868 return false; 736 return false;
869 } 737 }
870 738
871 void MediaStreamManager::FinalizeGenerateStream(const std::string& label,
872 DeviceRequest* request) {
873 const StreamDeviceInfoArray& requested_devices = request->devices;
874
875 // Partition the array of devices into audio vs video.
876 StreamDeviceInfoArray audio_devices, video_devices;
877 for (StreamDeviceInfoArray::const_iterator device_it =
878 requested_devices.begin();
879 device_it != requested_devices.end(); ++device_it) {
880 if (IsAudioMediaType(device_it->device.type)) {
881 audio_devices.push_back(*device_it);
882 } else if (IsVideoMediaType(device_it->device.type)) {
883 video_devices.push_back(*device_it);
884 } else {
885 NOTREACHED();
886 }
887 }
888
889 request->requester->StreamGenerated(label, audio_devices, video_devices);
890 }
891
892 void MediaStreamManager::FinalizeRequestFailed(
893 const std::string& label,
894 DeviceRequest* request) {
895 if (request->requester)
896 request->requester->StreamGenerationFailed(label);
897
898 if (request->request.request_type == MEDIA_DEVICE_ACCESS &&
899 !request->callback.is_null()) {
900 request->callback.Run(MediaStreamDevices(), request->ui_proxy.Pass());
901 }
902
903 DeleteRequest(label);
904 }
905
906 void MediaStreamManager::FinalizeOpenDevice(const std::string& label,
907 DeviceRequest* request) {
908 const StreamDeviceInfoArray& requested_devices = request->devices;
909 request->requester->DeviceOpened(label, requested_devices.front());
910 }
911
912 void MediaStreamManager::FinalizeEnumerateDevices(const std::string& label,
913 DeviceRequest* request) {
914 for (StreamDeviceInfoArray::iterator it = request->devices.begin();
915 it != request->devices.end(); ++it) {
916 TranslateDeviceIdToSourceId(request->request, &it->device);
917 }
918 request->requester->DevicesEnumerated(label, request->devices);
919 }
920
921 void MediaStreamManager::FinalizeMediaAccessRequest(
922 const std::string& label,
923 DeviceRequest* request,
924 const MediaStreamDevices& devices) {
925 if (!request->callback.is_null())
926 request->callback.Run(devices, request->ui_proxy.Pass());
927
928 // Delete the request since it is done.
929 DeleteRequest(label);
930 }
931
932 void MediaStreamManager::InitializeDeviceManagersOnIOThread() { 739 void MediaStreamManager::InitializeDeviceManagersOnIOThread() {
933 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 740 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
934 if (device_thread_) 741 if (device_thread_)
935 return; 742 return;
936 743
937 device_thread_.reset(new base::Thread("MediaStreamDeviceThread")); 744 device_thread_.reset(new base::Thread("MediaStreamDeviceThread"));
938 #if defined(OS_WIN) 745 #if defined(OS_WIN)
939 device_thread_->init_com_with_mta(true); 746 device_thread_->init_com_with_mta(true);
940 #endif 747 #endif
941 CHECK(device_thread_->Start()); 748 CHECK(device_thread_->Start());
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
976 request->SetState(device_it->device.type, MEDIA_REQUEST_STATE_DONE); 783 request->SetState(device_it->device.type, MEDIA_REQUEST_STATE_DONE);
977 784
978 if (IsAudioMediaType(device_it->device.type)) { 785 if (IsAudioMediaType(device_it->device.type)) {
979 // Store the native audio parameters in the device struct. 786 // Store the native audio parameters in the device struct.
980 // TODO(xians): Handle the tab capture sample rate/channel layout 787 // TODO(xians): Handle the tab capture sample rate/channel layout
981 // in AudioInputDeviceManager::Open(). 788 // in AudioInputDeviceManager::Open().
982 if (device_it->device.type != content::MEDIA_TAB_AUDIO_CAPTURE) { 789 if (device_it->device.type != content::MEDIA_TAB_AUDIO_CAPTURE) {
983 const StreamDeviceInfo* info = 790 const StreamDeviceInfo* info =
984 audio_input_device_manager_->GetOpenedDeviceInfoById( 791 audio_input_device_manager_->GetOpenedDeviceInfoById(
985 device_it->session_id); 792 device_it->session_id);
793 DCHECK_EQ(info->device.id, device_it->device.id);
986 device_it->device.input = info->device.input; 794 device_it->device.input = info->device.input;
987 device_it->device.matched_output = info->device.matched_output; 795 device_it->device.matched_output = info->device.matched_output;
988 } 796 }
989 } 797 }
990 if (RequestDone(*request)) 798 if (RequestDone(*request))
991 HandleRequestDone(label, request); 799 HandleRequestDone(label, request);
992 break; 800 break;
993 } 801 }
994 } 802 }
995 } 803 }
996 } 804 }
997 805
998 void MediaStreamManager::HandleRequestDone(const std::string& label, 806 void MediaStreamManager::HandleRequestDone(const std::string& label,
999 DeviceRequest* request) { 807 DeviceRequest* request) {
1000 DCHECK(RequestDone(*request)); 808 DCHECK(RequestDone(*request));
1001 DVLOG(1) << "HandleRequestDone(" 809 DVLOG(1) << "HandleRequestDone("
1002 << ", {label = " << label << "})"; 810 << ", {label = " << label << "})";
1003 811
812 const StreamDeviceInfoArray& requested_devices = request->devices;
1004 switch (request->request.request_type) { 813 switch (request->request.request_type) {
1005 case MEDIA_OPEN_DEVICE: 814 case MEDIA_OPEN_DEVICE:
1006 FinalizeOpenDevice(label, request); 815 request->requester->DeviceOpened(label, requested_devices.front());
1007 break; 816 break;
1008 case MEDIA_GENERATE_STREAM: { 817 case MEDIA_GENERATE_STREAM: {
1009 FinalizeGenerateStream(label, request); 818 // Partition the array of devices into audio vs video.
819 StreamDeviceInfoArray audio_devices, video_devices;
820 for (StreamDeviceInfoArray::const_iterator device_it =
821 requested_devices.begin();
822 device_it != requested_devices.end(); ++device_it) {
823 if (IsAudioMediaType(device_it->device.type)) {
824 audio_devices.push_back(*device_it);
825 } else if (IsVideoMediaType(device_it->device.type)) {
826 video_devices.push_back(*device_it);
827 } else {
828 NOTREACHED();
829 }
830 }
831
832 request->requester->StreamGenerated(label, audio_devices, video_devices);
1010 break; 833 break;
1011 } 834 }
1012 default: 835 default:
1013 NOTREACHED(); 836 NOTREACHED();
1014 break; 837 break;
1015 } 838 }
1016 839
1017 if (request->ui_proxy.get()) { 840 if (request->ui_proxy.get()) {
1018 request->ui_proxy->OnStarted( 841 request->ui_proxy->OnStarted(
1019 base::Bind(&MediaStreamManager::StopStreamFromUI, 842 base::Bind(&MediaStreamManager::StopStreamFromUI,
1020 base::Unretained(this), label)); 843 base::Unretained(this), label));
1021 } 844 }
1022 } 845 }
1023 846
1024 void MediaStreamManager::Closed(MediaStreamType stream_type, 847 void MediaStreamManager::Closed(MediaStreamType stream_type,
1025 int capture_session_id) { 848 int capture_session_id) {
1026 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 849 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1027 } 850 }
1028 851
1029 void MediaStreamManager::DevicesEnumerated( 852 void MediaStreamManager::DevicesEnumerated(
1030 MediaStreamType stream_type, const StreamDeviceInfoArray& devices) { 853 MediaStreamType stream_type, const StreamDeviceInfoArray& devices) {
1031 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 854 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1032 DVLOG(1) << "DevicesEnumerated";
1033 855
1034 // Only cache the device list when the device list has been changed. 856 // Only cache the device list when the device list has been changed.
1035 bool need_update_clients = false; 857 bool need_update_clients = false;
1036 EnumerationCache* cache = 858 EnumerationCache* cache =
1037 stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ? 859 stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ?
1038 &audio_enumeration_cache_ : &video_enumeration_cache_; 860 &audio_enumeration_cache_ : &video_enumeration_cache_;
1039 if (!cache->valid || 861 if (!cache->valid ||
1040 devices.size() != cache->devices.size() || 862 devices.size() != cache->devices.size() ||
1041 !std::equal(devices.begin(), devices.end(), cache->devices.begin(), 863 !std::equal(devices.begin(), devices.end(), cache->devices.begin(),
1042 StreamDeviceInfo::IsEqual)) { 864 StreamDeviceInfo::IsEqual)) {
(...skipping 14 matching lines...) Expand all
1057 ++it) { 879 ++it) {
1058 if (it->second->state(stream_type) == MEDIA_REQUEST_STATE_REQUESTED && 880 if (it->second->state(stream_type) == MEDIA_REQUEST_STATE_REQUESTED &&
1059 Requested(it->second->request, stream_type)) { 881 Requested(it->second->request, stream_type)) {
1060 if (it->second->request.request_type != MEDIA_ENUMERATE_DEVICES) 882 if (it->second->request.request_type != MEDIA_ENUMERATE_DEVICES)
1061 it->second->SetState(stream_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL); 883 it->second->SetState(stream_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
1062 label_list.push_back(it->first); 884 label_list.push_back(it->first);
1063 } 885 }
1064 } 886 }
1065 for (std::list<std::string>::iterator it = label_list.begin(); 887 for (std::list<std::string>::iterator it = label_list.begin();
1066 it != label_list.end(); ++it) { 888 it != label_list.end(); ++it) {
1067 DeviceRequest* request = FindRequest(*it); 889 DeviceRequest* request = requests_[*it];
1068 switch (request->request.request_type) { 890 switch (request->request.request_type) {
1069 case MEDIA_ENUMERATE_DEVICES: 891 case MEDIA_ENUMERATE_DEVICES:
1070 if (need_update_clients && request->requester) { 892 if (need_update_clients && request->requester)
1071 request->devices = devices; 893 request->requester->DevicesEnumerated(*it, devices);
1072 FinalizeEnumerateDevices(*it, request);
1073 }
1074 break; 894 break;
1075 default: 895 default:
1076 if (request->state(request->request.audio_type) == 896 if (request->state(request->request.audio_type) ==
1077 MEDIA_REQUEST_STATE_REQUESTED || 897 MEDIA_REQUEST_STATE_REQUESTED ||
1078 request->state(request->request.video_type) == 898 request->state(request->request.video_type) ==
1079 MEDIA_REQUEST_STATE_REQUESTED) { 899 MEDIA_REQUEST_STATE_REQUESTED) {
1080 // We are doing enumeration for other type of media, wait until it is 900 // We are doing enumeration for other type of media, wait until it is
1081 // all done before posting the request to UI because UI needs 901 // all done before posting the request to UI because UI needs
1082 // the device lists to handle the request. 902 // the device lists to handle the request.
1083 break; 903 break;
1084 } 904 }
1085 905
1086 // Continue to handle the request. 906 // Post the request to UI for permission approval.
1087 HandleRequest(*it); 907 PostRequestToUI(*it);
1088 break; 908 break;
1089 } 909 }
1090 } 910 }
1091 label_list.clear(); 911 label_list.clear();
1092 --active_enumeration_ref_count_[stream_type]; 912 --active_enumeration_ref_count_[stream_type];
1093 DCHECK_GE(active_enumeration_ref_count_[stream_type], 0); 913 DCHECK_GE(active_enumeration_ref_count_[stream_type], 0);
1094 } 914 }
1095 915
916 void MediaStreamManager::Error(MediaStreamType stream_type,
917 int capture_session_id,
918 MediaStreamProviderError error) {
919 // Find the device for the error call.
920 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
921 DVLOG(1) << "Error("
922 << "{stream_type = " << stream_type << "} ,"
923 << "{capture_session_id = " << capture_session_id << "})";
924
925
926 for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end();
927 ++it) {
928 StreamDeviceInfoArray& devices = it->second->devices;
929
930 // TODO(miu): BUG. It's possible for the audio (or video) device array in
931 // the "requester" to become out-of-sync with the order of devices we have
932 // here. See http://crbug.com/147650
933 int audio_device_idx = -1;
934 int video_device_idx = -1;
935 for (StreamDeviceInfoArray::iterator device_it = devices.begin();
936 device_it != devices.end(); ++device_it) {
937 if (IsAudioMediaType(device_it->device.type)) {
938 ++audio_device_idx;
939 } else if (IsVideoMediaType(device_it->device.type)) {
940 ++video_device_idx;
941 } else {
942 NOTREACHED();
943 continue;
944 }
945 if (device_it->device.type != stream_type ||
946 device_it->session_id != capture_session_id) {
947 continue;
948 }
949 // We've found the failing device. Find the error case:
950 // An error should only be reported to the MediaStreamManager if
951 // the request has not been fulfilled yet.
952 DCHECK(it->second->state(stream_type) != MEDIA_REQUEST_STATE_DONE);
953 if (it->second->state(stream_type) != MEDIA_REQUEST_STATE_DONE) {
954 // Request is not done, devices are not opened in this case.
955 if (devices.size() <= 1) {
956 scoped_ptr<DeviceRequest> request(it->second);
957 // 1. Device not opened and no other devices for this request ->
958 // signal stream error and remove the request.
959 if (request->requester)
960 request->requester->StreamGenerationFailed(it->first);
961
962 RemoveRequest(it);
963 } else {
964 // 2. Not opened but other devices exists for this request -> remove
965 // device from list, but don't signal an error.
966 devices.erase(device_it); // NOTE: This invalidates device_it!
967 it->second->SetState(stream_type, MEDIA_REQUEST_STATE_ERROR);
968 DVLOG(1) << "Error("
969 << ", {capture_session_id = " << capture_session_id << "})";
970 }
971 }
972 if (RequestDone(*it->second))
973 HandleRequestDone(it->first, it->second);
974 break;
975 }
976 }
977 }
978
1096 void MediaStreamManager::HandleAccessRequestResponse( 979 void MediaStreamManager::HandleAccessRequestResponse(
1097 const std::string& label, 980 const std::string& label,
1098 const MediaStreamDevices& devices) { 981 const MediaStreamDevices& devices) {
1099 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 982 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1100 DVLOG(1) << "HandleAccessRequestResponse(" 983 DVLOG(1) << "HandleAccessRequestResponse("
1101 << ", {label = " << label << "})"; 984 << ", {label = " << label << "})";
1102 985
1103 DeviceRequest* request = FindRequest(label); 986 DeviceRequests::iterator request_it = requests_.find(label);
1104 if (!request) { 987 if (request_it == requests_.end()) {
1105 // The request has been canceled before the UI returns.
1106 return;
1107 }
1108
1109 if (request->request.request_type == MEDIA_DEVICE_ACCESS) {
1110 FinalizeMediaAccessRequest(label, request, devices);
1111 return; 988 return;
1112 } 989 }
1113 990
1114 // Handle the case when the request was denied. 991 // Handle the case when the request was denied.
1115 if (devices.empty()) { 992 if (devices.empty()) {
1116 FinalizeRequestFailed(label, request); 993 // Notify the users about the request result.
994 scoped_ptr<DeviceRequest> request(request_it->second);
995 if (request->requester)
996 request->requester->StreamGenerationFailed(label);
997
998 if (request->request.request_type == MEDIA_DEVICE_ACCESS &&
999 !request->callback.is_null()) {
1000 request->callback.Run(MediaStreamDevices(), request->ui_proxy.Pass());
1001 }
1002
1003 RemoveRequest(request_it);
1004 return;
1005 }
1006
1007 if (request_it->second->request.request_type == MEDIA_DEVICE_ACCESS) {
1008 scoped_ptr<DeviceRequest> request(request_it->second);
1009 if (!request->callback.is_null())
1010 request->callback.Run(devices, request->ui_proxy.Pass());
1011
1012 // Delete the request since it is done.
1013 RemoveRequest(request_it);
1117 return; 1014 return;
1118 } 1015 }
1119 1016
1120 // Process all newly-accepted devices for this request. 1017 // Process all newly-accepted devices for this request.
1018 DeviceRequest* request = request_it->second;
1121 bool found_audio = false; 1019 bool found_audio = false;
1122 bool found_video = false; 1020 bool found_video = false;
1123 for (MediaStreamDevices::const_iterator device_it = devices.begin(); 1021 for (MediaStreamDevices::const_iterator device_it = devices.begin();
1124 device_it != devices.end(); ++device_it) { 1022 device_it != devices.end(); ++device_it) {
1125 StreamDeviceInfo device_info; 1023 StreamDeviceInfo device_info;
1126 device_info.device = *device_it; 1024 device_info.device = *device_it;
1127 1025
1128 // TODO(justinlin): Nicer way to do this? 1026 // TODO(justinlin): Nicer way to do this?
1129 // Re-append the device's id since we lost it when posting request to UI. 1027 // Re-append the device's id since we lost it when posting request to UI.
1130 if (device_info.device.type == content::MEDIA_TAB_VIDEO_CAPTURE || 1028 if (device_info.device.type == content::MEDIA_TAB_VIDEO_CAPTURE ||
(...skipping 20 matching lines...) Expand all
1151 if (device_info.device.type == request->request.audio_type) { 1049 if (device_info.device.type == request->request.audio_type) {
1152 found_audio = true; 1050 found_audio = true;
1153 } else if (device_info.device.type == request->request.video_type) { 1051 } else if (device_info.device.type == request->request.video_type) {
1154 found_video = true; 1052 found_video = true;
1155 } 1053 }
1156 1054
1157 // If this is request for a new MediaStream, a device is only opened once 1055 // If this is request for a new MediaStream, a device is only opened once
1158 // per render view. This is so that the permission to use a device can be 1056 // per render view. This is so that the permission to use a device can be
1159 // revoked by a single call to StopStreamDevice regardless of how many 1057 // revoked by a single call to StopStreamDevice regardless of how many
1160 // MediaStreams it is being used in. 1058 // MediaStreams it is being used in.
1059
1161 if (request->request.request_type == MEDIA_GENERATE_STREAM) { 1060 if (request->request.request_type == MEDIA_GENERATE_STREAM) {
1162 MediaRequestState state; 1061 MediaRequestState state;
1163 if (FindExistingRequestedDeviceInfo(request->requesting_process_id, 1062 if (FindExistingRequestedDeviceInfo(request->requesting_process_id,
1164 request->requesting_view_id, 1063 request->requesting_view_id,
1165 request->request.security_origin,
1166 request->request.request_type, 1064 request->request.request_type,
1167 device_info.device.id, 1065 device_it->id,
1168 device_info.device.type,
1169 &device_info, 1066 &device_info,
1170 &state)) { 1067 &state)) {
1171 request->devices.push_back(device_info); 1068 request->devices.push_back(device_info);
1172 request->SetState(device_info.device.type, state); 1069 request->SetState(device_info.device.type, state);
1173 DVLOG(1) << "HandleAccessRequestResponse - device already opened " 1070 DVLOG(1) << "HandleAccessRequestResponse - device already opened "
1174 << ", {label = " << label << "}" 1071 << ", {label = " << label << "}"
1175 << ", device_id = " << device_it->id << "}"; 1072 << ", device_id = " << device_it->id << "}";
1176 continue; 1073 continue;
1177 } 1074 }
1178 } 1075 }
1179 device_info.session_id = 1076 device_info.session_id =
1180 GetDeviceManager(device_info.device.type)->Open(device_info); 1077 GetDeviceManager(device_info.device.type)->Open(device_info);
1181 TranslateDeviceIdToSourceId(request->request, &device_info.device);
1182 request->devices.push_back(device_info); 1078 request->devices.push_back(device_info);
1183
1184 request->SetState(device_info.device.type, MEDIA_REQUEST_STATE_OPENING); 1079 request->SetState(device_info.device.type, MEDIA_REQUEST_STATE_OPENING);
1185 DVLOG(1) << "HandleAccessRequestResponse - opening device " 1080 DVLOG(1) << "HandleAccessRequestResponse - opening device "
1186 << ", {label = " << label << "}" 1081 << ", {label = " << label << "}"
1187 << ", {device_id = " << device_info.device.id << "}" 1082 << ", {device_id = " << device_it->id << "}"
1188 << ", {session_id = " << device_info.session_id << "}"; 1083 << ", {session_id = " << device_info.session_id << "}";
1189 } 1084 }
1190 1085
1191 // Check whether we've received all stream types requested. 1086 // Check whether we've received all stream types requested.
1192 if (!found_audio && IsAudioMediaType(request->request.audio_type)) { 1087 if (!found_audio && IsAudioMediaType(request->request.audio_type)) {
1193 request->SetState(request->request.audio_type, MEDIA_REQUEST_STATE_ERROR); 1088 request->SetState(request->request.audio_type, MEDIA_REQUEST_STATE_ERROR);
1194 DVLOG(1) << "Set no audio found label " << label; 1089 DVLOG(1) << "Set no audio found label " << label;
1195 } 1090 }
1196 1091
1197 if (!found_video && IsVideoMediaType(request->request.video_type)) 1092 if (!found_video && IsVideoMediaType(request->request.video_type))
1198 request->SetState(request->request.video_type, MEDIA_REQUEST_STATE_ERROR); 1093 request->SetState(request->request.video_type, MEDIA_REQUEST_STATE_ERROR);
1199 1094
1200 if (RequestDone(*request)) 1095 if (RequestDone(*request))
1201 HandleRequestDone(label, request); 1096 HandleRequestDone(label, request);
1202 } 1097 }
1203 1098
1204 void MediaStreamManager::StopStreamFromUI(const std::string& label) { 1099 void MediaStreamManager::StopStreamFromUI(const std::string& label) {
1205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1100 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1206 1101
1207 DeviceRequest* request = FindRequest(label); 1102 DeviceRequests::iterator it = requests_.find(label);
1208 if (!request) 1103 if (it == requests_.end())
1209 return; 1104 return;
1210 1105
1211 // Notify renderers that the stream has been stopped. 1106 // Notify renderers that the stream has been stopped.
1212 if (request->requester) { 1107 if (it->second->requester)
1213 request->requester->StopGeneratedStream(request->request.render_view_id, 1108 it->second->requester->StopGeneratedStream(
1214 label); 1109 it->second->request.render_view_id,
1215 } 1110 label);
1216 1111
1217 CancelRequest(label); 1112 CancelRequest(label);
1218 } 1113 }
1219 1114
1220 void MediaStreamManager::UseFakeDevice() { 1115 void MediaStreamManager::UseFakeDevice() {
1221 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1222 video_capture_manager()->UseFakeDevice(); 1117 video_capture_manager()->UseFakeDevice();
1223 audio_input_device_manager()->UseFakeDevice(); 1118 audio_input_device_manager()->UseFakeDevice();
1224 } 1119 }
1225 1120
1226 void MediaStreamManager::UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy> fake_ui) { 1121 void MediaStreamManager::UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy> fake_ui) {
1227 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1228 use_fake_ui_ = true; 1123 use_fake_ui_ = true;
1229 fake_ui_ = fake_ui.Pass(); 1124 fake_ui_ = fake_ui.Pass();
1230 } 1125 }
1231 1126
1232 void MediaStreamManager::WillDestroyCurrentMessageLoop() { 1127 void MediaStreamManager::WillDestroyCurrentMessageLoop() {
1233 DVLOG(3) << "MediaStreamManager::WillDestroyCurrentMessageLoop()";
1234 DCHECK_EQ(base::MessageLoop::current(), io_loop_); 1128 DCHECK_EQ(base::MessageLoop::current(), io_loop_);
1235 DCHECK(requests_.empty()); 1129 DCHECK(requests_.empty());
1236 if (device_thread_) { 1130 if (device_thread_) {
1237 StopMonitoring(); 1131 StopMonitoring();
1238 1132
1239 video_capture_manager_->Unregister(); 1133 video_capture_manager_->Unregister();
1240 audio_input_device_manager_->Unregister(); 1134 audio_input_device_manager_->Unregister();
1241 device_thread_.reset(); 1135 device_thread_.reset();
1242 } 1136 }
1243 1137
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
1325 } 1219 }
1326 1220
1327 // Always do enumeration even though some enumeration is in progress, 1221 // Always do enumeration even though some enumeration is in progress,
1328 // because those enumeration commands could be sent before these devices 1222 // because those enumeration commands could be sent before these devices
1329 // change. 1223 // change.
1330 ++active_enumeration_ref_count_[stream_type]; 1224 ++active_enumeration_ref_count_[stream_type];
1331 GetDeviceManager(stream_type)->EnumerateDevices(stream_type); 1225 GetDeviceManager(stream_type)->EnumerateDevices(stream_type);
1332 } 1226 }
1333 1227
1334 } // namespace content 1228 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698