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

Side by Side 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: Check the exceptions before the default setting, sites in the exceptions list can access the device… 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/media/media_stream_devices_controller.h"
6
7 #include "base/values.h"
8 #include "chrome/browser/content_settings/content_settings_provider.h"
9 #include "chrome/browser/content_settings/host_content_settings_map.h"
10 #include "chrome/browser/prefs/scoped_user_pref_update.h"
11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/common/content_settings.h"
14 #include "chrome/common/pref_names.h"
15
16 using content::BrowserThread;
17
18 namespace {
19
20 // A predicate that checks if a StreamDeviceInfo object has the same ID as the
21 // device ID specified at construction.
22 class DeviceIdEquals {
23 public:
24 explicit DeviceIdEquals(const std::string& device_id)
25 : device_id_(device_id) {
26 }
27
28 bool operator() (const content::MediaStreamDevice& device) {
29 return device.device_id == device_id_;
30 }
31
32 private:
33 std::string device_id_;
34 };
35
36 // A predicate that checks if a StreamDeviceInfo object has the same device
37 // name as the device name specified at construction.
38 class DeviceNameEquals {
39 public:
40 explicit DeviceNameEquals(const std::string& device_name)
41 : device_name_(device_name) {
42 }
43
44 bool operator() (const content::MediaStreamDevice& device) {
45 return device.name == device_name_;
46 }
47
48 private:
49 std::string device_name_;
50 };
51
52 const char kAudioKey[] = "audio";
53 const char kVideoKey[] = "video";
54
55 } // namespace
56
57 MediaStreamDevicesController::MediaStreamDevicesController(
58 Profile* profile,
59 const content::MediaStreamRequest* request,
60 const content::MediaResponseCallback& callback)
61 : profile_(profile),
62 request_(request),
63 callback_(callback) {
64 DCHECK(request_);
65 DCHECK(!request_->security_origin.is_empty());
66 has_audio_ = request_->devices.count(
67 content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE) != 0;
68 has_video_ = request_->devices.count(
69 content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE) != 0;
70 }
71
72 MediaStreamDevicesController::~MediaStreamDevicesController() {}
73
74 bool MediaStreamDevicesController::DismissInfoBarAndTakeActionOnSettings() {
75 // Deny the request and don't show the infobar if there is no devices.
76 if (!has_audio_ && !has_video_) {
77 // TODO(xians): We should detect this in a early state, and post a callback
78 // to tell the users that no device is available. Remove the code and add
79 // a DCHECK when this is done.
80 Deny();
81 return true;
82 }
83
84 // Checks if any exception has been made for this request, get the "always
85 // allowed" devices if they are available.
86 std::string audio, video;
87 GetAlwaysAllowedDevices(&audio, &video);
88 if ((has_audio_ && audio.empty()) || (has_video_ && video.empty())) {
89 // If there is no "always allowed" device for the origin, or the device is
90 // not available in the device lists, Check the default setting to see if
91 // the user has blocked the access to the media device.
92 if (IsMediaDeviceBlocked()) {
93 Deny();
94 return true;
95 }
96
97 // Show the infobar.
98 return false;
99 }
100
101 // Dismiss the infobar by selecting the "always allowed" devices.
102 Accept(audio, video, false);
103 return true;
104 }
105
106 content::MediaStreamDevices
107 MediaStreamDevicesController::GetAudioDevices() const {
108 if (!has_audio_)
109 return content::MediaStreamDevices();
110
111 content::MediaStreamDeviceMap::const_iterator it =
112 request_->devices.find(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE);
113 DCHECK(it != request_->devices.end());
114 return it->second;
115 }
116
117 content::MediaStreamDevices
118 MediaStreamDevicesController::GetVideoDevices() const {
119 if (!has_video_)
120 return content::MediaStreamDevices();
121
122 content::MediaStreamDeviceMap::const_iterator it =
123 request_->devices.find(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE);
124 DCHECK(it != request_->devices.end());
125 return it->second;
126 }
127
128 const GURL& MediaStreamDevicesController::GetSecurityOrigin() const {
129 return request_->security_origin;
130 }
131
132 void MediaStreamDevicesController::Accept(const std::string& audio_id,
133 const std::string& video_id,
134 bool always_allow) {
135 content::MediaStreamDevices devices;
136 std::string audio_device, video_device;
137 if (has_audio_) {
138 AddDeviceWithId(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE,
139 audio_id, &devices, &audio_device);
140 }
141 if (has_video_) {
142 AddDeviceWithId(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE,
143 video_id, &devices, &video_device);
144 }
145 DCHECK(!devices.empty());
146
147 if (always_allow)
148 AlwaysAllowOriginAndDevices(audio_device, video_device);
149
150 callback_.Run(devices);
151 }
152
153 void MediaStreamDevicesController::Deny() {
154 callback_.Run(content::MediaStreamDevices());
155 }
156
157 void MediaStreamDevicesController::AddDeviceWithId(
158 content::MediaStreamDeviceType type,
159 const std::string& id,
160 content::MediaStreamDevices* devices,
161 std::string* device_name) {
162 DCHECK(devices);
163 content::MediaStreamDeviceMap::const_iterator device_it =
164 request_->devices.find(type);
165 if (device_it != request_->devices.end()) {
166 content::MediaStreamDevices::const_iterator it = std::find_if(
167 device_it->second.begin(), device_it->second.end(), DeviceIdEquals(id));
168 if (it != device_it->second.end()) {
169 devices->push_back(*it);
170 *device_name = it->name;
171 }
172 }
173 }
174
175 bool MediaStreamDevicesController::ShouldAlwaysAllowOrigin() {
176 return profile_->GetHostContentSettingsMap()->ShouldAllowAllContent(
177 request_->security_origin, request_->security_origin,
178 CONTENT_SETTINGS_TYPE_MEDIASTREAM);
179 }
180
181 bool MediaStreamDevicesController::IsMediaDeviceBlocked() {
182 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
183 ContentSetting current_setting =
184 profile_->GetHostContentSettingsMap()->GetDefaultContentSetting(
185 CONTENT_SETTINGS_TYPE_MEDIASTREAM, NULL);
186 return (current_setting == CONTENT_SETTING_BLOCK);
187 }
188
189 void MediaStreamDevicesController::AlwaysAllowOriginAndDevices(
190 const std::string& audio_device,
191 const std::string& video_device) {
192 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
193 DCHECK(!audio_device.empty() || !video_device.empty());
194 DictionaryValue* dictionary_value = new DictionaryValue();
195 if (!audio_device.empty()) {
196 dictionary_value->SetString(kAudioKey, audio_device);
197 }
198 if (!video_device.empty()) {
199 dictionary_value->SetString(kVideoKey, video_device);
200 }
201
202 ContentSettingsPattern primary_pattern =
203 ContentSettingsPattern::FromURLNoWildcard(request_->security_origin);
204 profile_->GetHostContentSettingsMap()->SetWebsiteSetting(
205 primary_pattern,
206 ContentSettingsPattern::Wildcard(),
207 CONTENT_SETTINGS_TYPE_MEDIASTREAM,
208 NO_RESOURCE_IDENTIFIER,
209 dictionary_value);
210 }
211
212 void MediaStreamDevicesController::GetAlwaysAllowedDevices(
213 std::string* audio_id, std::string* video_id) {
214 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
215 DCHECK(audio_id->empty());
216 DCHECK(video_id->empty());
217 // If the request is from internal objects like chrome://URLs, use the first
218 // devices on the lists.
219 if (ShouldAlwaysAllowOrigin()) {
220 if (has_audio_) {
221 *audio_id =
222 GetFirstDevice(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE);
223 }
224 if (has_video_) {
225 *video_id =
226 GetFirstDevice(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE);
227 }
228 return;
229 }
230
231 // Checks the media exceptions to get the "always allowed" devices.
232 content_settings::SettingInfo info;
233 scoped_ptr<Value> value(
234 profile_->GetHostContentSettingsMap()->GetWebsiteSetting(
235 request_->security_origin,
236 request_->security_origin,
237 CONTENT_SETTINGS_TYPE_MEDIASTREAM,
238 NO_RESOURCE_IDENTIFIER,
239 &info));
240 if (!value.get() || !value->IsType(Value::TYPE_DICTIONARY))
241 return;
242
243 const DictionaryValue* value_dict =
244 static_cast<const DictionaryValue*>(value.get());
245 if (value_dict->empty())
246 return;
247
248 std::string audio_name, video_name;
249 value_dict->GetString(kAudioKey, &audio_name);
250 value_dict->GetString(kVideoKey, &video_name);
251
252 if (has_audio_ && !audio_name.empty()) {
253 *audio_id = GetDeviceIdByName(
254 content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE, audio_name);
255 }
256 if (has_video_ && !video_name.empty()) {
257 *video_id = GetDeviceIdByName(
258 content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE, video_name);
259 }
260
261 return;
262 }
263
264 std::string MediaStreamDevicesController::GetDeviceIdByName(
265 content::MediaStreamDeviceType type,
266 const std::string& name) {
267 content::MediaStreamDeviceMap::const_iterator device_it =
268 request_->devices.find(type);
269 if (device_it != request_->devices.end()) {
270 content::MediaStreamDevices::const_iterator it = std::find_if(
271 device_it->second.begin(), device_it->second.end(),
272 DeviceNameEquals(name));
273 if (it != device_it->second.end())
274 return it->device_id;
275 }
276
277 // Device is not available, return an empty string.
278 return std::string();
279 }
280
281 std::string MediaStreamDevicesController::GetFirstDevice(
282 content::MediaStreamDeviceType type) {
283 content::MediaStreamDeviceMap::const_iterator device_it =
284 request_->devices.find(type);
285 if (device_it != request_->devices.end())
286 return device_it->second.begin()->device_id;
287
288 return std::string();
289 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698