15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/media_stream_manager.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <list>
88bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
14effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/power_monitor/power_monitor.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/rand_util.h"
16a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#include "base/run_loop.h"
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/strings/stringprintf.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/browser_main_loop.h"
20a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/media/capture/web_contents_capture_util.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/audio_input_device_manager.h"
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "content/browser/renderer_host/media/device_request_message_filter.h"
23a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "content/browser/renderer_host/media/media_capture_devices_impl.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/media_stream_requester.h"
25868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "content/browser/renderer_host/media/media_stream_ui_proxy.h"
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/renderer_host/media/video_capture_manager.h"
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/browser/renderer_host/render_process_host_impl.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/content_browser_client.h"
301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "content/public/browser/media_device_id.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/media_observer.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/media_request_state.h"
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "content/public/browser/render_process_host.h"
341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "content/public/common/content_client.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_switches.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/media_stream_request.h"
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/audio_manager_base.h"
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/audio_parameters.h"
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/channel_layout.h"
405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "media/base/media_switches.h"
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "media/video/capture/video_capture_device_factory.h"
427dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_com_initializer.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
481320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_CHROMEOS)
491320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chromeos/audio/cras_audio_handler.h"
501320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Forward declaration of DeviceMonitorMac and its only useable method.
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class DeviceMonitorMac {
56a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void StartMonitoring(
585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner);
59a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
60a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates a random label used to identify requests.
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string RandomLabel() {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An earlier PeerConnection spec,
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://dev.w3.org/2011/webrtc/editor/webrtc.html, specified the
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MediaStream::label alphabet as containing 36 characters from
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // range: U+0021, U+0023 to U+0027, U+002A to U+002B, U+002D to U+002E,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // U+0030 to U+0039, U+0041 to U+005A, U+005E to U+007E.
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Here we use a safe subset.
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kAlphabet[] = "0123456789"
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string label(36, ' ');
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < label.size(); ++i) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int random_char = base::RandGenerator(sizeof(kAlphabet) - 1);
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    label[i] = kAlphabet[random_char];
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return label;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ParseStreamType(const StreamOptions& options,
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     MediaStreamType* audio_type,
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     MediaStreamType* video_type) {
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  *audio_type = MEDIA_NO_SERVICE;
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  *video_type = MEDIA_NO_SERVICE;
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (options.audio_requested) {
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     std::string audio_stream_source;
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     bool mandatory = false;
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     if (options.GetFirstAudioConstraintByName(kMediaStreamSource,
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               &audio_stream_source,
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               &mandatory)) {
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       DCHECK(mandatory);
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       // This is tab or screen capture.
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       if (audio_stream_source == kMediaStreamSourceTab) {
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         *audio_type = content::MEDIA_TAB_AUDIO_CAPTURE;
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       } else if (audio_stream_source == kMediaStreamSourceSystem) {
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         *audio_type = content::MEDIA_LOOPBACK_AUDIO_CAPTURE;
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       }
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     } else {
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       // This is normal audio device capture.
101a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       *audio_type = MEDIA_DEVICE_AUDIO_CAPTURE;
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     }
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (options.video_requested) {
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     std::string video_stream_source;
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     bool mandatory = false;
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     if (options.GetFirstVideoConstraintByName(kMediaStreamSource,
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               &video_stream_source,
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               &mandatory)) {
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       DCHECK(mandatory);
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       // This is tab or screen capture.
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       if (video_stream_source == kMediaStreamSourceTab) {
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         *video_type = content::MEDIA_TAB_VIDEO_CAPTURE;
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       } else if (video_stream_source == kMediaStreamSourceScreen) {
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         *video_type = content::MEDIA_DESKTOP_VIDEO_CAPTURE;
1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       } else if (video_stream_source == kMediaStreamSourceDesktop) {
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         *video_type = content::MEDIA_DESKTOP_VIDEO_CAPTURE;
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       }
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     } else {
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       // This is normal video device capture.
121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       *video_type = MEDIA_DEVICE_VIDEO_CAPTURE;
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     }
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// Turns off available audio effects (removes the flag) if the options
1276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)// explicitly turn them off.
1286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void FilterAudioEffects(const StreamOptions& options, int* effects) {
1296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(effects);
1306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // TODO(ajm): Should we also handle ECHO_CANCELLER here?
1316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::string value;
1326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (options.GetFirstAudioConstraintByName(
1336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          kMediaStreamAudioDucking, &value, NULL) && value == "false") {
1346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    *effects &= ~media::AudioParameters::DUCKING;
1356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
1366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
1376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Private helper method for SendMessageToNativeLog() that obtains the global
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// MediaStreamManager instance on the UI thread before sending |message| to the
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// webrtcLoggingPrivate API.
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DoAddLogMessage(const std::string& message) {
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Must be on the UI thread to access BrowserMainLoop.
143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // May be null in tests.
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(vrk): Handle this more elegantly by having native log messages become
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // no-ops until MediaStreamManager is aware that a renderer process has
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // started logging. crbug.com/333894
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (content::BrowserMainLoop::GetInstance()) {
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    BrowserThread::PostTask(
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        BrowserThread::IO,
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        FROM_HERE,
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::Bind(&MediaStreamManager::AddLogMessageOnIOThread,
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   base::Unretained(content::BrowserMainLoop::GetInstance()
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        ->media_stream_manager()),
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   message));
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Private helper method to generate a string for the log message that lists the
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// human readable names of |devices|.
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string GetLogMessageString(MediaStreamType stream_type,
1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                const StreamDeviceInfoArray& devices) {
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string output_string =
1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::StringPrintf("Getting devices for stream type %d:\n", stream_type);
1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (devices.empty()) {
1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    output_string += "No devices found.";
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (StreamDeviceInfoArray::const_iterator it = devices.begin();
1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         it != devices.end(); ++it) {
1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      output_string += "  " + it->device.name + "\n";
1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return output_string;
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Needed for MediaStreamManager::GenerateStream below.
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string ReturnEmptySalt() {
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return std::string();
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Clears the MediaStreamDevice.name from all devices in |devices|.
18246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)static void ClearDeviceLabels(content::StreamDeviceInfoArray* devices) {
18346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (content::StreamDeviceInfoArray::iterator device_itr = devices->begin();
18446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       device_itr != devices->end();
18546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       ++device_itr) {
18646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    device_itr->device.name.clear();
18746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
18846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
18946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// MediaStreamManager::DeviceRequest represents a request to either enumerate
1945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// available devices or open one or more devices.
1955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// TODO(perkj): MediaStreamManager still needs refactoring. I propose we create
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// several subclasses of DeviceRequest and move some of the responsibility of
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// the MediaStreamManager to the subclasses to get rid of the way too many if
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// statements in MediaStreamManager.
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MediaStreamManager::DeviceRequest {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeviceRequest(MediaStreamRequester* requester,
2021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                int requesting_process_id,
203116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                int requesting_frame_id,
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                int page_request_id,
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                const GURL& security_origin,
206effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                bool user_gesture,
2075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                MediaStreamRequestType request_type,
2085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                const StreamOptions& options,
2095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                const ResourceContext::SaltCallback& salt_callback)
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : requester(requester),
2111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        requesting_process_id(requesting_process_id),
212116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        requesting_frame_id(requesting_frame_id),
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        page_request_id(page_request_id),
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        security_origin(security_origin),
215effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        user_gesture(user_gesture),
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        request_type(request_type),
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        options(options),
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        salt_callback(salt_callback),
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        state_(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_NOT_REQUESTED),
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        audio_type_(MEDIA_NO_SERVICE),
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        video_type_(MEDIA_NO_SERVICE) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~DeviceRequest() {}
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void SetAudioType(MediaStreamType audio_type) {
22746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DCHECK(IsAudioInputMediaType(audio_type) ||
22846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)           audio_type == MEDIA_DEVICE_AUDIO_OUTPUT ||
22946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)           audio_type == MEDIA_NO_SERVICE);
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    audio_type_ = audio_type;
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MediaStreamType audio_type() const { return audio_type_; }
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void SetVideoType(MediaStreamType video_type) {
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(IsVideoMediaType(video_type) || video_type == MEDIA_NO_SERVICE);
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    video_type_ = video_type;
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MediaStreamType video_type() const { return video_type_; }
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Creates a MediaStreamRequest object that is used by this request when UI
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // is asked for permission and device selection.
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void CreateUIRequest(const std::string& requested_audio_device_id,
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       const std::string& requested_video_device_id) {
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(!ui_request_);
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui_request_.reset(new MediaStreamRequest(requesting_process_id,
248116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                             requesting_frame_id,
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             page_request_id,
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             security_origin,
251effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                             user_gesture,
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             request_type,
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             requested_audio_device_id,
2545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             requested_video_device_id,
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             audio_type_,
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             video_type_));
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Creates a tab capture specific MediaStreamRequest object that is used by
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // this request when UI is asked for permission and device selection.
261116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  void CreateTabCaptureUIRequest(int target_render_process_id,
262116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                 int target_render_frame_id,
263116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                 const std::string& tab_capture_id) {
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(!ui_request_);
2655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui_request_.reset(new MediaStreamRequest(target_render_process_id,
266116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                             target_render_frame_id,
2675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             page_request_id,
2685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             security_origin,
269effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                             user_gesture,
2705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             request_type,
2715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             "",
2725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             "",
2735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             audio_type_,
2745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             video_type_));
2755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui_request_->tab_capture_device_id = tab_capture_id;
2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const MediaStreamRequest* UIRequest() const { return ui_request_.get(); }
2795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the request state and notify observers.
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetState(MediaStreamType stream_type, MediaRequestState new_state) {
2827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (stream_type == NUM_MEDIA_TYPES) {
2837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      for (int i = MEDIA_NO_SERVICE + 1; i < NUM_MEDIA_TYPES; ++i) {
2847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        const MediaStreamType stream_type = static_cast<MediaStreamType>(i);
2857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        state_[stream_type] = new_state;
2867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      }
2877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else {
2887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      state_[stream_type] = new_state;
2897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MediaObserver* media_observer =
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetContentClient()->browser()->GetMediaObserver();
293a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (!media_observer)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // If |ui_request_| doesn't exist, it means that the request has not yet
2975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // been setup fully and there are no valid observers.
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!ui_request_)
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media_observer->OnMediaRequestStateChanged(
302116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        ui_request_->render_process_id, ui_request_->render_frame_id,
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ui_request_->page_request_id, ui_request_->security_origin,
304116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        stream_type, new_state);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MediaRequestState state(MediaStreamType stream_type) const {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return state_[stream_type];
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MediaStreamRequester* const requester;  // Can be NULL.
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
313868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // The render process id that requested this stream to be generated and that
3151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // will receive a handle to the MediaStream. This may be different from
3161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // MediaStreamRequest::render_process_id which in the tab capture case
3171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // specifies the target renderer from which audio and video is captured.
3181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int requesting_process_id;
3191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
320116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // The render frame id that requested this stream to be generated and that
3211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // will receive a handle to the MediaStream. This may be different from
322116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // MediaStreamRequest::render_frame_id which in the tab capture case
3231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // specifies the target renderer from which audio and video is captured.
324116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  const int requesting_frame_id;
3251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
326116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // An ID the render frame provided to identify this request.
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int page_request_id;
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const GURL security_origin;
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
331effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const bool user_gesture;
332effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const MediaStreamRequestType request_type;
3345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const StreamOptions options;
3365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ResourceContext::SaltCallback salt_callback;
338a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StreamDeviceInfoArray devices;
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Callback to the requester which audio/video devices have been selected.
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It can be null if the requester has no interest to know the result.
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Currently it is only used by |DEVICE_ACCESS| type.
344868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  MediaStreamManager::MediaRequestResponseCallback callback;
345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<MediaStreamUIProxy> ui_proxy;
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<MediaRequestState> state_;
3505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<MediaStreamRequest> ui_request_;
3515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MediaStreamType audio_type_;
3525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MediaStreamType video_type_;
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaStreamManager::EnumerationCache::EnumerationCache()
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : valid(false) {
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaStreamManager::EnumerationCache::~EnumerationCache() {
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3627dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochMediaStreamManager::MediaStreamManager()
3637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    : audio_manager_(NULL),
3647dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      monitoring_started_(false),
3651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_CHROMEOS)
3661320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      has_checked_keyboard_mic_(false),
3671320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
3687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      io_loop_(NULL),
3697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      use_fake_ui_(false) {}
3707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaStreamManager::MediaStreamManager(media::AudioManager* audio_manager)
372868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : audio_manager_(audio_manager),
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      monitoring_started_(false),
3741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_CHROMEOS)
3751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      has_checked_keyboard_mic_(false),
3761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      io_loop_(NULL),
378868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      use_fake_ui_(false) {
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(audio_manager_);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(active_enumeration_ref_count_, 0,
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         sizeof(active_enumeration_ref_count_));
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Some unit tests create the MSM in the IO thread and assumes the
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // initialization is done synchronously.
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InitializeDeviceManagersOnIOThread();
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserThread::PostTask(
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        BrowserThread::IO, FROM_HERE,
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&MediaStreamManager::InitializeDeviceManagersOnIOThread,
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   base::Unretained(this)));
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
393effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
394effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
395effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // BrowserMainLoop always creates the PowerMonitor instance before creating
396effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // MediaStreamManager, but power_monitor may be NULL in unit tests.
397effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (power_monitor)
398effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    power_monitor->AddObserver(this);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaStreamManager::~MediaStreamManager() {
402a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DVLOG(1) << "~MediaStreamManager";
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(requests_.empty());
4041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(!device_task_runner_.get());
405effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
406effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
407effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // The PowerMonitor instance owned by BrowserMainLoops always outlives the
408effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // MediaStreamManager, but it may be NULL in unit tests.
409effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (power_monitor)
410effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    power_monitor->RemoveObserver(this);
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoCaptureManager* MediaStreamManager::video_capture_manager() {
414effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
415868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(video_capture_manager_.get());
416868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return video_capture_manager_.get();
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputDeviceManager* MediaStreamManager::audio_input_device_manager() {
420effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
421868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(audio_input_device_manager_.get());
422868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return audio_input_device_manager_.get();
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string MediaStreamManager::MakeMediaAccessRequest(
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int render_process_id,
427116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int render_frame_id,
4287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int page_request_id,
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const StreamOptions& options,
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& security_origin,
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const MediaRequestResponseCallback& callback) {
432effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
434a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // TODO(perkj): The argument list with NULL parameters to DeviceRequest
435a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // suggests that this is the wrong design. Can this be refactored?
4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DeviceRequest* request = new DeviceRequest(NULL,
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             render_process_id,
438116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                             render_frame_id,
4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             page_request_id,
4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             security_origin,
441effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                             false,  // user gesture
4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             MEDIA_DEVICE_ACCESS,
4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             options,
4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             base::Bind(&ReturnEmptySalt));
4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string& label = AddRequest(request);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request->callback = callback;
449a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Post a task and handle the request asynchronously. The reason is that the
450a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // requester won't have a label for the request until this function returns
451a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // and thus can not handle a response. Using base::Unretained is safe since
452a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // MediaStreamManager is deleted on the UI thread, after the IO thread has
453a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // been stopped.
454a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  BrowserThread::PostTask(
455a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      BrowserThread::IO, FROM_HERE,
456a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::Bind(&MediaStreamManager::SetupRequest,
457a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 base::Unretained(this), label));
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return label;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MediaStreamManager::GenerateStream(MediaStreamRequester* requester,
4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        int render_process_id,
463116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                        int render_frame_id,
4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        const ResourceContext::SaltCallback& sc,
4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        int page_request_id,
4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        const StreamOptions& options,
467effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                        const GURL& security_origin,
468effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                        bool user_gesture) {
469effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
470a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DVLOG(1) << "GenerateStream()";
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CommandLine::ForCurrentProcess()->HasSwitch(
4725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          switches::kUseFakeUIForMediaStream)) {
473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy>());
474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DeviceRequest* request = new DeviceRequest(requester,
4771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                             render_process_id,
478116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                             render_frame_id,
4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             page_request_id,
4805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             security_origin,
481effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                             user_gesture,
4825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             MEDIA_GENERATE_STREAM,
4835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             options,
4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             sc);
4855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string& label = AddRequest(request);
487a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
488a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Post a task and handle the request asynchronously. The reason is that the
489a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // requester won't have a label for the request until this function returns
490a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // and thus can not handle a response. Using base::Unretained is safe since
491a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // MediaStreamManager is deleted on the UI thread, after the IO thread has
492a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // been stopped.
493a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  BrowserThread::PostTask(
494a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      BrowserThread::IO, FROM_HERE,
495a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::Bind(&MediaStreamManager::SetupRequest,
496a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 base::Unretained(this), label));
4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MediaStreamManager::CancelRequest(int render_process_id,
500116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                       int render_frame_id,
5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       int page_request_id) {
5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (DeviceRequests::const_iterator request_it = requests_.begin();
5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       request_it != requests_.end(); ++request_it) {
5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const DeviceRequest* request = request_it->second;
5055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (request->requesting_process_id == render_process_id &&
506116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        request->requesting_frame_id == render_frame_id &&
5075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        request->page_request_id == page_request_id) {
5085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CancelRequest(request_it->first);
5095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
5115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NOTREACHED();
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamManager::CancelRequest(const std::string& label) {
516effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
517f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << "CancelRequest({label = " << label <<  "})";
518a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DeviceRequest* request = FindRequest(label);
519a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!request) {
520a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // The request does not exist.
521a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    LOG(ERROR) << "The request with label = " << label  << " does not exist.";
5228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
5238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
5245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (request->request_type == MEDIA_ENUMERATE_DEVICES) {
5265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // It isn't an ideal use of "CancelRequest" to make it a requirement
5275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // for enumeration requests to be deleted via "CancelRequest" _after_
5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // the request has been successfully fulfilled.
5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // See note in FinalizeEnumerateDevices for a recommendation on how
5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // we should refactor this.
531a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DeleteRequest(label);
5328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
5338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
5348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // This is a request for opening one or more devices.
5368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  for (StreamDeviceInfoArray::iterator device_it = request->devices.begin();
537a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       device_it != request->devices.end(); ++device_it) {
538a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    MediaRequestState state = request->state(device_it->device.type);
5398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // If we have not yet requested the device to be opened - just ignore it.
540a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (state != MEDIA_REQUEST_STATE_OPENING &&
541a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        state != MEDIA_REQUEST_STATE_DONE) {
5428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      continue;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Stop the opening/opened devices of the requests.
545f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    CloseDevice(device_it->device.type, device_it->session_id);
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Cancel the request if still pending at UI side.
5498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  request->SetState(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_CLOSING);
550a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DeleteRequest(label);
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void MediaStreamManager::CancelAllRequests(int render_process_id) {
5548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DeviceRequests::iterator request_it = requests_.begin();
5558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  while (request_it != requests_.end()) {
5561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (request_it->second->requesting_process_id != render_process_id) {
5578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ++request_it;
5588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      continue;
5598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
5608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    std::string label = request_it->first;
5628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    ++request_it;
563f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    CancelRequest(label);
5648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
5658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
5668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void MediaStreamManager::StopStreamDevice(int render_process_id,
568116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                          int render_frame_id,
5698bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                          const std::string& device_id) {
570effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
571116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  DVLOG(1) << "StopStreamDevice({render_frame_id = " << render_frame_id <<  "} "
5728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)           << ", {device_id = " << device_id << "})";
573116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Find the first request for this |render_process_id| and |render_frame_id|
574f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // of type MEDIA_GENERATE_STREAM that has requested to use |device_id| and
575f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // stop it.
576f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (DeviceRequests::iterator request_it = requests_.begin();
577116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch       request_it != requests_.end(); ++request_it) {
5781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DeviceRequest* request = request_it->second;
5791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (request->requesting_process_id != render_process_id ||
580116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        request->requesting_frame_id != render_frame_id ||
5815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        request->request_type != MEDIA_GENERATE_STREAM) {
5828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      continue;
5838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
585f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    StreamDeviceInfoArray& devices = request->devices;
586f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (StreamDeviceInfoArray::iterator device_it = devices.begin();
587f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         device_it != devices.end(); ++device_it) {
588f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (device_it->device.id == device_id) {
589f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        StopDevice(device_it->device.type, device_it->session_id);
590f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return;
591f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
592f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
593f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
594f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
595f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
596f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MediaStreamManager::StopDevice(MediaStreamType type, int session_id) {
597f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << "StopDevice"
598f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << "{type = " << type << "}"
599f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << "{session_id = " << session_id << "}";
600f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DeviceRequests::iterator request_it = requests_.begin();
601f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  while (request_it != requests_.end()) {
602f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DeviceRequest* request = request_it->second;
6038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    StreamDeviceInfoArray* devices = &request->devices;
6045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (devices->empty()) {
6055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // There is no device in use yet by this request.
6065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ++request_it;
6075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      continue;
6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
6098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    StreamDeviceInfoArray::iterator device_it = devices->begin();
6108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    while (device_it != devices->end()) {
611f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (device_it->device.type != type ||
612f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          device_it->session_id != session_id) {
6138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        ++device_it;
614f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        continue;
6158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      }
6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
617f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (request->state(type) == MEDIA_REQUEST_STATE_DONE)
618f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        CloseDevice(type, session_id);
619f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      device_it = devices->erase(device_it);
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // If this request doesn't have any active devices after a device
6235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // has been stopped above, remove the request. Note that the request is
6245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // only deleted if a device as been removed from |devices|.
6258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (devices->empty()) {
626a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      std::string label = request_it->first;
6278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ++request_it;
628a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      DeleteRequest(label);
6298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    } else {
6308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ++request_it;
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
6338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
6348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
635f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MediaStreamManager::CloseDevice(MediaStreamType type, int session_id) {
636f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << "CloseDevice("
637f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << "{type = " << type <<  "} "
638f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << "{session_id = " << session_id << "})";
639f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  GetDeviceManager(type)->Close(session_id);
6408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  for (DeviceRequests::iterator request_it = requests_.begin();
6428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)       request_it != requests_.end() ; ++request_it) {
6438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    StreamDeviceInfoArray* devices = &request_it->second->devices;
6448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    for (StreamDeviceInfoArray::iterator device_it = devices->begin();
6458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)         device_it != devices->end(); ++device_it) {
646f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (device_it->session_id == session_id &&
647f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          device_it->device.type == type) {
6488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // Notify observers that this device is being closed.
6498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // Note that only one device per type can be opened.
650f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        request_it->second->SetState(type, MEDIA_REQUEST_STATE_CLOSING);
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string MediaStreamManager::EnumerateDevices(
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MediaStreamRequester* requester,
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int render_process_id,
659116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    int render_frame_id,
6605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ResourceContext::SaltCallback& sc,
6617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int page_request_id,
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MediaStreamType type,
6631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const GURL& security_origin) {
664effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
665a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(requester);
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
66746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)         type == MEDIA_DEVICE_VIDEO_CAPTURE ||
66846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)         type == MEDIA_DEVICE_AUDIO_OUTPUT);
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DeviceRequest* request = new DeviceRequest(requester,
6715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             render_process_id,
672116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                             render_frame_id,
6735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             page_request_id,
6745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             security_origin,
675effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                             false,  // user gesture
6765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             MEDIA_ENUMERATE_DEVICES,
6775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             StreamOptions(),
6785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             sc);
67946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (IsAudioInputMediaType(type) || type == MEDIA_DEVICE_AUDIO_OUTPUT)
6805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    request->SetAudioType(type);
6815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else if (IsVideoMediaType(type))
6825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    request->SetVideoType(type);
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string& label = AddRequest(request);
685a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Post a task and handle the request asynchronously. The reason is that the
686a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // requester won't have a label for the request until this function returns
687a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // and thus can not handle a response. Using base::Unretained is safe since
688a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // MediaStreamManager is deleted on the UI thread, after the IO thread has
689a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // been stopped.
690a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  BrowserThread::PostTask(
691a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      BrowserThread::IO, FROM_HERE,
692a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::Bind(&MediaStreamManager::DoEnumerateDevices,
693a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 base::Unretained(this), label));
694a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return label;
695a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
696a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
697a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::DoEnumerateDevices(const std::string& label) {
698effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
699a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DeviceRequest* request = FindRequest(label);
700a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!request)
701a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;  // This can happen if the request has been canceled.
702a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
70346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT) {
70446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DCHECK_EQ(MEDIA_NO_SERVICE, request->video_type());
70546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DCHECK_GE(active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_OUTPUT], 0);
70646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    request->SetState(MEDIA_DEVICE_AUDIO_OUTPUT, MEDIA_REQUEST_STATE_REQUESTED);
70746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_OUTPUT] == 0) {
70846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      ++active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_OUTPUT];
70946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      device_task_runner_->PostTask(
71046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          FROM_HERE,
71146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          base::Bind(&MediaStreamManager::EnumerateAudioOutputDevices,
71246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                     base::Unretained(this),
71346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                     label));
71446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
71546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return;
71646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
71746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
718a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  MediaStreamType type;
719a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EnumerationCache* cache;
7205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE) {
7215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_EQ(MEDIA_NO_SERVICE, request->video_type());
722a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    type = MEDIA_DEVICE_AUDIO_CAPTURE;
723a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    cache = &audio_enumeration_cache_;
724a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  } else {
7255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_EQ(MEDIA_DEVICE_VIDEO_CAPTURE, request->video_type());
72646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DCHECK_EQ(MEDIA_NO_SERVICE, request->audio_type());
727a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    type = MEDIA_DEVICE_VIDEO_CAPTURE;
728a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    cache = &video_enumeration_cache_;
729a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!EnumerationRequired(cache, type)) {
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Cached device list of this type exists. Just send it out.
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    request->SetState(type, MEDIA_REQUEST_STATE_REQUESTED);
734a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    request->devices = cache->devices;
735a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    FinalizeEnumerateDevices(label, request);
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StartEnumeration(request);
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
739f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << "Enumerate Devices ({label = " << label <<  "})";
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
742116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid MediaStreamManager::EnumerateAudioOutputDevices(const std::string& label) {
74346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(device_task_runner_->BelongsToCurrentThread());
74446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
74546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<media::AudioDeviceNames> device_names(
74646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      new media::AudioDeviceNames());
74746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  audio_manager_->GetAudioOutputDeviceNames(device_names.get());
74846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  StreamDeviceInfoArray devices;
74946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (media::AudioDeviceNames::iterator it = device_names->begin();
75046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       it != device_names->end(); ++it) {
75146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    StreamDeviceInfo device(MEDIA_DEVICE_AUDIO_OUTPUT,
75246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            it->device_name,
75346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            it->unique_id);
75446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    devices.push_back(device);
75546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
75646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
75746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  BrowserThread::PostTask(
75846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      BrowserThread::IO, FROM_HERE,
75946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::Bind(&MediaStreamManager::AudioOutputDevicesEnumerated,
76046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 base::Unretained(this),
76146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 devices));
76246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
76346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
76446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void MediaStreamManager::AudioOutputDevicesEnumerated(
76546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const StreamDeviceInfoArray& devices) {
76646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK_CURRENTLY_ON(BrowserThread::IO);
76746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DVLOG(1) << "AudioOutputDevicesEnumerated()";
76846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
76946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  std::string log_message = "New device enumeration result:\n" +
77046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            GetLogMessageString(MEDIA_DEVICE_AUDIO_OUTPUT,
77146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                                devices);
77246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  SendMessageToNativeLog(log_message);
77346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
77446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Publish the result for all requests waiting for device list(s).
77546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end();
77646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       ++it) {
77746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (it->second->state(MEDIA_DEVICE_AUDIO_OUTPUT) ==
77846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            MEDIA_REQUEST_STATE_REQUESTED &&
77946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        it->second->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT) {
78046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      DCHECK_EQ(MEDIA_ENUMERATE_DEVICES, it->second->request_type);
78146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      it->second->SetState(MEDIA_DEVICE_AUDIO_OUTPUT,
78246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                           MEDIA_REQUEST_STATE_PENDING_APPROVAL);
78346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      it->second->devices = devices;
78446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      FinalizeEnumerateDevices(it->first, it->second);
78546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
78646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
78746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
78846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  --active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_OUTPUT];
78946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK_GE(active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_OUTPUT], 0);
79046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
79146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
7925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MediaStreamManager::OpenDevice(MediaStreamRequester* requester,
7935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    int render_process_id,
794116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                    int render_frame_id,
7955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    const ResourceContext::SaltCallback& sc,
7965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    int page_request_id,
7975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    const std::string& device_id,
7985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    MediaStreamType type,
7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    const GURL& security_origin) {
800effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         type == MEDIA_DEVICE_VIDEO_CAPTURE);
8035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DVLOG(1) << "OpenDevice ({page_request_id = " << page_request_id <<  "})";
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StreamOptions options;
80546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (IsAudioInputMediaType(type)) {
8065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    options.audio_requested = true;
8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    options.mandatory_audio.push_back(
8085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        StreamOptions::Constraint(kMediaStreamSourceInfoId, device_id));
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (IsVideoMediaType(type)) {
8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    options.video_requested = true;
8115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    options.mandatory_video.push_back(
8125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        StreamOptions::Constraint(kMediaStreamSourceInfoId, device_id));
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DeviceRequest* request = new DeviceRequest(requester,
8175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             render_process_id,
818116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                             render_frame_id,
8195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             page_request_id,
8205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             security_origin,
821effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                             false,  // user gesture
8225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             MEDIA_OPEN_DEVICE,
8235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             options,
8245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             sc);
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string& label = AddRequest(request);
827a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Post a task and handle the request asynchronously. The reason is that the
828a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // requester won't have a label for the request until this function returns
829a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // and thus can not handle a response. Using base::Unretained is safe since
830a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // MediaStreamManager is deleted on the UI thread, after the IO thread has
831a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // been stopped.
832a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  BrowserThread::PostTask(
833a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      BrowserThread::IO, FROM_HERE,
834a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::Bind(&MediaStreamManager::SetupRequest,
835a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 base::Unretained(this), label));
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool MediaStreamManager::TranslateSourceIdToDeviceId(
8395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    MediaStreamType stream_type,
8405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const ResourceContext::SaltCallback& sc,
8415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const GURL& security_origin,
8425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const std::string& source_id,
8435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    std::string* device_id) const {
8445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ||
8455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         stream_type == MEDIA_DEVICE_VIDEO_CAPTURE);
8465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // The source_id can be empty if the constraint is set but empty.
8475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (source_id.empty())
8485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return false;
8495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
8505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const EnumerationCache* cache =
8515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ?
8525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      &audio_enumeration_cache_ : &video_enumeration_cache_;
8535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
8545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // If device monitoring hasn't started, the |device_guid| is not valid.
8555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!cache->valid)
8565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return false;
8575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
8585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (StreamDeviceInfoArray::const_iterator it = cache->devices.begin();
8595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu       it != cache->devices.end();
8605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu       ++it) {
8615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (content::DoesMediaDeviceIDMatchHMAC(sc, security_origin, source_id,
8625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                            it->device.id)) {
8635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      *device_id = it->device.id;
8645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return true;
8655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
8665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
8675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return false;
8685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
8695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
870a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::EnsureDeviceMonitorStarted() {
871effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
8725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StartMonitoring();
873f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
874f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
875f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MediaStreamManager::StopRemovedDevices(
876f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const StreamDeviceInfoArray& old_devices,
877f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const StreamDeviceInfoArray& new_devices) {
878f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << "StopRemovedDevices("
879f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << "{#old_devices = " << old_devices.size() <<  "} "
880f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << "{#new_devices = " << new_devices.size() << "})";
881f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (StreamDeviceInfoArray::const_iterator old_dev_it = old_devices.begin();
882f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       old_dev_it != old_devices.end(); ++old_dev_it) {
883f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool device_found = false;
8845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    StreamDeviceInfoArray::const_iterator new_dev_it = new_devices.begin();
8855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (; new_dev_it != new_devices.end(); ++new_dev_it) {
886f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (old_dev_it->device.id == new_dev_it->device.id) {
887f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        device_found = true;
888f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        break;
889f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
890f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
891f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
892f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!device_found) {
893f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // A device has been removed. We need to check if it is used by a
894f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // MediaStream and in that case cleanup and notify the render process.
895f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      StopRemovedDevice(old_dev_it->device);
896f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
897f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
898f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
899f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
900f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MediaStreamManager::StopRemovedDevice(const MediaStreamDevice& device) {
901f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::vector<int> session_ids;
902f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (DeviceRequests::const_iterator it = requests_.begin();
903f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       it != requests_.end() ; ++it) {
904f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const DeviceRequest* request = it->second;
905f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (StreamDeviceInfoArray::const_iterator device_it =
906f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)             request->devices.begin();
907f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         device_it != request->devices.end(); ++device_it) {
908a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      std::string source_id = content::GetHMACForMediaDeviceID(
9095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          request->salt_callback,
9105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          request->security_origin,
911a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          device.id);
912a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if (device_it->device.id == source_id &&
913a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          device_it->device.type == device.type) {
914f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        session_ids.push_back(device_it->session_id);
915f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        if (it->second->requester) {
916f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          it->second->requester->DeviceStopped(
917116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch              it->second->requesting_frame_id,
918f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)              it->first,
919f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)              *device_it);
920f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        }
921f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
922f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
923f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
924f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (std::vector<int>::const_iterator it = session_ids.begin();
925f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       it != session_ids.end(); ++it) {
926f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    StopDevice(device.type, *it);
927f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
928e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
929e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  std::ostringstream oss;
930e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  oss << "Media input device removed: type = " <<
931e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    (device.type == MEDIA_DEVICE_AUDIO_CAPTURE ? "audio" : "video") <<
932e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    ", id = " << device.id << ", name = " << device.name;
933e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  AddLogMessageOnIOThread(oss.str());
934f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
935f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamManager::StartMonitoring() {
937effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
9385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (monitoring_started_)
9395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
9405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!base::SystemMonitor::Get())
9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
9432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  monitoring_started_ = true;
9455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::SystemMonitor::Get()->AddDevicesChangedObserver(this);
9462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Enumerate both the audio and video devices to cache the device lists
9485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // and send them to media observer.
9495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ++active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_CAPTURE];
9505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  audio_input_device_manager_->EnumerateDevices(MEDIA_DEVICE_AUDIO_CAPTURE);
9515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ++active_enumeration_ref_count_[MEDIA_DEVICE_VIDEO_CAPTURE];
9525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  video_capture_manager_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
953a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
954a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_MACOSX)
955a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  BrowserThread::PostTask(
956a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      BrowserThread::UI, FROM_HERE,
957a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(&MediaStreamManager::StartMonitoringOnUIThread,
958a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 base::Unretained(this)));
959a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
962a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_MACOSX)
963a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MediaStreamManager::StartMonitoringOnUIThread() {
964effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
965a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  BrowserMainLoop* browser_main_loop = content::BrowserMainLoop::GetInstance();
9665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (browser_main_loop) {
9675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    browser_main_loop->device_monitor_mac()
9685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        ->StartMonitoring(audio_manager_->GetWorkerTaskRunner());
9695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
970a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
971a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
972a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamManager::StopMonitoring() {
974c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_EQ(base::MessageLoop::current(), io_loop_);
9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (monitoring_started_) {
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SystemMonitor::Get()->RemoveDevicesChangedObserver(this);
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    monitoring_started_ = false;
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClearEnumerationCache(&audio_enumeration_cache_);
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClearEnumerationCache(&video_enumeration_cache_);
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool MediaStreamManager::GetRequestedDeviceCaptureId(
9845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const DeviceRequest* request,
9855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MediaStreamType type,
9865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string* device_id) const {
9875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
9885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         type == MEDIA_DEVICE_VIDEO_CAPTURE);
9895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const StreamOptions::Constraints* mandatory =
9905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (type == MEDIA_DEVICE_AUDIO_CAPTURE) ?
9915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          &request->options.mandatory_audio : &request->options.mandatory_video;
9925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const StreamOptions::Constraints* optional =
9935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (type == MEDIA_DEVICE_AUDIO_CAPTURE) ?
9945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          &request->options.optional_audio : &request->options.optional_video;
9955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<std::string> source_ids;
9975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StreamOptions::GetConstraintsByName(*mandatory,
9985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      kMediaStreamSourceInfoId, &source_ids);
9995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (source_ids.size() > 1) {
10005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOG(ERROR) << "Only one mandatory " << kMediaStreamSourceInfoId
10015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        << " is supported.";
10025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
1003a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
10045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If a specific device has been requested we need to find the real device
10055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // id.
10065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (source_ids.size() == 1 &&
10075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !TranslateSourceIdToDeviceId(type,
10085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   request->salt_callback,
10095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   request->security_origin,
10105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   source_ids[0], device_id)) {
10115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOG(WARNING) << "Invalid mandatory " << kMediaStreamSourceInfoId
10125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 << " = " << source_ids[0] << ".";
10135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
10145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
10155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Check for optional audio sourceIDs.
10165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (device_id->empty()) {
10175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    StreamOptions::GetConstraintsByName(*optional,
10185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        kMediaStreamSourceInfoId,
10195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        &source_ids);
10205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Find the first sourceID that translates to device. Note that only one
10215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // device per type can call to GenerateStream is ever opened.
10225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (std::vector<std::string>::const_iterator it = source_ids.begin();
10235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         it != source_ids.end(); ++it) {
10245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (TranslateSourceIdToDeviceId(type,
10255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      request->salt_callback,
10265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      request->security_origin,
10275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      *it,
10285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      device_id)) {
10295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
10305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
1031a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
1032a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
1033a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return true;
1034a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1035a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1036a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::TranslateDeviceIdToSourceId(
1037a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DeviceRequest* request,
1038a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    MediaStreamDevice* device) {
10395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
104046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT ||
10415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE) {
1042a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    device->id = content::GetHMACForMediaDeviceID(
10435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        request->salt_callback,
10445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        request->security_origin,
1045a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        device->id);
1046a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
1047a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1048a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamManager::ClearEnumerationCache(EnumerationCache* cache) {
1050c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_EQ(base::MessageLoop::current(), io_loop_);
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache->valid = false;
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool MediaStreamManager::EnumerationRequired(EnumerationCache* cache,
10555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             MediaStreamType stream_type) {
10565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(base::MessageLoop::current(), io_loop_);
10575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (stream_type == MEDIA_NO_SERVICE)
10585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
10595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ||
10615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         stream_type == MEDIA_DEVICE_VIDEO_CAPTURE);
10625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_ANDROID)
10645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // There's no SystemMonitor on Android that notifies us when devices are
10655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // added or removed, so we need to populate the cache on every request.
10665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Fortunately, there is an already up-to-date cache in the browser side
10675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // audio manager that we can rely on, so the performance impact of
10685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // invalidating the cache like this, is minimal.
10695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (stream_type == MEDIA_DEVICE_AUDIO_CAPTURE) {
10705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Make sure the cache is marked as invalid so that FinalizeEnumerateDevices
10715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // will be called at the end of the enumeration.
10725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ClearEnumerationCache(cache);
10735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
10745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
10755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If the cache isn't valid, we need to start a full enumeration.
10765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return !cache->valid;
10775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
10785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaStreamManager::StartEnumeration(DeviceRequest* request) {
1080effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start monitoring the devices when doing the first enumeration.
10835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StartMonitoring();
10842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start enumeration for devices of all requested device types.
10865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const MediaStreamType streams[] = { request->audio_type(),
10875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      request->video_type() };
10885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(streams); ++i) {
10895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (streams[i] == MEDIA_NO_SERVICE)
10905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      continue;
10915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    request->SetState(streams[i], MEDIA_REQUEST_STATE_REQUESTED);
10925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_GE(active_enumeration_ref_count_[streams[i]], 0);
10935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (active_enumeration_ref_count_[streams[i]] == 0) {
10945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ++active_enumeration_ref_count_[streams[i]];
10955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GetDeviceManager(streams[i])->EnumerateDevices(streams[i]);
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string MediaStreamManager::AddRequest(DeviceRequest* request) {
1101effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a label for this request and verify it is unique.
11042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string unique_label;
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
11062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unique_label = RandomLabel();
11076d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  } while (FindRequest(unique_label) != NULL);
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11096d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  requests_.push_back(std::make_pair(unique_label, request));
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return unique_label;
11122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1114a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)MediaStreamManager::DeviceRequest*
1115a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)MediaStreamManager::FindRequest(const std::string& label) const {
11166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  for (DeviceRequests::const_iterator request_it = requests_.begin();
11176d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)       request_it != requests_.end(); ++request_it) {
11186d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (request_it->first == label)
11196d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      return request_it->second;
11206d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
11216d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return NULL;
1122a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1124a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::DeleteRequest(const std::string& label) {
11255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DVLOG(1) << "DeleteRequest({label= " << label << "})";
11266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  for (DeviceRequests::iterator request_it = requests_.begin();
11276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)       request_it != requests_.end(); ++request_it) {
11286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (request_it->first == label) {
11296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      scoped_ptr<DeviceRequest> request(request_it->second);
11306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      requests_.erase(request_it);
11316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      return;
11326d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    }
11336d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
11346d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  NOTREACHED();
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::PostRequestToUI(const std::string& label,
1138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                         DeviceRequest* request) {
1139effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
11405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(request->UIRequest());
1141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DVLOG(1) << "PostRequestToUI({label= " << label << "})";
1142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
11435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const MediaStreamType audio_type = request->audio_type();
11445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const MediaStreamType video_type = request->video_type();
1145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Post the request to UI and set the state.
114746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (IsAudioInputMediaType(audio_type))
1148a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    request->SetState(audio_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
1149a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (IsVideoMediaType(video_type))
1150a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    request->SetState(video_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
1151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (use_fake_ui_) {
1153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!fake_ui_)
1154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      fake_ui_.reset(new FakeMediaStreamUIProxy());
1155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    MediaStreamDevices devices;
1157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (audio_enumeration_cache_.valid) {
1158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      for (StreamDeviceInfoArray::const_iterator it =
1159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               audio_enumeration_cache_.devices.begin();
1160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           it != audio_enumeration_cache_.devices.end(); ++it) {
1161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        devices.push_back(it->device);
1162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
1163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (video_enumeration_cache_.valid) {
1165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      for (StreamDeviceInfoArray::const_iterator it =
1166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               video_enumeration_cache_.devices.begin();
1167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           it != video_enumeration_cache_.devices.end(); ++it) {
1168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        devices.push_back(it->device);
1169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
1170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    fake_ui_->SetAvailableDevices(devices);
1173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    request->ui_proxy = fake_ui_.Pass();
1175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
1176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    request->ui_proxy = MediaStreamUIProxy::Create();
1177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  request->ui_proxy->RequestAccess(
11805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *request->UIRequest(),
1181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::Bind(&MediaStreamManager::HandleAccessRequestResponse,
1182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 base::Unretained(this), label));
11832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::SetupRequest(const std::string& label) {
1186effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
1187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DeviceRequest* request = FindRequest(label);
1188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!request) {
1189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DVLOG(1) << "SetupRequest label " << label << " doesn't exist!!";
1190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;  // This can happen if the request has been canceled.
1191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
1192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
11935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!request->security_origin.is_valid()) {
1194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    LOG(ERROR) << "Invalid security origin. "
11955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               << request->security_origin;
1196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    FinalizeRequestFailed(label,
1197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                          request,
1198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                          MEDIA_DEVICE_INVALID_SECURITY_ORIGIN);
1199a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
1200a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
12012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MediaStreamType audio_type = MEDIA_NO_SERVICE;
12035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MediaStreamType video_type = MEDIA_NO_SERVICE;
12045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ParseStreamType(request->options, &audio_type, &video_type);
12055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  request->SetAudioType(audio_type);
12065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  request->SetVideoType(video_type);
12072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_web_contents_capture =
12092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      audio_type == MEDIA_TAB_AUDIO_CAPTURE ||
12102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      video_type == MEDIA_TAB_VIDEO_CAPTURE;
1211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (is_web_contents_capture && !SetupTabCaptureRequest(request)) {
1212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    FinalizeRequestFailed(label,
1213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                          request,
1214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                          MEDIA_DEVICE_TAB_CAPTURE_FAILURE);
1215a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
1216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
12172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1218ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  bool is_screen_capture =
1219ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      video_type == MEDIA_DESKTOP_VIDEO_CAPTURE;
1220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (is_screen_capture && !SetupScreenCaptureRequest(request)) {
1221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    FinalizeRequestFailed(label,
1222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                          request,
1223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                          MEDIA_DEVICE_SCREEN_CAPTURE_FAILURE);
1224a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
1225a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
12262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_CHROMEOS)
12281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  EnsureKeyboardMicChecked();
12291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
12301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
12315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!is_web_contents_capture && !is_screen_capture) {
12325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (EnumerationRequired(&audio_enumeration_cache_, audio_type) ||
12335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        EnumerationRequired(&video_enumeration_cache_, video_type)) {
12345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Enumerate the devices if there is no valid device lists to be used.
12355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      StartEnumeration(request);
12365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
12375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
12385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // Cache is valid, so log the cached devices for MediaStream requests.
12395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (request->request_type == MEDIA_GENERATE_STREAM) {
12405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        std::string log_message("Using cached devices for request.\n");
12415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (audio_type != MEDIA_NO_SERVICE) {
12425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          log_message +=
12435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              GetLogMessageString(audio_type, audio_enumeration_cache_.devices);
12445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
12455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (video_type != MEDIA_NO_SERVICE) {
12465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          log_message +=
12475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              GetLogMessageString(video_type, video_enumeration_cache_.devices);
12485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
12495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        SendMessageToNativeLog(log_message);
12505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
12515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
12525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!SetupDeviceCaptureRequest(request)) {
125423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      FinalizeRequestFailed(label, request, MEDIA_DEVICE_NO_HARDWARE);
12555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
12565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
12572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1258a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  PostRequestToUI(label, request);
1259a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
12602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool MediaStreamManager::SetupDeviceCaptureRequest(DeviceRequest* request) {
12625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK((request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
12635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          request->audio_type() == MEDIA_NO_SERVICE) &&
12645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         (request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE ||
12655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          request->video_type() == MEDIA_NO_SERVICE));
12665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string audio_device_id;
1267effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (request->options.audio_requested &&
1268effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      !GetRequestedDeviceCaptureId(request, request->audio_type(),
126923730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                     &audio_device_id)) {
1270effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return false;
12715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
12725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string video_device_id;
1274effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (request->options.video_requested &&
1275effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      !GetRequestedDeviceCaptureId(request, request->video_type(),
1276effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                   &video_device_id)) {
1277effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return false;
12785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
12795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  request->CreateUIRequest(audio_device_id, video_device_id);
12805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DVLOG(3) << "Audio requested " << request->options.audio_requested
12815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           << " device id = " << audio_device_id
12825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           << "Video requested " << request->options.video_requested
12835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           << " device id = " << video_device_id;
12845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
12855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
12865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1287a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool MediaStreamManager::SetupTabCaptureRequest(DeviceRequest* request) {
12885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(request->audio_type() == MEDIA_TAB_AUDIO_CAPTURE ||
12895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         request->video_type() == MEDIA_TAB_VIDEO_CAPTURE);
12905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string capture_device_id;
12925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool mandatory_audio = false;
12935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool mandatory_video = false;
12945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!request->options.GetFirstAudioConstraintByName(kMediaStreamSourceId,
12955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                      &capture_device_id,
12965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                      &mandatory_audio) &&
12975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !request->options.GetFirstVideoConstraintByName(kMediaStreamSourceId,
12985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                      &capture_device_id,
12995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                      &mandatory_video)) {
13005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
13015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
13025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(mandatory_audio || mandatory_video);
1303a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1304a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Customize options for a WebContents based capture.
1305a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  int target_render_process_id = 0;
1306116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  int target_render_frame_id = 0;
1307a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1308a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool has_valid_device_id = WebContentsCaptureUtil::ExtractTabCaptureTarget(
1309116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      capture_device_id, &target_render_process_id, &target_render_frame_id);
1310a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!has_valid_device_id ||
13115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (request->audio_type() != MEDIA_TAB_AUDIO_CAPTURE &&
13125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       request->audio_type() != MEDIA_NO_SERVICE) ||
13135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (request->video_type() != MEDIA_TAB_VIDEO_CAPTURE &&
13145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       request->video_type() != MEDIA_NO_SERVICE)) {
1315a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return false;
1316a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
13175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1318116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  request->CreateTabCaptureUIRequest(target_render_process_id,
1319116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                     target_render_frame_id,
1320116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                     capture_device_id);
13215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1322a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DVLOG(3) << "SetupTabCaptureRequest "
1323116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch           << ", {capture_device_id = " << capture_device_id <<  "}"
1324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)           << ", {target_render_process_id = " << target_render_process_id
1325a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)           << "}"
1326116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch           << ", {target_render_frame_id = " << target_render_frame_id << "}";
1327a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return true;
1328a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1329a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1330a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool MediaStreamManager::SetupScreenCaptureRequest(DeviceRequest* request) {
13315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(request->audio_type() == MEDIA_LOOPBACK_AUDIO_CAPTURE ||
13325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         request->video_type() == MEDIA_DESKTOP_VIDEO_CAPTURE);
1333a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // For screen capture we only support two valid combinations:
1335a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // (1) screen video capture only, or
1336a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // (2) screen video capture with loopback audio capture.
13375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (request->video_type() != MEDIA_DESKTOP_VIDEO_CAPTURE ||
13385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (request->audio_type() != MEDIA_NO_SERVICE &&
13395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       request->audio_type() != MEDIA_LOOPBACK_AUDIO_CAPTURE)) {
1340a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    LOG(ERROR) << "Invalid screen capture request.";
1341a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return false;
1342a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
13435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
13445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string video_device_id;
13455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (request->video_type() == MEDIA_DESKTOP_VIDEO_CAPTURE) {
13465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string video_stream_source;
13475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool mandatory = false;
13485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!request->options.GetFirstVideoConstraintByName(
13495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        kMediaStreamSource,
13505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        &video_stream_source,
13515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        &mandatory)) {
13525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      LOG(ERROR) << kMediaStreamSource << " not found.";
13535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return false;
13545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
13555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(mandatory);
13565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
13575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (video_stream_source == kMediaStreamSourceDesktop) {
13585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (!request->options.GetFirstVideoConstraintByName(
13595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          kMediaStreamSourceId,
13605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          &video_device_id,
13615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          &mandatory)) {
13625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        LOG(ERROR) << kMediaStreamSourceId << " not found.";
13635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return false;
13645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
13655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DCHECK(mandatory);
13665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
13675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
13685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
13695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  request->CreateUIRequest("", video_device_id);
1370a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return true;
1371a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1372a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1373a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)StreamDeviceInfoArray MediaStreamManager::GetDevicesOpenedByRequest(
1374a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const std::string& label) const {
1375a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DeviceRequest* request = FindRequest(label);
1376a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!request)
1377a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return StreamDeviceInfoArray();
1378a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return request->devices;
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13818bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool MediaStreamManager::FindExistingRequestedDeviceInfo(
1382a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const DeviceRequest& new_request,
1383a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const MediaStreamDevice& new_device_info,
1384a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    StreamDeviceInfo* existing_device_info,
1385a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    MediaRequestState* existing_request_state) const {
1386a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(existing_device_info);
1387a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(existing_request_state);
1388a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1389a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::string source_id = content::GetHMACForMediaDeviceID(
13905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new_request.salt_callback,
13915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new_request.security_origin,
1392a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      new_device_info.id);
1393a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
13948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  for (DeviceRequests::const_iterator it = requests_.begin();
13958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)       it != requests_.end() ; ++it) {
13968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const DeviceRequest* request = it->second;
1397a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (request->requesting_process_id == new_request.requesting_process_id &&
1398116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        request->requesting_frame_id == new_request.requesting_frame_id &&
13995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        request->request_type == new_request.request_type) {
14008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      for (StreamDeviceInfoArray::const_iterator device_it =
14018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)               request->devices.begin();
14028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)           device_it != request->devices.end(); ++device_it) {
1403a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        if (device_it->device.id == source_id &&
1404a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            device_it->device.type == new_device_info.type) {
14056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          *existing_device_info = *device_it;
14066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          // Make sure that the audio |effects| reflect what the request
14076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          // is set to and not what the capabilities are.
14086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          FilterAudioEffects(request->options,
14096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)              &existing_device_info->device.input.effects);
14106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          *existing_request_state = request->state(device_it->device.type);
14118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          return true;
14128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
14138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      }
14148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
14158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
14168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return false;
14178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
14188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1419a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::FinalizeGenerateStream(const std::string& label,
1420a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                DeviceRequest* request) {
1421a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DVLOG(1) << "FinalizeGenerateStream label " << label;
1422a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const StreamDeviceInfoArray& requested_devices = request->devices;
1423a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1424a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Partition the array of devices into audio vs video.
1425a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  StreamDeviceInfoArray audio_devices, video_devices;
1426a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (StreamDeviceInfoArray::const_iterator device_it =
1427a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)           requested_devices.begin();
1428a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       device_it != requested_devices.end(); ++device_it) {
142946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (IsAudioInputMediaType(device_it->device.type)) {
1430a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      audio_devices.push_back(*device_it);
1431a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    } else if (IsVideoMediaType(device_it->device.type)) {
1432a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      video_devices.push_back(*device_it);
1433a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    } else {
1434a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      NOTREACHED();
1435a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
1436a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
1437a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
14385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  request->requester->StreamGenerated(
1439116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      request->requesting_frame_id,
14405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request->page_request_id,
14415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      label, audio_devices, video_devices);
1442a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1443a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1444a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::FinalizeRequestFailed(
1445a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const std::string& label,
1446a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DeviceRequest* request,
1447a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    content::MediaStreamRequestResult result) {
1448a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (request->requester)
14495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    request->requester->StreamGenerationFailed(
1450116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch        request->requesting_frame_id,
1451a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        request->page_request_id,
1452a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        result);
1453a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
14545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (request->request_type == MEDIA_DEVICE_ACCESS &&
1455a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      !request->callback.is_null()) {
1456a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    request->callback.Run(MediaStreamDevices(), request->ui_proxy.Pass());
1457a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
1458a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1459a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DeleteRequest(label);
1460a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1461a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1462a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::FinalizeOpenDevice(const std::string& label,
1463a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                            DeviceRequest* request) {
1464a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const StreamDeviceInfoArray& requested_devices = request->devices;
1465116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  request->requester->DeviceOpened(request->requesting_frame_id,
14665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   request->page_request_id,
14675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   label, requested_devices.front());
1468a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1469a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1470a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::FinalizeEnumerateDevices(const std::string& label,
1471a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                  DeviceRequest* request) {
1472effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
14735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(request->request_type, MEDIA_ENUMERATE_DEVICES);
14741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(((request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
14751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci           request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT) &&
14761320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          request->video_type() == MEDIA_NO_SERVICE) ||
14771320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci         (request->audio_type() == MEDIA_NO_SERVICE &&
14781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci          request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE));
14795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (request->security_origin.is_valid()) {
14815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (StreamDeviceInfoArray::iterator it = request->devices.begin();
14825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         it != request->devices.end(); ++it) {
14835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      TranslateDeviceIdToSourceId(request, &it->device);
14845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
14855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
14865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    request->devices.clear();
1487a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
14885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (use_fake_ui_) {
14901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (!fake_ui_)
14911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      fake_ui_.reset(new FakeMediaStreamUIProxy());
14921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    request->ui_proxy = fake_ui_.Pass();
14931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  } else {
14941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    request->ui_proxy = MediaStreamUIProxy::Create();
14951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
14961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
14971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // Output label permissions are based on input permission.
14981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  MediaStreamType type =
14991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
15001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT
15011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ? MEDIA_DEVICE_AUDIO_CAPTURE
15021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      : MEDIA_DEVICE_VIDEO_CAPTURE;
15031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
15041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  request->ui_proxy->CheckAccess(
15051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      request->security_origin,
15061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      type,
15071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      request->requesting_process_id,
15081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      request->requesting_frame_id,
15091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      base::Bind(&MediaStreamManager::HandleCheckMediaAccessResponse,
15101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 base::Unretained(this),
15111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                 label));
15121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
15131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
15141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid MediaStreamManager::HandleCheckMediaAccessResponse(
15151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    const std::string& label,
15161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    bool have_access) {
15171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_CURRENTLY_ON(BrowserThread::IO);
15181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
15191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DeviceRequest* request = FindRequest(label);
15201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!request) {
15211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    // This can happen if the request was cancelled.
15221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    DVLOG(1) << "The request with label " << label << " does not exist.";
15231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    return;
15241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
15251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
15261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!have_access)
152746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    ClearDeviceLabels(&request->devices);
152846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
15295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  request->requester->DevicesEnumerated(
1530116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      request->requesting_frame_id,
15315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request->page_request_id,
15325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      label,
15335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request->devices);
15345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
15355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(tommi):
15365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Ideally enumeration requests should be deleted once they have been served
15375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // (as any request).  However, this implementation mixes requests and
15385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // notifications together so enumeration requests are kept open by some
15395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // implementations (only Pepper?) and enumerations are done again when
15405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // device notifications are fired.
15415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Implementations that just want to request the device list and be done
15425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // (e.g. DeviceRequestMessageFilter), they must (confusingly) call
15435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // CancelRequest() after the request has been fulfilled.  This is not
15445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // obvious, not consistent in this class (see e.g. FinalizeMediaAccessRequest)
15455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // and can lead to subtle bugs (requests not deleted at all deleted too
15465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // early).
15475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //
15485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Basically, it is not clear that using requests as an additional layer on
15495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // top of device notifications is necessary or good.
15505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //
15515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // To add to this, MediaStreamManager currently relies on the external
15525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // implementations of MediaStreamRequester to delete enumeration requests via
15535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // CancelRequest and e.g. DeviceRequestMessageFilter does this.  However the
15545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Pepper implementation does not seem to to this at all (and from what I can
15555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // see, it is the only implementation that uses an enumeration request as a
15565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // notification mechanism).
15575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //
15585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // We should decouple notifications from enumeration requests and once that
15595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // has been done, remove the requirement to call CancelRequest() to delete
15605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // enumeration requests and uncomment the following line:
15615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //
15625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // DeleteRequest(label);
1563a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1564a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1565a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::FinalizeMediaAccessRequest(
1566a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const std::string& label,
1567a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DeviceRequest* request,
1568a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const MediaStreamDevices& devices) {
1569a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!request->callback.is_null())
1570a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    request->callback.Run(devices, request->ui_proxy.Pass());
1571a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1572a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Delete the request since it is done.
1573a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DeleteRequest(label);
1574a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1575a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
15762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaStreamManager::InitializeDeviceManagersOnIOThread() {
1577effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
15781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (device_task_runner_.get())
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  device_task_runner_ = audio_manager_->GetWorkerTaskRunner();
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_input_device_manager_ = new AudioInputDeviceManager(audio_manager_);
15845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  audio_input_device_manager_->Register(this, device_task_runner_);
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We want to be notified of IO message loop destruction to delete the thread
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and the device managers.
1588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  io_loop_ = base::MessageLoop::current();
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_loop_->AddDestructionObserver(this);
15905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
15915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (CommandLine::ForCurrentProcess()->HasSwitch(
1592cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      switches::kUseFakeDeviceForMediaStream)) {
15935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    audio_input_device_manager()->UseFakeDevice();
15945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1595cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
159646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  video_capture_manager_ =
159746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      new VideoCaptureManager(media::VideoCaptureDeviceFactory::CreateFactory(
159846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI)));
15995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  video_capture_manager_->Register(this, device_task_runner_);
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamManager::Opened(MediaStreamType stream_type,
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                int capture_session_id) {
1604effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
16058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DVLOG(1) << "Opened({stream_type = " << stream_type <<  "} "
16068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)           << "{capture_session_id = " << capture_session_id << "})";
16078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Find the request(s) containing this device and mark it as used.
16088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // It can be used in several requests since the same device can be
16098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // requested from the same web page.
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (DeviceRequests::iterator request_it = requests_.begin();
16118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)       request_it != requests_.end(); ++request_it) {
16128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const std::string& label = request_it->first;
16138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    DeviceRequest* request = request_it->second;
16148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    StreamDeviceInfoArray* devices = &(request->devices);
16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (StreamDeviceInfoArray::iterator device_it = devices->begin();
16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         device_it != devices->end(); ++device_it) {
16172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (device_it->device.type == stream_type &&
1618f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          device_it->session_id == capture_session_id) {
1619f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        CHECK(request->state(device_it->device.type) ==
1620f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            MEDIA_REQUEST_STATE_OPENING);
16218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // We've found a matching request.
16228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        request->SetState(device_it->device.type, MEDIA_REQUEST_STATE_DONE);
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
162446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        if (IsAudioInputMediaType(device_it->device.type)) {
16252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // Store the native audio parameters in the device struct.
16262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // TODO(xians): Handle the tab capture sample rate/channel layout
16272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // in AudioInputDeviceManager::Open().
16282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (device_it->device.type != content::MEDIA_TAB_AUDIO_CAPTURE) {
16292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            const StreamDeviceInfo* info =
16302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                audio_input_device_manager_->GetOpenedDeviceInfoById(
16312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    device_it->session_id);
163258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            device_it->device.input = info->device.input;
16336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
16346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            // Since the audio input device manager will set the input
16356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            // parameters to the default settings (including supported effects),
16366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            // we need to adjust those settings here according to what the
16376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            // request asks for.
16386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)            FilterAudioEffects(request->options,
16396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                &device_it->device.input.effects);
16406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
164158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            device_it->device.matched_output = info->device.matched_output;
16422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
16438bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
16448bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (RequestDone(*request))
16458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          HandleRequestDone(label, request);
16468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        break;
16478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      }
16488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
16498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
16508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
16518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
16528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void MediaStreamManager::HandleRequestDone(const std::string& label,
16538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                           DeviceRequest* request) {
16548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(RequestDone(*request));
16558bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DVLOG(1) << "HandleRequestDone("
16568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)           << ", {label = " << label <<  "})";
16578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
16585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  switch (request->request_type) {
16598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case MEDIA_OPEN_DEVICE:
1660a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      FinalizeOpenDevice(label, request);
16618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      break;
16628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case MEDIA_GENERATE_STREAM: {
1663a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      FinalizeGenerateStream(label, request);
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
16718bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (request->ui_proxy.get()) {
16728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    request->ui_proxy->OnStarted(
1673f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        base::Bind(&MediaStreamManager::StopMediaStreamFromBrowser,
1674effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   base::Unretained(this),
1675effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   label),
1676effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        base::Bind(&MediaStreamManager::OnMediaStreamUIWindowId,
1677effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   base::Unretained(this),
1678effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   request->video_type(),
1679effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   request->devices));
16808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamManager::Closed(MediaStreamType stream_type,
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                int capture_session_id) {
1685effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamManager::DevicesEnumerated(
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MediaStreamType stream_type, const StreamDeviceInfoArray& devices) {
1690effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
1691f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << "DevicesEnumerated("
16925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           << "{stream_type = " << stream_type << "})" << std::endl;
16935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
16945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string log_message = "New device enumeration result:\n" +
16955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            GetLogMessageString(stream_type, devices);
16965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SendMessageToNativeLog(log_message);
16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Only cache the device list when the device list has been changed.
16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool need_update_clients = false;
17002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EnumerationCache* cache =
17012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ?
17022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &audio_enumeration_cache_ : &video_enumeration_cache_;
17032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!cache->valid ||
17042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      devices.size() != cache->devices.size() ||
17052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !std::equal(devices.begin(), devices.end(), cache->devices.begin(),
17062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  StreamDeviceInfo::IsEqual)) {
1707f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    StopRemovedDevices(cache->devices, devices);
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cache->devices = devices;
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    need_update_clients = true;
1710f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1711f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // The device might not be able to be enumerated when it is not warmed up,
1712f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // for example, when the machine just wakes up from sleep. We set the cache
1713f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // to be invalid so that the next media request will trigger the
1714f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // enumeration again. See issue/317673.
1715a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    cache->valid = !devices.empty();
17166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (need_update_clients && monitoring_started_)
17192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NotifyDevicesChanged(stream_type, devices);
17202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Publish the result for all requests waiting for device list(s).
17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find the requests waiting for this device list, store their labels and
17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // release the iterator before calling device settings. We might get a call
17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // back from device_settings that will need to iterate through devices.
17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::list<std::string> label_list;
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end();
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
1728868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (it->second->state(stream_type) == MEDIA_REQUEST_STATE_REQUESTED &&
17295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        (it->second->audio_type() == stream_type ||
17305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         it->second->video_type() == stream_type)) {
17315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (it->second->request_type != MEDIA_ENUMERATE_DEVICES)
17322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        it->second->SetState(stream_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      label_list.push_back(it->first);
17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::list<std::string>::iterator it = label_list.begin();
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != label_list.end(); ++it) {
1739a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DeviceRequest* request = FindRequest(*it);
17405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    switch (request->request_type) {
17412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case MEDIA_ENUMERATE_DEVICES:
1742a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        if (need_update_clients && request->requester) {
1743a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          request->devices = devices;
1744a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          FinalizeEnumerateDevices(*it, request);
1745a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        }
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
17485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (request->state(request->audio_type()) ==
17492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                MEDIA_REQUEST_STATE_REQUESTED ||
17505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            request->state(request->video_type()) ==
17512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                MEDIA_REQUEST_STATE_REQUESTED) {
17522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // We are doing enumeration for other type of media, wait until it is
17532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // all done before posting the request to UI because UI needs
17542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // the device lists to handle the request.
17552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
17562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
1757a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        if (!SetupDeviceCaptureRequest(request)) {
1758a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          FinalizeRequestFailed(*it,
1759a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                request,
176023730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                MEDIA_DEVICE_NO_HARDWARE);
1761a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        } else {
17625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          PostRequestToUI(*it, request);
1763a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        }
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  label_list.clear();
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  --active_enumeration_ref_count_[stream_type];
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(active_enumeration_ref_count_[stream_type], 0);
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid MediaStreamManager::Aborted(MediaStreamType stream_type,
17735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                 int capture_session_id) {
17745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK_CURRENTLY_ON(BrowserThread::IO);
17755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DVLOG(1) << "Aborted({stream_type = " << stream_type <<  "} "
17765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu           << "{capture_session_id = " << capture_session_id << "})";
17775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  StopDevice(stream_type, capture_session_id);
17785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
17795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
17805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
17815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MediaStreamManager::SendMessageToNativeLog(const std::string& message) {
17825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BrowserThread::PostTask(
17835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      BrowserThread::UI, FROM_HERE,
17845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(DoAddLogMessage, message));
17855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
17865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1787effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid MediaStreamManager::OnSuspend() {
1788effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  SendMessageToNativeLog("Power state suspended.");
1789effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
1790effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1791effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid MediaStreamManager::OnResume() {
1792effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  SendMessageToNativeLog("Power state resumed.");
1793effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
1794effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
17955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MediaStreamManager::AddLogMessageOnIOThread(const std::string& message) {
17965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Get render process ids on the IO thread.
1797effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
17985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
17995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Grab all unique process ids that request a MediaStream or have a
18005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // MediaStream running.
18015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::set<int> requesting_process_ids;
18025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (DeviceRequests::const_iterator it = requests_.begin();
18035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       it != requests_.end(); ++it) {
18045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DeviceRequest* request = it->second;
18055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (request->request_type == MEDIA_GENERATE_STREAM)
18065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      requesting_process_ids.insert(request->requesting_process_id);
18075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
18085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
18095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // MediaStreamManager is a singleton in BrowserMainLoop, which owns the UI
18105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // thread. MediaStreamManager has the same lifetime as the UI thread, so it is
18115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // safe to use base::Unretained.
18125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BrowserThread::PostTask(
18135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      BrowserThread::UI,
18145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FROM_HERE,
18155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&MediaStreamManager::AddLogMessageOnUIThread,
18165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 base::Unretained(this),
18175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 requesting_process_ids,
18185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 message));
18195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
18205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
18215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MediaStreamManager::AddLogMessageOnUIThread(
18225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::set<int>& requesting_process_ids,
18235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& message) {
18245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(ENABLE_WEBRTC)
18255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Must be on the UI thread to access RenderProcessHost from process ID.
1826effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
18275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
18285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (std::set<int>::const_iterator it = requesting_process_ids.begin();
18295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       it != requesting_process_ids.end(); ++it) {
18305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Log the message to all renderers that are requesting a MediaStream or
18315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // have a MediaStream running.
18325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    content::RenderProcessHostImpl* render_process_host_impl =
18335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        static_cast<content::RenderProcessHostImpl*>(
18345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            content::RenderProcessHost::FromID(*it));
18355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (render_process_host_impl)
18365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      render_process_host_impl->WebRtcLogMessage(message);
18375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
18385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
18395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
18405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1841868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void MediaStreamManager::HandleAccessRequestResponse(
1842868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::string& label,
1843a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const MediaStreamDevices& devices,
1844a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    content::MediaStreamRequestResult result) {
1845effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
18468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DVLOG(1) << "HandleAccessRequestResponse("
18478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)           << ", {label = " << label <<  "})";
1848868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1849a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DeviceRequest* request = FindRequest(label);
1850a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!request) {
1851a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // The request has been canceled before the UI returned.
18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (request->request_type == MEDIA_DEVICE_ACCESS) {
1856a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    FinalizeMediaAccessRequest(label, request, devices);
1857868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1858868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1859868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1860a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Handle the case when the request was denied.
1861a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (result != MEDIA_DEVICE_OK) {
1862a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    FinalizeRequestFailed(label, request, result);
18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1865e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK(!devices.empty());
18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Process all newly-accepted devices for this request.
1868868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found_audio = false;
1869868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found_video = false;
1870868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (MediaStreamDevices::const_iterator device_it = devices.begin();
18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       device_it != devices.end(); ++device_it) {
1872868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    StreamDeviceInfo device_info;
1873868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    device_info.device = *device_it;
18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (device_info.device.type == content::MEDIA_TAB_VIDEO_CAPTURE ||
18762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        device_info.device.type == content::MEDIA_TAB_AUDIO_CAPTURE) {
18775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      device_info.device.id = request->UIRequest()->tab_capture_device_id;
18782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Initialize the sample_rate and channel_layout here since for audio
18802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // mirroring, we don't go through EnumerateDevices where these are usually
18812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // initialized.
18822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (device_info.device.type == content::MEDIA_TAB_AUDIO_CAPTURE) {
18832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        const media::AudioParameters parameters =
18842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            audio_manager_->GetDefaultOutputStreamParameters();
18852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        int sample_rate = parameters.sample_rate();
18862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // If we weren't able to get the native sampling rate or the sample_rate
18872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // is outside the valid range for input devices set reasonable defaults.
18882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (sample_rate <= 0 || sample_rate > 96000)
18892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          sample_rate = 44100;
18902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
189158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        device_info.device.input.sample_rate = sample_rate;
189258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        device_info.device.input.channel_layout = media::CHANNEL_LAYOUT_STEREO;
18932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
18942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
18952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (device_info.device.type == request->audio_type()) {
18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found_audio = true;
18985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else if (device_info.device.type == request->video_type()) {
18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found_video = true;
19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
19028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // If this is request for a new MediaStream, a device is only opened once
1903116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // per render frame. This is so that the permission to use a device can be
19048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // revoked by a single call to StopStreamDevice regardless of how many
19058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // MediaStreams it is being used in.
19065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (request->request_type == MEDIA_GENERATE_STREAM) {
19078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      MediaRequestState state;
1908a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if (FindExistingRequestedDeviceInfo(*request,
1909a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                          device_info.device,
19108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                          &device_info,
19118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                          &state)) {
19128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        request->devices.push_back(device_info);
19138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        request->SetState(device_info.device.type, state);
19148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        DVLOG(1) << "HandleAccessRequestResponse - device already opened "
1915a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 << ", {label = " << label <<  "}"
1916a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 << ", device_id = " << device_it->id << "}";
19178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        continue;
19188bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      }
19198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
19208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    device_info.session_id =
19218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        GetDeviceManager(device_info.device.type)->Open(device_info);
1922a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    TranslateDeviceIdToSourceId(request, &device_info.device);
19238bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    request->devices.push_back(device_info);
1924a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
19258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    request->SetState(device_info.device.type, MEDIA_REQUEST_STATE_OPENING);
19268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    DVLOG(1) << "HandleAccessRequestResponse - opening device "
19278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)             << ", {label = " << label <<  "}"
1928a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             << ", {device_id = " << device_info.device.id << "}"
19298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)             << ", {session_id = " << device_info.session_id << "}";
19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check whether we've received all stream types requested.
193346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!found_audio && IsAudioInputMediaType(request->audio_type())) {
19345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    request->SetState(request->audio_type(), MEDIA_REQUEST_STATE_ERROR);
19358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    DVLOG(1) << "Set no audio found label " << label;
19368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!found_video && IsVideoMediaType(request->video_type()))
19395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    request->SetState(request->video_type(), MEDIA_REQUEST_STATE_ERROR);
19408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
19418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (RequestDone(*request))
19428bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    HandleRequestDone(label, request);
19432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
19442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1945f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MediaStreamManager::StopMediaStreamFromBrowser(const std::string& label) {
1946effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
19472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1948a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DeviceRequest* request = FindRequest(label);
1949a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!request)
19502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
19512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1952f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Notify renderers that the devices in the stream will be stopped.
19530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (request->requester) {
1954f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (StreamDeviceInfoArray::iterator device_it = request->devices.begin();
1955f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         device_it != request->devices.end(); ++device_it) {
1956116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      request->requester->DeviceStopped(request->requesting_frame_id,
1957f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                        label,
1958f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                        *device_it);
1959f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
19600f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
19612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  CancelRequest(label);
19632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
19642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1965868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void MediaStreamManager::UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy> fake_ui) {
1966effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
1967868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  use_fake_ui_ = true;
1968868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  fake_ui_ = fake_ui.Pass();
19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamManager::WillDestroyCurrentMessageLoop() {
1972a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DVLOG(3) << "MediaStreamManager::WillDestroyCurrentMessageLoop()";
1973c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_EQ(base::MessageLoop::current(), io_loop_);
19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(requests_.empty());
19751320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (device_task_runner_.get()) {
19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StopMonitoring();
19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    video_capture_manager_->Unregister();
19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    audio_input_device_manager_->Unregister();
19805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    device_task_runner_ = NULL;
19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_input_device_manager_ = NULL;
19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  video_capture_manager_ = NULL;
19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaStreamManager::NotifyDevicesChanged(
19882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MediaStreamType stream_type,
19892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const StreamDeviceInfoArray& devices) {
1990effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
19912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MediaObserver* media_observer =
19922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetContentClient()->browser()->GetMediaObserver();
19932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Map the devices to MediaStreamDevices.
19952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MediaStreamDevices new_devices;
19962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (StreamDeviceInfoArray::const_iterator it = devices.begin();
19972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != devices.end(); ++it) {
19982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    new_devices.push_back(it->device);
19992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
20002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
200146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (IsAudioInputMediaType(stream_type)) {
2002a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    MediaCaptureDevicesImpl::GetInstance()->OnAudioCaptureDevicesChanged(
2003a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        new_devices);
20040529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (media_observer)
20050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      media_observer->OnAudioCaptureDevicesChanged();
20062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (IsVideoMediaType(stream_type)) {
2007a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    MediaCaptureDevicesImpl::GetInstance()->OnVideoCaptureDevicesChanged(
2008a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        new_devices);
20090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (media_observer)
20100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      media_observer->OnVideoCaptureDevicesChanged();
20112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
20122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NOTREACHED();
20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MediaStreamManager::RequestDone(const DeviceRequest& request) const {
2017effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
201946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const bool requested_audio = IsAudioInputMediaType(request.audio_type());
20205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const bool requested_video = IsVideoMediaType(request.video_type());
20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool audio_done =
20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !requested_audio ||
20245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request.state(request.audio_type()) == MEDIA_REQUEST_STATE_DONE ||
20255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request.state(request.audio_type()) == MEDIA_REQUEST_STATE_ERROR;
20262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!audio_done)
20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool video_done =
20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !requested_video ||
20315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request.state(request.video_type()) == MEDIA_REQUEST_STATE_DONE ||
20325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request.state(request.video_type()) == MEDIA_REQUEST_STATE_ERROR;
20332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!video_done)
20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaStreamProvider* MediaStreamManager::GetDeviceManager(
20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MediaStreamType stream_type) {
20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsVideoMediaType(stream_type)) {
20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return video_capture_manager();
204346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  } else if (IsAudioInputMediaType(stream_type)) {
20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return audio_input_device_manager();
20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamManager::OnDevicesChanged(
20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SystemMonitor::DeviceType device_type) {
2052effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: This method is only called in response to physical audio/video device
20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // changes (from the operating system).
20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MediaStreamType stream_type;
20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (device_type == base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE) {
20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stream_type = MEDIA_DEVICE_AUDIO_CAPTURE;
20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (device_type == base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE) {
20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stream_type = MEDIA_DEVICE_VIDEO_CAPTURE;
20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Uninteresting device change.
20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Always do enumeration even though some enumeration is in progress,
20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // because those enumeration commands could be sent before these devices
20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // change.
20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++active_enumeration_ref_count_[stream_type];
20702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GetDeviceManager(stream_type)->EnumerateDevices(stream_type);
20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2073effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid MediaStreamManager::OnMediaStreamUIWindowId(MediaStreamType video_type,
2074effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                                 StreamDeviceInfoArray devices,
2075effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                                 gfx::NativeViewId window_id) {
2076effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
2077effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!window_id)
2078effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return;
2079effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
2080effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Pass along for desktop capturing. Ignored for other stream types.
2081effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (video_type == MEDIA_DESKTOP_VIDEO_CAPTURE) {
2082effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    for (StreamDeviceInfoArray::iterator it = devices.begin();
2083effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch         it != devices.end();
2084effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch         ++it) {
2085effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (it->device.type == MEDIA_DESKTOP_VIDEO_CAPTURE) {
2086effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        video_capture_manager_->SetDesktopCaptureWindowId(it->session_id,
2087effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                                          window_id);
2088effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        break;
2089effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      }
2090effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    }
2091effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
2092effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
2093effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
20941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_CHROMEOS)
20951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid MediaStreamManager::EnsureKeyboardMicChecked() {
20961320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_CURRENTLY_ON(BrowserThread::IO);
20971320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (!has_checked_keyboard_mic_) {
20981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    has_checked_keyboard_mic_ = true;
20991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    BrowserThread::PostTask(
21001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        BrowserThread::UI, FROM_HERE,
21011320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        base::Bind(&MediaStreamManager::CheckKeyboardMicOnUIThread,
21021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   base::Unretained(this)));
21031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
21041320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
21051320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
21061320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid MediaStreamManager::CheckKeyboardMicOnUIThread() {
21071320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK_CURRENTLY_ON(BrowserThread::UI);
21081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
21091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // We will post this on the device thread before the media media access
21101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // request is posted on the UI thread, so setting the keyboard mic info will
21111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // be done before any stream is created.
21121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (chromeos::CrasAudioHandler::Get()->HasKeyboardMic()) {
21131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    device_task_runner_->PostTask(
21141320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        FROM_HERE,
21151320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        base::Bind(&MediaStreamManager::SetKeyboardMicOnDeviceThread,
21161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                   base::Unretained(this)));
21171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
21181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
21191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
21201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid MediaStreamManager::SetKeyboardMicOnDeviceThread() {
21211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DCHECK(device_task_runner_->BelongsToCurrentThread());
21221320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  audio_manager_->SetHasKeyboardMic();
21231320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
21241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
21251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
2127