media_stream_devices_controller.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
1a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard// Use of this source code is governed by a BSD-style license that can be
3a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard// found in the LICENSE file.
4a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard
5a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#include "chrome/browser/media/media_stream_devices_controller.h"
6a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard
7a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#include "base/command_line.h"
8a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#include "base/prefs/pref_service.h"
9a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#include "base/values.h"
10a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#include "chrome/browser/content_settings/content_settings_provider.h"
11a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#include "chrome/browser/content_settings/host_content_settings_map.h"
12a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#include "chrome/browser/content_settings/tab_specific_content_settings.h"
13a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#include "chrome/browser/media/media_capture_devices_dispatcher.h"
14a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#include "chrome/browser/media/media_stream_capture_indicator.h"
15a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#include "chrome/browser/prefs/scoped_user_pref_update.h"
16a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#include "chrome/browser/profiles/profile.h"
17a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#include "chrome/browser/ui/browser.h"
18a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#include "chrome/common/chrome_switches.h"
19a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#include "chrome/common/content_settings.h"
20a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#include "chrome/common/content_settings_pattern.h"
21a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#include "chrome/common/pref_names.h"
22a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#include "components/user_prefs/pref_registry_syncable.h"
23a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#include "content/public/browser/browser_thread.h"
24a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#include "content/public/common/media_stream_request.h"
25a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard
26a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#if defined(OS_CHROMEOS)
27a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#include "chrome/browser/chromeos/login/user_manager.h"
28a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#endif
29a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard
30a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellardusing content::BrowserThread;
31a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard
32a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellardnamespace {
33a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard
34a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellardbool HasAnyAvailableDevice() {
35a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  const content::MediaStreamDevices& audio_devices =
36a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard      MediaCaptureDevicesDispatcher::GetInstance()->GetAudioCaptureDevices();
37a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  const content::MediaStreamDevices& video_devices =
38a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard      MediaCaptureDevicesDispatcher::GetInstance()->GetVideoCaptureDevices();
39a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard
40a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  return !audio_devices.empty() || !video_devices.empty();
41a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard}
42a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard
43a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellardbool IsInKioskMode() {
44a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode))
45a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard    return true;
46a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard
47a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#if defined(OS_CHROMEOS)
48a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  const chromeos::UserManager* user_manager = chromeos::UserManager::Get();
49a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  return user_manager && user_manager->IsLoggedInAsKioskApp();
50a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#else
51a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  return false;
52a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard#endif
53a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard}
54a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard
55a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard}  // namespace
56a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard
57a75c6163e605f35b14f26930dd9227e4f337ec9eTom StellardMediaStreamDevicesController::MediaStreamDevicesController(
58a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard    content::WebContents* web_contents,
59a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard    const content::MediaStreamRequest& request,
60a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard    const content::MediaResponseCallback& callback)
61a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard    : web_contents_(web_contents),
62a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard      request_(request),
63a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard      callback_(callback),
64a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard      microphone_requested_(
65a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard          request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE),
66a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard      webcam_requested_(
67a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard          request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE) {
68a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  profile_ = Profile::FromBrowserContext(web_contents->GetBrowserContext());
691b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  content_settings_ = TabSpecificContentSettings::FromWebContents(web_contents);
70a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard
71a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  // Don't call GetDevicePolicy from the initializer list since the
729aacd5cc67ccbc3984bce6a0b40768a6cec2ec2dChristian König  // implementation depends on member variables.
739aacd5cc67ccbc3984bce6a0b40768a6cec2ec2dChristian König  if (microphone_requested_ &&
74a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard      GetDevicePolicy(prefs::kAudioCaptureAllowed,
75a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard                      prefs::kAudioCaptureAllowedUrls) == ALWAYS_DENY) {
7688a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    microphone_requested_ = false;
7788a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  }
7888a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer
7988a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  if (webcam_requested_ &&
8088a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer      GetDevicePolicy(prefs::kVideoCaptureAllowed,
8188a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer                      prefs::kVideoCaptureAllowedUrls) == ALWAYS_DENY) {
8288a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    webcam_requested_ = false;
8388a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  }
8488a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer}
8588a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer
8688a2e2388bfeee66cb6d873558431b0e0af7e316Michel DänzerMediaStreamDevicesController::~MediaStreamDevicesController() {}
8788a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer
8888a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer// static
8988a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzervoid MediaStreamDevicesController::RegisterUserPrefs(
9088a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    user_prefs::PrefRegistrySyncable* prefs) {
9188a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  prefs->RegisterBooleanPref(prefs::kVideoCaptureAllowed,
9288a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer                             true,
9388a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
9488a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  prefs->RegisterBooleanPref(prefs::kAudioCaptureAllowed,
9588a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer                             true,
9688a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer                             user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
9788a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  prefs->RegisterListPref(prefs::kVideoCaptureAllowedUrls,
9888a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer                          user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
9988a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  prefs->RegisterListPref(prefs::kAudioCaptureAllowedUrls,
10088a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer                          user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
10188a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer}
10288a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer
10388a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer
10488a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzerbool MediaStreamDevicesController::DismissInfoBarAndTakeActionOnSettings() {
10588a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  // If this is a no UI check for policies only go straight to accept - policy
10688a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  // check will be done automatically on the way.
10788a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  if (request_.request_type == content::MEDIA_OPEN_DEVICE) {
10888a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    Accept(false);
10988a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    return true;
11088a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  }
11188a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer
11288a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  // Tab capture is allowed for extensions only and infobar is not shown for
11388a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  // extensions.
11488a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  if (request_.audio_type == content::MEDIA_TAB_AUDIO_CAPTURE ||
11588a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer      request_.video_type == content::MEDIA_TAB_VIDEO_CAPTURE) {
11688a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    Deny(false);
11788a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    return true;
11888a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  }
11988a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer
12088a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  // Deny the request if the security origin is empty, this happens with
12188a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  // file access without |--allow-file-access-from-files| flag.
12288a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  if (request_.security_origin.is_empty()) {
12388a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    Deny(false);
12488a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    return true;
12588a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  }
12688a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer
12788a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  // Deny the request if there is no device attached to the OS.
12888a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  if (!HasAnyAvailableDevice()) {
12988a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    Deny(false);
13088a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    return true;
13188a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  }
13288a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer
13388a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  // Check if any allow exception has been made for this request.
13488a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  if (IsRequestAllowedByDefault()) {
13588a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    Accept(false);
13688a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    return true;
13788a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  }
13888a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer
13988a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  // Check if any block exception has been made for this request.
14088a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  if (IsRequestBlockedByDefault()) {
14188a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    Deny(false);
14288a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    return true;
14388a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  }
14488a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer
14588a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  // Check if the media default setting is set to block.
14688a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  if (IsDefaultMediaAccessBlocked()) {
14788a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    Deny(false);
14888a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    return true;
14988a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  }
15088a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer
15188a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  // Show the infobar.
15288a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  return false;
15388a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer}
15488a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer
15588a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzerconst std::string& MediaStreamDevicesController::GetSecurityOriginSpec() const {
15688a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  return request_.security_origin.spec();
15788a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer}
15888a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer
15988a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzervoid MediaStreamDevicesController::Accept(bool update_content_setting) {
16088a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  if (content_settings_)
16188a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    content_settings_->OnMediaStreamAllowed();
16288a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer
16388a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  // Get the default devices for the request.
16488a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  content::MediaStreamDevices devices;
16588a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  if (microphone_requested_ || webcam_requested_) {
16688a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    switch (request_.request_type) {
16788a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer      case content::MEDIA_OPEN_DEVICE:
16888a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer        // For open device request pick the desired device or fall back to the
16988a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer        // first available of the given type.
17088a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer        MediaCaptureDevicesDispatcher::GetInstance()->GetRequestedDevice(
17188a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer            request_.requested_device_id,
17288a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer            microphone_requested_,
17388a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer            webcam_requested_,
17488a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer            &devices);
17588a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer        break;
17688a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer      case content::MEDIA_DEVICE_ACCESS:
17788a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer      case content::MEDIA_GENERATE_STREAM:
178a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard      case content::MEDIA_ENUMERATE_DEVICES:
179a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard        // Get the default devices for the request.
180a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard        MediaCaptureDevicesDispatcher::GetInstance()->
181a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard            GetDefaultDevicesForProfile(profile_,
182a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard                                        microphone_requested_,
183a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard                                        webcam_requested_,
184a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard                                        &devices);
185a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard        break;
186a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard    }
187a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard
188a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard    if (update_content_setting && IsSchemeSecure() && !devices.empty())
189a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard      SetPermission(true);
190a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  }
191a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard
192a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  scoped_ptr<content::MediaStreamUI> ui;
193a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  if (!devices.empty()) {
19488a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    ui = MediaCaptureDevicesDispatcher::GetInstance()->
195a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard        GetMediaStreamCaptureIndicator()->RegisterMediaStream(
196a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard            web_contents_, devices);
197a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  }
198a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  callback_.Run(devices, ui.Pass());
199a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard}
200a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard
201a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellardvoid MediaStreamDevicesController::Deny(bool update_content_setting) {
202a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  // TODO(markusheintz): Replace CONTENT_SETTINGS_TYPE_MEDIA_STREAM with the
203a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  // appropriate new CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC and
204a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA.
205a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  if (content_settings_) {
206a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard    content_settings_->OnContentBlocked(CONTENT_SETTINGS_TYPE_MEDIASTREAM,
207a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard                                        std::string());
208a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  }
209a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard
210a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  if (update_content_setting)
211a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard    SetPermission(false);
212a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard
213a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  callback_.Run(content::MediaStreamDevices(),
214a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard                scoped_ptr<content::MediaStreamUI>());
215a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard}
216a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard
217a75c6163e605f35b14f26930dd9227e4f337ec9eTom StellardMediaStreamDevicesController::DevicePolicy
218a75c6163e605f35b14f26930dd9227e4f337ec9eTom StellardMediaStreamDevicesController::GetDevicePolicy(
219a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard    const char* policy_name,
220a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard    const char* whitelist_policy_name) const {
221a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
222a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard
223a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  // If the security origin policy matches a value in the whitelist, allow it.
224fe41287ffa8cb35421cadfb16d4cc27c5fcb8b76Christian König  // Otherwise, check the |policy_name| master switch for the default behavior.
22588a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer
226a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  PrefService* prefs = profile_->GetPrefs();
227a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard
22888a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  // TODO(tommi): Remove the kiosk mode check when the whitelist below
2297446a0407d4e61a826385c11ed6c401837baf095Michel Dänzer  // is visible in the media exceptions UI.
23088a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  // See discussion here: https://codereview.chromium.org/15738004/
23188a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer  if (IsInKioskMode()) {
23288a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    const base::ListValue* list = prefs->GetList(whitelist_policy_name);
23388a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    std::string value;
23488a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer    for (size_t i = 0; i < list->GetSize(); ++i) {
23588a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer      if (list->GetString(i, &value)) {
23688a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer        ContentSettingsPattern pattern =
23788a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer            ContentSettingsPattern::FromString(value);
2389aacd5cc67ccbc3984bce6a0b40768a6cec2ec2dChristian König        if (pattern == ContentSettingsPattern::Wildcard()) {
23988a2e2388bfeee66cb6d873558431b0e0af7e316Michel Dänzer          DLOG(WARNING) << "Ignoring wildcard URL pattern: " << value;
240a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard          continue;
2419aacd5cc67ccbc3984bce6a0b40768a6cec2ec2dChristian König        }
242a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard        DLOG_IF(ERROR, !pattern.IsValid()) << "Invalid URL pattern: " << value;
243a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard        if (pattern.IsValid() && pattern.Matches(request_.security_origin))
244a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard          return ALWAYS_ALLOW;
245a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard      }
246a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard    }
247a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  }
248fe41287ffa8cb35421cadfb16d4cc27c5fcb8b76Christian König
249a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  // If a match was not found, check if audio capture is otherwise disallowed
250a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  // or if the user should be prompted.  Setting the policy value to "true"
2519aacd5cc67ccbc3984bce6a0b40768a6cec2ec2dChristian König  // is equal to not setting it at all, so from hereon out, we will return
252a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  // either POLICY_NOT_SET (prompt) or ALWAYS_DENY (no prompt, no access).
253a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  if (!prefs->GetBoolean(policy_name))
254a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard    return ALWAYS_DENY;
255a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard
256a75c6163e605f35b14f26930dd9227e4f337ec9eTom Stellard  return POLICY_NOT_SET;
2571b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer}
2581b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer
2591b11395a36a44a902cfb3e1783758544662df73fMichel Dänzerbool MediaStreamDevicesController::IsRequestAllowedByDefault() const {
2601b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  // The request from internal objects like chrome://URLs is always allowed.
2611b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  if (ShouldAlwaysAllowOrigin())
2621b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer    return true;
2631b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer
2641b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  struct {
2651b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer    bool has_capability;
2661b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer    const char* policy_name;
2671b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer    const char* list_policy_name;
2681b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer    ContentSettingsType settings_type;
2691b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  } device_checks[] = {
2701b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer    { microphone_requested_, prefs::kAudioCaptureAllowed,
2711b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer      prefs::kAudioCaptureAllowedUrls, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC },
2721b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer    { webcam_requested_, prefs::kVideoCaptureAllowed,
2731b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer      prefs::kVideoCaptureAllowedUrls,
2741b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer      CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA },
2751b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  };
2761b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer
2771b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(device_checks); ++i) {
2781b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer    if (!device_checks[i].has_capability)
2791b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer      continue;
2801b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer
2811b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer    DevicePolicy policy = GetDevicePolicy(device_checks[i].policy_name,
2821b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer                                          device_checks[i].list_policy_name);
2839aacd5cc67ccbc3984bce6a0b40768a6cec2ec2dChristian König    if (policy == ALWAYS_DENY ||
2849aacd5cc67ccbc3984bce6a0b40768a6cec2ec2dChristian König        (policy == POLICY_NOT_SET &&
2851b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer         profile_->GetHostContentSettingsMap()->GetContentSetting(
2861b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer            request_.security_origin, request_.security_origin,
2871b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer            device_checks[i].settings_type, NO_RESOURCE_IDENTIFIER) !=
2881b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer         CONTENT_SETTING_ALLOW)) {
2891b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer      return false;
2901b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer    }
2911b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer    // If we get here, then either policy is set to ALWAYS_ALLOW or the content
2921b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer    // settings allow the request by default.
2931b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  }
2941b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer
2951b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  return true;
2961b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer}
2971b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer
2981b11395a36a44a902cfb3e1783758544662df73fMichel Dänzerbool MediaStreamDevicesController::IsRequestBlockedByDefault() const {
2991b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  if (microphone_requested_ &&
3001b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer      profile_->GetHostContentSettingsMap()->GetContentSetting(
3011b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer          request_.security_origin,
3021b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer          request_.security_origin,
3031b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer          CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
3041b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer          NO_RESOURCE_IDENTIFIER) != CONTENT_SETTING_BLOCK) {
3051b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer    return false;
3061b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  }
3071b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer
3081b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  if (webcam_requested_ &&
3091b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer      profile_->GetHostContentSettingsMap()->GetContentSetting(
3101b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer          request_.security_origin,
3111b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer          request_.security_origin,
3121b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer          CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
3131b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer          NO_RESOURCE_IDENTIFIER) != CONTENT_SETTING_BLOCK) {
3141b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer    return false;
3151b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  }
3161b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer
3171b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  return true;
3181b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer}
3191b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer
3201b11395a36a44a902cfb3e1783758544662df73fMichel Dänzerbool MediaStreamDevicesController::IsDefaultMediaAccessBlocked() const {
3211b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3221b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  // TODO(markusheintz): Replace CONTENT_SETTINGS_TYPE_MEDIA_STREAM with the
3231b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  // appropriate new CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC and
3241b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA.
3251b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  ContentSetting current_setting =
3261b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer      profile_->GetHostContentSettingsMap()->GetDefaultContentSetting(
3279aacd5cc67ccbc3984bce6a0b40768a6cec2ec2dChristian König          CONTENT_SETTINGS_TYPE_MEDIASTREAM, NULL);
3281b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  return (current_setting == CONTENT_SETTING_BLOCK);
3291b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer}
3301b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer
3311b11395a36a44a902cfb3e1783758544662df73fMichel Dänzerbool MediaStreamDevicesController::IsSchemeSecure() const {
3321b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  return (request_.security_origin.SchemeIsSecure());
3331b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer}
3341b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer
3351b11395a36a44a902cfb3e1783758544662df73fMichel Dänzerbool MediaStreamDevicesController::ShouldAlwaysAllowOrigin() const {
3361b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  // TODO(markusheintz): Replace CONTENT_SETTINGS_TYPE_MEDIA_STREAM with the
3371b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  // appropriate new CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC and
3381b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  // CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA.
3391b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  return profile_->GetHostContentSettingsMap()->ShouldAllowAllContent(
3401b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer      request_.security_origin, request_.security_origin,
3411b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer      CONTENT_SETTINGS_TYPE_MEDIASTREAM);
3421b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer}
3431b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer
3441b11395a36a44a902cfb3e1783758544662df73fMichel Dänzervoid MediaStreamDevicesController::SetPermission(bool allowed) const {
3451b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3461b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer#if defined(OS_ANDROID)
3471b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  // We do not support sticky operations on Android yet.
3481b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  return;
3491b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer#endif
3501b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  ContentSettingsPattern primary_pattern =
3511b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer      ContentSettingsPattern::FromURLNoWildcard(request_.security_origin);
3521b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  // Check the pattern is valid or not. When the request is from a file access,
3531b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  // no exception will be made.
3541b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  if (!primary_pattern.IsValid())
3551b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer    return;
3561b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer
3571b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  ContentSetting content_setting = allowed ?
3581b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer      CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
3591b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  if (microphone_requested_) {
3601b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer      profile_->GetHostContentSettingsMap()->SetContentSetting(
3619aacd5cc67ccbc3984bce6a0b40768a6cec2ec2dChristian König        primary_pattern,
3629aacd5cc67ccbc3984bce6a0b40768a6cec2ec2dChristian König        ContentSettingsPattern::Wildcard(),
3631b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer        CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
3641b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer        std::string(),
3651b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer        content_setting);
3661b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  }
3671b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  if (webcam_requested_) {
3681b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer    profile_->GetHostContentSettingsMap()->SetContentSetting(
3691b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer        primary_pattern,
3709aacd5cc67ccbc3984bce6a0b40768a6cec2ec2dChristian König        ContentSettingsPattern::Wildcard(),
3719aacd5cc67ccbc3984bce6a0b40768a6cec2ec2dChristian König        CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
3721b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer        std::string(),
3731b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer        content_setting);
3741b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer  }
3751b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer}
3761b11395a36a44a902cfb3e1783758544662df73fMichel Dänzer