| 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 |