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

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: Add CONTENT_EXPORT to resolve linker issues on components builds. Also, IWYU. 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;
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::IsAudioMediaStreamDeviceType(it->first)) {
55 has_audio_ |= !it->second.empty();
56 } else if (content::IsVideoMediaStreamDeviceType(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 FindSubsetOfDevices(&content::IsAudioMediaStreamDeviceType,
123 107 &all_audio_devices);
124 content::MediaStreamDeviceMap::const_iterator it = 108 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 } 109 }
129 110
130 content::MediaStreamDevices 111 content::MediaStreamDevices
131 MediaStreamDevicesController::GetVideoDevices() const { 112 MediaStreamDevicesController::GetVideoDevices() const {
132 if (!has_video_) 113 content::MediaStreamDevices all_video_devices;
133 return content::MediaStreamDevices(); 114 FindSubsetOfDevices(&content::IsVideoMediaStreamDeviceType,
134 115 &all_video_devices);
135 content::MediaStreamDeviceMap::const_iterator it = 116 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 } 117 }
140 118
141 const GURL& MediaStreamDevicesController::GetSecurityOrigin() const { 119 const std::string& MediaStreamDevicesController::GetSecurityOriginSpec() const {
142 return request_.security_origin; 120 return request_.security_origin.spec();
121 }
122
123 bool MediaStreamDevicesController::IsSafeToAlwaysAllowAudio() const {
124 return IsSafeToAlwaysAllow(
125 &content::IsAudioMediaStreamDeviceType,
126 content::MEDIA_STREAM_DEVICE_TYPE_USER_AUDIO_CAPTURE);
127 }
128
129 bool MediaStreamDevicesController::IsSafeToAlwaysAllowVideo() const {
130 return IsSafeToAlwaysAllow(
131 &content::IsVideoMediaStreamDeviceType,
132 content::MEDIA_STREAM_DEVICE_TYPE_USER_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::IsAudioMediaStreamDeviceType,
143 audio_id);
144 if (audio_device) {
145 if (audio_device->type !=
146 content::MEDIA_STREAM_DEVICE_TYPE_USER_AUDIO_CAPTURE) {
147 always_allow = false; // override for non-user audio device type
148 }
149 devices.push_back(*audio_device);
150 audio_device_name = audio_device->name;
153 } 151 }
154 if (has_video_) { 152
155 AddDeviceWithId(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE, 153 const content::MediaStreamDevice* const video_device =
156 video_id, &devices, &video_device); 154 FindFirstDeviceWithIdInSubset(&content::IsVideoMediaStreamDeviceType,
155 video_id);
156 if (video_device) {
157 if (video_device->type !=
158 content::MEDIA_STREAM_DEVICE_TYPE_USER_VIDEO_CAPTURE) {
159 always_allow = false; // override for non-user video device type
160 }
161 devices.push_back(*video_device);
162 video_device_name = video_device->name;
157 } 163 }
164
158 DCHECK(!devices.empty()); 165 DCHECK(!devices.empty());
159 166
160 if (always_allow) 167 if (always_allow)
161 AlwaysAllowOriginAndDevices(audio_device, video_device); 168 AlwaysAllowOriginAndDevices(audio_device_name, video_device_name);
162 169
163 callback_.Run(devices); 170 callback_.Run(devices);
164 } 171 }
165 172
166 void MediaStreamDevicesController::Deny() { 173 void MediaStreamDevicesController::Deny() {
167 callback_.Run(content::MediaStreamDevices()); 174 callback_.Run(content::MediaStreamDevices());
168 } 175 }
169 176
170 void MediaStreamDevicesController::AddDeviceWithId( 177 bool MediaStreamDevicesController::IsSafeToAlwaysAllow(
171 content::MediaStreamDeviceType type, 178 FilterByDeviceTypeFunc is_included,
172 const std::string& id, 179 content::MediaStreamDeviceType user_type) const {
173 content::MediaStreamDevices* devices, 180 DCHECK(user_type == content::MEDIA_STREAM_DEVICE_TYPE_USER_AUDIO_CAPTURE ||
174 std::string* device_name) { 181 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 182
181 content::MediaStreamDevices::const_iterator it = std::find_if( 183 if (!request_.security_origin.SchemeIsSecure()) {
182 device_it->second.begin(), device_it->second.end(), DeviceIdEquals(id)); 184 return false;
183 if (it == device_it->second.end()) 185 }
184 return;
185 186
186 devices->push_back(*it); 187 // If non-user devices are available for the choosing, then it's not safe.
187 *device_name = it->name; 188 for (content::MediaStreamDeviceMap::const_iterator it =
189 request_.devices.begin();
190 it != request_.devices.end(); ++it) {
191 if (it->first != user_type && is_included(it->first)) {
192 return false;
no longer working on chromium 2012/08/31 13:38:23 I may miss something here, how possibly get into t
miu 2012/09/01 01:32:00 Example: When checking the video devices, if it->f
193 }
194 }
195
196 return true;
188 } 197 }
189 198
190 bool MediaStreamDevicesController::ShouldAlwaysAllowOrigin() { 199 bool MediaStreamDevicesController::ShouldAlwaysAllowOrigin() {
191 return profile_->GetHostContentSettingsMap()->ShouldAllowAllContent( 200 return profile_->GetHostContentSettingsMap()->ShouldAllowAllContent(
192 request_.security_origin, request_.security_origin, 201 request_.security_origin, request_.security_origin,
193 CONTENT_SETTINGS_TYPE_MEDIASTREAM); 202 CONTENT_SETTINGS_TYPE_MEDIASTREAM);
194 } 203 }
195 204
196 bool MediaStreamDevicesController::IsMediaDeviceBlocked() { 205 bool MediaStreamDevicesController::IsMediaDeviceBlocked() {
197 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 206 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
(...skipping 27 matching lines...) Expand all
225 234
226 void MediaStreamDevicesController::GetAlwaysAllowedDevices( 235 void MediaStreamDevicesController::GetAlwaysAllowedDevices(
227 std::string* audio_id, std::string* video_id) { 236 std::string* audio_id, std::string* video_id) {
228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 237 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
229 DCHECK(audio_id->empty()); 238 DCHECK(audio_id->empty());
230 DCHECK(video_id->empty()); 239 DCHECK(video_id->empty());
231 // If the request is from internal objects like chrome://URLs, use the first 240 // If the request is from internal objects like chrome://URLs, use the first
232 // devices on the lists. 241 // devices on the lists.
233 if (ShouldAlwaysAllowOrigin()) { 242 if (ShouldAlwaysAllowOrigin()) {
234 if (has_audio_) { 243 if (has_audio_) {
235 *audio_id = 244 *audio_id = GetFirstDeviceId(
236 GetFirstDeviceId(content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE); 245 content::MEDIA_STREAM_DEVICE_TYPE_USER_AUDIO_CAPTURE);
237 } 246 }
238 if (has_video_) { 247 if (has_video_) {
239 *video_id = 248 *video_id = GetFirstDeviceId(
240 GetFirstDeviceId(content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE); 249 content::MEDIA_STREAM_DEVICE_TYPE_USER_VIDEO_CAPTURE);
241 } 250 }
242 return; 251 return;
243 } 252 }
244 253
245 // "Always allowed" option is only available for secure connection. 254 // "Always allowed" option is only available for secure connection.
246 if (!request_.security_origin.SchemeIsSecure()) 255 if (!request_.security_origin.SchemeIsSecure())
247 return; 256 return;
248 257
249 // Checks the media exceptions to get the "always allowed" devices. 258 // Checks the media exceptions to get the "always allowed" devices.
250 scoped_ptr<Value> value( 259 scoped_ptr<Value> value(
(...skipping 11 matching lines...) Expand all
262 const DictionaryValue* value_dict = NULL; 271 const DictionaryValue* value_dict = NULL;
263 if (!value->GetAsDictionary(&value_dict) || value_dict->empty()) 272 if (!value->GetAsDictionary(&value_dict) || value_dict->empty())
264 return; 273 return;
265 274
266 std::string audio_name, video_name; 275 std::string audio_name, video_name;
267 value_dict->GetString(kAudioKey, &audio_name); 276 value_dict->GetString(kAudioKey, &audio_name);
268 value_dict->GetString(kVideoKey, &video_name); 277 value_dict->GetString(kVideoKey, &video_name);
269 278
270 if (has_audio_ && !audio_name.empty()) { 279 if (has_audio_ && !audio_name.empty()) {
271 *audio_id = GetDeviceIdByName( 280 *audio_id = GetDeviceIdByName(
272 content::MEDIA_STREAM_DEVICE_TYPE_AUDIO_CAPTURE, audio_name); 281 content::MEDIA_STREAM_DEVICE_TYPE_USER_AUDIO_CAPTURE, audio_name);
273 } 282 }
274 if (has_video_ && !video_name.empty()) { 283 if (has_video_ && !video_name.empty()) {
275 *video_id = GetDeviceIdByName( 284 *video_id = GetDeviceIdByName(
276 content::MEDIA_STREAM_DEVICE_TYPE_VIDEO_CAPTURE, video_name); 285 content::MEDIA_STREAM_DEVICE_TYPE_USER_VIDEO_CAPTURE, video_name);
277 } 286 }
278 } 287 }
279 288
280 std::string MediaStreamDevicesController::GetDeviceIdByName( 289 std::string MediaStreamDevicesController::GetDeviceIdByName(
281 content::MediaStreamDeviceType type, 290 content::MediaStreamDeviceType type,
282 const std::string& name) { 291 const std::string& name) {
283 content::MediaStreamDeviceMap::const_iterator device_it = 292 content::MediaStreamDeviceMap::const_iterator device_it =
284 request_.devices.find(type); 293 request_.devices.find(type);
285 if (device_it != request_.devices.end()) { 294 if (device_it != request_.devices.end()) {
286 content::MediaStreamDevices::const_iterator it = std::find_if( 295 content::MediaStreamDevices::const_iterator it = std::find_if(
287 device_it->second.begin(), device_it->second.end(), 296 device_it->second.begin(), device_it->second.end(),
288 DeviceNameEquals(name)); 297 DeviceNameEquals(name));
289 if (it != device_it->second.end()) 298 if (it != device_it->second.end())
290 return it->device_id; 299 return it->device_id;
291 } 300 }
292 301
293 // Device is not available, return an empty string. 302 // Device is not available, return an empty string.
294 return std::string(); 303 return std::string();
295 } 304 }
296 305
297 std::string MediaStreamDevicesController::GetFirstDeviceId( 306 std::string MediaStreamDevicesController::GetFirstDeviceId(
298 content::MediaStreamDeviceType type) { 307 content::MediaStreamDeviceType type) {
299 content::MediaStreamDeviceMap::const_iterator device_it = 308 content::MediaStreamDeviceMap::const_iterator device_it =
300 request_.devices.find(type); 309 request_.devices.find(type);
301 if (device_it != request_.devices.end()) 310 if (device_it != request_.devices.end())
302 return device_it->second.begin()->device_id; 311 return device_it->second.begin()->device_id;
303 312
304 return std::string(); 313 return std::string();
305 } 314 }
315
316 void MediaStreamDevicesController::FindSubsetOfDevices(
317 FilterByDeviceTypeFunc is_included,
318 content::MediaStreamDevices* out) const {
319 for (content::MediaStreamDeviceMap::const_iterator it =
320 request_.devices.begin();
321 it != request_.devices.end(); ++it) {
322 if (is_included(it->first)) {
323 out->insert(out->end(), it->second.begin(), it->second.end());
324 }
325 }
326 }
327
328 const content::MediaStreamDevice*
329 MediaStreamDevicesController::FindFirstDeviceWithIdInSubset(
330 FilterByDeviceTypeFunc is_included,
331 const std::string& device_id) const {
332 for (content::MediaStreamDeviceMap::const_iterator it =
333 request_.devices.begin();
334 it != request_.devices.end(); ++it) {
335 if (!is_included(it->first)) {
336 continue;
337 }
338 for (content::MediaStreamDevices::const_iterator device_it =
339 it->second.begin();
340 device_it != it->second.end(); ++device_it) {
341 const content::MediaStreamDevice& candidate = *device_it;
no longer working on chromium 2012/08/31 13:38:23 Do we need this local variable?
miu 2012/09/01 01:32:00 No. I did it for readability (no runtime cost sin
342 if (candidate.device_id == device_id) {
343 return &candidate;
344 }
345 }
346 }
347 return NULL;
348 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698