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"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/content_switches.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/media_stream_request.h"
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/audio_manager_base.h"
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/audio/audio_parameters.h"
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "media/base/channel_layout.h"
395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "media/base/media_switches.h"
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "media/video/capture/video_capture_device_factory.h"
417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_com_initializer.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content {
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
49a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// Forward declaration of DeviceMonitorMac and its only useable method.
50a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class DeviceMonitorMac {
51a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) public:
525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  void StartMonitoring(
535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const scoped_refptr<base::SingleThreadTaskRunner>& device_task_runner);
54a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)};
55a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Creates a random label used to identify requests.
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string RandomLabel() {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // An earlier PeerConnection spec,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // http://dev.w3.org/2011/webrtc/editor/webrtc.html, specified the
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // MediaStream::label alphabet as containing 36 characters from
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // range: U+0021, U+0023 to U+0027, U+002A to U+002B, U+002D to U+002E,
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // U+0030 to U+0039, U+0041 to U+005A, U+005E to U+007E.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Here we use a safe subset.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char kAlphabet[] = "0123456789"
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string label(36, ' ');
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < label.size(); ++i) {
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int random_char = base::RandGenerator(sizeof(kAlphabet) - 1);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    label[i] = kAlphabet[random_char];
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return label;
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void ParseStreamType(const StreamOptions& options,
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     MediaStreamType* audio_type,
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                     MediaStreamType* video_type) {
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  *audio_type = MEDIA_NO_SERVICE;
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  *video_type = MEDIA_NO_SERVICE;
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (options.audio_requested) {
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     std::string audio_stream_source;
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     bool mandatory = false;
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     if (options.GetFirstAudioConstraintByName(kMediaStreamSource,
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               &audio_stream_source,
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               &mandatory)) {
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       DCHECK(mandatory);
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       // This is tab or screen capture.
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       if (audio_stream_source == kMediaStreamSourceTab) {
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         *audio_type = content::MEDIA_TAB_AUDIO_CAPTURE;
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       } else if (audio_stream_source == kMediaStreamSourceSystem) {
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         *audio_type = content::MEDIA_LOOPBACK_AUDIO_CAPTURE;
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       }
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     } else {
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       // This is normal audio device capture.
96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       *audio_type = MEDIA_DEVICE_AUDIO_CAPTURE;
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     }
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (options.video_requested) {
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     std::string video_stream_source;
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     bool mandatory = false;
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     if (options.GetFirstVideoConstraintByName(kMediaStreamSource,
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               &video_stream_source,
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                               &mandatory)) {
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       DCHECK(mandatory);
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       // This is tab or screen capture.
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       if (video_stream_source == kMediaStreamSourceTab) {
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         *video_type = content::MEDIA_TAB_VIDEO_CAPTURE;
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       } else if (video_stream_source == kMediaStreamSourceScreen) {
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         *video_type = content::MEDIA_DESKTOP_VIDEO_CAPTURE;
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       } else if (video_stream_source == kMediaStreamSourceDesktop) {
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         *video_type = content::MEDIA_DESKTOP_VIDEO_CAPTURE;
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       }
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     } else {
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       // This is normal video device capture.
116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)       *video_type = MEDIA_DEVICE_VIDEO_CAPTURE;
1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)     }
1185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Private helper method for SendMessageToNativeLog() that obtains the global
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// MediaStreamManager instance on the UI thread before sending |message| to the
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// webrtcLoggingPrivate API.
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void DoAddLogMessage(const std::string& message) {
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Must be on the UI thread to access BrowserMainLoop.
126effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // May be null in tests.
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(vrk): Handle this more elegantly by having native log messages become
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // no-ops until MediaStreamManager is aware that a renderer process has
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // started logging. crbug.com/333894
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (content::BrowserMainLoop::GetInstance()) {
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    BrowserThread::PostTask(
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        BrowserThread::IO,
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        FROM_HERE,
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        base::Bind(&MediaStreamManager::AddLogMessageOnIOThread,
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   base::Unretained(content::BrowserMainLoop::GetInstance()
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        ->media_stream_manager()),
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                   message));
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Private helper method to generate a string for the log message that lists the
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// human readable names of |devices|.
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string GetLogMessageString(MediaStreamType stream_type,
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                const StreamDeviceInfoArray& devices) {
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string output_string =
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::StringPrintf("Getting devices for stream type %d:\n", stream_type);
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (devices.empty()) {
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    output_string += "No devices found.";
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (StreamDeviceInfoArray::const_iterator it = devices.begin();
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         it != devices.end(); ++it) {
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      output_string += "  " + it->device.name + "\n";
1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return output_string;
1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Needed for MediaStreamManager::GenerateStream below.
1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)std::string ReturnEmptySalt() {
1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return std::string();
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Clears the MediaStreamDevice.name from all devices in |devices|.
16546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)static void ClearDeviceLabels(content::StreamDeviceInfoArray* devices) {
16646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (content::StreamDeviceInfoArray::iterator device_itr = devices->begin();
16746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       device_itr != devices->end();
16846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       ++device_itr) {
16946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    device_itr->device.name.clear();
17046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
17146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
17246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// MediaStreamManager::DeviceRequest represents a request to either enumerate
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// available devices or open one or more devices.
1785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// TODO(perkj): MediaStreamManager still needs refactoring. I propose we create
1795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// several subclasses of DeviceRequest and move some of the responsibility of
1805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// the MediaStreamManager to the subclasses to get rid of the way too many if
1815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// statements in MediaStreamManager.
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MediaStreamManager::DeviceRequest {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeviceRequest(MediaStreamRequester* requester,
1851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                int requesting_process_id,
186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                int requesting_view_id,
1875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                int page_request_id,
1885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                const GURL& security_origin,
18946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                bool have_permission,
190effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                bool user_gesture,
1915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                MediaStreamRequestType request_type,
1925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                const StreamOptions& options,
1935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                const ResourceContext::SaltCallback& salt_callback)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : requester(requester),
1951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        requesting_process_id(requesting_process_id),
1961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        requesting_view_id(requesting_view_id),
1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        page_request_id(page_request_id),
1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        security_origin(security_origin),
19946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        have_permission(have_permission),
200effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        user_gesture(user_gesture),
2015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        request_type(request_type),
2025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        options(options),
2035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        salt_callback(salt_callback),
2045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        state_(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_NOT_REQUESTED),
2055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        audio_type_(MEDIA_NO_SERVICE),
2065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        video_type_(MEDIA_NO_SERVICE) {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~DeviceRequest() {}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void SetAudioType(MediaStreamType audio_type) {
21246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DCHECK(IsAudioInputMediaType(audio_type) ||
21346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)           audio_type == MEDIA_DEVICE_AUDIO_OUTPUT ||
21446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)           audio_type == MEDIA_NO_SERVICE);
2155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    audio_type_ = audio_type;
2165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MediaStreamType audio_type() const { return audio_type_; }
2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void SetVideoType(MediaStreamType video_type) {
2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(IsVideoMediaType(video_type) || video_type == MEDIA_NO_SERVICE);
2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    video_type_ = video_type;
2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MediaStreamType video_type() const { return video_type_; }
2265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Creates a MediaStreamRequest object that is used by this request when UI
2285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // is asked for permission and device selection.
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void CreateUIRequest(const std::string& requested_audio_device_id,
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                       const std::string& requested_video_device_id) {
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(!ui_request_);
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui_request_.reset(new MediaStreamRequest(requesting_process_id,
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             requesting_view_id,
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             page_request_id,
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             security_origin,
236effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                             user_gesture,
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             request_type,
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             requested_audio_device_id,
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             requested_video_device_id,
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             audio_type_,
2415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             video_type_));
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Creates a tab capture specific MediaStreamRequest object that is used by
2455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // this request when UI is asked for permission and device selection.
2465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  void CreateTabCatureUIRequest(int target_render_process_id,
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                int target_render_view_id,
2485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                const std::string& tab_capture_id) {
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(!ui_request_);
2505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui_request_.reset(new MediaStreamRequest(target_render_process_id,
2515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             target_render_view_id,
2525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             page_request_id,
2535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             security_origin,
254effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                             user_gesture,
2555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             request_type,
2565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             "",
2575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             "",
2585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             audio_type_,
2595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             video_type_));
2605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ui_request_->tab_capture_device_id = tab_capture_id;
2615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
2625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const MediaStreamRequest* UIRequest() const { return ui_request_.get(); }
2645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Update the request state and notify observers.
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetState(MediaStreamType stream_type, MediaRequestState new_state) {
2677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    if (stream_type == NUM_MEDIA_TYPES) {
2687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      for (int i = MEDIA_NO_SERVICE + 1; i < NUM_MEDIA_TYPES; ++i) {
2697dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        const MediaStreamType stream_type = static_cast<MediaStreamType>(i);
2707dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        state_[stream_type] = new_state;
2717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      }
2727dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else {
2737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      state_[stream_type] = new_state;
2747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MediaObserver* media_observer =
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetContentClient()->browser()->GetMediaObserver();
278a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (!media_observer)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // If |ui_request_| doesn't exist, it means that the request has not yet
2825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // been setup fully and there are no valid observers.
2835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!ui_request_)
2845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
2855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If we appended a device_id scheme, we want to remove it when notifying
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // observers which may be in different modules since this scheme is only
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // used internally within the content module.
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string device_id =
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        WebContentsCaptureUtil::StripWebContentsDeviceScheme(
2915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            ui_request_->tab_capture_device_id);
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    media_observer->OnMediaRequestStateChanged(
2945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ui_request_->render_process_id, ui_request_->render_view_id,
2955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        ui_request_->page_request_id, ui_request_->security_origin,
296868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        MediaStreamDevice(stream_type, device_id, device_id), new_state);
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MediaRequestState state(MediaStreamType stream_type) const {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return state_[stream_type];
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MediaStreamRequester* const requester;  // Can be NULL.
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
305868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // The render process id that requested this stream to be generated and that
3071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // will receive a handle to the MediaStream. This may be different from
3081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // MediaStreamRequest::render_process_id which in the tab capture case
3091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // specifies the target renderer from which audio and video is captured.
3101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int requesting_process_id;
3111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // The render view id that requested this stream to be generated and that
3131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // will receive a handle to the MediaStream. This may be different from
3141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // MediaStreamRequest::render_view_id which in the tab capture case
3151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  // specifies the target renderer from which audio and video is captured.
3161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)  const int requesting_view_id;
3171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)
3185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // An ID the render view provided to identify this request.
3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const int page_request_id;
3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const GURL security_origin;
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
32346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // This is used when enumerating devices; if we don't have device access
32446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // permission, we remove the device label.
32546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  bool have_permission;
32646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
327effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  const bool user_gesture;
328effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const MediaStreamRequestType request_type;
3305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const StreamOptions options;
3325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ResourceContext::SaltCallback salt_callback;
334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StreamDeviceInfoArray devices;
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Callback to the requester which audio/video devices have been selected.
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // It can be null if the requester has no interest to know the result.
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Currently it is only used by |DEVICE_ACCESS| type.
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  MediaStreamManager::MediaRequestResponseCallback callback;
341868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
342868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<MediaStreamUIProxy> ui_proxy;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<MediaRequestState> state_;
3465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  scoped_ptr<MediaStreamRequest> ui_request_;
3475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MediaStreamType audio_type_;
3485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MediaStreamType video_type_;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaStreamManager::EnumerationCache::EnumerationCache()
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : valid(false) {
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaStreamManager::EnumerationCache::~EnumerationCache() {
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3587dbb3d5cf0c15f500944d211057644d6a2f37371Ben MurdochMediaStreamManager::MediaStreamManager()
3597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    : audio_manager_(NULL),
3607dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      monitoring_started_(false),
3617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      io_loop_(NULL),
3627dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      use_fake_ui_(false) {}
3637dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaStreamManager::MediaStreamManager(media::AudioManager* audio_manager)
365868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : audio_manager_(audio_manager),
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      monitoring_started_(false),
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      io_loop_(NULL),
368868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      use_fake_ui_(false) {
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(audio_manager_);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  memset(active_enumeration_ref_count_, 0,
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         sizeof(active_enumeration_ref_count_));
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Some unit tests create the MSM in the IO thread and assumes the
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // initialization is done synchronously.
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (BrowserThread::CurrentlyOn(BrowserThread::IO)) {
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    InitializeDeviceManagersOnIOThread();
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    BrowserThread::PostTask(
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        BrowserThread::IO, FROM_HERE,
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&MediaStreamManager::InitializeDeviceManagersOnIOThread,
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   base::Unretained(this)));
3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
383effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
384effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
385effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // BrowserMainLoop always creates the PowerMonitor instance before creating
386effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // MediaStreamManager, but power_monitor may be NULL in unit tests.
387effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (power_monitor)
388effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    power_monitor->AddObserver(this);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaStreamManager::~MediaStreamManager() {
392a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DVLOG(1) << "~MediaStreamManager";
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(requests_.empty());
3945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(!device_task_runner_);
395effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
396effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  base::PowerMonitor* power_monitor = base::PowerMonitor::Get();
397effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // The PowerMonitor instance owned by BrowserMainLoops always outlives the
398effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // MediaStreamManager, but it may be NULL in unit tests.
399effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (power_monitor)
400effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    power_monitor->RemoveObserver(this);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)VideoCaptureManager* MediaStreamManager::video_capture_manager() {
404effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
405868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(video_capture_manager_.get());
406868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return video_capture_manager_.get();
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)AudioInputDeviceManager* MediaStreamManager::audio_input_device_manager() {
410effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
411868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(audio_input_device_manager_.get());
412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return audio_input_device_manager_.get();
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string MediaStreamManager::MakeMediaAccessRequest(
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int render_process_id,
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int render_view_id,
4187dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int page_request_id,
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const StreamOptions& options,
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& security_origin,
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const MediaRequestResponseCallback& callback) {
422effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
424a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // TODO(perkj): The argument list with NULL parameters to DeviceRequest
425a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // suggests that this is the wrong design. Can this be refactored?
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DeviceRequest* request = new DeviceRequest(NULL,
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             render_process_id,
4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             render_view_id,
4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             page_request_id,
4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             security_origin,
43146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                             true,
432effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                             false,  // user gesture
4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             MEDIA_DEVICE_ACCESS,
4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             options,
4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             base::Bind(&ReturnEmptySalt));
4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string& label = AddRequest(request);
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  request->callback = callback;
440a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Post a task and handle the request asynchronously. The reason is that the
441a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // requester won't have a label for the request until this function returns
442a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // and thus can not handle a response. Using base::Unretained is safe since
443a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // MediaStreamManager is deleted on the UI thread, after the IO thread has
444a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // been stopped.
445a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  BrowserThread::PostTask(
446a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      BrowserThread::IO, FROM_HERE,
447a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::Bind(&MediaStreamManager::SetupRequest,
448a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 base::Unretained(this), label));
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return label;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MediaStreamManager::GenerateStream(MediaStreamRequester* requester,
4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        int render_process_id,
4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        int render_view_id,
4555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        const ResourceContext::SaltCallback& sc,
4565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        int page_request_id,
4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        const StreamOptions& options,
458effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                        const GURL& security_origin,
459effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                        bool user_gesture) {
460effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
461a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DVLOG(1) << "GenerateStream()";
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (CommandLine::ForCurrentProcess()->HasSwitch(
4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          switches::kUseFakeUIForMediaStream)) {
464eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy>());
465eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  }
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DeviceRequest* request = new DeviceRequest(requester,
4681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)                                             render_process_id,
469a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                             render_view_id,
4705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             page_request_id,
4715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             security_origin,
47246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                             true,
473effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                             user_gesture,
4745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             MEDIA_GENERATE_STREAM,
4755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             options,
4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             sc);
4775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string& label = AddRequest(request);
479a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
480a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Post a task and handle the request asynchronously. The reason is that the
481a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // requester won't have a label for the request until this function returns
482a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // and thus can not handle a response. Using base::Unretained is safe since
483a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // MediaStreamManager is deleted on the UI thread, after the IO thread has
484a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // been stopped.
485a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  BrowserThread::PostTask(
486a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      BrowserThread::IO, FROM_HERE,
487a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::Bind(&MediaStreamManager::SetupRequest,
488a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 base::Unretained(this), label));
4895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MediaStreamManager::CancelRequest(int render_process_id,
4925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       int render_view_id,
4935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                       int page_request_id) {
4945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (DeviceRequests::const_iterator request_it = requests_.begin();
4955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       request_it != requests_.end(); ++request_it) {
4965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const DeviceRequest* request = request_it->second;
4975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (request->requesting_process_id == render_process_id &&
4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        request->requesting_view_id == render_view_id &&
4995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        request->page_request_id == page_request_id) {
5005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      CancelRequest(request_it->first);
5015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
5035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
5045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  NOTREACHED();
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamManager::CancelRequest(const std::string& label) {
508effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
509f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << "CancelRequest({label = " << label <<  "})";
510a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DeviceRequest* request = FindRequest(label);
511a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!request) {
512a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // The request does not exist.
513a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    LOG(ERROR) << "The request with label = " << label  << " does not exist.";
5148bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
5158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
5165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
5175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (request->request_type == MEDIA_ENUMERATE_DEVICES) {
5185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // It isn't an ideal use of "CancelRequest" to make it a requirement
5195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // for enumeration requests to be deleted via "CancelRequest" _after_
5205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // the request has been successfully fulfilled.
5215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // See note in FinalizeEnumerateDevices for a recommendation on how
5225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // we should refactor this.
523a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DeleteRequest(label);
5248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    return;
5258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
5268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // This is a request for opening one or more devices.
5288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  for (StreamDeviceInfoArray::iterator device_it = request->devices.begin();
529a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       device_it != request->devices.end(); ++device_it) {
530a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    MediaRequestState state = request->state(device_it->device.type);
5318bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // If we have not yet requested the device to be opened - just ignore it.
532a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (state != MEDIA_REQUEST_STATE_OPENING &&
533a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        state != MEDIA_REQUEST_STATE_DONE) {
5348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      continue;
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // Stop the opening/opened devices of the requests.
537f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    CloseDevice(device_it->device.type, device_it->session_id);
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5398bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Cancel the request if still pending at UI side.
5418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  request->SetState(NUM_MEDIA_TYPES, MEDIA_REQUEST_STATE_CLOSING);
542a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DeleteRequest(label);
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5458bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void MediaStreamManager::CancelAllRequests(int render_process_id) {
5468bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DeviceRequests::iterator request_it = requests_.begin();
5478bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  while (request_it != requests_.end()) {
5481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (request_it->second->requesting_process_id != render_process_id) {
5498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ++request_it;
5508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      continue;
5518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
5528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5538bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    std::string label = request_it->first;
5548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    ++request_it;
555f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    CancelRequest(label);
5568bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
5578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
5588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
5598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void MediaStreamManager::StopStreamDevice(int render_process_id,
5608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                          int render_view_id,
5618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                          const std::string& device_id) {
562effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
5638bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DVLOG(1) << "StopStreamDevice({render_view_id = " << render_view_id <<  "} "
5648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)           << ", {device_id = " << device_id << "})";
565f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Find the first request for this |render_process_id| and |render_view_id|
566f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // of type MEDIA_GENERATE_STREAM that has requested to use |device_id| and
567f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // stop it.
568f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (DeviceRequests::iterator request_it = requests_.begin();
569f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       request_it  != requests_.end(); ++request_it) {
5701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    DeviceRequest* request = request_it->second;
5711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)    if (request->requesting_process_id != render_process_id ||
5721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)        request->requesting_view_id != render_view_id ||
5735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        request->request_type != MEDIA_GENERATE_STREAM) {
5748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      continue;
5758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
577f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    StreamDeviceInfoArray& devices = request->devices;
578f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (StreamDeviceInfoArray::iterator device_it = devices.begin();
579f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         device_it != devices.end(); ++device_it) {
580f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (device_it->device.id == device_id) {
581f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        StopDevice(device_it->device.type, device_it->session_id);
582f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        return;
583f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
584f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
585f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
586f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
587f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
588f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MediaStreamManager::StopDevice(MediaStreamType type, int session_id) {
589f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << "StopDevice"
590f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << "{type = " << type << "}"
591f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << "{session_id = " << session_id << "}";
592f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DeviceRequests::iterator request_it = requests_.begin();
593f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  while (request_it != requests_.end()) {
594f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    DeviceRequest* request = request_it->second;
5958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    StreamDeviceInfoArray* devices = &request->devices;
5965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (devices->empty()) {
5975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // There is no device in use yet by this request.
5985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ++request_it;
5995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      continue;
6005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
6018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    StreamDeviceInfoArray::iterator device_it = devices->begin();
6028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    while (device_it != devices->end()) {
603f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (device_it->device.type != type ||
604f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          device_it->session_id != session_id) {
6058bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        ++device_it;
606f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        continue;
6078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      }
6085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
609f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (request->state(type) == MEDIA_REQUEST_STATE_DONE)
610f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        CloseDevice(type, session_id);
611f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      device_it = devices->erase(device_it);
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
6145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // If this request doesn't have any active devices after a device
6155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // has been stopped above, remove the request. Note that the request is
6165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // only deleted if a device as been removed from |devices|.
6178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    if (devices->empty()) {
618a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      std::string label = request_it->first;
6198bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ++request_it;
620a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      DeleteRequest(label);
6218bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    } else {
6228bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      ++request_it;
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6248bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
6258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
6268bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
627f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MediaStreamManager::CloseDevice(MediaStreamType type, int session_id) {
628f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << "CloseDevice("
629f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << "{type = " << type <<  "} "
630f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << "{session_id = " << session_id << "})";
631f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  GetDeviceManager(type)->Close(session_id);
6328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
6338bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  for (DeviceRequests::iterator request_it = requests_.begin();
6348bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)       request_it != requests_.end() ; ++request_it) {
6358bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    StreamDeviceInfoArray* devices = &request_it->second->devices;
6368bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    for (StreamDeviceInfoArray::iterator device_it = devices->begin();
6378bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)         device_it != devices->end(); ++device_it) {
638f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (device_it->session_id == session_id &&
639f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          device_it->device.type == type) {
6408bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // Notify observers that this device is being closed.
6418bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // Note that only one device per type can be opened.
642f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        request_it->second->SetState(type, MEDIA_REQUEST_STATE_CLOSING);
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string MediaStreamManager::EnumerateDevices(
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MediaStreamRequester* requester,
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int render_process_id,
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int render_view_id,
6525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const ResourceContext::SaltCallback& sc,
6537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    int page_request_id,
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MediaStreamType type,
65546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const GURL& security_origin,
65646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    bool have_permission) {
657effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
658a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(requester);
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
66046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)         type == MEDIA_DEVICE_VIDEO_CAPTURE ||
66146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)         type == MEDIA_DEVICE_AUDIO_OUTPUT);
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DeviceRequest* request = new DeviceRequest(requester,
6645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             render_process_id,
6655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             render_view_id,
6665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             page_request_id,
6675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             security_origin,
66846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                             have_permission,
669effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                             false,  // user gesture
6705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             MEDIA_ENUMERATE_DEVICES,
6715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             StreamOptions(),
6725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             sc);
67346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (IsAudioInputMediaType(type) || type == MEDIA_DEVICE_AUDIO_OUTPUT)
6745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    request->SetAudioType(type);
6755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  else if (IsVideoMediaType(type))
6765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    request->SetVideoType(type);
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string& label = AddRequest(request);
679a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Post a task and handle the request asynchronously. The reason is that the
680a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // requester won't have a label for the request until this function returns
681a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // and thus can not handle a response. Using base::Unretained is safe since
682a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // MediaStreamManager is deleted on the UI thread, after the IO thread has
683a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // been stopped.
684a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  BrowserThread::PostTask(
685a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      BrowserThread::IO, FROM_HERE,
686a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::Bind(&MediaStreamManager::DoEnumerateDevices,
687a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 base::Unretained(this), label));
688a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return label;
689a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
690a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
691a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::DoEnumerateDevices(const std::string& label) {
692effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
693a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DeviceRequest* request = FindRequest(label);
694a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!request)
695a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;  // This can happen if the request has been canceled.
696a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
69746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT) {
69846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DCHECK_EQ(MEDIA_NO_SERVICE, request->video_type());
69946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DCHECK_GE(active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_OUTPUT], 0);
70046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    request->SetState(MEDIA_DEVICE_AUDIO_OUTPUT, MEDIA_REQUEST_STATE_REQUESTED);
70146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_OUTPUT] == 0) {
70246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      ++active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_OUTPUT];
70346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      device_task_runner_->PostTask(
70446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          FROM_HERE,
70546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          base::Bind(&MediaStreamManager::EnumerateAudioOutputDevices,
70646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                     base::Unretained(this),
70746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                     label));
70846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
70946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    return;
71046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
71146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
712a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  MediaStreamType type;
713a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  EnumerationCache* cache;
7145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE) {
7155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_EQ(MEDIA_NO_SERVICE, request->video_type());
716a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    type = MEDIA_DEVICE_AUDIO_CAPTURE;
717a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    cache = &audio_enumeration_cache_;
718a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  } else {
7195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_EQ(MEDIA_DEVICE_VIDEO_CAPTURE, request->video_type());
72046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    DCHECK_EQ(MEDIA_NO_SERVICE, request->audio_type());
721a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    type = MEDIA_DEVICE_VIDEO_CAPTURE;
722a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    cache = &video_enumeration_cache_;
723a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!EnumerationRequired(cache, type)) {
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Cached device list of this type exists. Just send it out.
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    request->SetState(type, MEDIA_REQUEST_STATE_REQUESTED);
728a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    request->devices = cache->devices;
729a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    FinalizeEnumerateDevices(label, request);
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    StartEnumeration(request);
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
733f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << "Enumerate Devices ({label = " << label <<  "})";
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
73646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void MediaStreamManager::EnumerateAudioOutputDevices(
73746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const std::string& label) {
73846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK(device_task_runner_->BelongsToCurrentThread());
73946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
74046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  scoped_ptr<media::AudioDeviceNames> device_names(
74146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      new media::AudioDeviceNames());
74246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  audio_manager_->GetAudioOutputDeviceNames(device_names.get());
74346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  StreamDeviceInfoArray devices;
74446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (media::AudioDeviceNames::iterator it = device_names->begin();
74546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       it != device_names->end(); ++it) {
74646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    StreamDeviceInfo device(MEDIA_DEVICE_AUDIO_OUTPUT,
74746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            it->device_name,
74846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            it->unique_id);
74946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    devices.push_back(device);
75046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
75146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
75246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  BrowserThread::PostTask(
75346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      BrowserThread::IO, FROM_HERE,
75446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      base::Bind(&MediaStreamManager::AudioOutputDevicesEnumerated,
75546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 base::Unretained(this),
75646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                 devices));
75746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
75846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
75946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)void MediaStreamManager::AudioOutputDevicesEnumerated(
76046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    const StreamDeviceInfoArray& devices) {
76146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK_CURRENTLY_ON(BrowserThread::IO);
76246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DVLOG(1) << "AudioOutputDevicesEnumerated()";
76346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
76446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  std::string log_message = "New device enumeration result:\n" +
76546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                            GetLogMessageString(MEDIA_DEVICE_AUDIO_OUTPUT,
76646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                                devices);
76746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  SendMessageToNativeLog(log_message);
76846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
76946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  // Publish the result for all requests waiting for device list(s).
77046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end();
77146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)       ++it) {
77246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (it->second->state(MEDIA_DEVICE_AUDIO_OUTPUT) ==
77346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)            MEDIA_REQUEST_STATE_REQUESTED &&
77446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        it->second->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT) {
77546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      DCHECK_EQ(MEDIA_ENUMERATE_DEVICES, it->second->request_type);
77646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      it->second->SetState(MEDIA_DEVICE_AUDIO_OUTPUT,
77746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                           MEDIA_REQUEST_STATE_PENDING_APPROVAL);
77846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      it->second->devices = devices;
77946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      FinalizeEnumerateDevices(it->first, it->second);
78046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
78146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
78246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
78346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  --active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_OUTPUT];
78446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  DCHECK_GE(active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_OUTPUT], 0);
78546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
78646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MediaStreamManager::OpenDevice(MediaStreamRequester* requester,
7885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    int render_process_id,
7895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    int render_view_id,
7905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    const ResourceContext::SaltCallback& sc,
7915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    int page_request_id,
7925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    const std::string& device_id,
7935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    MediaStreamType type,
7945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    const GURL& security_origin) {
795effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         type == MEDIA_DEVICE_VIDEO_CAPTURE);
7985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DVLOG(1) << "OpenDevice ({page_request_id = " << page_request_id <<  "})";
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StreamOptions options;
80046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (IsAudioInputMediaType(type)) {
8015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    options.audio_requested = true;
8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    options.mandatory_audio.push_back(
8035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        StreamOptions::Constraint(kMediaStreamSourceInfoId, device_id));
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (IsVideoMediaType(type)) {
8055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    options.video_requested = true;
8065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    options.mandatory_video.push_back(
8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        StreamOptions::Constraint(kMediaStreamSourceInfoId, device_id));
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DeviceRequest* request = new DeviceRequest(requester,
8125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             render_process_id,
8135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             render_view_id,
8145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             page_request_id,
8155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             security_origin,
81646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)                                             true,
817effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                             false,  // user gesture
8185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             MEDIA_OPEN_DEVICE,
8195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             options,
8205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             sc);
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const std::string& label = AddRequest(request);
823a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Post a task and handle the request asynchronously. The reason is that the
824a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // requester won't have a label for the request until this function returns
825a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // and thus can not handle a response. Using base::Unretained is safe since
826a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // MediaStreamManager is deleted on the UI thread, after the IO thread has
827a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // been stopped.
828a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  BrowserThread::PostTask(
829a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      BrowserThread::IO, FROM_HERE,
830a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      base::Bind(&MediaStreamManager::SetupRequest,
831a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 base::Unretained(this), label));
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8345c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liubool MediaStreamManager::TranslateSourceIdToDeviceId(
8355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    MediaStreamType stream_type,
8365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const ResourceContext::SaltCallback& sc,
8375c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const GURL& security_origin,
8385c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const std::string& source_id,
8395c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    std::string* device_id) const {
8405c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK(stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ||
8415c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu         stream_type == MEDIA_DEVICE_VIDEO_CAPTURE);
8425c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // The source_id can be empty if the constraint is set but empty.
8435c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (source_id.empty())
8445c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return false;
8455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
8465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const EnumerationCache* cache =
8475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ?
8485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      &audio_enumeration_cache_ : &video_enumeration_cache_;
8495c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
8505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // If device monitoring hasn't started, the |device_guid| is not valid.
8515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!cache->valid)
8525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return false;
8535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
8545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  for (StreamDeviceInfoArray::const_iterator it = cache->devices.begin();
8555c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu       it != cache->devices.end();
8565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu       ++it) {
8575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (content::DoesMediaDeviceIDMatchHMAC(sc, security_origin, source_id,
8585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                            it->device.id)) {
8595c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      *device_id = it->device.id;
8605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return true;
8615c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
8625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
8635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return false;
8645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
8655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
866a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::EnsureDeviceMonitorStarted() {
867effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
8685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StartMonitoring();
869f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
870f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
871f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MediaStreamManager::StopRemovedDevices(
872f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const StreamDeviceInfoArray& old_devices,
873f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const StreamDeviceInfoArray& new_devices) {
874f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << "StopRemovedDevices("
875f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << "{#old_devices = " << old_devices.size() <<  "} "
876f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)           << "{#new_devices = " << new_devices.size() << "})";
877f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (StreamDeviceInfoArray::const_iterator old_dev_it = old_devices.begin();
878f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       old_dev_it != old_devices.end(); ++old_dev_it) {
879f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    bool device_found = false;
8805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    StreamDeviceInfoArray::const_iterator new_dev_it = new_devices.begin();
8815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (; new_dev_it != new_devices.end(); ++new_dev_it) {
882f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      if (old_dev_it->device.id == new_dev_it->device.id) {
883f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        device_found = true;
884f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        break;
885f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
886f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
887f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
888f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    if (!device_found) {
889f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // A device has been removed. We need to check if it is used by a
890f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      // MediaStream and in that case cleanup and notify the render process.
891f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      StopRemovedDevice(old_dev_it->device);
892f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
893f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
894f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
895f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
896f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MediaStreamManager::StopRemovedDevice(const MediaStreamDevice& device) {
897f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  std::vector<int> session_ids;
898f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (DeviceRequests::const_iterator it = requests_.begin();
899f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       it != requests_.end() ; ++it) {
900f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    const DeviceRequest* request = it->second;
901f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (StreamDeviceInfoArray::const_iterator device_it =
902f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)             request->devices.begin();
903f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         device_it != request->devices.end(); ++device_it) {
904a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      std::string source_id = content::GetHMACForMediaDeviceID(
9055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          request->salt_callback,
9065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          request->security_origin,
907a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          device.id);
908a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if (device_it->device.id == source_id &&
909a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          device_it->device.type == device.type) {
910f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        session_ids.push_back(device_it->session_id);
911f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        if (it->second->requester) {
912f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          it->second->requester->DeviceStopped(
913f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)              it->second->requesting_view_id,
914f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)              it->first,
915f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)              *device_it);
916f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        }
917f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      }
918f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
919f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
920f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  for (std::vector<int>::const_iterator it = session_ids.begin();
921f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)       it != session_ids.end(); ++it) {
922f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    StopDevice(device.type, *it);
923f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  }
924e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
925e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  std::ostringstream oss;
926e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  oss << "Media input device removed: type = " <<
927e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    (device.type == MEDIA_DEVICE_AUDIO_CAPTURE ? "audio" : "video") <<
928e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    ", id = " << device.id << ", name = " << device.name;
929e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  AddLogMessageOnIOThread(oss.str());
930f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)}
931f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamManager::StartMonitoring() {
933effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
9345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (monitoring_started_)
9355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
9365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!base::SystemMonitor::Get())
9382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
9392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  monitoring_started_ = true;
9415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::SystemMonitor::Get()->AddDevicesChangedObserver(this);
9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Enumerate both the audio and video devices to cache the device lists
9445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // and send them to media observer.
9455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ++active_enumeration_ref_count_[MEDIA_DEVICE_AUDIO_CAPTURE];
9465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  audio_input_device_manager_->EnumerateDevices(MEDIA_DEVICE_AUDIO_CAPTURE);
9475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ++active_enumeration_ref_count_[MEDIA_DEVICE_VIDEO_CAPTURE];
9485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  video_capture_manager_->EnumerateDevices(MEDIA_DEVICE_VIDEO_CAPTURE);
949a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
950a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_MACOSX)
951a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  BrowserThread::PostTask(
952a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      BrowserThread::UI, FROM_HERE,
953a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::Bind(&MediaStreamManager::StartMonitoringOnUIThread,
954a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                 base::Unretained(this)));
955a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
958a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#if defined(OS_MACOSX)
959a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void MediaStreamManager::StartMonitoringOnUIThread() {
960effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
961a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  BrowserMainLoop* browser_main_loop = content::BrowserMainLoop::GetInstance();
9625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (browser_main_loop) {
9635c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    browser_main_loop->device_monitor_mac()
9645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        ->StartMonitoring(audio_manager_->GetWorkerTaskRunner());
9655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
966a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)}
967a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#endif
968a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamManager::StopMonitoring() {
970c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_EQ(base::MessageLoop::current(), io_loop_);
9712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (monitoring_started_) {
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SystemMonitor::Get()->RemoveDevicesChangedObserver(this);
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    monitoring_started_ = false;
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClearEnumerationCache(&audio_enumeration_cache_);
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ClearEnumerationCache(&video_enumeration_cache_);
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool MediaStreamManager::GetRequestedDeviceCaptureId(
9805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const DeviceRequest* request,
9815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    MediaStreamType type,
9825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string* device_id) const {
9835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(type == MEDIA_DEVICE_AUDIO_CAPTURE ||
9845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         type == MEDIA_DEVICE_VIDEO_CAPTURE);
9855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const StreamOptions::Constraints* mandatory =
9865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (type == MEDIA_DEVICE_AUDIO_CAPTURE) ?
9875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          &request->options.mandatory_audio : &request->options.mandatory_video;
9885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const StreamOptions::Constraints* optional =
9895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (type == MEDIA_DEVICE_AUDIO_CAPTURE) ?
9905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          &request->options.optional_audio : &request->options.optional_video;
9915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::vector<std::string> source_ids;
9935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StreamOptions::GetConstraintsByName(*mandatory,
9945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      kMediaStreamSourceInfoId, &source_ids);
9955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (source_ids.size() > 1) {
9965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOG(ERROR) << "Only one mandatory " << kMediaStreamSourceInfoId
9975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        << " is supported.";
9985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
999a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
10005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If a specific device has been requested we need to find the real device
10015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // id.
10025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (source_ids.size() == 1 &&
10035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !TranslateSourceIdToDeviceId(type,
10045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   request->salt_callback,
10055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   request->security_origin,
10065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   source_ids[0], device_id)) {
10075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    LOG(WARNING) << "Invalid mandatory " << kMediaStreamSourceInfoId
10085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 << " = " << source_ids[0] << ".";
10095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
10105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
10115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Check for optional audio sourceIDs.
10125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (device_id->empty()) {
10135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    StreamOptions::GetConstraintsByName(*optional,
10145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        kMediaStreamSourceInfoId,
10155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        &source_ids);
10165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Find the first sourceID that translates to device. Note that only one
10175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // device per type can call to GenerateStream is ever opened.
10185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (std::vector<std::string>::const_iterator it = source_ids.begin();
10195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         it != source_ids.end(); ++it) {
10205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (TranslateSourceIdToDeviceId(type,
10215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      request->salt_callback,
10225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      request->security_origin,
10235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      *it,
10245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      device_id)) {
10255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        break;
10265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
1027a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
1028a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
1029a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return true;
1030a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1031a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1032a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::TranslateDeviceIdToSourceId(
1033a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DeviceRequest* request,
1034a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    MediaStreamDevice* device) {
10355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
103646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      request->audio_type() == MEDIA_DEVICE_AUDIO_OUTPUT ||
10375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE) {
1038a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    device->id = content::GetHMACForMediaDeviceID(
10395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        request->salt_callback,
10405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        request->security_origin,
1041a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        device->id);
1042a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
1043a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1044a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamManager::ClearEnumerationCache(EnumerationCache* cache) {
1046c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_EQ(base::MessageLoop::current(), io_loop_);
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  cache->valid = false;
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool MediaStreamManager::EnumerationRequired(EnumerationCache* cache,
10515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                             MediaStreamType stream_type) {
10525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(base::MessageLoop::current(), io_loop_);
10535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (stream_type == MEDIA_NO_SERVICE)
10545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
10555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ||
10575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         stream_type == MEDIA_DEVICE_VIDEO_CAPTURE);
10585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(OS_ANDROID)
10605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // There's no SystemMonitor on Android that notifies us when devices are
10615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // added or removed, so we need to populate the cache on every request.
10625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Fortunately, there is an already up-to-date cache in the browser side
10635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // audio manager that we can rely on, so the performance impact of
10645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // invalidating the cache like this, is minimal.
10655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (stream_type == MEDIA_DEVICE_AUDIO_CAPTURE) {
10665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Make sure the cache is marked as invalid so that FinalizeEnumerateDevices
10675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // will be called at the end of the enumeration.
10685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ClearEnumerationCache(cache);
10695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
10705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
10715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // If the cache isn't valid, we need to start a full enumeration.
10725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return !cache->valid;
10735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
10745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaStreamManager::StartEnumeration(DeviceRequest* request) {
1076effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start monitoring the devices when doing the first enumeration.
10795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  StartMonitoring();
10802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start enumeration for devices of all requested device types.
10825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const MediaStreamType streams[] = { request->audio_type(),
10835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                      request->video_type() };
10845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(streams); ++i) {
10855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (streams[i] == MEDIA_NO_SERVICE)
10865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      continue;
10875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    request->SetState(streams[i], MEDIA_REQUEST_STATE_REQUESTED);
10885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK_GE(active_enumeration_ref_count_[streams[i]], 0);
10895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (active_enumeration_ref_count_[streams[i]] == 0) {
10905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ++active_enumeration_ref_count_[streams[i]];
10915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      GetDeviceManager(streams[i])->EnumerateDevices(streams[i]);
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string MediaStreamManager::AddRequest(DeviceRequest* request) {
1097effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a label for this request and verify it is unique.
11002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string unique_label;
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
11022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    unique_label = RandomLabel();
11036d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  } while (FindRequest(unique_label) != NULL);
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11056d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  requests_.push_back(std::make_pair(unique_label, request));
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return unique_label;
11082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1110a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)MediaStreamManager::DeviceRequest*
1111a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)MediaStreamManager::FindRequest(const std::string& label) const {
11126d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  for (DeviceRequests::const_iterator request_it = requests_.begin();
11136d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)       request_it != requests_.end(); ++request_it) {
11146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (request_it->first == label)
11156d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      return request_it->second;
11166d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
11176d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  return NULL;
1118a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1119a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1120a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::DeleteRequest(const std::string& label) {
11215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DVLOG(1) << "DeleteRequest({label= " << label << "})";
11226d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  for (DeviceRequests::iterator request_it = requests_.begin();
11236d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)       request_it != requests_.end(); ++request_it) {
11246d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    if (request_it->first == label) {
11256d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      scoped_ptr<DeviceRequest> request(request_it->second);
11266d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      requests_.erase(request_it);
11276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)      return;
11286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)    }
11296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
11306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  NOTREACHED();
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::PostRequestToUI(const std::string& label,
1134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                         DeviceRequest* request) {
1135effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
11365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(request->UIRequest());
1137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DVLOG(1) << "PostRequestToUI({label= " << label << "})";
1138a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
11395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const MediaStreamType audio_type = request->audio_type();
11405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const MediaStreamType video_type = request->video_type();
1141a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1142a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Post the request to UI and set the state.
114346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (IsAudioInputMediaType(audio_type))
1144a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    request->SetState(audio_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
1145a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (IsVideoMediaType(video_type))
1146a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    request->SetState(video_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
1147868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1148868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (use_fake_ui_) {
1149868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!fake_ui_)
1150868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      fake_ui_.reset(new FakeMediaStreamUIProxy());
1151868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1152868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    MediaStreamDevices devices;
1153868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (audio_enumeration_cache_.valid) {
1154868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      for (StreamDeviceInfoArray::const_iterator it =
1155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               audio_enumeration_cache_.devices.begin();
1156868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           it != audio_enumeration_cache_.devices.end(); ++it) {
1157868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        devices.push_back(it->device);
1158868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
1159868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1160868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (video_enumeration_cache_.valid) {
1161868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      for (StreamDeviceInfoArray::const_iterator it =
1162868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)               video_enumeration_cache_.devices.begin();
1163868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)           it != video_enumeration_cache_.devices.end(); ++it) {
1164868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        devices.push_back(it->device);
1165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
1166868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
1167868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    fake_ui_->SetAvailableDevices(devices);
1169868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1170868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    request->ui_proxy = fake_ui_.Pass();
1171868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
1172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    request->ui_proxy = MediaStreamUIProxy::Create();
1173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  request->ui_proxy->RequestAccess(
11765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *request->UIRequest(),
1177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      base::Bind(&MediaStreamManager::HandleAccessRequestResponse,
1178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                 base::Unretained(this), label));
11792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
11802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::SetupRequest(const std::string& label) {
1182effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
1183a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DeviceRequest* request = FindRequest(label);
1184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!request) {
1185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DVLOG(1) << "SetupRequest label " << label << " doesn't exist!!";
1186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;  // This can happen if the request has been canceled.
1187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
1188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
11895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!request->security_origin.is_valid()) {
1190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    LOG(ERROR) << "Invalid security origin. "
11915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)               << request->security_origin;
1192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    FinalizeRequestFailed(label,
1193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                          request,
1194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                          MEDIA_DEVICE_INVALID_SECURITY_ORIGIN);
1195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
1196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
11972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
11985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MediaStreamType audio_type = MEDIA_NO_SERVICE;
11995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  MediaStreamType video_type = MEDIA_NO_SERVICE;
12005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ParseStreamType(request->options, &audio_type, &video_type);
12015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  request->SetAudioType(audio_type);
12025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  request->SetVideoType(video_type);
12032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool is_web_contents_capture =
12052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      audio_type == MEDIA_TAB_AUDIO_CAPTURE ||
12062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      video_type == MEDIA_TAB_VIDEO_CAPTURE;
1207a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (is_web_contents_capture && !SetupTabCaptureRequest(request)) {
1208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    FinalizeRequestFailed(label,
1209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                          request,
1210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                          MEDIA_DEVICE_TAB_CAPTURE_FAILURE);
1211a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
1212a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
12132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1214ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  bool is_screen_capture =
1215ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      video_type == MEDIA_DESKTOP_VIDEO_CAPTURE;
1216a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (is_screen_capture && !SetupScreenCaptureRequest(request)) {
1217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    FinalizeRequestFailed(label,
1218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                          request,
1219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                          MEDIA_DEVICE_SCREEN_CAPTURE_FAILURE);
1220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return;
1221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
12222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!is_web_contents_capture && !is_screen_capture) {
12245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (EnumerationRequired(&audio_enumeration_cache_, audio_type) ||
12255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        EnumerationRequired(&video_enumeration_cache_, video_type)) {
12265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Enumerate the devices if there is no valid device lists to be used.
12275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      StartEnumeration(request);
12285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
12295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else {
12305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        // Cache is valid, so log the cached devices for MediaStream requests.
12315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (request->request_type == MEDIA_GENERATE_STREAM) {
12325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        std::string log_message("Using cached devices for request.\n");
12335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (audio_type != MEDIA_NO_SERVICE) {
12345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          log_message +=
12355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              GetLogMessageString(audio_type, audio_enumeration_cache_.devices);
12365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
12375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (video_type != MEDIA_NO_SERVICE) {
12385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          log_message +=
12395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)              GetLogMessageString(video_type, video_enumeration_cache_.devices);
12405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
12415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        SendMessageToNativeLog(log_message);
12425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
12435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
12445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!SetupDeviceCaptureRequest(request)) {
124623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)      FinalizeRequestFailed(label, request, MEDIA_DEVICE_NO_HARDWARE);
12475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return;
12485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
12492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1250a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  PostRequestToUI(label, request);
1251a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
12522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
12535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool MediaStreamManager::SetupDeviceCaptureRequest(DeviceRequest* request) {
12545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK((request->audio_type() == MEDIA_DEVICE_AUDIO_CAPTURE ||
12555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          request->audio_type() == MEDIA_NO_SERVICE) &&
12565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         (request->video_type() == MEDIA_DEVICE_VIDEO_CAPTURE ||
12575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          request->video_type() == MEDIA_NO_SERVICE));
12585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string audio_device_id;
1259effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (request->options.audio_requested &&
1260effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      !GetRequestedDeviceCaptureId(request, request->audio_type(),
126123730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                     &audio_device_id)) {
1262effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return false;
12635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
12645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string video_device_id;
1266effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (request->options.video_requested &&
1267effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      !GetRequestedDeviceCaptureId(request, request->video_type(),
1268effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                   &video_device_id)) {
1269effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return false;
12705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
12715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  request->CreateUIRequest(audio_device_id, video_device_id);
12725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DVLOG(3) << "Audio requested " << request->options.audio_requested
12735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           << " device id = " << audio_device_id
12745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           << "Video requested " << request->options.video_requested
12755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           << " device id = " << video_device_id;
12765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return true;
12775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
12785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool MediaStreamManager::SetupTabCaptureRequest(DeviceRequest* request) {
12805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(request->audio_type() == MEDIA_TAB_AUDIO_CAPTURE ||
12815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         request->video_type() == MEDIA_TAB_VIDEO_CAPTURE);
12825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
12835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string capture_device_id;
12845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool mandatory_audio = false;
12855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool mandatory_video = false;
12865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!request->options.GetFirstAudioConstraintByName(kMediaStreamSourceId,
12875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                      &capture_device_id,
12885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                      &mandatory_audio) &&
12895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      !request->options.GetFirstVideoConstraintByName(kMediaStreamSourceId,
12905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                      &capture_device_id,
12915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                                      &mandatory_video)) {
12925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return false;
12935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
12945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(mandatory_audio || mandatory_video);
1295a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1296a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Customize options for a WebContents based capture.
1297a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  int target_render_process_id = 0;
1298a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  int target_render_view_id = 0;
12992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1300a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // TODO(justinlin): Can't plumb audio mirroring using stream type right
1301a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // now, so plumbing by device_id. Will revisit once it's refactored.
1302a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // http://crbug.com/163100
1303a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::string tab_capture_device_id =
13045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      WebContentsCaptureUtil::AppendWebContentsDeviceScheme(capture_device_id);
1305a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1306a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  bool has_valid_device_id = WebContentsCaptureUtil::ExtractTabCaptureTarget(
1307a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      tab_capture_device_id, &target_render_process_id,
1308a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      &target_render_view_id);
1309a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!has_valid_device_id ||
13105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (request->audio_type() != MEDIA_TAB_AUDIO_CAPTURE &&
13115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       request->audio_type() != MEDIA_NO_SERVICE) ||
13125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (request->video_type() != MEDIA_TAB_VIDEO_CAPTURE &&
13135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       request->video_type() != MEDIA_NO_SERVICE)) {
1314a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return false;
1315a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
13165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
13175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  request->CreateTabCatureUIRequest(target_render_process_id,
13185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    target_render_view_id,
13195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                    tab_capture_device_id);
13205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1321a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DVLOG(3) << "SetupTabCaptureRequest "
1322a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)           << ", {tab_capture_device_id = " << tab_capture_device_id <<  "}"
1323a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)           << ", {target_render_process_id = " << target_render_process_id
1324a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)           << "}"
1325a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)           << ", {target_render_view_id = " << target_render_view_id << "}";
1326a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return true;
1327a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1328a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1329a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)bool MediaStreamManager::SetupScreenCaptureRequest(DeviceRequest* request) {
13305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK(request->audio_type() == MEDIA_LOOPBACK_AUDIO_CAPTURE ||
13315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         request->video_type() == MEDIA_DESKTOP_VIDEO_CAPTURE);
1332a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1333a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // For screen capture we only support two valid combinations:
1334a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // (1) screen video capture only, or
1335a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // (2) screen video capture with loopback audio capture.
13365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (request->video_type() != MEDIA_DESKTOP_VIDEO_CAPTURE ||
13375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      (request->audio_type() != MEDIA_NO_SERVICE &&
13385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       request->audio_type() != MEDIA_LOOPBACK_AUDIO_CAPTURE)) {
1339a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    LOG(ERROR) << "Invalid screen capture request.";
1340a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return false;
1341a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
13425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
13435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string video_device_id;
13445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (request->video_type() == MEDIA_DESKTOP_VIDEO_CAPTURE) {
13455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    std::string video_stream_source;
13465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    bool mandatory = false;
13475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (!request->options.GetFirstVideoConstraintByName(
13485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        kMediaStreamSource,
13495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        &video_stream_source,
13505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        &mandatory)) {
13515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      LOG(ERROR) << kMediaStreamSource << " not found.";
13525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return false;
13535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
13545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DCHECK(mandatory);
13555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
13565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (video_stream_source == kMediaStreamSourceDesktop) {
13575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (!request->options.GetFirstVideoConstraintByName(
13585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          kMediaStreamSourceId,
13595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          &video_device_id,
13605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          &mandatory)) {
13615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        LOG(ERROR) << kMediaStreamSourceId << " not found.";
13625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return false;
13635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      }
13645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DCHECK(mandatory);
13655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
13665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
13675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
13685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  request->CreateUIRequest("", video_device_id);
1369a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return true;
1370a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1371a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1372a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)StreamDeviceInfoArray MediaStreamManager::GetDevicesOpenedByRequest(
1373a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const std::string& label) const {
1374a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DeviceRequest* request = FindRequest(label);
1375a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!request)
1376a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return StreamDeviceInfoArray();
1377a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return request->devices;
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13808bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)bool MediaStreamManager::FindExistingRequestedDeviceInfo(
1381a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const DeviceRequest& new_request,
1382a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const MediaStreamDevice& new_device_info,
1383a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    StreamDeviceInfo* existing_device_info,
1384a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    MediaRequestState* existing_request_state) const {
1385a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(existing_device_info);
1386a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DCHECK(existing_request_state);
1387a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1388a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  std::string source_id = content::GetHMACForMediaDeviceID(
13895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new_request.salt_callback,
13905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      new_request.security_origin,
1391a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      new_device_info.id);
1392a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
13938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  for (DeviceRequests::const_iterator it = requests_.begin();
13948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)       it != requests_.end() ; ++it) {
13958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const DeviceRequest* request = it->second;
1396a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (request->requesting_process_id == new_request.requesting_process_id &&
1397a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        request->requesting_view_id == new_request.requesting_view_id &&
13985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        request->request_type == new_request.request_type) {
13998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      for (StreamDeviceInfoArray::const_iterator device_it =
14008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)               request->devices.begin();
14018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)           device_it != request->devices.end(); ++device_it) {
1402a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        if (device_it->device.id == source_id &&
1403a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            device_it->device.type == new_device_info.type) {
1404a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            *existing_device_info = *device_it;
1405a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            *existing_request_state = request->state(device_it->device.type);
14068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          return true;
14078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
14088bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      }
14098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
14108bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
14118bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  return false;
14128bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
14138bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
1414a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::FinalizeGenerateStream(const std::string& label,
1415a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                DeviceRequest* request) {
1416a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DVLOG(1) << "FinalizeGenerateStream label " << label;
1417a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const StreamDeviceInfoArray& requested_devices = request->devices;
1418a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1419a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Partition the array of devices into audio vs video.
1420a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  StreamDeviceInfoArray audio_devices, video_devices;
1421a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (StreamDeviceInfoArray::const_iterator device_it =
1422a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)           requested_devices.begin();
1423a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)       device_it != requested_devices.end(); ++device_it) {
142446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    if (IsAudioInputMediaType(device_it->device.type)) {
1425a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      audio_devices.push_back(*device_it);
1426a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    } else if (IsVideoMediaType(device_it->device.type)) {
1427a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      video_devices.push_back(*device_it);
1428a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    } else {
1429a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      NOTREACHED();
1430a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    }
1431a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
1432a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
14335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  request->requester->StreamGenerated(
14345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request->requesting_view_id,
14355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request->page_request_id,
14365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      label, audio_devices, video_devices);
1437a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1438a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1439a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::FinalizeRequestFailed(
1440a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const std::string& label,
1441a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    DeviceRequest* request,
1442a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    content::MediaStreamRequestResult result) {
1443a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (request->requester)
14445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    request->requester->StreamGenerationFailed(
14455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        request->requesting_view_id,
1446a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        request->page_request_id,
1447a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        result);
1448a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
14495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (request->request_type == MEDIA_DEVICE_ACCESS &&
1450a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      !request->callback.is_null()) {
1451a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    request->callback.Run(MediaStreamDevices(), request->ui_proxy.Pass());
1452a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
1453a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1454a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DeleteRequest(label);
1455a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1456a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1457a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::FinalizeOpenDevice(const std::string& label,
1458a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                            DeviceRequest* request) {
1459a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  const StreamDeviceInfoArray& requested_devices = request->devices;
14605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  request->requester->DeviceOpened(request->requesting_view_id,
14615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   request->page_request_id,
14625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                   label, requested_devices.front());
1463a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1464a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1465a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::FinalizeEnumerateDevices(const std::string& label,
1466a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                                  DeviceRequest* request) {
1467effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
14685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DCHECK_EQ(request->request_type, MEDIA_ENUMERATE_DEVICES);
14695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (request->security_origin.is_valid()) {
14715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (StreamDeviceInfoArray::iterator it = request->devices.begin();
14725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         it != request->devices.end(); ++it) {
14735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      TranslateDeviceIdToSourceId(request, &it->device);
14745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
14755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  } else {
14765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    request->devices.clear();
1477a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  }
14785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
147946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!request->have_permission)
148046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    ClearDeviceLabels(&request->devices);
148146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
14825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  request->requester->DevicesEnumerated(
14835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request->requesting_view_id,
14845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request->page_request_id,
14855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      label,
14865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request->devices);
14875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
14885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(tommi):
14895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Ideally enumeration requests should be deleted once they have been served
14905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // (as any request).  However, this implementation mixes requests and
14915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // notifications together so enumeration requests are kept open by some
14925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // implementations (only Pepper?) and enumerations are done again when
14935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // device notifications are fired.
14945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Implementations that just want to request the device list and be done
14955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // (e.g. DeviceRequestMessageFilter), they must (confusingly) call
14965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // CancelRequest() after the request has been fulfilled.  This is not
14975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // obvious, not consistent in this class (see e.g. FinalizeMediaAccessRequest)
14985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // and can lead to subtle bugs (requests not deleted at all deleted too
14995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // early).
15005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //
15015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Basically, it is not clear that using requests as an additional layer on
15025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // top of device notifications is necessary or good.
15035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //
15045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // To add to this, MediaStreamManager currently relies on the external
15055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // implementations of MediaStreamRequester to delete enumeration requests via
15065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // CancelRequest and e.g. DeviceRequestMessageFilter does this.  However the
15075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Pepper implementation does not seem to to this at all (and from what I can
15085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // see, it is the only implementation that uses an enumeration request as a
15095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // notification mechanism).
15105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //
15115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // We should decouple notifications from enumeration requests and once that
15125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // has been done, remove the requirement to call CancelRequest() to delete
15135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // enumeration requests and uncomment the following line:
15145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  //
15155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // DeleteRequest(label);
1516a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1517a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1518a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void MediaStreamManager::FinalizeMediaAccessRequest(
1519a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const std::string& label,
1520a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DeviceRequest* request,
1521a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const MediaStreamDevices& devices) {
1522a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!request->callback.is_null())
1523a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    request->callback.Run(devices, request->ui_proxy.Pass());
1524a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1525a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Delete the request since it is done.
1526a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DeleteRequest(label);
1527a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1528a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
15292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaStreamManager::InitializeDeviceManagersOnIOThread() {
1530effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
15315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (device_task_runner_)
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  device_task_runner_ = audio_manager_->GetWorkerTaskRunner();
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_input_device_manager_ = new AudioInputDeviceManager(audio_manager_);
15375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  audio_input_device_manager_->Register(this, device_task_runner_);
15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We want to be notified of IO message loop destruction to delete the thread
15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and the device managers.
1541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  io_loop_ = base::MessageLoop::current();
15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  io_loop_->AddDestructionObserver(this);
15435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
15445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (CommandLine::ForCurrentProcess()->HasSwitch(
1545cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      switches::kUseFakeDeviceForMediaStream)) {
15465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    audio_input_device_manager()->UseFakeDevice();
15475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
1548cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
154946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  video_capture_manager_ =
155046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      new VideoCaptureManager(media::VideoCaptureDeviceFactory::CreateFactory(
155146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)          BrowserThread::GetMessageLoopProxyForThread(BrowserThread::UI)));
15525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  video_capture_manager_->Register(this, device_task_runner_);
15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamManager::Opened(MediaStreamType stream_type,
15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                int capture_session_id) {
1557effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
15588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DVLOG(1) << "Opened({stream_type = " << stream_type <<  "} "
15598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)           << "{capture_session_id = " << capture_session_id << "})";
15608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // Find the request(s) containing this device and mark it as used.
15618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // It can be used in several requests since the same device can be
15628bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  // requested from the same web page.
15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (DeviceRequests::iterator request_it = requests_.begin();
15648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)       request_it != requests_.end(); ++request_it) {
15658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    const std::string& label = request_it->first;
15668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    DeviceRequest* request = request_it->second;
15678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    StreamDeviceInfoArray* devices = &(request->devices);
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (StreamDeviceInfoArray::iterator device_it = devices->begin();
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         device_it != devices->end(); ++device_it) {
15702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (device_it->device.type == stream_type &&
1571f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)          device_it->session_id == capture_session_id) {
1572f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        CHECK(request->state(device_it->device.type) ==
1573f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)            MEDIA_REQUEST_STATE_OPENING);
15748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        // We've found a matching request.
15758bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        request->SetState(device_it->device.type, MEDIA_REQUEST_STATE_DONE);
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
157746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)        if (IsAudioInputMediaType(device_it->device.type)) {
15782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // Store the native audio parameters in the device struct.
15792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // TODO(xians): Handle the tab capture sample rate/channel layout
15802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // in AudioInputDeviceManager::Open().
15812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          if (device_it->device.type != content::MEDIA_TAB_AUDIO_CAPTURE) {
15822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            const StreamDeviceInfo* info =
15832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                audio_input_device_manager_->GetOpenedDeviceInfoById(
15842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    device_it->session_id);
158558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            device_it->device.input = info->device.input;
158658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)            device_it->device.matched_output = info->device.matched_output;
15872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          }
15888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        }
15898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        if (RequestDone(*request))
15908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)          HandleRequestDone(label, request);
15918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        break;
15928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      }
15938bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
15948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
15958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)}
15968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
15978bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)void MediaStreamManager::HandleRequestDone(const std::string& label,
15988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                           DeviceRequest* request) {
15998bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DCHECK(RequestDone(*request));
16008bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DVLOG(1) << "HandleRequestDone("
16018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)           << ", {label = " << label <<  "})";
16028bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
16035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  switch (request->request_type) {
16048bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case MEDIA_OPEN_DEVICE:
1605a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      FinalizeOpenDevice(label, request);
16068bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      break;
16078bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    case MEDIA_GENERATE_STREAM: {
1608a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      FinalizeGenerateStream(label, request);
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16158bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
16168bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (request->ui_proxy.get()) {
16178bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    request->ui_proxy->OnStarted(
1618f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)        base::Bind(&MediaStreamManager::StopMediaStreamFromBrowser,
1619effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   base::Unretained(this),
1620effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   label),
1621effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        base::Bind(&MediaStreamManager::OnMediaStreamUIWindowId,
1622effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   base::Unretained(this),
1623effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   request->video_type(),
1624effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                   request->devices));
16258bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamManager::Closed(MediaStreamType stream_type,
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                int capture_session_id) {
1630effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamManager::DevicesEnumerated(
16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MediaStreamType stream_type, const StreamDeviceInfoArray& devices) {
1635effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
1636f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  DVLOG(1) << "DevicesEnumerated("
16375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           << "{stream_type = " << stream_type << "})" << std::endl;
16385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
16395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string log_message = "New device enumeration result:\n" +
16405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            GetLogMessageString(stream_type, devices);
16415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  SendMessageToNativeLog(log_message);
16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Only cache the device list when the device list has been changed.
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool need_update_clients = false;
16452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EnumerationCache* cache =
16462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      stream_type == MEDIA_DEVICE_AUDIO_CAPTURE ?
16472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &audio_enumeration_cache_ : &video_enumeration_cache_;
16482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!cache->valid ||
16492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      devices.size() != cache->devices.size() ||
16502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      !std::equal(devices.begin(), devices.end(), cache->devices.begin(),
16512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                  StreamDeviceInfo::IsEqual)) {
1652f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    StopRemovedDevices(cache->devices, devices);
16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    cache->devices = devices;
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    need_update_clients = true;
1655f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
1656f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // The device might not be able to be enumerated when it is not warmed up,
1657f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // for example, when the machine just wakes up from sleep. We set the cache
1658f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // to be invalid so that the next media request will trigger the
1659f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    // enumeration again. See issue/317673.
1660a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    cache->valid = !devices.empty();
16616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  }
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (need_update_clients && monitoring_started_)
16642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NotifyDevicesChanged(stream_type, devices);
16652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Publish the result for all requests waiting for device list(s).
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find the requests waiting for this device list, store their labels and
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // release the iterator before calling device settings. We might get a call
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // back from device_settings that will need to iterate through devices.
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::list<std::string> label_list;
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (DeviceRequests::iterator it = requests_.begin(); it != requests_.end();
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
1673868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (it->second->state(stream_type) == MEDIA_REQUEST_STATE_REQUESTED &&
16745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        (it->second->audio_type() == stream_type ||
16755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)         it->second->video_type() == stream_type)) {
16765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (it->second->request_type != MEDIA_ENUMERATE_DEVICES)
16772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        it->second->SetState(stream_type, MEDIA_REQUEST_STATE_PENDING_APPROVAL);
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      label_list.push_back(it->first);
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::list<std::string>::iterator it = label_list.begin();
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != label_list.end(); ++it) {
1684a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    DeviceRequest* request = FindRequest(*it);
16855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    switch (request->request_type) {
16862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case MEDIA_ENUMERATE_DEVICES:
1687a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        if (need_update_clients && request->requester) {
1688a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          request->devices = devices;
1689a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          FinalizeEnumerateDevices(*it, request);
1690a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        }
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
16935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (request->state(request->audio_type()) ==
16942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                MEDIA_REQUEST_STATE_REQUESTED ||
16955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            request->state(request->video_type()) ==
16962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                MEDIA_REQUEST_STATE_REQUESTED) {
16972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // We are doing enumeration for other type of media, wait until it is
16982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // all done before posting the request to UI because UI needs
16992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          // the device lists to handle the request.
17002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          break;
17012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        }
1702a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        if (!SetupDeviceCaptureRequest(request)) {
1703a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)          FinalizeRequestFailed(*it,
1704a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                request,
170523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                MEDIA_DEVICE_NO_HARDWARE);
1706a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        } else {
17075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          PostRequestToUI(*it, request);
1708a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        }
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        break;
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  label_list.clear();
17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  --active_enumeration_ref_count_[stream_type];
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_GE(active_enumeration_ref_count_[stream_type], 0);
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17175c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid MediaStreamManager::Aborted(MediaStreamType stream_type,
17185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                 int capture_session_id) {
17195c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DCHECK_CURRENTLY_ON(BrowserThread::IO);
17205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  DVLOG(1) << "Aborted({stream_type = " << stream_type <<  "} "
17215c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu           << "{capture_session_id = " << capture_session_id << "})";
17225c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  StopDevice(stream_type, capture_session_id);
17235c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
17245c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
17255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
17265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MediaStreamManager::SendMessageToNativeLog(const std::string& message) {
17275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BrowserThread::PostTask(
17285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      BrowserThread::UI, FROM_HERE,
17295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(DoAddLogMessage, message));
17305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
17315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1732effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid MediaStreamManager::OnSuspend() {
1733effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  SendMessageToNativeLog("Power state suspended.");
1734effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
1735effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
1736effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid MediaStreamManager::OnResume() {
1737effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  SendMessageToNativeLog("Power state resumed.");
1738effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
1739effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
17405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MediaStreamManager::AddLogMessageOnIOThread(const std::string& message) {
17415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Get render process ids on the IO thread.
1742effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
17435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
17445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Grab all unique process ids that request a MediaStream or have a
17455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // MediaStream running.
17465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::set<int> requesting_process_ids;
17475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (DeviceRequests::const_iterator it = requests_.begin();
17485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       it != requests_.end(); ++it) {
17495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    DeviceRequest* request = it->second;
17505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (request->request_type == MEDIA_GENERATE_STREAM)
17515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      requesting_process_ids.insert(request->requesting_process_id);
17525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
17535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
17545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // MediaStreamManager is a singleton in BrowserMainLoop, which owns the UI
17555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // thread. MediaStreamManager has the same lifetime as the UI thread, so it is
17565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // safe to use base::Unretained.
17575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  BrowserThread::PostTask(
17585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      BrowserThread::UI,
17595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      FROM_HERE,
17605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      base::Bind(&MediaStreamManager::AddLogMessageOnUIThread,
17615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 base::Unretained(this),
17625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 requesting_process_ids,
17635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                 message));
17645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
17655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
17665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void MediaStreamManager::AddLogMessageOnUIThread(
17675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::set<int>& requesting_process_ids,
17685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& message) {
17695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#if defined(ENABLE_WEBRTC)
17705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // Must be on the UI thread to access RenderProcessHost from process ID.
1771effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::UI);
17725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
17735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (std::set<int>::const_iterator it = requesting_process_ids.begin();
17745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       it != requesting_process_ids.end(); ++it) {
17755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // Log the message to all renderers that are requesting a MediaStream or
17765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    // have a MediaStream running.
17775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    content::RenderProcessHostImpl* render_process_host_impl =
17785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        static_cast<content::RenderProcessHostImpl*>(
17795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            content::RenderProcessHost::FromID(*it));
17805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (render_process_host_impl)
17815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      render_process_host_impl->WebRtcLogMessage(message);
17825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
17835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
17845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
17855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1786868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void MediaStreamManager::HandleAccessRequestResponse(
1787868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const std::string& label,
1788a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    const MediaStreamDevices& devices,
1789a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    content::MediaStreamRequestResult result) {
1790effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
17918bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  DVLOG(1) << "HandleAccessRequestResponse("
17928bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)           << ", {label = " << label <<  "})";
1793868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1794a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DeviceRequest* request = FindRequest(label);
1795a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!request) {
1796a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    // The request has been canceled before the UI returned.
17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (request->request_type == MEDIA_DEVICE_ACCESS) {
1801a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    FinalizeMediaAccessRequest(label, request, devices);
1802868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return;
1803868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
1804868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
1805a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  // Handle the case when the request was denied.
1806a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  if (result != MEDIA_DEVICE_OK) {
1807a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    FinalizeRequestFailed(label, request, result);
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1810e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  DCHECK(!devices.empty());
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Process all newly-accepted devices for this request.
1813868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found_audio = false;
1814868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool found_video = false;
1815868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (MediaStreamDevices::const_iterator device_it = devices.begin();
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       device_it != devices.end(); ++device_it) {
1817868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    StreamDeviceInfo device_info;
1818868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    device_info.device = *device_it;
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // TODO(justinlin): Nicer way to do this?
18212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Re-append the device's id since we lost it when posting request to UI.
18222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (device_info.device.type == content::MEDIA_TAB_VIDEO_CAPTURE ||
18232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        device_info.device.type == content::MEDIA_TAB_AUDIO_CAPTURE) {
18245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      device_info.device.id = request->UIRequest()->tab_capture_device_id;
18252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Initialize the sample_rate and channel_layout here since for audio
18272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // mirroring, we don't go through EnumerateDevices where these are usually
18282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // initialized.
18292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (device_info.device.type == content::MEDIA_TAB_AUDIO_CAPTURE) {
18302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        const media::AudioParameters parameters =
18312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            audio_manager_->GetDefaultOutputStreamParameters();
18322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        int sample_rate = parameters.sample_rate();
18332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // If we weren't able to get the native sampling rate or the sample_rate
18342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // is outside the valid range for input devices set reasonable defaults.
18352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        if (sample_rate <= 0 || sample_rate > 96000)
18362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          sample_rate = 44100;
18372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
183858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        device_info.device.input.sample_rate = sample_rate;
183958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)        device_info.device.input.channel_layout = media::CHANNEL_LAYOUT_STEREO;
18402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      }
18412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
18422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (device_info.device.type == request->audio_type()) {
18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found_audio = true;
18455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    } else if (device_info.device.type == request->video_type()) {
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      found_video = true;
18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18488bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
18498bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // If this is request for a new MediaStream, a device is only opened once
18508bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // per render view. This is so that the permission to use a device can be
18518bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // revoked by a single call to StopStreamDevice regardless of how many
18528bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    // MediaStreams it is being used in.
18535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (request->request_type == MEDIA_GENERATE_STREAM) {
18548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      MediaRequestState state;
1855a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      if (FindExistingRequestedDeviceInfo(*request,
1856a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                          device_info.device,
18578bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                          &device_info,
18588bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)                                          &state)) {
18598bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        request->devices.push_back(device_info);
18608bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        request->SetState(device_info.device.type, state);
18618bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        DVLOG(1) << "HandleAccessRequestResponse - device already opened "
1862a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 << ", {label = " << label <<  "}"
1863a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                 << ", device_id = " << device_it->id << "}";
18648bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        continue;
18658bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)      }
18668bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    }
18678bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    device_info.session_id =
18688bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)        GetDeviceManager(device_info.device.type)->Open(device_info);
1869a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    TranslateDeviceIdToSourceId(request, &device_info.device);
18708bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    request->devices.push_back(device_info);
1871a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
18728bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    request->SetState(device_info.device.type, MEDIA_REQUEST_STATE_OPENING);
18738bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    DVLOG(1) << "HandleAccessRequestResponse - opening device "
18748bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)             << ", {label = " << label <<  "}"
1875a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)             << ", {device_id = " << device_info.device.id << "}"
18768bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)             << ", {session_id = " << device_info.session_id << "}";
18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check whether we've received all stream types requested.
188046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (!found_audio && IsAudioInputMediaType(request->audio_type())) {
18815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    request->SetState(request->audio_type(), MEDIA_REQUEST_STATE_ERROR);
18828bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    DVLOG(1) << "Set no audio found label " << label;
18838bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  }
18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (!found_video && IsVideoMediaType(request->video_type()))
18865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    request->SetState(request->video_type(), MEDIA_REQUEST_STATE_ERROR);
18878bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)
18888bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  if (RequestDone(*request))
18898bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)    HandleRequestDone(label, request);
18902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
18912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1892f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void MediaStreamManager::StopMediaStreamFromBrowser(const std::string& label) {
1893effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
18942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1895a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DeviceRequest* request = FindRequest(label);
1896a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  if (!request)
18972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
18982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1899f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  // Notify renderers that the devices in the stream will be stopped.
19000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  if (request->requester) {
1901f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    for (StreamDeviceInfoArray::iterator device_it = request->devices.begin();
1902f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)         device_it != request->devices.end(); ++device_it) {
1903f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)      request->requester->DeviceStopped(request->requesting_view_id,
1904f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                        label,
1905f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                                        *device_it);
1906f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    }
19070f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
19082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19098bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles)  CancelRequest(label);
19102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
19112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1912868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void MediaStreamManager::UseFakeUI(scoped_ptr<FakeMediaStreamUIProxy> fake_ui) {
1913effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
1914868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  use_fake_ui_ = true;
1915868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  fake_ui_ = fake_ui.Pass();
19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamManager::WillDestroyCurrentMessageLoop() {
1919a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  DVLOG(3) << "MediaStreamManager::WillDestroyCurrentMessageLoop()";
1920c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DCHECK_EQ(base::MessageLoop::current(), io_loop_);
19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(requests_.empty());
19225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (device_task_runner_) {
19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StopMonitoring();
19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    video_capture_manager_->Unregister();
19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    audio_input_device_manager_->Unregister();
19275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    device_task_runner_ = NULL;
19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  audio_input_device_manager_ = NULL;
19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  video_capture_manager_ = NULL;
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void MediaStreamManager::NotifyDevicesChanged(
19352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    MediaStreamType stream_type,
19362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const StreamDeviceInfoArray& devices) {
1937effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
19382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MediaObserver* media_observer =
19392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetContentClient()->browser()->GetMediaObserver();
19402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
19412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Map the devices to MediaStreamDevices.
19422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  MediaStreamDevices new_devices;
19432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (StreamDeviceInfoArray::const_iterator it = devices.begin();
19442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)       it != devices.end(); ++it) {
19452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    new_devices.push_back(it->device);
19462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
19472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
194846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  if (IsAudioInputMediaType(stream_type)) {
1949a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    MediaCaptureDevicesImpl::GetInstance()->OnAudioCaptureDevicesChanged(
1950a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        new_devices);
19510529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (media_observer)
19520529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      media_observer->OnAudioCaptureDevicesChanged();
19532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (IsVideoMediaType(stream_type)) {
1954a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    MediaCaptureDevicesImpl::GetInstance()->OnVideoCaptureDevicesChanged(
1955a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)        new_devices);
19560529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch    if (media_observer)
19570529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch      media_observer->OnVideoCaptureDevicesChanged();
19582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
19592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NOTREACHED();
19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MediaStreamManager::RequestDone(const DeviceRequest& request) const {
1964effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
196646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  const bool requested_audio = IsAudioInputMediaType(request.audio_type());
19675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const bool requested_video = IsVideoMediaType(request.video_type());
19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool audio_done =
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !requested_audio ||
19715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request.state(request.audio_type()) == MEDIA_REQUEST_STATE_DONE ||
19725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request.state(request.audio_type()) == MEDIA_REQUEST_STATE_ERROR;
19732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!audio_done)
19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool video_done =
19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !requested_video ||
19785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request.state(request.video_type()) == MEDIA_REQUEST_STATE_DONE ||
19795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      request.state(request.video_type()) == MEDIA_REQUEST_STATE_ERROR;
19802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!video_done)
19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaStreamProvider* MediaStreamManager::GetDeviceManager(
19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    MediaStreamType stream_type) {
19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsVideoMediaType(stream_type)) {
19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return video_capture_manager();
199046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  } else if (IsAudioInputMediaType(stream_type)) {
19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return audio_input_device_manager();
19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamManager::OnDevicesChanged(
19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::SystemMonitor::DeviceType device_type) {
1999effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: This method is only called in response to physical audio/video device
20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // changes (from the operating system).
20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MediaStreamType stream_type;
20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (device_type == base::SystemMonitor::DEVTYPE_AUDIO_CAPTURE) {
20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stream_type = MEDIA_DEVICE_AUDIO_CAPTURE;
20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (device_type == base::SystemMonitor::DEVTYPE_VIDEO_CAPTURE) {
20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stream_type = MEDIA_DEVICE_VIDEO_CAPTURE;
20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Uninteresting device change.
20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Always do enumeration even though some enumeration is in progress,
20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // because those enumeration commands could be sent before these devices
20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // change.
20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++active_enumeration_ref_count_[stream_type];
20172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GetDeviceManager(stream_type)->EnumerateDevices(stream_type);
20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2020effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid MediaStreamManager::OnMediaStreamUIWindowId(MediaStreamType video_type,
2021effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                                 StreamDeviceInfoArray devices,
2022effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                                 gfx::NativeViewId window_id) {
2023effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  DCHECK_CURRENTLY_ON(BrowserThread::IO);
2024effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (!window_id)
2025effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    return;
2026effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
2027effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  // Pass along for desktop capturing. Ignored for other stream types.
2028effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  if (video_type == MEDIA_DESKTOP_VIDEO_CAPTURE) {
2029effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    for (StreamDeviceInfoArray::iterator it = devices.begin();
2030effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch         it != devices.end();
2031effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch         ++it) {
2032effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      if (it->device.type == MEDIA_DESKTOP_VIDEO_CAPTURE) {
2033effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        video_capture_manager_->SetDesktopCaptureWindowId(it->session_id,
2034effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch                                                          window_id);
2035effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch        break;
2036effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch      }
2037effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch    }
2038effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch  }
2039effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}
2040effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch
20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace content
2042