media_stream_devices_controller.cc revision 5821806d5e7f356e8fa4b058a389a808ea183019
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 "chrome/browser/media/media_stream_devices_controller.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/content_settings/content_settings_provider.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/content_settings/host_content_settings_map.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/tab_capture/tab_capture_registry.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/api/tab_capture/tab_capture_registry_factory.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/prefs/scoped_user_pref_update.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/browser.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/content_settings.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/common/media_stream_request.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A predicate that checks if a StreamDeviceInfo object has the same device 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// name as the device name specified at construction. 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DeviceNameEquals { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit DeviceNameEquals(const std::string& device_name) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : device_name_(device_name) { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool operator() (const content::MediaStreamDevice& device) { 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return device.name == device_name_; 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string device_name_; 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kAudioKey[] = "audio"; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kVideoKey[] = "video"; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaStreamDevicesController::MediaStreamDevicesController( 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::MediaStreamRequest* request, 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::MediaResponseCallback& callback) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : has_audio_(false), 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_video_(false), 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_(profile), 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_(*request), 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_(callback) { 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (content::MediaStreamDeviceMap::const_iterator it = 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.devices.begin(); 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != request_.devices.end(); ++it) { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (content::IsAudioMediaType(it->first)) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_audio_ |= !it->second.empty(); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (content::IsVideoMediaType(it->first)) { 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) has_video_ |= !it->second.empty(); 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaStreamDevicesController::~MediaStreamDevicesController() {} 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MediaStreamDevicesController::DismissInfoBarAndTakeActionOnSettings() { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For tab media requests, we need to make sure the request came from the 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // extension API, so we check the registry here. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::MediaStreamDeviceMap::const_iterator tab_video = 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.devices.find(content::MEDIA_TAB_VIDEO_CAPTURE); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::MediaStreamDeviceMap::const_iterator tab_audio = 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.devices.find(content::MEDIA_TAB_AUDIO_CAPTURE); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tab_video != request_.devices.end() || 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tab_audio != request_.devices.end()) { 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::TabCaptureRegistry* registry = 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::TabCaptureRegistryFactory::GetForProfile(profile_); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!tab_audio->second.empty() || !tab_video->second.empty()); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string audio_device_id; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string video_device_id; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!tab_audio->second.empty()) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_device_id = tab_audio->second[0].device_id; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!tab_video->second.empty()) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) video_device_id = tab_video->second[0].device_id; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!registry->VerifyRequest(!video_device_id.empty() ? 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) video_device_id : audio_device_id)) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Deny(); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Accept(audio_device_id, video_device_id, false); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Deny the request if the security origin is empty, this happens with 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // file access without |--allow-file-access-from-files| flag. 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (request_.security_origin.is_empty()) { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Deny(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Deny the request and don't show the infobar if there is no devices. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!has_audio_ && !has_video_) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(xians): We should detect this in a early state, and post a callback 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to tell the users that no device is available. Remove the code and add 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // a DCHECK when this is done. 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Deny(); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Checks if any exception has been made for this request, get the "always 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // allowed" devices if they are available. 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string audio, video; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GetAlwaysAllowedDevices(&audio, &video); 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((has_audio_ && audio.empty()) || (has_video_ && video.empty())) { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If there is no "always allowed" device for the origin, or the device is 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // not available in the device lists, Check the default setting to see if 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the user has blocked the access to the media device. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsMediaDeviceBlocked()) { 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Deny(); 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Show the infobar. 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Dismiss the infobar by selecting the "always allowed" devices. 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Accept(audio, video, false); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)content::MediaStreamDevices 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaStreamDevicesController::GetAudioDevices() const { 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::MediaStreamDevices all_audio_devices; 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_audio_) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FindSubsetOfDevices(&content::IsAudioMediaType, &all_audio_devices); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return all_audio_devices; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)content::MediaStreamDevices 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaStreamDevicesController::GetVideoDevices() const { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::MediaStreamDevices all_video_devices; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_video_) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FindSubsetOfDevices(&content::IsVideoMediaType, &all_video_devices); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return all_video_devices; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const std::string& MediaStreamDevicesController::GetSecurityOriginSpec() const { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return request_.security_origin.spec(); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MediaStreamDevicesController::IsSafeToAlwaysAllowAudio() const { 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return IsSafeToAlwaysAllow( 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &content::IsAudioMediaType, content::MEDIA_DEVICE_AUDIO_CAPTURE); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MediaStreamDevicesController::IsSafeToAlwaysAllowVideo() const { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return IsSafeToAlwaysAllow( 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &content::IsVideoMediaType, content::MEDIA_DEVICE_VIDEO_CAPTURE); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamDevicesController::Accept(const std::string& audio_id, 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& video_id, 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool always_allow) { 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::MediaStreamDevices devices; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string audio_device_name, video_device_name; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::MediaStreamDevice* const audio_device = 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FindFirstDeviceWithIdInSubset(&content::IsAudioMediaType, audio_id); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (audio_device) { 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (audio_device->type != content::MEDIA_DEVICE_AUDIO_CAPTURE) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) always_allow = false; // Override for virtual audio device type. 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) devices.push_back(*audio_device); 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_device_name = audio_device->name; 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::MediaStreamDevice* const video_device = 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FindFirstDeviceWithIdInSubset(&content::IsVideoMediaType, video_id); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (video_device) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (video_device->type != content::MEDIA_DEVICE_VIDEO_CAPTURE) 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) always_allow = false; // Override for virtual video device type. 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) devices.push_back(*video_device); 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) video_device_name = video_device->name; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!devices.empty()); 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (always_allow) 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) AlwaysAllowOriginAndDevices(audio_device_name, video_device_name); 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_.Run(devices); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamDevicesController::Deny() { 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) callback_.Run(content::MediaStreamDevices()); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MediaStreamDevicesController::IsSafeToAlwaysAllow( 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilterByDeviceTypeFunc is_included, 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::MediaStreamDeviceType device_type) const { 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(device_type == content::MEDIA_DEVICE_AUDIO_CAPTURE || 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) device_type == content::MEDIA_DEVICE_VIDEO_CAPTURE); 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!request_.security_origin.SchemeIsSecure()) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If non-physical devices are available for the choosing, then it's not safe. 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool safe_devices_found = false; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (content::MediaStreamDeviceMap::const_iterator it = 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.devices.begin(); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != request_.devices.end(); ++it) { 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it->first != device_type && is_included(it->first)) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) safe_devices_found = true; 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return safe_devices_found; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MediaStreamDevicesController::ShouldAlwaysAllowOrigin() { 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return profile_->GetHostContentSettingsMap()->ShouldAllowAllContent( 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.security_origin, request_.security_origin, 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CONTENT_SETTINGS_TYPE_MEDIASTREAM); 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool MediaStreamDevicesController::IsMediaDeviceBlocked() { 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ContentSetting current_setting = 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_->GetHostContentSettingsMap()->GetDefaultContentSetting( 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CONTENT_SETTINGS_TYPE_MEDIASTREAM, NULL); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (current_setting == CONTENT_SETTING_BLOCK); 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamDevicesController::AlwaysAllowOriginAndDevices( 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& audio_device, 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& video_device) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!audio_device.empty() || !video_device.empty()); 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DictionaryValue* dictionary_value = new DictionaryValue(); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!audio_device.empty()) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dictionary_value->SetString(kAudioKey, audio_device); 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!video_device.empty()) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dictionary_value->SetString(kVideoKey, video_device); 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ContentSettingsPattern primary_pattern = 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ContentSettingsPattern::FromURLNoWildcard(request_.security_origin); 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_->GetHostContentSettingsMap()->SetWebsiteSetting( 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) primary_pattern, 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ContentSettingsPattern::Wildcard(), 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CONTENT_SETTINGS_TYPE_MEDIASTREAM, 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NO_RESOURCE_IDENTIFIER, 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dictionary_value); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamDevicesController::GetAlwaysAllowedDevices( 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* audio_id, std::string* video_id) { 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(audio_id->empty()); 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(video_id->empty()); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the request is from internal objects like chrome://URLs, use the first 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // devices on the lists. 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ShouldAlwaysAllowOrigin()) { 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_audio_) 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *audio_id = GetFirstDeviceId(content::MEDIA_DEVICE_AUDIO_CAPTURE); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_video_) 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *video_id = GetFirstDeviceId(content::MEDIA_DEVICE_VIDEO_CAPTURE); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // "Always allowed" option is only available for secure connection. 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!request_.security_origin.SchemeIsSecure()) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Checks the media exceptions to get the "always allowed" devices. 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<Value> value( 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_->GetHostContentSettingsMap()->GetWebsiteSetting( 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.security_origin, 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.security_origin, 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CONTENT_SETTINGS_TYPE_MEDIASTREAM, 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NO_RESOURCE_IDENTIFIER, 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL)); 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value.get()) { 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const DictionaryValue* value_dict = NULL; 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!value->GetAsDictionary(&value_dict) || value_dict->empty()) 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string audio_name, video_name; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value_dict->GetString(kAudioKey, &audio_name); 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value_dict->GetString(kVideoKey, &video_name); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_audio_ && !audio_name.empty()) 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *audio_id = GetDeviceIdByName(content::MEDIA_DEVICE_AUDIO_CAPTURE, 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) audio_name); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (has_video_ && !video_name.empty()) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *video_id = GetDeviceIdByName(content::MEDIA_DEVICE_VIDEO_CAPTURE, 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) video_name); 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string MediaStreamDevicesController::GetDeviceIdByName( 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::MediaStreamDeviceType type, 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& name) { 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::MediaStreamDeviceMap::const_iterator device_it = 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.devices.find(type); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (device_it != request_.devices.end()) { 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::MediaStreamDevices::const_iterator it = std::find_if( 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) device_it->second.begin(), device_it->second.end(), 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeviceNameEquals(name)); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (it != device_it->second.end()) 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return it->device_id; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Device is not available, return an empty string. 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string MediaStreamDevicesController::GetFirstDeviceId( 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::MediaStreamDeviceType type) { 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::MediaStreamDeviceMap::const_iterator device_it = 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.devices.find(type); 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (device_it != request_.devices.end()) 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return device_it->second.begin()->device_id; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(); 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MediaStreamDevicesController::FindSubsetOfDevices( 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilterByDeviceTypeFunc is_included, 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::MediaStreamDevices* out) const { 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (content::MediaStreamDeviceMap::const_iterator it = 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.devices.begin(); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != request_.devices.end(); ++it) { 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_included(it->first)) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out->insert(out->end(), it->second.begin(), it->second.end()); 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const content::MediaStreamDevice* 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)MediaStreamDevicesController::FindFirstDeviceWithIdInSubset( 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FilterByDeviceTypeFunc is_included, 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& device_id) const { 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (content::MediaStreamDeviceMap::const_iterator it = 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) request_.devices.begin(); 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != request_.devices.end(); ++it) { 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_included(it->first)) continue; 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (content::MediaStreamDevices::const_iterator device_it = 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it->second.begin(); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) device_it != it->second.end(); ++device_it) { 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::MediaStreamDevice& candidate = *device_it; 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (candidate.device_id == device_id) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return &candidate; 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 364