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

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: 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 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 } // namespace
53
54 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
55 static const char kVideoKey[] = "video";
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 DCHECK(has_audio_ || has_video_);
76 // If the request is from internal objects like chrome://URLs, use the first
77 // devices on the lists.
78 if (IsInternalContent()) {
79 std::string audio, video;
80 if (has_audio_) {
81 audio = GetFirstDevice(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE);
82 if (audio.empty())
83 return false;
84 }
85 if (has_video_) {
86 video = GetFirstDevice(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE);
87 if (video.empty())
88 return false;
89 }
90
91 Accept(audio, video, false);
92 return true;
93 }
94
95 // If the user has blocked the access to the media device in content
96 // settings, deny the request without showing the infobar.
97 if (IsMediaDeviceBlocked()){
98 Deny();
99 return true;
100 }
101
102 // If there are "always allowed" devices for the request, accept the request
103 // without showing the infobar.
104 std::string audio, video;
105 GetAlwaysAllowedDevices(&audio, &video);
106 // If there is no "always allowed" device for the origin, or the device is
107 // not available in the device lists, force showing the infobar.
108 if ((has_audio_ && audio.empty()) || (has_video_ && video.empty()))
109 return false;
110
111 Accept(audio, video, false);
112 return true;
113 }
114
115 content::MediaStreamDevices
116 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.
117 if (!has_audio_)
118 return content::MediaStreamDevices();
119
120 content::MediaStreamDeviceMap::const_iterator it =
121 request_->devices.find(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE);
122 DCHECK(it != request_->devices.end());
123 return it->second;
124 }
125
126 content::MediaStreamDevices
127 MediaStreamDevicesController::GetVideoDevices() const {
128 if (!has_video_)
129 return content::MediaStreamDevices();
130
131 content::MediaStreamDeviceMap::const_iterator it =
132 request_->devices.find(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE);
133 DCHECK(it != request_->devices.end());
134 return it->second;
135 }
136
137 const GURL& MediaStreamDevicesController::GetSecurityOrigin() const {
138 return request_->security_origin;
139 }
140
141 void MediaStreamDevicesController::Accept(const std::string& audio_id,
142 const std::string& video_id,
143 bool always_allow) {
144 content::MediaStreamDevices devices;
145 std::string audio_device, video_device;
146 if (has_audio_) {
147 AddDeviceWithId(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE,
148 audio_id, &devices, &audio_device);
149 }
150 if (has_video_) {
151 AddDeviceWithId(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE,
152 video_id, &devices, &video_device);
153 }
154 DCHECK(!devices.empty());
155
156 if (always_allow)
157 AlwaysAllowOriginAndDevices(audio_device, video_device);
158
159 callback_.Run(devices);
160 }
161
162 void MediaStreamDevicesController::Deny() {
163 callback_.Run(content::MediaStreamDevices());
164 }
165
166 void MediaStreamDevicesController::AddDeviceWithId(
167 content::MediaStreamDeviceType type,
168 const std::string& id,
169 content::MediaStreamDevices* devices,
170 std::string* device_name) {
171 DCHECK(devices);
172 content::MediaStreamDeviceMap::const_iterator device_it =
173 request_->devices.find(type);
174 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.
175 content::MediaStreamDevices::const_iterator it = std::find_if(
176 device_it->second.begin(), device_it->second.end(), DeviceIdEquals(id));
177 if (it != device_it->second.end()) {
178 devices->push_back(*it);
179 *device_name = it->name;
180 }
181 }
182 }
183
184 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.
185 return profile_->GetHostContentSettingsMap()->ShouldAllowAllContent(
186 request_->security_origin, request_->security_origin,
187 CONTENT_SETTINGS_TYPE_MEDIASTREAM);
188 }
189
190 bool MediaStreamDevicesController::IsMediaDeviceBlocked() {
191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
192 ContentSetting current_setting =
193 profile_->GetHostContentSettingsMap()->GetDefaultContentSetting(
194 CONTENT_SETTINGS_TYPE_MEDIASTREAM, NULL);
195 return (current_setting == CONTENT_SETTING_BLOCK);
196 }
197
198 void MediaStreamDevicesController::AlwaysAllowOriginAndDevices(
199 const std::string& audio_device,
200 const std::string& video_device) {
201 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
202 DCHECK(!audio_device.empty() || !video_device.empty());
203 DictionaryValue* dictionary_value = new DictionaryValue();
204 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.
205 dictionary_value->SetString(kAudioKey, audio_device);
206 }
207 if (!video_device.empty()) {
208 dictionary_value->SetString(kVideoKey, video_device);
209 }
210
211 ContentSettingsPattern primary_pattern =
212 ContentSettingsPattern::FromURLNoWildcard(request_->security_origin);
213 profile_->GetHostContentSettingsMap()->SetWebsiteSetting(
214 primary_pattern,
215 ContentSettingsPattern::Wildcard(),
216 CONTENT_SETTINGS_TYPE_MEDIASTREAM,
217 NO_RESOURCE_IDENTIFIER,
218 dictionary_value);
219 }
220
221 void MediaStreamDevicesController::GetAlwaysAllowedDevices(
222 std::string* audio_id, std::string* video_id) {
223 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
224 DCHECK(audio_id->empty());
225 DCHECK(video_id->empty());
226 content_settings::SettingInfo info;
227 scoped_ptr<Value> value(
228 profile_->GetHostContentSettingsMap()->GetWebsiteSetting(
229 request_->security_origin,
230 request_->security_origin,
231 CONTENT_SETTINGS_TYPE_MEDIASTREAM,
232 NO_RESOURCE_IDENTIFIER,
233 &info));
234 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
235 return;
236
237 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.
238 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
239 return;
240
241 std::string audio_name, video_name;
242 value_dict->GetString(kAudioKey, &audio_name);
243 value_dict->GetString(kVideoKey, &video_name);
244
245 if (!audio_name.empty()) {
246 *audio_id = GetDeviceIdByName(
247 content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE, audio_name);
248 }
249 if (!video_name.empty()) {
250 *video_id = GetDeviceIdByName(
251 content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE, video_name);
252 }
253
254 return;
255 }
256
257 std::string MediaStreamDevicesController::GetDeviceIdByName(
258 content::MediaStreamDeviceType type,
259 const std::string& name) {
260 content::MediaStreamDeviceMap::const_iterator device_it =
261 request_->devices.find(type);
262 if (device_it != request_->devices.end()) {
263 content::MediaStreamDevices::const_iterator it = std::find_if(
264 device_it->second.begin(), device_it->second.end(),
265 DeviceNameEquals(name));
266 if (it != device_it->second.end())
267 return it->device_id;
268 }
269
270 // Device is not available, return an empty string.
271 return std::string();
272 }
273
274 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.
275 content::MediaStreamDeviceType type) {
276 content::MediaStreamDeviceMap::const_iterator device_it =
277 request_->devices.find(type);
278 if (device_it != request_->devices.end())
279 return device_it->second.begin()->device_id;
280
281 return std::string();
282 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698