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