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

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

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

Powered by Google App Engine
This is Rietveld 408576698