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

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: Simplify: Use only one AudioInputDeviceManager and VideoCaptureManager, like before. 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 #include "content/public/common/media_stream_request.h"
15 16
16 using content::BrowserThread; 17 using content::BrowserThread;
17 18
18 namespace { 19 namespace {
19 20
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 21 // A predicate that checks if a StreamDeviceInfo object has the same device
37 // name as the device name specified at construction. 22 // name as the device name specified at construction.
38 class DeviceNameEquals { 23 class DeviceNameEquals {
39 public: 24 public:
40 explicit DeviceNameEquals(const std::string& device_name) 25 explicit DeviceNameEquals(const std::string& device_name)
41 : device_name_(device_name) { 26 : device_name_(device_name) {
42 } 27 }
43 28
44 bool operator() (const content::MediaStreamDevice& device) { 29 bool operator() (const content::MediaStreamDevice& device) {
45 return device.name == device_name_; 30 return device.name == device_name_;
46 } 31 }
47 32
48 private: 33 private:
49 std::string device_name_; 34 std::string device_name_;
50 }; 35 };
51 36
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"; 37 const char kAudioKey[] = "audio";
61 const char kVideoKey[] = "video"; 38 const char kVideoKey[] = "video";
62 39
63 } // namespace 40 } // namespace
64 41
65 MediaStreamDevicesController::MediaStreamDevicesController( 42 MediaStreamDevicesController::MediaStreamDevicesController(
66 Profile* profile, 43 Profile* profile,
67 const content::MediaStreamRequest* request, 44 const content::MediaStreamRequest* request,
68 const content::MediaResponseCallback& callback) 45 const content::MediaResponseCallback& callback)
69 : profile_(profile), 46 : profile_(profile),
70 request_(*request), 47 request_(*request),
71 callback_(callback) { 48 callback_(callback) {
72 has_audio_ = 49 has_audio_ = false;
73 HasDevice(request_, content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE); 50 has_video_ = 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.
74 has_video_ = 51 for (content::MediaStreamDeviceMap::const_iterator it =
75 HasDevice(request_, content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE); 52 request_.devices.begin();
53 it != request_.devices.end(); ++it) {
54 if (content::IsAudioMediaType(it->first)) {
55 has_audio_ |= !it->second.empty();
56 } else if (content::IsVideoMediaType(it->first)) {
57 has_video_ |= !it->second.empty();
58 }
59 }
76 } 60 }
77 61
78 MediaStreamDevicesController::~MediaStreamDevicesController() {} 62 MediaStreamDevicesController::~MediaStreamDevicesController() {}
79 63
80 bool MediaStreamDevicesController::DismissInfoBarAndTakeActionOnSettings() { 64 bool MediaStreamDevicesController::DismissInfoBarAndTakeActionOnSettings() {
81 // Deny the request if the security origin is empty, this happens with 65 // Deny the request if the security origin is empty, this happens with
82 // file access without |--allow-file-access-from-files| flag. 66 // file access without |--allow-file-access-from-files| flag.
83 if (request_.security_origin.is_empty()) { 67 if (request_.security_origin.is_empty()) {
84 Deny(); 68 Deny();
85 return true; 69 return true;
(...skipping 25 matching lines...) Expand all
111 return false; 95 return false;
112 } 96 }
113 97
114 // Dismiss the infobar by selecting the "always allowed" devices. 98 // Dismiss the infobar by selecting the "always allowed" devices.
115 Accept(audio, video, false); 99 Accept(audio, video, false);
116 return true; 100 return true;
117 } 101 }
118 102
119 content::MediaStreamDevices 103 content::MediaStreamDevices
120 MediaStreamDevicesController::GetAudioDevices() const { 104 MediaStreamDevicesController::GetAudioDevices() const {
121 if (!has_audio_) 105 content::MediaStreamDevices all_audio_devices;
122 return content::MediaStreamDevices(); 106 if (has_audio_) {
tommi (sloooow) - chröme 2012/09/10 09:17:25 no need for {} same throughout since the file wasn
miu 2012/09/10 21:24:38 Done; but only to be style-consistent with the exi
123 107 FindSubsetOfDevices(&content::IsAudioMediaType, &all_audio_devices);
124 content::MediaStreamDeviceMap::const_iterator it = 108 }
125 request_.devices.find(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE); 109 return all_audio_devices;
126 DCHECK(it != request_.devices.end());
127 return it->second;
128 } 110 }
129 111
130 content::MediaStreamDevices 112 content::MediaStreamDevices
131 MediaStreamDevicesController::GetVideoDevices() const { 113 MediaStreamDevicesController::GetVideoDevices() const {
132 if (!has_video_) 114 content::MediaStreamDevices all_video_devices;
133 return content::MediaStreamDevices(); 115 if (has_video_) {
134 116 FindSubsetOfDevices(&content::IsVideoMediaType, &all_video_devices);
135 content::MediaStreamDeviceMap::const_iterator it = 117 }
136 request_.devices.find(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE); 118 return all_video_devices;
137 DCHECK(it != request_.devices.end());
138 return it->second;
139 } 119 }
140 120
141 const GURL& MediaStreamDevicesController::GetSecurityOrigin() const { 121 const std::string& MediaStreamDevicesController::GetSecurityOriginSpec() const {
142 return request_.security_origin; 122 return request_.security_origin.spec();
123 }
124
125 bool MediaStreamDevicesController::IsSafeToAlwaysAllowAudio() const {
126 return IsSafeToAlwaysAllow(
127 &content::IsAudioMediaType, content::MEDIA_DEVICE_AUDIO_CAPTURE);
128 }
129
130 bool MediaStreamDevicesController::IsSafeToAlwaysAllowVideo() const {
131 return IsSafeToAlwaysAllow(
132 &content::IsVideoMediaType, content::MEDIA_DEVICE_VIDEO_CAPTURE);
143 } 133 }
144 134
145 void MediaStreamDevicesController::Accept(const std::string& audio_id, 135 void MediaStreamDevicesController::Accept(const std::string& audio_id,
146 const std::string& video_id, 136 const std::string& video_id,
147 bool always_allow) { 137 bool always_allow) {
148 content::MediaStreamDevices devices; 138 content::MediaStreamDevices devices;
149 std::string audio_device, video_device; 139 std::string audio_device_name, video_device_name;
150 if (has_audio_) { 140
151 AddDeviceWithId(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE, 141 const content::MediaStreamDevice* const audio_device =
152 audio_id, &devices, &audio_device); 142 FindFirstDeviceWithIdInSubset(&content::IsAudioMediaType, audio_id);
143 if (audio_device) {
144 if (audio_device->type != content::MEDIA_DEVICE_AUDIO_CAPTURE) {
145 always_allow = false; // override for virtual audio device type
scherkus (not reviewing) 2012/09/10 11:08:59 try to use proper sentence structure for comments
miu 2012/09/10 21:24:38 Done.
146 }
147 devices.push_back(*audio_device);
148 audio_device_name = audio_device->name;
153 } 149 }
154 if (has_video_) { 150
155 AddDeviceWithId(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE, 151 const content::MediaStreamDevice* const video_device =
156 video_id, &devices, &video_device); 152 FindFirstDeviceWithIdInSubset(&content::IsVideoMediaType, video_id);
153 if (video_device) {
154 if (video_device->type != content::MEDIA_DEVICE_VIDEO_CAPTURE) {
155 always_allow = false; // override for virtual video device type
scherkus (not reviewing) 2012/09/10 11:08:59 ditto
miu 2012/09/10 21:24:38 Done.
156 }
157 devices.push_back(*video_device);
158 video_device_name = video_device->name;
157 } 159 }
160
158 DCHECK(!devices.empty()); 161 DCHECK(!devices.empty());
159 162
160 if (always_allow) 163 if (always_allow)
161 AlwaysAllowOriginAndDevices(audio_device, video_device); 164 AlwaysAllowOriginAndDevices(audio_device_name, video_device_name);
162 165
163 callback_.Run(devices); 166 callback_.Run(devices);
164 } 167 }
165 168
166 void MediaStreamDevicesController::Deny() { 169 void MediaStreamDevicesController::Deny() {
167 callback_.Run(content::MediaStreamDevices()); 170 callback_.Run(content::MediaStreamDevices());
168 } 171 }
169 172
170 void MediaStreamDevicesController::AddDeviceWithId( 173 bool MediaStreamDevicesController::IsSafeToAlwaysAllow(
171 content::MediaStreamDeviceType type, 174 FilterByDeviceTypeFunc is_included,
172 const std::string& id, 175 content::MediaStreamDeviceType device_type) const {
173 content::MediaStreamDevices* devices, 176 DCHECK(device_type == content::MEDIA_DEVICE_AUDIO_CAPTURE ||
174 std::string* device_name) { 177 device_type == content::MEDIA_DEVICE_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 178
181 content::MediaStreamDevices::const_iterator it = std::find_if( 179 if (!request_.security_origin.SchemeIsSecure()) {
182 device_it->second.begin(), device_it->second.end(), DeviceIdEquals(id)); 180 return false;
183 if (it == device_it->second.end()) 181 }
184 return;
185 182
186 devices->push_back(*it); 183 // If non-physical devices are available for the choosing, then it's not safe.
187 *device_name = it->name; 184 bool safe_devices_found = false;
185 for (content::MediaStreamDeviceMap::const_iterator it =
186 request_.devices.begin();
187 it != request_.devices.end(); ++it) {
188 if (it->first != device_type && is_included(it->first)) {
189 return false;
190 }
191 safe_devices_found = true;
192 }
193
194 return safe_devices_found;
188 } 195 }
189 196
190 bool MediaStreamDevicesController::ShouldAlwaysAllowOrigin() { 197 bool MediaStreamDevicesController::ShouldAlwaysAllowOrigin() {
191 return profile_->GetHostContentSettingsMap()->ShouldAllowAllContent( 198 return profile_->GetHostContentSettingsMap()->ShouldAllowAllContent(
192 request_.security_origin, request_.security_origin, 199 request_.security_origin, request_.security_origin,
193 CONTENT_SETTINGS_TYPE_MEDIASTREAM); 200 CONTENT_SETTINGS_TYPE_MEDIASTREAM);
194 } 201 }
195 202
196 bool MediaStreamDevicesController::IsMediaDeviceBlocked() { 203 bool MediaStreamDevicesController::IsMediaDeviceBlocked() {
197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 204 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
(...skipping 27 matching lines...) Expand all
225 232
226 void MediaStreamDevicesController::GetAlwaysAllowedDevices( 233 void MediaStreamDevicesController::GetAlwaysAllowedDevices(
227 std::string* audio_id, std::string* video_id) { 234 std::string* audio_id, std::string* video_id) {
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 235 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
229 DCHECK(audio_id->empty()); 236 DCHECK(audio_id->empty());
230 DCHECK(video_id->empty()); 237 DCHECK(video_id->empty());
231 // If the request is from internal objects like chrome://URLs, use the first 238 // If the request is from internal objects like chrome://URLs, use the first
232 // devices on the lists. 239 // devices on the lists.
233 if (ShouldAlwaysAllowOrigin()) { 240 if (ShouldAlwaysAllowOrigin()) {
234 if (has_audio_) { 241 if (has_audio_) {
235 *audio_id = 242 *audio_id = GetFirstDeviceId(content::MEDIA_DEVICE_AUDIO_CAPTURE);
236 GetFirstDeviceId(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE);
237 } 243 }
238 if (has_video_) { 244 if (has_video_) {
239 *video_id = 245 *video_id = GetFirstDeviceId(content::MEDIA_DEVICE_VIDEO_CAPTURE);
240 GetFirstDeviceId(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE);
241 } 246 }
242 return; 247 return;
243 } 248 }
244 249
245 // "Always allowed" option is only available for secure connection. 250 // "Always allowed" option is only available for secure connection.
246 if (!request_.security_origin.SchemeIsSecure()) 251 if (!request_.security_origin.SchemeIsSecure())
247 return; 252 return;
248 253
249 // Checks the media exceptions to get the "always allowed" devices. 254 // Checks the media exceptions to get the "always allowed" devices.
250 scoped_ptr<Value> value( 255 scoped_ptr<Value> value(
(...skipping 11 matching lines...) Expand all
262 const DictionaryValue* value_dict = NULL; 267 const DictionaryValue* value_dict = NULL;
263 if (!value->GetAsDictionary(&value_dict) || value_dict->empty()) 268 if (!value->GetAsDictionary(&value_dict) || value_dict->empty())
264 return; 269 return;
265 270
266 std::string audio_name, video_name; 271 std::string audio_name, video_name;
267 value_dict->GetString(kAudioKey, &audio_name); 272 value_dict->GetString(kAudioKey, &audio_name);
268 value_dict->GetString(kVideoKey, &video_name); 273 value_dict->GetString(kVideoKey, &video_name);
269 274
270 if (has_audio_ && !audio_name.empty()) { 275 if (has_audio_ && !audio_name.empty()) {
271 *audio_id = GetDeviceIdByName( 276 *audio_id = GetDeviceIdByName(
272 content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE, audio_name); 277 content::MEDIA_DEVICE_AUDIO_CAPTURE, audio_name);
273 } 278 }
274 if (has_video_ && !video_name.empty()) { 279 if (has_video_ && !video_name.empty()) {
275 *video_id = GetDeviceIdByName( 280 *video_id = GetDeviceIdByName(
276 content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE, video_name); 281 content::MEDIA_DEVICE_VIDEO_CAPTURE, video_name);
277 } 282 }
278 } 283 }
279 284
280 std::string MediaStreamDevicesController::GetDeviceIdByName( 285 std::string MediaStreamDevicesController::GetDeviceIdByName(
281 content::MediaStreamDeviceType type, 286 content::MediaStreamDeviceType type,
282 const std::string& name) { 287 const std::string& name) {
283 content::MediaStreamDeviceMap::const_iterator device_it = 288 content::MediaStreamDeviceMap::const_iterator device_it =
284 request_.devices.find(type); 289 request_.devices.find(type);
285 if (device_it != request_.devices.end()) { 290 if (device_it != request_.devices.end()) {
286 content::MediaStreamDevices::const_iterator it = std::find_if( 291 content::MediaStreamDevices::const_iterator it = std::find_if(
287 device_it->second.begin(), device_it->second.end(), 292 device_it->second.begin(), device_it->second.end(),
288 DeviceNameEquals(name)); 293 DeviceNameEquals(name));
289 if (it != device_it->second.end()) 294 if (it != device_it->second.end())
290 return it->device_id; 295 return it->device_id;
291 } 296 }
292 297
293 // Device is not available, return an empty string. 298 // Device is not available, return an empty string.
294 return std::string(); 299 return std::string();
295 } 300 }
296 301
297 std::string MediaStreamDevicesController::GetFirstDeviceId( 302 std::string MediaStreamDevicesController::GetFirstDeviceId(
298 content::MediaStreamDeviceType type) { 303 content::MediaStreamDeviceType type) {
299 content::MediaStreamDeviceMap::const_iterator device_it = 304 content::MediaStreamDeviceMap::const_iterator device_it =
300 request_.devices.find(type); 305 request_.devices.find(type);
301 if (device_it != request_.devices.end()) 306 if (device_it != request_.devices.end())
302 return device_it->second.begin()->device_id; 307 return device_it->second.begin()->device_id;
303 308
304 return std::string(); 309 return std::string();
305 } 310 }
311
312 void MediaStreamDevicesController::FindSubsetOfDevices(
313 FilterByDeviceTypeFunc is_included,
314 content::MediaStreamDevices* out) const {
315 for (content::MediaStreamDeviceMap::const_iterator it =
316 request_.devices.begin();
317 it != request_.devices.end(); ++it) {
318 if (is_included(it->first)) {
319 out->insert(out->end(), it->second.begin(), it->second.end());
320 }
321 }
322 }
323
324 const content::MediaStreamDevice*
325 MediaStreamDevicesController::FindFirstDeviceWithIdInSubset(
326 FilterByDeviceTypeFunc is_included,
327 const std::string& device_id) const {
328 for (content::MediaStreamDeviceMap::const_iterator it =
329 request_.devices.begin();
330 it != request_.devices.end(); ++it) {
331 if (!is_included(it->first)) {
332 continue;
333 }
334 for (content::MediaStreamDevices::const_iterator device_it =
335 it->second.begin();
336 device_it != it->second.end(); ++device_it) {
337 const content::MediaStreamDevice& candidate = *device_it;
338 if (candidate.device_id == device_id) {
339 return &candidate;
340 }
341 }
342 }
343 return NULL;
344 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698