OLD | NEW |
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/webrtc/media_stream_devices_controller.h" | 5 #include "chrome/browser/media/webrtc/media_stream_devices_controller.h" |
6 | 6 |
7 #include <map> | 7 #include <map> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 | 75 |
76 return false; | 76 return false; |
77 } | 77 } |
78 | 78 |
79 using PermissionActionCallback = | 79 using PermissionActionCallback = |
80 base::Callback<void(ContentSettingsType, | 80 base::Callback<void(ContentSettingsType, |
81 PermissionRequestGestureType, | 81 PermissionRequestGestureType, |
82 const GURL&, | 82 const GURL&, |
83 Profile*)>; | 83 Profile*)>; |
84 | 84 |
85 void RecordSinglePermissionAction(const content::MediaStreamRequest& request, | 85 // Calls |action_callback| for each permission requested. |
86 ContentSettingsType content_type, | 86 void RecordPermissionAction(bool is_asking_for_audio, |
87 Profile* profile, | 87 bool is_asking_for_video, |
88 PermissionActionCallback callback) { | 88 const GURL& security_origin, |
89 if (ContentTypeIsRequested(content_type, request)) { | 89 Profile* profile, |
90 // TODO(stefanocs): Pass the actual |gesture_type| once this file has been | 90 PermissionActionCallback action_callback) { |
91 // refactored into PermissionContext. | 91 // TODO(stefanocs): Pass the actual |gesture_type| once this file has been |
92 callback.Run(content_type, PermissionRequestGestureType::UNKNOWN, | 92 // refactored into PermissionContext. |
93 request.security_origin, profile); | 93 if (is_asking_for_audio) { |
| 94 action_callback.Run(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, |
| 95 PermissionRequestGestureType::UNKNOWN, security_origin, |
| 96 profile); |
| 97 } |
| 98 if (is_asking_for_video) { |
| 99 action_callback.Run(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, |
| 100 PermissionRequestGestureType::UNKNOWN, security_origin, |
| 101 profile); |
94 } | 102 } |
95 } | 103 } |
96 | 104 |
97 // Calls |action_function| for each permission requested by |request|. | |
98 void RecordPermissionAction(const content::MediaStreamRequest& request, | |
99 Profile* profile, | |
100 PermissionActionCallback callback) { | |
101 RecordSinglePermissionAction(request, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, | |
102 profile, callback); | |
103 RecordSinglePermissionAction( | |
104 request, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, profile, callback); | |
105 } | |
106 | |
107 #if defined(OS_ANDROID) | |
108 // Callback for the permission update infobar when the site and Chrome | |
109 // permissions are mismatched on Android. | |
110 void OnPermissionConflictResolved( | |
111 std::unique_ptr<MediaStreamDevicesController> controller, | |
112 bool allowed) { | |
113 if (allowed) | |
114 controller->PermissionGranted(); | |
115 else | |
116 controller->ForcePermissionDeniedTemporarily(); | |
117 } | |
118 | |
119 #endif // defined(OS_ANDROID) | |
120 | |
121 // This helper class helps to measure the number of media stream requests that | 105 // This helper class helps to measure the number of media stream requests that |
122 // occur. It ensures that only one request will be recorded per navigation, per | 106 // occur. It ensures that only one request will be recorded per navigation, per |
123 // frame. TODO(raymes): Remove this when https://crbug.com/526324 is fixed. | 107 // frame. TODO(raymes): Remove this when https://crbug.com/526324 is fixed. |
124 class MediaPermissionRequestLogger : content::WebContentsObserver { | 108 class MediaPermissionRequestLogger : content::WebContentsObserver { |
125 // Map of <render process id, render frame id> -> | 109 // Map of <render process id, render frame id> -> |
126 // MediaPermissionRequestLogger. | 110 // MediaPermissionRequestLogger. |
127 using RequestMap = std::map<std::pair<int, int>, | 111 using RequestMap = std::map<std::pair<int, int>, |
128 std::unique_ptr<MediaPermissionRequestLogger>>; | 112 std::unique_ptr<MediaPermissionRequestLogger>>; |
129 | 113 |
130 public: | 114 public: |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 void MediaStreamDevicesController::RegisterProfilePrefs( | 231 void MediaStreamDevicesController::RegisterProfilePrefs( |
248 user_prefs::PrefRegistrySyncable* prefs) { | 232 user_prefs::PrefRegistrySyncable* prefs) { |
249 prefs->RegisterBooleanPref(prefs::kVideoCaptureAllowed, true); | 233 prefs->RegisterBooleanPref(prefs::kVideoCaptureAllowed, true); |
250 prefs->RegisterBooleanPref(prefs::kAudioCaptureAllowed, true); | 234 prefs->RegisterBooleanPref(prefs::kAudioCaptureAllowed, true); |
251 prefs->RegisterListPref(prefs::kVideoCaptureAllowedUrls); | 235 prefs->RegisterListPref(prefs::kVideoCaptureAllowedUrls); |
252 prefs->RegisterListPref(prefs::kAudioCaptureAllowedUrls); | 236 prefs->RegisterListPref(prefs::kAudioCaptureAllowedUrls); |
253 } | 237 } |
254 | 238 |
255 MediaStreamDevicesController::~MediaStreamDevicesController() { | 239 MediaStreamDevicesController::~MediaStreamDevicesController() { |
256 if (!callback_.is_null()) { | 240 if (!callback_.is_null()) { |
257 RecordPermissionAction(request_, profile_, | 241 RecordPermissionAction(IsAskingForAudio(), IsAskingForVideo(), GetOrigin(), |
| 242 profile_, |
258 base::Bind(PermissionUmaUtil::PermissionIgnored)); | 243 base::Bind(PermissionUmaUtil::PermissionIgnored)); |
259 callback_.Run(content::MediaStreamDevices(), | 244 callback_.Run(content::MediaStreamDevices(), |
260 content::MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN, | 245 content::MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN, |
261 std::unique_ptr<content::MediaStreamUI>()); | 246 std::unique_ptr<content::MediaStreamUI>()); |
262 } | 247 } |
263 } | 248 } |
264 | 249 |
265 bool MediaStreamDevicesController::IsAskingForAudio() const { | 250 bool MediaStreamDevicesController::IsAskingForAudio() const { |
266 return old_audio_setting_ == CONTENT_SETTING_ASK; | 251 return old_audio_setting_ == CONTENT_SETTING_ASK; |
267 } | 252 } |
268 | 253 |
269 bool MediaStreamDevicesController::IsAskingForVideo() const { | 254 bool MediaStreamDevicesController::IsAskingForVideo() const { |
270 return old_video_setting_ == CONTENT_SETTING_ASK; | 255 return old_video_setting_ == CONTENT_SETTING_ASK; |
271 } | 256 } |
272 | 257 |
273 base::string16 MediaStreamDevicesController::GetMessageText() const { | 258 base::string16 MediaStreamDevicesController::GetMessageText() const { |
274 int message_id = IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO; | 259 int message_id = IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO; |
275 if (!IsAskingForAudio()) | 260 if (!IsAskingForAudio()) |
276 message_id = IDS_MEDIA_CAPTURE_VIDEO_ONLY; | 261 message_id = IDS_MEDIA_CAPTURE_VIDEO_ONLY; |
277 else if (!IsAskingForVideo()) | 262 else if (!IsAskingForVideo()) |
278 message_id = IDS_MEDIA_CAPTURE_AUDIO_ONLY; | 263 message_id = IDS_MEDIA_CAPTURE_AUDIO_ONLY; |
279 return l10n_util::GetStringFUTF16( | 264 return l10n_util::GetStringFUTF16( |
280 message_id, | 265 message_id, |
281 url_formatter::FormatUrlForSecurityDisplay( | 266 url_formatter::FormatUrlForSecurityDisplay( |
282 GetOrigin(), url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC)); | 267 GetOrigin(), url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC)); |
283 } | 268 } |
284 | 269 |
285 void MediaStreamDevicesController::ForcePermissionDeniedTemporarily() { | 270 #if defined(OS_ANDROID) |
286 set_persist(false); | 271 void MediaStreamDevicesController::AndroidOSPromptAnswered(bool allowed) { |
287 // TODO(tsergeant): Determine whether it is appropriate to record permission | 272 DCHECK(old_audio_setting_ != CONTENT_SETTING_ASK && |
288 // action metrics here, as this is a different sort of user action. | 273 old_video_setting_ != CONTENT_SETTING_ASK); |
289 RunCallback(CONTENT_SETTING_BLOCK, | 274 |
290 CONTENT_SETTING_BLOCK, | 275 ContentSetting audio_setting = old_audio_setting_; |
| 276 ContentSetting video_setting = old_video_setting_; |
| 277 |
| 278 if (!allowed) { |
| 279 // Only permissions that were previously ALLOW for a site will have had |
| 280 // their android permissions requested. It's only in that case that we need |
| 281 // to change the setting to BLOCK to reflect that it wasn't allowed. |
| 282 if (audio_setting == CONTENT_SETTING_ALLOW) |
| 283 audio_setting = CONTENT_SETTING_BLOCK; |
| 284 if (video_setting == CONTENT_SETTING_ALLOW) |
| 285 video_setting = CONTENT_SETTING_BLOCK; |
| 286 } |
| 287 |
| 288 RunCallback(audio_setting, video_setting, |
291 content::MEDIA_DEVICE_PERMISSION_DENIED); | 289 content::MEDIA_DEVICE_PERMISSION_DENIED); |
292 set_persist(true); | |
293 } | 290 } |
| 291 #endif // defined(OS_ANDROID) |
294 | 292 |
295 PermissionRequest::IconId MediaStreamDevicesController::GetIconId() const { | 293 PermissionRequest::IconId MediaStreamDevicesController::GetIconId() const { |
296 #if defined(OS_ANDROID) | 294 #if defined(OS_ANDROID) |
297 return IsAskingForVideo() ? IDR_INFOBAR_MEDIA_STREAM_CAMERA | 295 return IsAskingForVideo() ? IDR_INFOBAR_MEDIA_STREAM_CAMERA |
298 : IDR_INFOBAR_MEDIA_STREAM_MIC; | 296 : IDR_INFOBAR_MEDIA_STREAM_MIC; |
299 #else | 297 #else |
300 return IsAskingForVideo() ? ui::kVideocamIcon : ui::kMicrophoneIcon; | 298 return IsAskingForVideo() ? ui::kVideocamIcon : ui::kMicrophoneIcon; |
301 #endif | 299 #endif |
302 } | 300 } |
303 | 301 |
304 base::string16 MediaStreamDevicesController::GetMessageTextFragment() const { | 302 base::string16 MediaStreamDevicesController::GetMessageTextFragment() const { |
305 int message_id = IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO_PERMISSION_FRAGMENT; | 303 int message_id = IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO_PERMISSION_FRAGMENT; |
306 if (!IsAskingForAudio()) | 304 if (!IsAskingForAudio()) |
307 message_id = IDS_MEDIA_CAPTURE_VIDEO_ONLY_PERMISSION_FRAGMENT; | 305 message_id = IDS_MEDIA_CAPTURE_VIDEO_ONLY_PERMISSION_FRAGMENT; |
308 else if (!IsAskingForVideo()) | 306 else if (!IsAskingForVideo()) |
309 message_id = IDS_MEDIA_CAPTURE_AUDIO_ONLY_PERMISSION_FRAGMENT; | 307 message_id = IDS_MEDIA_CAPTURE_AUDIO_ONLY_PERMISSION_FRAGMENT; |
310 return l10n_util::GetStringUTF16(message_id); | 308 return l10n_util::GetStringUTF16(message_id); |
311 } | 309 } |
312 | 310 |
313 GURL MediaStreamDevicesController::GetOrigin() const { | 311 GURL MediaStreamDevicesController::GetOrigin() const { |
314 return request_.security_origin; | 312 return request_.security_origin; |
315 } | 313 } |
316 | 314 |
317 void MediaStreamDevicesController::PermissionGranted() { | 315 void MediaStreamDevicesController::PermissionGranted() { |
318 RecordPermissionAction(request_, profile_, | 316 RecordPermissionAction(IsAskingForAudio(), IsAskingForVideo(), GetOrigin(), |
| 317 profile_, |
319 base::Bind(PermissionUmaUtil::PermissionGranted)); | 318 base::Bind(PermissionUmaUtil::PermissionGranted)); |
320 RunCallback(GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, | 319 RunCallback(GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, |
321 old_audio_setting_, CONTENT_SETTING_ALLOW), | 320 old_audio_setting_, CONTENT_SETTING_ALLOW), |
322 GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, | 321 GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, |
323 old_video_setting_, CONTENT_SETTING_ALLOW), | 322 old_video_setting_, CONTENT_SETTING_ALLOW), |
324 content::MEDIA_DEVICE_PERMISSION_DENIED); | 323 content::MEDIA_DEVICE_PERMISSION_DENIED); |
325 } | 324 } |
326 | 325 |
327 void MediaStreamDevicesController::PermissionDenied() { | 326 void MediaStreamDevicesController::PermissionDenied() { |
328 RecordPermissionAction(request_, profile_, | 327 RecordPermissionAction(IsAskingForAudio(), IsAskingForVideo(), GetOrigin(), |
| 328 profile_, |
329 base::Bind(PermissionUmaUtil::PermissionDenied)); | 329 base::Bind(PermissionUmaUtil::PermissionDenied)); |
330 RunCallback(GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, | 330 RunCallback(GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, |
331 old_audio_setting_, CONTENT_SETTING_BLOCK), | 331 old_audio_setting_, CONTENT_SETTING_BLOCK), |
332 GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, | 332 GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, |
333 old_video_setting_, CONTENT_SETTING_BLOCK), | 333 old_video_setting_, CONTENT_SETTING_BLOCK), |
334 content::MEDIA_DEVICE_PERMISSION_DENIED); | 334 content::MEDIA_DEVICE_PERMISSION_DENIED); |
335 } | 335 } |
336 | 336 |
337 bool MediaStreamDevicesController::ShouldShowPersistenceToggle() const { | 337 bool MediaStreamDevicesController::ShouldShowPersistenceToggle() const { |
338 return PermissionUtil::ShouldShowPersistenceToggle(); | 338 return PermissionUtil::ShouldShowPersistenceToggle(); |
339 } | 339 } |
340 | 340 |
341 void MediaStreamDevicesController::Cancelled() { | 341 void MediaStreamDevicesController::Cancelled() { |
342 RecordPermissionAction(request_, profile_, | 342 RecordPermissionAction(IsAskingForAudio(), IsAskingForVideo(), GetOrigin(), |
| 343 profile_, |
343 base::Bind(PermissionUmaUtil::PermissionDismissed)); | 344 base::Bind(PermissionUmaUtil::PermissionDismissed)); |
344 RunCallback(old_audio_setting_, old_video_setting_, | 345 RunCallback(old_audio_setting_, old_video_setting_, |
345 content::MEDIA_DEVICE_PERMISSION_DISMISSED); | 346 content::MEDIA_DEVICE_PERMISSION_DISMISSED); |
346 } | 347 } |
347 | 348 |
348 void MediaStreamDevicesController::RequestFinished() { | 349 void MediaStreamDevicesController::RequestFinished() { |
349 delete this; | 350 delete this; |
350 } | 351 } |
351 | 352 |
352 PermissionRequestType MediaStreamDevicesController::GetPermissionRequestType() | 353 PermissionRequestType MediaStreamDevicesController::GetPermissionRequestType() |
(...skipping 29 matching lines...) Expand all Loading... |
382 | 383 |
383 if (controller->IsAllowedForVideo()) { | 384 if (controller->IsAllowedForVideo()) { |
384 content_settings_types.push_back( | 385 content_settings_types.push_back( |
385 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA); | 386 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA); |
386 } | 387 } |
387 if (!content_settings_types.empty() && | 388 if (!content_settings_types.empty() && |
388 PermissionUpdateInfoBarDelegate::ShouldShowPermissionInfobar( | 389 PermissionUpdateInfoBarDelegate::ShouldShowPermissionInfobar( |
389 web_contents, content_settings_types)) { | 390 web_contents, content_settings_types)) { |
390 PermissionUpdateInfoBarDelegate::Create( | 391 PermissionUpdateInfoBarDelegate::Create( |
391 web_contents, content_settings_types, | 392 web_contents, content_settings_types, |
392 base::Bind(&OnPermissionConflictResolved, base::Passed(&controller))); | 393 base::Bind(&MediaStreamDevicesController::AndroidOSPromptAnswered, |
| 394 base::Passed(&controller))); |
393 } | 395 } |
394 #endif | 396 #endif |
395 return; | 397 return; |
396 } | 398 } |
397 | 399 |
398 delegate->ShowPrompt(request.user_gesture, web_contents, | 400 delegate->ShowPrompt(request.user_gesture, web_contents, |
399 std::move(controller)); | 401 std::move(controller)); |
400 } | 402 } |
401 | 403 |
402 MediaStreamDevicesController::MediaStreamDevicesController( | 404 MediaStreamDevicesController::MediaStreamDevicesController( |
(...skipping 319 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
722 } | 724 } |
723 } | 725 } |
724 | 726 |
725 // Don't approve device requests if the tab was hidden. | 727 // Don't approve device requests if the tab was hidden. |
726 // TODO(qinmin): Add a test for this. http://crbug.com/396869. | 728 // TODO(qinmin): Add a test for this. http://crbug.com/396869. |
727 // TODO(raymes): Shouldn't this apply to all permissions not just audio/video? | 729 // TODO(raymes): Shouldn't this apply to all permissions not just audio/video? |
728 return web_contents_->GetRenderWidgetHostView()->IsShowing(); | 730 return web_contents_->GetRenderWidgetHostView()->IsShowing(); |
729 #endif | 731 #endif |
730 return true; | 732 return true; |
731 } | 733 } |
OLD | NEW |