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

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 + Addressed Tommis comments except WillDestroyCurrentMessageLoop. 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
575 bool MediaStreamManager::TranslateSourceIdToDeviceId(
576 MediaStreamType stream_type,
577 const GURL& security_origin,
578 const std::string& source_id,
579 std::string* device_id) {
570 DCHECK(stream_type == MEDIA_DEVICE_AUDIO_CAPTURE || 580 DCHECK(stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ||
571 stream_type == MEDIA_DEVICE_VIDEO_CAPTURE); 581 stream_type == MEDIA_DEVICE_VIDEO_CAPTURE);
572 if (device_guid.empty()) 582 DCHECK(!source_id.empty());
573 return false;
574 583
575 EnumerationCache* cache = 584 EnumerationCache* cache =
576 stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ? 585 stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ?
577 &audio_enumeration_cache_ : &video_enumeration_cache_; 586 &audio_enumeration_cache_ : &video_enumeration_cache_;
578 587
579 // If device monitoring hasn't started, the |device_guid| is not valid. 588 // If device monitoring hasn't started, the |device_guid| is not valid.
580 if (!cache->valid) 589 if (!cache->valid)
581 return false; 590 return false;
582 591
583 for (StreamDeviceInfoArray::const_iterator it = cache->devices.begin(); 592 for (StreamDeviceInfoArray::const_iterator it = cache->devices.begin();
584 it != cache->devices.end(); 593 it != cache->devices.end();
585 ++it) { 594 ++it) {
586 if (content::DoesMediaDeviceIDMatchHMAC( 595 if (content::DoesMediaDeviceIDMatchHMAC(security_origin, source_id,
587 security_origin, device_guid, it->device.id)) { 596 it->device.id)) {
588 *raw_device_id = it->device.id; 597 *device_id = it->device.id;
589 return true; 598 return true;
590 } 599 }
591 } 600 }
592 return false; 601 return false;
593 } 602 }
594 603
595 void MediaStreamManager::ClearEnumerationCache(EnumerationCache* cache) { 604 void MediaStreamManager::ClearEnumerationCache(EnumerationCache* cache) {
596 DCHECK_EQ(base::MessageLoop::current(), io_loop_); 605 DCHECK_EQ(base::MessageLoop::current(), io_loop_);
597 cache->valid = false; 606 cache->valid = false;
598 } 607 }
(...skipping 27 matching lines...) Expand all
626 std::string unique_label; 635 std::string unique_label;
627 do { 636 do {
628 unique_label = RandomLabel(); 637 unique_label = RandomLabel();
629 } while (requests_.find(unique_label) != requests_.end()); 638 } while (requests_.find(unique_label) != requests_.end());
630 639
631 requests_.insert(std::make_pair(unique_label, request)); 640 requests_.insert(std::make_pair(unique_label, request));
632 641
633 return unique_label; 642 return unique_label;
634 } 643 }
635 644
636 void MediaStreamManager::RemoveRequest(DeviceRequests::iterator it) { 645 MediaStreamManager::DeviceRequest*
646 MediaStreamManager::FindRequest(const std::string& label) {
647 DeviceRequests::iterator request_it = requests_.find(label);
648 return request_it == requests_.end() ? NULL : request_it->second;
649 }
650
651 void MediaStreamManager::DeleteRequest(const std::string& label) {
652 DeviceRequests::iterator it = requests_.find(label);
653 scoped_ptr<DeviceRequest> request(it->second);
637 requests_.erase(it); 654 requests_.erase(it);
638 } 655 }
639 656
640 void MediaStreamManager::PostRequestToUI(const std::string& label) { 657 void MediaStreamManager::PostRequestToUI(const std::string& label) {
641 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 658 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
642 DeviceRequest* request = requests_[label]; 659 DeviceRequest* request = FindRequest(label);
643 660
644 if (use_fake_ui_) { 661 if (use_fake_ui_) {
645 if (!fake_ui_) 662 if (!fake_ui_)
646 fake_ui_.reset(new FakeMediaStreamUIProxy()); 663 fake_ui_.reset(new FakeMediaStreamUIProxy());
647 664
648 MediaStreamDevices devices; 665 MediaStreamDevices devices;
649 if (audio_enumeration_cache_.valid) { 666 if (audio_enumeration_cache_.valid) {
650 for (StreamDeviceInfoArray::const_iterator it = 667 for (StreamDeviceInfoArray::const_iterator it =
651 audio_enumeration_cache_.devices.begin(); 668 audio_enumeration_cache_.devices.begin();
652 it != audio_enumeration_cache_.devices.end(); ++it) { 669 it != audio_enumeration_cache_.devices.end(); ++it) {
(...skipping 16 matching lines...) Expand all
669 } 686 }
670 687
671 request->ui_proxy->RequestAccess( 688 request->ui_proxy->RequestAccess(
672 request->request, 689 request->request,
673 base::Bind(&MediaStreamManager::HandleAccessRequestResponse, 690 base::Bind(&MediaStreamManager::HandleAccessRequestResponse,
674 base::Unretained(this), label)); 691 base::Unretained(this), label));
675 } 692 }
676 693
677 void MediaStreamManager::HandleRequest(const std::string& label) { 694 void MediaStreamManager::HandleRequest(const std::string& label) {
678 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 695 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
679 DeviceRequest* request = requests_[label]; 696 DeviceRequest* request = FindRequest(label);
680 697
681 const MediaStreamType audio_type = request->request.audio_type; 698 const MediaStreamType audio_type = request->request.audio_type;
682 const MediaStreamType video_type = request->request.video_type; 699 const MediaStreamType video_type = request->request.video_type;
683 700
684 bool is_web_contents_capture = 701 bool is_web_contents_capture =
685 audio_type == MEDIA_TAB_AUDIO_CAPTURE || 702 audio_type == MEDIA_TAB_AUDIO_CAPTURE ||
686 video_type == MEDIA_TAB_VIDEO_CAPTURE; 703 video_type == MEDIA_TAB_VIDEO_CAPTURE;
704 if (is_web_contents_capture && !SetupTabCaptureRequest(request)) {
705 FinalizeRequestFailed(label, request);
706 return;
707 }
687 708
688 bool is_screen_capture = 709 bool is_screen_capture =
689 video_type == MEDIA_DESKTOP_VIDEO_CAPTURE; 710 video_type == MEDIA_DESKTOP_VIDEO_CAPTURE;
711 if (is_screen_capture && !SetupScreenCaptureRequest(request)) {
712 FinalizeRequestFailed(label, request);
713 return;
714 }
690 715
691 if (!is_web_contents_capture && 716 if (!is_web_contents_capture &&
692 !is_screen_capture && 717 !is_screen_capture &&
693 ((IsAudioMediaType(audio_type) && !audio_enumeration_cache_.valid) || 718 ((IsAudioMediaType(audio_type) && !audio_enumeration_cache_.valid) ||
694 (IsVideoMediaType(video_type) && !video_enumeration_cache_.valid))) { 719 (IsVideoMediaType(video_type) && !video_enumeration_cache_.valid))) {
695 // Enumerate the devices if there is no valid device lists to be used. 720 // Enumerate the devices if there is no valid device lists to be used.
696 StartEnumeration(request); 721 StartEnumeration(request);
697 return; 722 return;
698 } 723 }
699 724
725 // If a specific device has been requested we need to find the real device id.
726 if (!TranslateRequestedSourceIdToDeviceId(&request->request)) {
727 FinalizeRequestFailed(label, request);
728 return;
729 }
730
700 // No need to do new device enumerations, post the request to UI 731 // No need to do new device enumerations, post the request to UI
701 // immediately. 732 // immediately.
702 if (IsAudioMediaType(audio_type)) 733 if (IsAudioMediaType(audio_type))
703 request->SetState(audio_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL); 734 request->SetState(audio_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
704 if (IsVideoMediaType(video_type)) 735 if (IsVideoMediaType(video_type))
705 request->SetState(video_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL); 736 request->SetState(video_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
706 737
707 PostRequestToUI(label); 738 PostRequestToUI(label);
708 } 739 }
709 740
741 bool MediaStreamManager::SetupTabCaptureRequest(DeviceRequest* request) {
742 DCHECK(request->request.audio_type == MEDIA_TAB_AUDIO_CAPTURE ||
743 request->request.video_type == MEDIA_TAB_VIDEO_CAPTURE);
744
745 MediaStreamRequest* ms_request = &request->request;
746 // Customize options for a WebContents based capture.
747 int target_render_process_id = 0;
748 int target_render_view_id = 0;
749
750 // TODO(justinlin): Can't plumb audio mirroring using stream type right
751 // now, so plumbing by device_id. Will revisit once it's refactored.
752 // http://crbug.com/163100
753 std::string tab_capture_device_id =
754 WebContentsCaptureUtil::AppendWebContentsDeviceScheme(
755 !ms_request->requested_video_device_id.empty() ?
756 ms_request->requested_video_device_id :
757 ms_request->requested_audio_device_id);
758
759 bool has_valid_device_id = WebContentsCaptureUtil::ExtractTabCaptureTarget(
760 tab_capture_device_id, &target_render_process_id,
761 &target_render_view_id);
762 if (!has_valid_device_id ||
763 (ms_request->audio_type != MEDIA_TAB_AUDIO_CAPTURE &&
764 ms_request->audio_type != MEDIA_NO_SERVICE) ||
765 (ms_request->video_type != MEDIA_TAB_VIDEO_CAPTURE &&
766 ms_request->video_type != MEDIA_NO_SERVICE)) {
767 return false;
768 }
769 ms_request->tab_capture_device_id = tab_capture_device_id;
770 ms_request->render_process_id = target_render_process_id;
771 ms_request->render_view_id = target_render_view_id;
772 DVLOG(3) << "SetupTabCaptureRequest "
773 << ", {tab_capture_device_id = " << tab_capture_device_id << "}"
774 << ", {target_render_process_id = " << target_render_process_id
775 << "}"
776 << ", {target_render_view_id = " << target_render_view_id << "}";
777 return true;
778 }
779
780 bool MediaStreamManager::SetupScreenCaptureRequest(DeviceRequest* request) {
781 DCHECK(request->request.audio_type == MEDIA_LOOPBACK_AUDIO_CAPTURE ||
782 request->request.video_type == MEDIA_DESKTOP_VIDEO_CAPTURE);
783 const MediaStreamRequest& ms_request = request->request;
784
785 // For screen capture we only support two valid combinations:
786 // (1) screen video capture only, or
787 // (2) screen video capture with loopback audio capture.
788 if (ms_request.video_type != MEDIA_DESKTOP_VIDEO_CAPTURE ||
789 (ms_request.audio_type != MEDIA_NO_SERVICE &&
790 ms_request.audio_type != MEDIA_LOOPBACK_AUDIO_CAPTURE)) {
791 // TODO(sergeyu): Surface error message to the calling JS code.
792 LOG(ERROR) << "Invalid screen capture request.";
793 return false;
794 }
795 return true;
796 }
797
798 const StreamDeviceInfo* MediaStreamManager::FindRequestedDeviceInfoForTest(
799 const std::string& source_id,
800 int render_process_id,
801 int render_view_id,
802 MediaStreamRequestType type) {
803 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
804 for (DeviceRequests::const_iterator it = requests_.begin();
805 it != requests_.end() ; ++it) {
806 const DeviceRequest* request = it->second;
807 if (request->request.render_process_id == render_process_id &&
808 request->request.render_view_id == render_view_id &&
809 request->request.request_type == type) {
810 for (StreamDeviceInfoArray::const_iterator device_it =
811 request->devices.begin();
812 device_it != request->devices.end(); ++device_it) {
813 if (source_id == device_it->device.id) {
814 return &*device_it;
815 }
816 }
817 }
818 }
819 return NULL;
820 }
821
822 void MediaStreamManager::WillDestroyCurrentMessageLoopForTest() {
823 base::RunLoop().RunUntilIdle();
824 WillDestroyCurrentMessageLoop();
825 }
826
710 bool MediaStreamManager::FindExistingRequestedDeviceInfo( 827 bool MediaStreamManager::FindExistingRequestedDeviceInfo(
711 int render_process_id, 828 int render_process_id,
712 int render_view_id, 829 int render_view_id,
830 const GURL& security_origin,
713 MediaStreamRequestType type, 831 MediaStreamRequestType type,
714 const std::string& device_id, 832 const std::string& device_id,
833 MediaStreamType device_type,
715 StreamDeviceInfo* device_info, 834 StreamDeviceInfo* device_info,
716 MediaRequestState* request_state) const { 835 MediaRequestState* request_state) const {
717 DCHECK(device_info); 836 DCHECK(device_info);
718 DCHECK(request_state); 837 DCHECK(request_state);
838
839 std::string source_id = content::GetHMACForMediaDeviceID(
840 security_origin,
841 device_id);
842
719 for (DeviceRequests::const_iterator it = requests_.begin(); 843 for (DeviceRequests::const_iterator it = requests_.begin();
720 it != requests_.end() ; ++it) { 844 it != requests_.end() ; ++it) {
721 const DeviceRequest* request = it->second; 845 const DeviceRequest* request = it->second;
722 if (request->requesting_process_id ==render_process_id && 846 if (request->requesting_process_id == render_process_id &&
723 request->requesting_view_id == render_view_id && 847 request->requesting_view_id == render_view_id &&
724 request->request.request_type == type) { 848 request->request.request_type == type) {
725 for (StreamDeviceInfoArray::const_iterator device_it = 849 for (StreamDeviceInfoArray::const_iterator device_it =
726 request->devices.begin(); 850 request->devices.begin();
727 device_it != request->devices.end(); ++device_it) { 851 device_it != request->devices.end(); ++device_it) {
728 if (device_it->device.id == device_id) { 852 if (device_it->device.id == source_id &&
853 device_it->device.type == device_type) {
729 *device_info = *device_it; 854 *device_info = *device_it;
730 *request_state = request->state(device_it->device.type); 855 *request_state = request->state(device_it->device.type);
731 return true; 856 return true;
732 } 857 }
733 } 858 }
734 } 859 }
735 } 860 }
736 return false; 861 return false;
737 } 862 }
738 863
864 void MediaStreamManager::FinalizeGenerateStream(const std::string& label,
865 DeviceRequest* request) {
866 const StreamDeviceInfoArray& requested_devices = request->devices;
867
868 // Partition the array of devices into audio vs video.
869 StreamDeviceInfoArray audio_devices, video_devices;
870 for (StreamDeviceInfoArray::const_iterator device_it =
871 requested_devices.begin();
872 device_it != requested_devices.end(); ++device_it) {
873 if (IsAudioMediaType(device_it->device.type)) {
874 audio_devices.push_back(*device_it);
875 } else if (IsVideoMediaType(device_it->device.type)) {
876 video_devices.push_back(*device_it);
877 } else {
878 NOTREACHED();
879 }
880 }
881
882 request->requester->StreamGenerated(label, audio_devices, video_devices);
883 }
884
885 void MediaStreamManager::FinalizeRequestFailed(
886 const std::string& label,
887 DeviceRequest* request) {
888 if (request->requester)
889 request->requester->StreamGenerationFailed(label);
890
891 if (request->request.request_type == MEDIA_DEVICE_ACCESS &&
892 !request->callback.is_null()) {
893 request->callback.Run(MediaStreamDevices(), request->ui_proxy.Pass());
894 }
895
896 DeleteRequest(label);
897 }
898
899 void MediaStreamManager::FinalizeOpenDevice(const std::string& label,
900 DeviceRequest* request) {
901 const StreamDeviceInfoArray& requested_devices = request->devices;
902 request->requester->DeviceOpened(label, requested_devices.front());
903 }
904
905 void MediaStreamManager::FinalizeEnumerateDevices(const std::string& label,
906 DeviceRequest* request) {
907 for (StreamDeviceInfoArray::iterator it = request->devices.begin();
908 it != request->devices.end(); ++it) {
909 it->device.id = content::GetHMACForMediaDeviceID(
910 request->request.security_origin, it->device.id);
911 }
912 request->requester->DevicesEnumerated(label, request->devices);
913 }
914
915 void MediaStreamManager::FinalizeMediaAccessRequest(
916 const std::string& label,
917 DeviceRequest* request,
918 const MediaStreamDevices& devices) {
919 if (!request->callback.is_null())
920 request->callback.Run(devices, request->ui_proxy.Pass());
921
922 // Delete the request since it is done.
923 DeleteRequest(label);
924 }
925
739 void MediaStreamManager::InitializeDeviceManagersOnIOThread() { 926 void MediaStreamManager::InitializeDeviceManagersOnIOThread() {
740 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 927 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
741 if (device_thread_) 928 if (device_thread_)
742 return; 929 return;
743 930
744 device_thread_.reset(new base::Thread("MediaStreamDeviceThread")); 931 device_thread_.reset(new base::Thread("MediaStreamDeviceThread"));
745 #if defined(OS_WIN) 932 #if defined(OS_WIN)
746 device_thread_->init_com_with_mta(true); 933 device_thread_->init_com_with_mta(true);
747 #endif 934 #endif
748 CHECK(device_thread_->Start()); 935 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); 970 request->SetState(device_it->device.type, MEDIA_REQUEST_STATE_DONE);
784 971
785 if (IsAudioMediaType(device_it->device.type)) { 972 if (IsAudioMediaType(device_it->device.type)) {
786 // Store the native audio parameters in the device struct. 973 // Store the native audio parameters in the device struct.
787 // TODO(xians): Handle the tab capture sample rate/channel layout 974 // TODO(xians): Handle the tab capture sample rate/channel layout
788 // in AudioInputDeviceManager::Open(). 975 // in AudioInputDeviceManager::Open().
789 if (device_it->device.type != content::MEDIA_TAB_AUDIO_CAPTURE) { 976 if (device_it->device.type != content::MEDIA_TAB_AUDIO_CAPTURE) {
790 const StreamDeviceInfo* info = 977 const StreamDeviceInfo* info =
791 audio_input_device_manager_->GetOpenedDeviceInfoById( 978 audio_input_device_manager_->GetOpenedDeviceInfoById(
792 device_it->session_id); 979 device_it->session_id);
793 DCHECK_EQ(info->device.id, device_it->device.id);
794 device_it->device.input = info->device.input; 980 device_it->device.input = info->device.input;
795 device_it->device.matched_output = info->device.matched_output; 981 device_it->device.matched_output = info->device.matched_output;
796 } 982 }
797 } 983 }
798 if (RequestDone(*request)) 984 if (RequestDone(*request))
799 HandleRequestDone(label, request); 985 HandleRequestDone(label, request);
800 break; 986 break;
801 } 987 }
802 } 988 }
803 } 989 }
804 } 990 }
805 991
806 void MediaStreamManager::HandleRequestDone(const std::string& label, 992 void MediaStreamManager::HandleRequestDone(const std::string& label,
807 DeviceRequest* request) { 993 DeviceRequest* request) {
808 DCHECK(RequestDone(*request)); 994 DCHECK(RequestDone(*request));
809 DVLOG(1) << "HandleRequestDone(" 995 DVLOG(1) << "HandleRequestDone("
810 << ", {label = " << label << "})"; 996 << ", {label = " << label << "})";
811 997
812 const StreamDeviceInfoArray& requested_devices = request->devices;
813 switch (request->request.request_type) { 998 switch (request->request.request_type) {
814 case MEDIA_OPEN_DEVICE: 999 case MEDIA_OPEN_DEVICE:
815 request->requester->DeviceOpened(label, requested_devices.front()); 1000 FinalizeOpenDevice(label, request);
816 break; 1001 break;
817 case MEDIA_GENERATE_STREAM: { 1002 case MEDIA_GENERATE_STREAM: {
818 // Partition the array of devices into audio vs video. 1003 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; 1004 break;
834 } 1005 }
835 default: 1006 default:
836 NOTREACHED(); 1007 NOTREACHED();
837 break; 1008 break;
838 } 1009 }
839 1010
840 if (request->ui_proxy.get()) { 1011 if (request->ui_proxy.get()) {
841 request->ui_proxy->OnStarted( 1012 request->ui_proxy->OnStarted(
842 base::Bind(&MediaStreamManager::StopStreamFromUI, 1013 base::Bind(&MediaStreamManager::StopStreamFromUI,
843 base::Unretained(this), label)); 1014 base::Unretained(this), label));
844 } 1015 }
845 } 1016 }
846 1017
847 void MediaStreamManager::Closed(MediaStreamType stream_type, 1018 void MediaStreamManager::Closed(MediaStreamType stream_type,
848 int capture_session_id) { 1019 int capture_session_id) {
849 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1020 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
850 } 1021 }
851 1022
852 void MediaStreamManager::DevicesEnumerated( 1023 void MediaStreamManager::DevicesEnumerated(
853 MediaStreamType stream_type, const StreamDeviceInfoArray& devices) { 1024 MediaStreamType stream_type, const StreamDeviceInfoArray& devices) {
854 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1025 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1026 DVLOG(1) << "DevicesEnumerated";
855 1027
856 // Only cache the device list when the device list has been changed. 1028 // Only cache the device list when the device list has been changed.
857 bool need_update_clients = false; 1029 bool need_update_clients = false;
858 EnumerationCache* cache = 1030 EnumerationCache* cache =
859 stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ? 1031 stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ?
860 &audio_enumeration_cache_ : &video_enumeration_cache_; 1032 &audio_enumeration_cache_ : &video_enumeration_cache_;
861 if (!cache->valid || 1033 if (!cache->valid ||
862 devices.size() != cache->devices.size() || 1034 devices.size() != cache->devices.size() ||
863 !std::equal(devices.begin(), devices.end(), cache->devices.begin(), 1035 !std::equal(devices.begin(), devices.end(), cache->devices.begin(),
864 StreamDeviceInfo::IsEqual)) { 1036 StreamDeviceInfo::IsEqual)) {
(...skipping 14 matching lines...) Expand all
879 ++it) { 1051 ++it) {
880 if (it->second->state(stream_type) == MEDIA_REQUEST_STATE_REQUESTED && 1052 if (it->second->state(stream_type) == MEDIA_REQUEST_STATE_REQUESTED &&
881 Requested(it->second->request, stream_type)) { 1053 Requested(it->second->request, stream_type)) {
882 if (it->second->request.request_type != MEDIA_ENUMERATE_DEVICES) 1054 if (it->second->request.request_type != MEDIA_ENUMERATE_DEVICES)
883 it->second->SetState(stream_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL); 1055 it->second->SetState(stream_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
884 label_list.push_back(it->first); 1056 label_list.push_back(it->first);
885 } 1057 }
886 } 1058 }
887 for (std::list<std::string>::iterator it = label_list.begin(); 1059 for (std::list<std::string>::iterator it = label_list.begin();
888 it != label_list.end(); ++it) { 1060 it != label_list.end(); ++it) {
889 DeviceRequest* request = requests_[*it]; 1061 DeviceRequest* request = FindRequest(*it);
890 switch (request->request.request_type) { 1062 switch (request->request.request_type) {
891 case MEDIA_ENUMERATE_DEVICES: 1063 case MEDIA_ENUMERATE_DEVICES:
892 if (need_update_clients && request->requester) 1064 if (need_update_clients && request->requester) {
893 request->requester->DevicesEnumerated(*it, devices); 1065 request->devices = devices;
1066 FinalizeEnumerateDevices(*it, request);
1067 }
894 break; 1068 break;
895 default: 1069 default:
896 if (request->state(request->request.audio_type) == 1070 if (request->state(request->request.audio_type) ==
897 MEDIA_REQUEST_STATE_REQUESTED || 1071 MEDIA_REQUEST_STATE_REQUESTED ||
898 request->state(request->request.video_type) == 1072 request->state(request->request.video_type) ==
899 MEDIA_REQUEST_STATE_REQUESTED) { 1073 MEDIA_REQUEST_STATE_REQUESTED) {
900 // We are doing enumeration for other type of media, wait until it is 1074 // 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 1075 // all done before posting the request to UI because UI needs
902 // the device lists to handle the request. 1076 // the device lists to handle the request.
903 break; 1077 break;
904 } 1078 }
905 1079
906 // Post the request to UI for permission approval. 1080 // Continue to handle the request.
907 PostRequestToUI(*it); 1081 HandleRequest(*it);
908 break; 1082 break;
909 } 1083 }
910 } 1084 }
911 label_list.clear(); 1085 label_list.clear();
912 --active_enumeration_ref_count_[stream_type]; 1086 --active_enumeration_ref_count_[stream_type];
913 DCHECK_GE(active_enumeration_ref_count_[stream_type], 0); 1087 DCHECK_GE(active_enumeration_ref_count_[stream_type], 0);
914 } 1088 }
915 1089
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( 1090 void MediaStreamManager::HandleAccessRequestResponse(
980 const std::string& label, 1091 const std::string& label,
981 const MediaStreamDevices& devices) { 1092 const MediaStreamDevices& devices) {
982 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1093 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
983 DVLOG(1) << "HandleAccessRequestResponse(" 1094 DVLOG(1) << "HandleAccessRequestResponse("
984 << ", {label = " << label << "})"; 1095 << ", {label = " << label << "})";
985 1096
986 DeviceRequests::iterator request_it = requests_.find(label); 1097 DeviceRequest* request = FindRequest(label);
987 if (request_it == requests_.end()) { 1098 if (!request) {
1099 // The request has been canceled before the UI returns.
1100 return;
1101 }
1102
1103 if (request->request.request_type == MEDIA_DEVICE_ACCESS) {
1104 FinalizeMediaAccessRequest(label, request, devices);
988 return; 1105 return;
989 } 1106 }
990 1107
991 // Handle the case when the request was denied. 1108 // Handle the case when the request was denied.
992 if (devices.empty()) { 1109 if (devices.empty()) {
993 // Notify the users about the request result. 1110 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; 1111 return;
1015 } 1112 }
1016 1113
1017 // Process all newly-accepted devices for this request. 1114 // Process all newly-accepted devices for this request.
1018 DeviceRequest* request = request_it->second;
1019 bool found_audio = false; 1115 bool found_audio = false;
1020 bool found_video = false; 1116 bool found_video = false;
1021 for (MediaStreamDevices::const_iterator device_it = devices.begin(); 1117 for (MediaStreamDevices::const_iterator device_it = devices.begin();
1022 device_it != devices.end(); ++device_it) { 1118 device_it != devices.end(); ++device_it) {
1023 StreamDeviceInfo device_info; 1119 StreamDeviceInfo device_info;
1024 device_info.device = *device_it; 1120 device_info.device = *device_it;
1025 1121
1026 // TODO(justinlin): Nicer way to do this? 1122 // TODO(justinlin): Nicer way to do this?
1027 // Re-append the device's id since we lost it when posting request to UI. 1123 // 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 || 1124 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) { 1145 if (device_info.device.type == request->request.audio_type) {
1050 found_audio = true; 1146 found_audio = true;
1051 } else if (device_info.device.type == request->request.video_type) { 1147 } else if (device_info.device.type == request->request.video_type) {
1052 found_video = true; 1148 found_video = true;
1053 } 1149 }
1054 1150
1055 // If this is request for a new MediaStream, a device is only opened once 1151 // 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 1152 // 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 1153 // revoked by a single call to StopStreamDevice regardless of how many
1058 // MediaStreams it is being used in. 1154 // MediaStreams it is being used in.
1059
1060 if (request->request.request_type == MEDIA_GENERATE_STREAM) { 1155 if (request->request.request_type == MEDIA_GENERATE_STREAM) {
1061 MediaRequestState state; 1156 MediaRequestState state;
1062 if (FindExistingRequestedDeviceInfo(request->requesting_process_id, 1157 if (FindExistingRequestedDeviceInfo(request->requesting_process_id,
1063 request->requesting_view_id, 1158 request->requesting_view_id,
1159 request->request.security_origin,
1064 request->request.request_type, 1160 request->request.request_type,
1065 device_it->id, 1161 device_info.device.id,
1162 device_info.device.type,
1066 &device_info, 1163 &device_info,
1067 &state)) { 1164 &state)) {
1068 request->devices.push_back(device_info); 1165 request->devices.push_back(device_info);
1069 request->SetState(device_info.device.type, state); 1166 request->SetState(device_info.device.type, state);
1070 DVLOG(1) << "HandleAccessRequestResponse - device already opened " 1167 DVLOG(1) << "HandleAccessRequestResponse - device already opened "
1071 << ", {label = " << label << "}" 1168 << ", {label = " << label << "}"
1072 << ", device_id = " << device_it->id << "}"; 1169 << ", device_id = " << device_it->id << "}";
1073 continue; 1170 continue;
1074 } 1171 }
1075 } 1172 }
1076 device_info.session_id = 1173 device_info.session_id =
1077 GetDeviceManager(device_info.device.type)->Open(device_info); 1174 GetDeviceManager(device_info.device.type)->Open(device_info);
1175 device_info.device.id = content::GetHMACForMediaDeviceID(
1176 request->request.security_origin,
1177 device_info.device.id);
1078 request->devices.push_back(device_info); 1178 request->devices.push_back(device_info);
1179
1079 request->SetState(device_info.device.type, MEDIA_REQUEST_STATE_OPENING); 1180 request->SetState(device_info.device.type, MEDIA_REQUEST_STATE_OPENING);
1080 DVLOG(1) << "HandleAccessRequestResponse - opening device " 1181 DVLOG(1) << "HandleAccessRequestResponse - opening device "
1081 << ", {label = " << label << "}" 1182 << ", {label = " << label << "}"
1082 << ", {device_id = " << device_it->id << "}" 1183 << ", {device_id = " << device_info.device.id << "}"
1083 << ", {session_id = " << device_info.session_id << "}"; 1184 << ", {session_id = " << device_info.session_id << "}";
1084 } 1185 }
1085 1186
1086 // Check whether we've received all stream types requested. 1187 // Check whether we've received all stream types requested.
1087 if (!found_audio && IsAudioMediaType(request->request.audio_type)) { 1188 if (!found_audio && IsAudioMediaType(request->request.audio_type)) {
1088 request->SetState(request->request.audio_type, MEDIA_REQUEST_STATE_ERROR); 1189 request->SetState(request->request.audio_type, MEDIA_REQUEST_STATE_ERROR);
1089 DVLOG(1) << "Set no audio found label " << label; 1190 DVLOG(1) << "Set no audio found label " << label;
1090 } 1191 }
1091 1192
1092 if (!found_video && IsVideoMediaType(request->request.video_type)) 1193 if (!found_video && IsVideoMediaType(request->request.video_type))
1093 request->SetState(request->request.video_type, MEDIA_REQUEST_STATE_ERROR); 1194 request->SetState(request->request.video_type, MEDIA_REQUEST_STATE_ERROR);
1094 1195
1095 if (RequestDone(*request)) 1196 if (RequestDone(*request))
1096 HandleRequestDone(label, request); 1197 HandleRequestDone(label, request);
1097 } 1198 }
1098 1199
1099 void MediaStreamManager::StopStreamFromUI(const std::string& label) { 1200 void MediaStreamManager::StopStreamFromUI(const std::string& label) {
1100 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1201 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1101 1202
1102 DeviceRequests::iterator it = requests_.find(label); 1203 DeviceRequest* request = FindRequest(label);
1103 if (it == requests_.end()) 1204 if (!request)
1104 return; 1205 return;
1105 1206
1106 // Notify renderers that the stream has been stopped. 1207 // Notify renderers that the stream has been stopped.
1107 if (it->second->requester) 1208 if (request->requester) {
1108 it->second->requester->StopGeneratedStream( 1209 request->requester->StopGeneratedStream(request->request.render_view_id,
1109 it->second->request.render_view_id, 1210 label);
1110 label); 1211 }
1111 1212
1112 CancelRequest(label); 1213 CancelRequest(label);
1113 } 1214 }
1114 1215
1115 void MediaStreamManager::UseFakeDevice() { 1216 void MediaStreamManager::UseFakeDevice() {
1116 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1217 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1117 video_capture_manager()->UseFakeDevice(); 1218 video_capture_manager()->UseFakeDevice();
1118 audio_input_device_manager()->UseFakeDevice(); 1219 audio_input_device_manager()->UseFakeDevice();
1119 } 1220 }
1120 1221
1121 void MediaStreamManager::UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy> fake_ui) { 1222 void MediaStreamManager::UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy> fake_ui) {
1122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 1223 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
1123 use_fake_ui_ = true; 1224 use_fake_ui_ = true;
1124 fake_ui_ = fake_ui.Pass(); 1225 fake_ui_ = fake_ui.Pass();
1125 } 1226 }
1126 1227
1127 void MediaStreamManager::WillDestroyCurrentMessageLoop() { 1228 void MediaStreamManager::WillDestroyCurrentMessageLoop() {
1229 DVLOG(3) << "MediaStreamManager::WillDestroyCurrentMessageLoop()";
1128 DCHECK_EQ(base::MessageLoop::current(), io_loop_); 1230 DCHECK_EQ(base::MessageLoop::current(), io_loop_);
1129 DCHECK(requests_.empty()); 1231 DCHECK(requests_.empty());
1130 if (device_thread_) { 1232 if (device_thread_) {
1131 StopMonitoring(); 1233 StopMonitoring();
1132 1234
1133 video_capture_manager_->Unregister(); 1235 video_capture_manager_->Unregister();
1134 audio_input_device_manager_->Unregister(); 1236 audio_input_device_manager_->Unregister();
1135 device_thread_.reset(); 1237 device_thread_.reset();
1136 } 1238 }
1137 1239
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
1219 } 1321 }
1220 1322
1221 // Always do enumeration even though some enumeration is in progress, 1323 // Always do enumeration even though some enumeration is in progress,
1222 // because those enumeration commands could be sent before these devices 1324 // because those enumeration commands could be sent before these devices
1223 // change. 1325 // change.
1224 ++active_enumeration_ref_count_[stream_type]; 1326 ++active_enumeration_ref_count_[stream_type];
1225 GetDeviceManager(stream_type)->EnumerateDevices(stream_type); 1327 GetDeviceManager(stream_type)->EnumerateDevices(stream_type);
1226 } 1328 }
1227 1329
1228 } // namespace content 1330 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698