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

Side by Side Diff: chrome/browser/media/media_stream_devices_controller.cc

Issue 10912004: Begin adding support for tab mirroring via the MediaStream audio/video capturing (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 3 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/media/media_stream_devices_controller.h" 5 #include "chrome/browser/media/media_stream_devices_controller.h"
6 6
7 #include "base/values.h" 7 #include "base/values.h"
8 #include "chrome/browser/content_settings/content_settings_provider.h" 8 #include "chrome/browser/content_settings/content_settings_provider.h"
9 #include "chrome/browser/content_settings/host_content_settings_map.h" 9 #include "chrome/browser/content_settings/host_content_settings_map.h"
10 #include "chrome/browser/prefs/scoped_user_pref_update.h" 10 #include "chrome/browser/prefs/scoped_user_pref_update.h"
11 #include "chrome/browser/profiles/profile.h" 11 #include "chrome/browser/profiles/profile.h"
12 #include "chrome/browser/ui/browser.h" 12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/common/content_settings.h" 13 #include "chrome/common/content_settings.h"
14 #include "chrome/common/pref_names.h" 14 #include "chrome/common/pref_names.h"
15 15
16 using content::BrowserThread; 16 using content::BrowserThread;
17 17
18 namespace { 18 namespace {
19 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 20 // A predicate that checks if a StreamDeviceInfo object has the same device
37 // name as the device name specified at construction. 21 // name as the device name specified at construction.
38 class DeviceNameEquals { 22 class DeviceNameEquals {
39 public: 23 public:
40 explicit DeviceNameEquals(const std::string& device_name) 24 explicit DeviceNameEquals(const std::string& device_name)
41 : device_name_(device_name) { 25 : device_name_(device_name) {
42 } 26 }
43 27
44 bool operator() (const content::MediaStreamDevice& device) { 28 bool operator() (const content::MediaStreamDevice& device) {
45 return device.name == device_name_; 29 return device.name == device_name_;
46 } 30 }
47 31
48 private: 32 private:
49 std::string device_name_; 33 std::string device_name_;
50 }; 34 };
51 35
52 // Whether |request| contains any device of given |type|.
53 bool HasDevice(const content::MediaStreamRequest& request,
54 content::MediaStreamDeviceType type) {
55 content::MediaStreamDeviceMap::const_iterator device_it =
56 request.devices.find(type);
57 return device_it != request.devices.end() && !device_it->second.empty();
58 }
59
60 const char kAudioKey[] = "audio"; 36 const char kAudioKey[] = "audio";
61 const char kVideoKey[] = "video"; 37 const char kVideoKey[] = "video";
62 38
63 } // namespace 39 } // namespace
64 40
65 MediaStreamDevicesController::MediaStreamDevicesController( 41 MediaStreamDevicesController::MediaStreamDevicesController(
66 Profile* profile, 42 Profile* profile,
67 const content::MediaStreamRequest* request, 43 const content::MediaStreamRequest* request,
68 const content::MediaResponseCallback& callback) 44 const content::MediaResponseCallback& callback)
69 : profile_(profile), 45 : profile_(profile),
70 request_(*request), 46 request_(*request),
71 callback_(callback) { 47 callback_(callback) {
72 has_audio_ = 48 has_audio_ = false;
tommi (sloooow) - chröme 2012/09/10 09:17:25 initialize these in the initializer list
miu 2012/09/10 21:24:38 Done.
73 HasDevice(request_, content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE); 49 has_video_ = false;
74 has_video_ = 50 for (content::MediaStreamDeviceMap::const_iterator it =
75 HasDevice(request_, content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE); 51 request_.devices.begin();
52 it != request_.devices.end(); ++it) {
53 if (content::IsAudioMediaStreamDeviceType(it->first)) {
54 has_audio_ |= !it->second.empty();
55 } else if (content::IsVideoMediaStreamDeviceType(it->first)) {
56 has_video_ |= !it->second.empty();
57 }
58 }
76 } 59 }
77 60
78 MediaStreamDevicesController::~MediaStreamDevicesController() {} 61 MediaStreamDevicesController::~MediaStreamDevicesController() {}
79 62
80 bool MediaStreamDevicesController::DismissInfoBarAndTakeActionOnSettings() { 63 bool MediaStreamDevicesController::DismissInfoBarAndTakeActionOnSettings() {
81 // Deny the request if the security origin is empty, this happens with 64 // Deny the request if the security origin is empty, this happens with
82 // file access without |--allow-file-access-from-files| flag. 65 // file access without |--allow-file-access-from-files| flag.
83 if (request_.security_origin.is_empty()) { 66 if (request_.security_origin.is_empty()) {
84 Deny(); 67 Deny();
85 return true; 68 return true;
(...skipping 25 matching lines...) Expand all
111 return false; 94 return false;
112 } 95 }
113 96
114 // Dismiss the infobar by selecting the "always allowed" devices. 97 // Dismiss the infobar by selecting the "always allowed" devices.
115 Accept(audio, video, false); 98 Accept(audio, video, false);
116 return true; 99 return true;
117 } 100 }
118 101
119 content::MediaStreamDevices 102 content::MediaStreamDevices
120 MediaStreamDevicesController::GetAudioDevices() const { 103 MediaStreamDevicesController::GetAudioDevices() const {
121 if (!has_audio_) 104 content::MediaStreamDevices all_audio_devices;
no longer working on chromium 2012/08/31 13:38:22 why not a early return if !has_audio_
miu 2012/09/01 01:32:00 Done.
122 return content::MediaStreamDevices(); 105 FindSubsetOfDevices(&content::IsAudioMediaStreamDeviceType,
123 106 &all_audio_devices);
124 content::MediaStreamDeviceMap::const_iterator it = 107 return all_audio_devices;
125 request_.devices.find(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE);
126 DCHECK(it != request_.devices.end());
127 return it->second;
128 } 108 }
129 109
130 content::MediaStreamDevices 110 content::MediaStreamDevices
131 MediaStreamDevicesController::GetVideoDevices() const { 111 MediaStreamDevicesController::GetVideoDevices() const {
132 if (!has_video_) 112 content::MediaStreamDevices all_video_devices;
no longer working on chromium 2012/08/31 13:38:22 ditto
miu 2012/09/01 01:32:00 Done.
133 return content::MediaStreamDevices(); 113 FindSubsetOfDevices(&content::IsVideoMediaStreamDeviceType,
134 114 &all_video_devices);
135 content::MediaStreamDeviceMap::const_iterator it = 115 return all_video_devices;
136 request_.devices.find(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE);
137 DCHECK(it != request_.devices.end());
138 return it->second;
139 } 116 }
140 117
141 const GURL& MediaStreamDevicesController::GetSecurityOrigin() const { 118 const std::string& MediaStreamDevicesController::GetSecurityOriginSpec() const {
142 return request_.security_origin; 119 return request_.security_origin.spec();
tommi (sloooow) - chröme 2012/09/10 09:17:25 why not return const GURL&? i.e. return request_.
no longer working on chromium 2012/09/10 11:00:17 This function is used by the UI, and only the spec
120 }
121
122 bool MediaStreamDevicesController::IsSafeToAlwaysAllowAudio() const {
123 return IsSafeToAlwaysAllow(
124 &content::IsAudioMediaStreamDeviceType,
125 content::MEDIA_STREAM_DEVICE_TYPE_USER_AUDIO_CAPTURE);
126 }
127
128 bool MediaStreamDevicesController::IsSafeToAlwaysAllowVideo() const {
129 return IsSafeToAlwaysAllow(
130 &content::IsVideoMediaStreamDeviceType,
131 content::MEDIA_STREAM_DEVICE_TYPE_USER_VIDEO_CAPTURE);
143 } 132 }
144 133
145 void MediaStreamDevicesController::Accept(const std::string& audio_id, 134 void MediaStreamDevicesController::Accept(const std::string& audio_id,
146 const std::string& video_id, 135 const std::string& video_id,
147 bool always_allow) { 136 bool always_allow) {
148 content::MediaStreamDevices devices; 137 content::MediaStreamDevices devices;
149 std::string audio_device, video_device; 138 std::string audio_device_name, video_device_name;
150 if (has_audio_) { 139
151 AddDeviceWithId(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE, 140 const content::MediaStreamDevice* const audio_device =
152 audio_id, &devices, &audio_device); 141 FindFirstDeviceWithIdInSubset(&content::IsAudioMediaStreamDeviceType,
142 audio_id);
143 if (audio_device) {
144 if (audio_device->type !=
145 content::MEDIA_STREAM_DEVICE_TYPE_USER_AUDIO_CAPTURE) {
146 always_allow = false; // override for non-user audio device type
147 }
148 devices.push_back(*audio_device);
149 audio_device_name = audio_device->name;
153 } 150 }
154 if (has_video_) { 151
155 AddDeviceWithId(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE, 152 const content::MediaStreamDevice* const video_device =
156 video_id, &devices, &video_device); 153 FindFirstDeviceWithIdInSubset(&content::IsVideoMediaStreamDeviceType,
154 video_id);
155 if (video_device) {
156 if (video_device->type !=
157 content::MEDIA_STREAM_DEVICE_TYPE_USER_VIDEO_CAPTURE) {
158 always_allow = false; // override for non-user video device type
159 }
160 devices.push_back(*video_device);
161 video_device_name = video_device->name;
157 } 162 }
163
158 DCHECK(!devices.empty()); 164 DCHECK(!devices.empty());
159 165
160 if (always_allow) 166 if (always_allow)
161 AlwaysAllowOriginAndDevices(audio_device, video_device); 167 AlwaysAllowOriginAndDevices(audio_device_name, video_device_name);
162 168
163 callback_.Run(devices); 169 callback_.Run(devices);
164 } 170 }
165 171
166 void MediaStreamDevicesController::Deny() { 172 void MediaStreamDevicesController::Deny() {
167 callback_.Run(content::MediaStreamDevices()); 173 callback_.Run(content::MediaStreamDevices());
168 } 174 }
169 175
170 void MediaStreamDevicesController::AddDeviceWithId( 176 bool MediaStreamDevicesController::IsSafeToAlwaysAllow(
171 content::MediaStreamDeviceType type, 177 FilterByDeviceTypeFunc is_included,
172 const std::string& id, 178 content::MediaStreamDeviceType user_type) const {
173 content::MediaStreamDevices* devices, 179 DCHECK(user_type == content::MEDIA_STREAM_DEVICE_TYPE_USER_AUDIO_CAPTURE ||
174 std::string* device_name) { 180 user_type == content::MEDIA_STREAM_DEVICE_TYPE_USER_VIDEO_CAPTURE);
175 DCHECK(devices);
176 content::MediaStreamDeviceMap::const_iterator device_it =
177 request_.devices.find(type);
178 if (device_it == request_.devices.end())
179 return;
180 181
181 content::MediaStreamDevices::const_iterator it = std::find_if( 182 if (!request_.security_origin.SchemeIsSecure()) {
182 device_it->second.begin(), device_it->second.end(), DeviceIdEquals(id)); 183 return false;
183 if (it == device_it->second.end()) 184 }
184 return;
185 185
186 devices->push_back(*it); 186 // If non-user devices are available for the choosing, then it's not safe.
187 *device_name = it->name; 187 for (content::MediaStreamDeviceMap::const_iterator it =
188 request_.devices.begin();
189 it != request_.devices.end(); ++it) {
190 if (it->first != user_type && is_included(it->first)) {
191 return false;
192 }
193 }
194
195 return true;
188 } 196 }
189 197
190 bool MediaStreamDevicesController::ShouldAlwaysAllowOrigin() { 198 bool MediaStreamDevicesController::ShouldAlwaysAllowOrigin() {
191 return profile_->GetHostContentSettingsMap()->ShouldAllowAllContent( 199 return profile_->GetHostContentSettingsMap()->ShouldAllowAllContent(
192 request_.security_origin, request_.security_origin, 200 request_.security_origin, request_.security_origin,
193 CONTENT_SETTINGS_TYPE_MEDIASTREAM); 201 CONTENT_SETTINGS_TYPE_MEDIASTREAM);
194 } 202 }
195 203
196 bool MediaStreamDevicesController::IsMediaDeviceBlocked() { 204 bool MediaStreamDevicesController::IsMediaDeviceBlocked() {
197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 205 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
(...skipping 27 matching lines...) Expand all
225 233
226 void MediaStreamDevicesController::GetAlwaysAllowedDevices( 234 void MediaStreamDevicesController::GetAlwaysAllowedDevices(
227 std::string* audio_id, std::string* video_id) { 235 std::string* audio_id, std::string* video_id) {
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 236 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
229 DCHECK(audio_id->empty()); 237 DCHECK(audio_id->empty());
230 DCHECK(video_id->empty()); 238 DCHECK(video_id->empty());
231 // If the request is from internal objects like chrome://URLs, use the first 239 // If the request is from internal objects like chrome://URLs, use the first
232 // devices on the lists. 240 // devices on the lists.
233 if (ShouldAlwaysAllowOrigin()) { 241 if (ShouldAlwaysAllowOrigin()) {
234 if (has_audio_) { 242 if (has_audio_) {
235 *audio_id = 243 *audio_id = GetFirstDeviceId(
236 GetFirstDeviceId(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE); 244 content::MEDIA_STREAM_DEVICE_TYPE_USER_AUDIO_CAPTURE);
237 } 245 }
238 if (has_video_) { 246 if (has_video_) {
239 *video_id = 247 *video_id = GetFirstDeviceId(
240 GetFirstDeviceId(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE); 248 content::MEDIA_STREAM_DEVICE_TYPE_USER_VIDEO_CAPTURE);
241 } 249 }
242 return; 250 return;
243 } 251 }
244 252
245 // "Always allowed" option is only available for secure connection. 253 // "Always allowed" option is only available for secure connection.
246 if (!request_.security_origin.SchemeIsSecure()) 254 if (!request_.security_origin.SchemeIsSecure())
247 return; 255 return;
248 256
249 // Checks the media exceptions to get the "always allowed" devices. 257 // Checks the media exceptions to get the "always allowed" devices.
250 scoped_ptr<Value> value( 258 scoped_ptr<Value> value(
(...skipping 11 matching lines...) Expand all
262 const DictionaryValue* value_dict = NULL; 270 const DictionaryValue* value_dict = NULL;
263 if (!value->GetAsDictionary(&value_dict) || value_dict->empty()) 271 if (!value->GetAsDictionary(&value_dict) || value_dict->empty())
264 return; 272 return;
265 273
266 std::string audio_name, video_name; 274 std::string audio_name, video_name;
267 value_dict->GetString(kAudioKey, &audio_name); 275 value_dict->GetString(kAudioKey, &audio_name);
268 value_dict->GetString(kVideoKey, &video_name); 276 value_dict->GetString(kVideoKey, &video_name);
269 277
270 if (has_audio_ && !audio_name.empty()) { 278 if (has_audio_ && !audio_name.empty()) {
271 *audio_id = GetDeviceIdByName( 279 *audio_id = GetDeviceIdByName(
272 content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE, audio_name); 280 content::MEDIA_STREAM_DEVICE_TYPE_USER_AUDIO_CAPTURE, audio_name);
273 } 281 }
274 if (has_video_ && !video_name.empty()) { 282 if (has_video_ && !video_name.empty()) {
275 *video_id = GetDeviceIdByName( 283 *video_id = GetDeviceIdByName(
276 content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE, video_name); 284 content::MEDIA_STREAM_DEVICE_TYPE_USER_VIDEO_CAPTURE, video_name);
277 } 285 }
278 } 286 }
279 287
280 std::string MediaStreamDevicesController::GetDeviceIdByName( 288 std::string MediaStreamDevicesController::GetDeviceIdByName(
281 content::MediaStreamDeviceType type, 289 content::MediaStreamDeviceType type,
282 const std::string& name) { 290 const std::string& name) {
283 content::MediaStreamDeviceMap::const_iterator device_it = 291 content::MediaStreamDeviceMap::const_iterator device_it =
284 request_.devices.find(type); 292 request_.devices.find(type);
285 if (device_it != request_.devices.end()) { 293 if (device_it != request_.devices.end()) {
286 content::MediaStreamDevices::const_iterator it = std::find_if( 294 content::MediaStreamDevices::const_iterator it = std::find_if(
287 device_it->second.begin(), device_it->second.end(), 295 device_it->second.begin(), device_it->second.end(),
288 DeviceNameEquals(name)); 296 DeviceNameEquals(name));
289 if (it != device_it->second.end()) 297 if (it != device_it->second.end())
290 return it->device_id; 298 return it->device_id;
291 } 299 }
292 300
293 // Device is not available, return an empty string. 301 // Device is not available, return an empty string.
294 return std::string(); 302 return std::string();
295 } 303 }
296 304
297 std::string MediaStreamDevicesController::GetFirstDeviceId( 305 std::string MediaStreamDevicesController::GetFirstDeviceId(
298 content::MediaStreamDeviceType type) { 306 content::MediaStreamDeviceType type) {
299 content::MediaStreamDeviceMap::const_iterator device_it = 307 content::MediaStreamDeviceMap::const_iterator device_it =
300 request_.devices.find(type); 308 request_.devices.find(type);
301 if (device_it != request_.devices.end()) 309 if (device_it != request_.devices.end())
302 return device_it->second.begin()->device_id; 310 return device_it->second.begin()->device_id;
303 311
304 return std::string(); 312 return std::string();
305 } 313 }
314
315 void MediaStreamDevicesController::FindSubsetOfDevices(
316 FilterByDeviceTypeFunc is_included,
317 content::MediaStreamDevices* out) const {
318 for (content::MediaStreamDeviceMap::const_iterator it =
319 request_.devices.begin();
320 it != request_.devices.end(); ++it) {
321 if (is_included(it->first)) {
322 out->insert(out->end(), it->second.begin(), it->second.end());
no longer working on chromium 2012/08/31 13:38:22 Curiously, what is the benefit of using insert her
miu 2012/09/01 01:32:00 Google C++ style discourages returning non-POD typ
323 }
324 }
325 }
326
327 const content::MediaStreamDevice*
328 MediaStreamDevicesController::FindFirstDeviceWithIdInSubset(
329 FilterByDeviceTypeFunc is_included,
330 const std::string& device_id) const {
331 for (content::MediaStreamDeviceMap::const_iterator it =
332 request_.devices.begin();
333 it != request_.devices.end(); ++it) {
334 if (!is_included(it->first)) {
335 continue;
336 }
337 for (content::MediaStreamDevices::const_iterator device_it =
338 it->second.begin();
339 device_it != it->second.end(); ++device_it) {
340 const content::MediaStreamDevice& candidate = *device_it;
341 if (candidate.device_id == device_id) {
342 return &candidate;
343 }
344 }
345 }
346 return NULL;
347 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698