Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1128)

Unified Diff: chrome/browser/media/media_stream_devices_controller.cc

Issue 10537099: add "always allow" option to the mediastream infobar and allow user to allow/not allow acces to devi (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: use only content settings, added a device controller, addressed all the comments Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/media/media_stream_devices_controller.cc
diff --git a/chrome/browser/media/media_stream_devices_controller.cc b/chrome/browser/media/media_stream_devices_controller.cc
new file mode 100644
index 0000000000000000000000000000000000000000..54c291a822902186f755b75cc8c238182052c399
--- /dev/null
+++ b/chrome/browser/media/media_stream_devices_controller.cc
@@ -0,0 +1,282 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/media/media_stream_devices_controller.h"
+
+#include "base/values.h"
+#include "chrome/browser/content_settings/content_settings_provider.h"
+#include "chrome/browser/content_settings/host_content_settings_map.h"
+#include "chrome/browser/prefs/scoped_user_pref_update.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/common/content_settings.h"
+#include "chrome/common/pref_names.h"
+
+using content::BrowserThread;
+
+namespace {
+
+// A predicate that checks if a StreamDeviceInfo object has the same ID as the
+// device ID specified at construction.
+class DeviceIdEquals {
+ public:
+ explicit DeviceIdEquals(const std::string& device_id)
+ : device_id_(device_id) {
+ }
+
+ bool operator() (const content::MediaStreamDevice& device) {
+ return device.device_id == device_id_;
+ }
+
+ private:
+ std::string device_id_;
+};
+
+// A predicate that checks if a StreamDeviceInfo object has the same device
+// name as the device name specified at construction.
+class DeviceNameEquals {
+ public:
+ explicit DeviceNameEquals(const std::string& device_name)
+ : device_name_(device_name) {
+ }
+
+ bool operator() (const content::MediaStreamDevice& device) {
+ return device.name == device_name_;
+ }
+
+ private:
+ std::string device_name_;
+};
+
+} // namespace
+
+static const char kAudioKey[] = "audio";
Ivan Korotkov 2012/06/14 17:14:12 This can be moved to the anonymous namespace inste
no longer working on chromium 2012/06/15 16:52:07 Done.
Bernhard Bauer 2012/06/18 17:38:14 Sorry I'm late here, but it actually doesn't matte
no longer working on chromium 2012/06/19 12:23:16 :) thanks. It is more like a matter of taste. Both
+static const char kVideoKey[] = "video";
+
+MediaStreamDevicesController::MediaStreamDevicesController(
+ Profile* profile,
+ const content::MediaStreamRequest* request,
+ const content::MediaResponseCallback& callback)
+ : profile_(profile),
+ request_(request),
+ callback_(callback) {
+ DCHECK(request_);
+ DCHECK(!request_->security_origin.is_empty());
+ has_audio_ = request_->devices.count(
+ content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) != 0;
+ has_video_ = request_->devices.count(
+ content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) != 0;
+}
+
+MediaStreamDevicesController::~MediaStreamDevicesController() {}
+
+bool MediaStreamDevicesController::DismissInfoBarAndTakeActionOnSettings() {
+ DCHECK(has_audio_ || has_video_);
+ // If the request is from internal objects like chrome://URLs, use the first
+ // devices on the lists.
+ if (IsInternalContent()) {
+ std::string audio, video;
+ if (has_audio_) {
+ audio = GetFirstDevice(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE);
+ if (audio.empty())
+ return false;
+ }
+ if (has_video_) {
+ video = GetFirstDevice(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE);
+ if (video.empty())
+ return false;
+ }
+
+ Accept(audio, video, false);
+ return true;
+ }
+
+ // If the user has blocked the access to the media device in content
+ // settings, deny the request without showing the infobar.
+ if (IsMediaDeviceBlocked()){
+ Deny();
+ return true;
+ }
+
+ // If there are "always allowed" devices for the request, accept the request
+ // without showing the infobar.
+ std::string audio, video;
+ GetAlwaysAllowedDevices(&audio, &video);
+ // If there is no "always allowed" device for the origin, or the device is
+ // not available in the device lists, force showing the infobar.
+ if ((has_audio_ && audio.empty()) || (has_video_ && video.empty()))
+ return false;
+
+ Accept(audio, video, false);
+ return true;
+}
+
+content::MediaStreamDevices
+ MediaStreamDevicesController::GetAudioDevices() const {
Bernhard Bauer 2012/06/18 17:38:14 I think we don't indent the method name if we have
no longer working on chromium 2012/06/19 12:23:16 Done.
+ if (!has_audio_)
+ return content::MediaStreamDevices();
+
+ content::MediaStreamDeviceMap::const_iterator it =
+ request_->devices.find(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE);
+ DCHECK(it != request_->devices.end());
+ return it->second;
+}
+
+content::MediaStreamDevices
+ MediaStreamDevicesController::GetVideoDevices() const {
+ if (!has_video_)
+ return content::MediaStreamDevices();
+
+ content::MediaStreamDeviceMap::const_iterator it =
+ request_->devices.find(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE);
+ DCHECK(it != request_->devices.end());
+ return it->second;
+}
+
+const GURL& MediaStreamDevicesController::GetSecurityOrigin() const {
+ return request_->security_origin;
+}
+
+void MediaStreamDevicesController::Accept(const std::string& audio_id,
+ const std::string& video_id,
+ bool always_allow) {
+ content::MediaStreamDevices devices;
+ std::string audio_device, video_device;
+ if (has_audio_) {
+ AddDeviceWithId(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE,
+ audio_id, &devices, &audio_device);
+ }
+ if (has_video_) {
+ AddDeviceWithId(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE,
+ video_id, &devices, &video_device);
+ }
+ DCHECK(!devices.empty());
+
+ if (always_allow)
+ AlwaysAllowOriginAndDevices(audio_device, video_device);
+
+ callback_.Run(devices);
+}
+
+void MediaStreamDevicesController::Deny() {
+ callback_.Run(content::MediaStreamDevices());
+}
+
+void MediaStreamDevicesController::AddDeviceWithId(
+ content::MediaStreamDeviceType type,
+ const std::string& id,
+ content::MediaStreamDevices* devices,
+ std::string* device_name) {
+ DCHECK(devices);
+ content::MediaStreamDeviceMap::const_iterator device_it =
+ request_->devices.find(type);
+ if (device_it != request_->devices.end()) {
Bernhard Bauer 2012/06/18 17:38:14 You could negative the condition and early-return.
no longer working on chromium 2012/06/19 12:23:16 Done.
+ content::MediaStreamDevices::const_iterator it = std::find_if(
+ device_it->second.begin(), device_it->second.end(), DeviceIdEquals(id));
+ if (it != device_it->second.end()) {
+ devices->push_back(*it);
+ *device_name = it->name;
+ }
+ }
+}
+
+bool MediaStreamDevicesController::IsInternalContent() {
Ivan Korotkov 2012/06/14 17:14:12 Please rename to something like IsAutoAllowed/Shou
no longer working on chromium 2012/06/15 16:52:07 Done.
+ return profile_->GetHostContentSettingsMap()->ShouldAllowAllContent(
+ request_->security_origin, request_->security_origin,
+ CONTENT_SETTINGS_TYPE_MEDIASTREAM);
+}
+
+bool MediaStreamDevicesController::IsMediaDeviceBlocked() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ ContentSetting current_setting =
+ profile_->GetHostContentSettingsMap()->GetDefaultContentSetting(
+ CONTENT_SETTINGS_TYPE_MEDIASTREAM, NULL);
+ return (current_setting == CONTENT_SETTING_BLOCK);
+}
+
+void MediaStreamDevicesController::AlwaysAllowOriginAndDevices(
+ const std::string& audio_device,
+ const std::string& video_device) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(!audio_device.empty() || !video_device.empty());
+ DictionaryValue* dictionary_value = new DictionaryValue();
+ if (!audio_device.empty()) {
Bernhard Bauer 2012/06/18 17:38:14 You might want to leave out the braces. Personally
no longer working on chromium 2012/06/19 12:23:16 Done.
+ dictionary_value->SetString(kAudioKey, audio_device);
+ }
+ if (!video_device.empty()) {
+ dictionary_value->SetString(kVideoKey, video_device);
+ }
+
+ ContentSettingsPattern primary_pattern =
+ ContentSettingsPattern::FromURLNoWildcard(request_->security_origin);
+ profile_->GetHostContentSettingsMap()->SetWebsiteSetting(
+ primary_pattern,
+ ContentSettingsPattern::Wildcard(),
+ CONTENT_SETTINGS_TYPE_MEDIASTREAM,
+ NO_RESOURCE_IDENTIFIER,
+ dictionary_value);
+}
+
+void MediaStreamDevicesController::GetAlwaysAllowedDevices(
+ std::string* audio_id, std::string* video_id) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(audio_id->empty());
+ DCHECK(video_id->empty());
+ content_settings::SettingInfo info;
+ scoped_ptr<Value> value(
+ profile_->GetHostContentSettingsMap()->GetWebsiteSetting(
+ request_->security_origin,
+ request_->security_origin,
+ CONTENT_SETTINGS_TYPE_MEDIASTREAM,
+ NO_RESOURCE_IDENTIFIER,
+ &info));
+ if (!value.get() || !value->IsType(Value::TYPE_DICTIONARY))
Bernhard Bauer 2012/06/18 17:38:14 Add a NOTREACHED() if we get an unexpected type ba
no longer working on chromium 2012/06/19 12:23:16 We can't put a NOTREACHED() here, if it can't find
+ return;
+
+ DictionaryValue* value_dict = static_cast<DictionaryValue*>(value.get());
Ivan Korotkov 2012/06/14 17:14:12 This can be made const
no longer working on chromium 2012/06/15 16:52:07 Done.
+ if (value_dict->empty())
Bernhard Bauer 2012/06/18 17:38:14 This isn't reeaaally necessary. If the dictionary
no longer working on chromium 2012/06/19 12:23:16 I was thinking about adding a DCHECK here, but not
Bernhard Bauer 2012/06/19 14:33:34 The easiest thing would be to do nothing at all. T
+ return;
+
+ std::string audio_name, video_name;
+ value_dict->GetString(kAudioKey, &audio_name);
+ value_dict->GetString(kVideoKey, &video_name);
+
+ if (!audio_name.empty()) {
+ *audio_id = GetDeviceIdByName(
+ content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE, audio_name);
+ }
+ if (!video_name.empty()) {
+ *video_id = GetDeviceIdByName(
+ content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE, video_name);
+ }
+
+ return;
+}
+
+std::string MediaStreamDevicesController::GetDeviceIdByName(
+ content::MediaStreamDeviceType type,
+ const std::string& name) {
+ content::MediaStreamDeviceMap::const_iterator device_it =
+ request_->devices.find(type);
+ if (device_it != request_->devices.end()) {
+ content::MediaStreamDevices::const_iterator it = std::find_if(
+ device_it->second.begin(), device_it->second.end(),
+ DeviceNameEquals(name));
+ if (it != device_it->second.end())
+ return it->device_id;
+ }
+
+ // Device is not available, return an empty string.
+ return std::string();
+}
+
+std::string MediaStreamDevicesController::GetFirstDevice(
Bernhard Bauer 2012/06/18 17:38:14 I think this returns a device ID? Could you change
no longer working on chromium 2012/06/19 12:23:16 Done.
+ content::MediaStreamDeviceType type) {
+ content::MediaStreamDeviceMap::const_iterator device_it =
+ request_->devices.find(type);
+ if (device_it != request_->devices.end())
+ return device_it->second.begin()->device_id;
+
+ return std::string();
+}

Powered by Google App Engine
This is Rietveld 408576698