| 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" |
| 11 #include "base/command_line.h" |
| 11 #include "base/memory/ptr_util.h" | 12 #include "base/memory/ptr_util.h" |
| 12 #include "base/metrics/histogram_macros.h" | 13 #include "base/metrics/histogram_macros.h" |
| 13 #include "base/strings/utf_string_conversions.h" | 14 #include "base/strings/utf_string_conversions.h" |
| 14 #include "base/values.h" | 15 #include "base/values.h" |
| 15 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | 16 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
| 16 #include "chrome/browser/content_settings/tab_specific_content_settings.h" | 17 #include "chrome/browser/content_settings/tab_specific_content_settings.h" |
| 17 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h" | 18 #include "chrome/browser/media/webrtc/media_capture_devices_dispatcher.h" |
| 18 #include "chrome/browser/media/webrtc/media_stream_capture_indicator.h" | 19 #include "chrome/browser/media/webrtc/media_stream_capture_indicator.h" |
| 19 #include "chrome/browser/media/webrtc/media_stream_device_permissions.h" | 20 #include "chrome/browser/media/webrtc/media_stream_device_permissions.h" |
| 20 #include "chrome/browser/permissions/permission_manager.h" | 21 #include "chrome/browser/permissions/permission_manager.h" |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 75 | 76 |
| 76 return false; | 77 return false; |
| 77 } | 78 } |
| 78 | 79 |
| 79 using PermissionActionCallback = | 80 using PermissionActionCallback = |
| 80 base::Callback<void(ContentSettingsType, | 81 base::Callback<void(ContentSettingsType, |
| 81 PermissionRequestGestureType, | 82 PermissionRequestGestureType, |
| 82 const GURL&, | 83 const GURL&, |
| 83 Profile*)>; | 84 Profile*)>; |
| 84 | 85 |
| 85 void RecordSinglePermissionAction(const content::MediaStreamRequest& request, | 86 |
| 86 ContentSettingsType content_type, | 87 // Calls |action_function| for each permission requested by |request|. |
| 87 Profile* profile, | 88 void RecordPermissionAction(bool is_asking_for_audio, |
| 88 PermissionActionCallback callback) { | 89 bool is_asking_for_video, |
| 89 if (ContentTypeIsRequested(content_type, request)) { | 90 const GURL& security_origin, |
| 90 // TODO(stefanocs): Pass the actual |gesture_type| once this file has been | 91 Profile* profile, |
| 91 // refactored into PermissionContext. | 92 PermissionActionCallback callback) { |
| 92 callback.Run(content_type, PermissionRequestGestureType::UNKNOWN, | 93 // TODO(stefanocs): Pass the actual |gesture_type| once this file has been |
| 93 request.security_origin, profile); | 94 // refactored into PermissionContext. |
| 95 if (is_asking_for_audio) { |
| 96 callback.Run(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, |
| 97 PermissionRequestGestureType::UNKNOWN, security_origin, |
| 98 profile); |
| 99 } |
| 100 |
| 101 if (is_asking_for_video) { |
| 102 callback.Run(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, |
| 103 PermissionRequestGestureType::UNKNOWN, security_origin, |
| 104 profile); |
| 94 } | 105 } |
| 95 } | 106 } |
| 96 | 107 |
| 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 | 108 // 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 | 109 // 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. | 110 // frame. TODO(raymes): Remove this when https://crbug.com/526324 is fixed. |
| 124 class MediaPermissionRequestLogger : content::WebContentsObserver { | 111 class MediaPermissionRequestLogger : content::WebContentsObserver { |
| 125 // Map of <render process id, render frame id> -> | 112 // Map of <render process id, render frame id> -> |
| 126 // MediaPermissionRequestLogger. | 113 // MediaPermissionRequestLogger. |
| 127 using RequestMap = std::map<std::pair<int, int>, | 114 using RequestMap = std::map<std::pair<int, int>, |
| 128 std::unique_ptr<MediaPermissionRequestLogger>>; | 115 std::unique_ptr<MediaPermissionRequestLogger>>; |
| 129 | 116 |
| 130 public: | 117 public: |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 // device id is non-empty, then the corresponding device list must not be | 186 // device id is non-empty, then the corresponding device list must not be |
| 200 // NULL. | 187 // NULL. |
| 201 if (!device_id.empty() && !devices->FindById(device_id)) | 188 if (!device_id.empty() && !devices->FindById(device_id)) |
| 202 return false; | 189 return false; |
| 203 | 190 |
| 204 return true; | 191 return true; |
| 205 } | 192 } |
| 206 | 193 |
| 207 } // namespace | 194 } // namespace |
| 208 | 195 |
| 209 // Stores whether a permission has been requested or blocked during the course | 196 namespace internal { |
| 210 // of a permission request, as well as the denial reason | |
| 211 class MediaStreamDevicesController::MediaPermissionStatus { | |
| 212 public: | |
| 213 explicit MediaPermissionStatus(const content::MediaStreamRequest& request) | |
| 214 : audio_requested_( | |
| 215 ContentTypeIsRequested(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, | |
| 216 request)), | |
| 217 video_requested_( | |
| 218 ContentTypeIsRequested(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, | |
| 219 request)) {} | |
| 220 | 197 |
| 221 ~MediaPermissionStatus() {} | 198 MediaStreamPermissionRequest::MediaStreamPermissionRequest( |
| 199 Profile* profile, |
| 200 bool is_asking_for_audio, |
| 201 bool is_asking_for_video, |
| 202 GURL security_origin, |
| 203 base::Callback<void(ContentSetting, bool)> prompt_answered_callback) |
| 204 : profile_(profile), |
| 205 is_asking_for_audio_(is_asking_for_audio), |
| 206 is_asking_for_video_(is_asking_for_video), |
| 207 security_origin_(security_origin), |
| 208 prompt_answered_callback_(prompt_answered_callback) {} |
| 222 | 209 |
| 223 bool audio_requested() const { return audio_requested_; } | 210 MediaStreamPermissionRequest::~MediaStreamPermissionRequest() { |
| 224 bool video_requested() const { return video_requested_; } | 211 RecordPermissionAction(is_asking_for_audio_, is_asking_for_video_, |
| 212 security_origin_, profile_, |
| 213 base::Bind(PermissionUmaUtil::PermissionIgnored)); |
| 214 } |
| 225 | 215 |
| 226 bool audio_blocked() const { return audio_blocked_; } | 216 bool MediaStreamPermissionRequest::IsAskingForAudio() const { |
| 227 bool video_blocked() const { return video_blocked_; } | 217 return is_asking_for_audio_; |
| 218 } |
| 228 | 219 |
| 229 content::MediaStreamRequestResult denial_reason() const { | 220 bool MediaStreamPermissionRequest::IsAskingForVideo() const { |
| 230 return denial_reason_; | 221 return is_asking_for_video_; |
| 231 } | 222 } |
| 232 | 223 |
| 233 void SetAudioBlocked(content::MediaStreamRequestResult denial_reason) { | 224 base::string16 MediaStreamPermissionRequest::GetMessageText() const { |
| 234 DCHECK(audio_requested_); | 225 int message_id = IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO; |
| 235 audio_blocked_ = true; | 226 if (!IsAskingForAudio()) |
| 236 denial_reason_ = denial_reason; | 227 message_id = IDS_MEDIA_CAPTURE_VIDEO_ONLY; |
| 237 } | 228 else if (!IsAskingForVideo()) |
| 229 message_id = IDS_MEDIA_CAPTURE_AUDIO_ONLY; |
| 230 return l10n_util::GetStringFUTF16( |
| 231 message_id, |
| 232 url_formatter::FormatUrlForSecurityDisplay( |
| 233 GetOrigin(), url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC)); |
| 234 } |
| 238 | 235 |
| 239 void SetVideoBlocked(content::MediaStreamRequestResult denial_reason) { | 236 PermissionRequest::IconId MediaStreamPermissionRequest::GetIconId() const { |
| 240 DCHECK(video_requested_); | 237 #if defined(OS_ANDROID) |
| 241 video_blocked_ = true; | 238 return IsAskingForVideo() ? IDR_INFOBAR_MEDIA_STREAM_CAMERA |
| 242 denial_reason_ = denial_reason; | 239 : IDR_INFOBAR_MEDIA_STREAM_MIC; |
| 243 } | 240 #else |
| 241 return IsAskingForVideo() ? ui::kVideocamIcon : ui::kMicrophoneIcon; |
| 242 #endif |
| 243 } |
| 244 | 244 |
| 245 private: | 245 base::string16 MediaStreamPermissionRequest::GetMessageTextFragment() const { |
| 246 bool audio_requested_ = false; | 246 int message_id = IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO_PERMISSION_FRAGMENT; |
| 247 bool video_requested_ = false; | 247 if (!IsAskingForAudio()) |
| 248 bool audio_blocked_ = false; | 248 message_id = IDS_MEDIA_CAPTURE_VIDEO_ONLY_PERMISSION_FRAGMENT; |
| 249 bool video_blocked_ = false; | 249 else if (!IsAskingForVideo()) |
| 250 message_id = IDS_MEDIA_CAPTURE_AUDIO_ONLY_PERMISSION_FRAGMENT; |
| 251 return l10n_util::GetStringUTF16(message_id); |
| 252 } |
| 250 | 253 |
| 251 content::MediaStreamRequestResult denial_reason_ = content::MEDIA_DEVICE_OK; | 254 GURL MediaStreamPermissionRequest::GetOrigin() const { |
| 252 }; | 255 return security_origin_; |
| 256 } |
| 257 |
| 258 void MediaStreamPermissionRequest::PermissionGranted() { |
| 259 RecordPermissionAction(is_asking_for_audio_, is_asking_for_video_, |
| 260 security_origin_, profile_, |
| 261 base::Bind(PermissionUmaUtil::PermissionGranted)); |
| 262 prompt_answered_callback_.Run(CONTENT_SETTING_ALLOW, persist()); |
| 263 } |
| 264 |
| 265 void MediaStreamPermissionRequest::PermissionDenied() { |
| 266 RecordPermissionAction(is_asking_for_audio_, is_asking_for_video_, |
| 267 security_origin_, profile_, |
| 268 base::Bind(PermissionUmaUtil::PermissionDenied)); |
| 269 prompt_answered_callback_.Run(CONTENT_SETTING_BLOCK, persist()); |
| 270 } |
| 271 |
| 272 bool MediaStreamPermissionRequest::ShouldShowPersistenceToggle() const { |
| 273 return PermissionUtil::ShouldShowPersistenceToggle(); |
| 274 } |
| 275 |
| 276 void MediaStreamPermissionRequest::Cancelled() { |
| 277 RecordPermissionAction(is_asking_for_audio_, is_asking_for_video_, |
| 278 security_origin_, profile_, |
| 279 base::Bind(PermissionUmaUtil::PermissionDismissed)); |
| 280 prompt_answered_callback_.Run(CONTENT_SETTING_ASK, persist()); |
| 281 } |
| 282 |
| 283 void MediaStreamPermissionRequest::RequestFinished() { |
| 284 delete this; |
| 285 } |
| 286 |
| 287 PermissionRequestType MediaStreamPermissionRequest::GetPermissionRequestType() |
| 288 const { |
| 289 return PermissionRequestType::MEDIA_STREAM; |
| 290 } |
| 291 |
| 292 } // namespace internal |
| 253 | 293 |
| 254 // Implementation of PermissionPromptDelegate which actually shows a permission | 294 // Implementation of PermissionPromptDelegate which actually shows a permission |
| 255 // prompt. | 295 // prompt. |
| 256 class MediaStreamDevicesController::PermissionPromptDelegateImpl | 296 class MediaStreamDevicesController::PermissionPromptDelegateImpl |
| 257 : public internal::PermissionPromptDelegate { | 297 : public internal::PermissionPromptDelegate { |
| 258 public: | 298 public: |
| 259 void ShowPrompt( | 299 void ShowPrompt(bool user_gesture, |
| 260 bool user_gesture, | 300 content::WebContents* web_contents, |
| 261 content::WebContents* web_contents, | 301 std::unique_ptr<internal::MediaStreamPermissionRequest> |
| 262 std::unique_ptr<MediaStreamDevicesController> controller) override { | 302 request) override { |
| 263 #if defined(OS_ANDROID) | 303 #if defined(OS_ANDROID) |
| 264 PermissionUmaUtil::RecordPermissionPromptShown( | 304 PermissionUmaUtil::RecordPermissionPromptShown( |
| 265 controller->GetPermissionRequestType(), | 305 request->GetPermissionRequestType(), |
| 266 PermissionUtil::GetGestureType(user_gesture)); | 306 PermissionUtil::GetGestureType(user_gesture)); |
| 267 if (PermissionDialogDelegate::ShouldShowDialog(user_gesture)) { | 307 if (PermissionDialogDelegate::ShouldShowDialog(user_gesture)) { |
| 268 PermissionDialogDelegate::CreateMediaStreamDialog( | 308 PermissionDialogDelegate::CreateMediaStreamDialog( |
| 269 web_contents, user_gesture, std::move(controller)); | 309 web_contents, user_gesture, std::move(request)); |
| 270 } else { | 310 } else { |
| 271 MediaStreamInfoBarDelegateAndroid::Create(web_contents, user_gesture, | 311 MediaStreamInfoBarDelegateAndroid::Create(web_contents, user_gesture, |
| 272 std::move(controller)); | 312 std::move(request)); |
| 273 } | 313 } |
| 274 #else | 314 #else |
| 275 PermissionRequestManager* permission_request_manager = | 315 PermissionRequestManager* permission_request_manager = |
| 276 PermissionRequestManager::FromWebContents(web_contents); | 316 PermissionRequestManager::FromWebContents(web_contents); |
| 277 if (permission_request_manager) | 317 if (permission_request_manager) |
| 278 permission_request_manager->AddRequest(controller.release()); | 318 permission_request_manager->AddRequest(request.release()); |
| 279 #endif | 319 #endif |
| 280 } | 320 } |
| 281 }; | 321 }; |
| 282 | 322 |
| 283 // static | 323 // static |
| 284 void MediaStreamDevicesController::RequestPermissions( | 324 void MediaStreamDevicesController::RequestPermissions( |
| 285 const content::MediaStreamRequest& request, | 325 const content::MediaStreamRequest& request, |
| 286 const content::MediaResponseCallback& callback) { | 326 const content::MediaResponseCallback& callback) { |
| 287 PermissionPromptDelegateImpl delegate; | 327 PermissionPromptDelegateImpl delegate; |
| 288 RequestPermissionsWithDelegate(request, callback, &delegate); | 328 RequestPermissionsWithDelegate(request, callback, &delegate); |
| 289 } | 329 } |
| 290 | 330 |
| 291 // static | 331 // static |
| 292 void MediaStreamDevicesController::RegisterProfilePrefs( | 332 void MediaStreamDevicesController::RegisterProfilePrefs( |
| 293 user_prefs::PrefRegistrySyncable* prefs) { | 333 user_prefs::PrefRegistrySyncable* prefs) { |
| 294 prefs->RegisterBooleanPref(prefs::kVideoCaptureAllowed, true); | 334 prefs->RegisterBooleanPref(prefs::kVideoCaptureAllowed, true); |
| 295 prefs->RegisterBooleanPref(prefs::kAudioCaptureAllowed, true); | 335 prefs->RegisterBooleanPref(prefs::kAudioCaptureAllowed, true); |
| 296 prefs->RegisterListPref(prefs::kVideoCaptureAllowedUrls); | 336 prefs->RegisterListPref(prefs::kVideoCaptureAllowedUrls); |
| 297 prefs->RegisterListPref(prefs::kAudioCaptureAllowedUrls); | 337 prefs->RegisterListPref(prefs::kAudioCaptureAllowedUrls); |
| 298 } | 338 } |
| 299 | 339 |
| 300 MediaStreamDevicesController::~MediaStreamDevicesController() { | 340 MediaStreamDevicesController::~MediaStreamDevicesController() { |
| 301 if (!callback_.is_null()) { | 341 if (!callback_.is_null()) { |
| 302 RecordPermissionAction(request_, profile_, | |
| 303 base::Bind(PermissionUmaUtil::PermissionIgnored)); | |
| 304 callback_.Run(content::MediaStreamDevices(), | 342 callback_.Run(content::MediaStreamDevices(), |
| 305 content::MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN, | 343 content::MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN, |
| 306 std::unique_ptr<content::MediaStreamUI>()); | 344 std::unique_ptr<content::MediaStreamUI>()); |
| 307 } | 345 } |
| 308 } | 346 } |
| 309 | 347 |
| 310 bool MediaStreamDevicesController::IsAskingForAudio() const { | 348 bool MediaStreamDevicesController::IsAskingForAudio() const { |
| 311 return old_audio_setting_ == CONTENT_SETTING_ASK; | 349 return audio_setting_ == CONTENT_SETTING_ASK; |
| 312 } | 350 } |
| 313 | 351 |
| 314 bool MediaStreamDevicesController::IsAskingForVideo() const { | 352 bool MediaStreamDevicesController::IsAskingForVideo() const { |
| 315 return old_video_setting_ == CONTENT_SETTING_ASK; | 353 return video_setting_ == CONTENT_SETTING_ASK; |
| 316 } | 354 } |
| 317 | 355 |
| 318 base::string16 MediaStreamDevicesController::GetMessageText() const { | 356 void MediaStreamDevicesController::PromptAnswered(ContentSetting setting, |
| 319 int message_id = IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO; | 357 bool persist) { |
| 320 if (!IsAskingForAudio()) | 358 if (setting != CONTENT_SETTING_ALLOW) |
| 321 message_id = IDS_MEDIA_CAPTURE_VIDEO_ONLY; | 359 denial_reason_ = content::MEDIA_DEVICE_PERMISSION_DENIED; |
| 322 else if (!IsAskingForVideo()) | 360 |
| 323 message_id = IDS_MEDIA_CAPTURE_AUDIO_ONLY; | 361 HostContentSettingsMap* host_content_settings_map = |
| 324 return l10n_util::GetStringFUTF16( | 362 HostContentSettingsMapFactory::GetForProfile(profile_); |
| 325 message_id, | 363 if (audio_setting_ == CONTENT_SETTING_ASK) { |
| 326 url_formatter::FormatUrlForSecurityDisplay( | 364 if (persist) { |
| 327 GetOrigin(), url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC)); | 365 host_content_settings_map->SetContentSettingDefaultScope( |
| 366 request_.security_origin, GURL(), |
| 367 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, std::string(), setting); |
| 368 } |
| 369 audio_setting_ = setting; |
| 370 } |
| 371 |
| 372 if (video_setting_ == CONTENT_SETTING_ASK) { |
| 373 if (persist) { |
| 374 host_content_settings_map->SetContentSettingDefaultScope( |
| 375 request_.security_origin, GURL(), |
| 376 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, std::string(), setting); |
| 377 } |
| 378 video_setting_ = setting; |
| 379 } |
| 380 |
| 381 RunCallback(); |
| 328 } | 382 } |
| 329 | 383 |
| 330 void MediaStreamDevicesController::ForcePermissionDeniedTemporarily() { | 384 void MediaStreamDevicesController::PromptAnsweredGroupedRequest( |
| 331 set_persist(false); | 385 const std::vector<ContentSetting>& response) { |
| 332 // TODO(tsergeant): Determine whether it is appropriate to record permission | 386 if (audio_setting_ == CONTENT_SETTING_ASK) |
| 333 // action metrics here, as this is a different sort of user action. | 387 audio_setting_ = response.front(); |
| 334 RunCallback(CONTENT_SETTING_BLOCK, | 388 |
| 335 CONTENT_SETTING_BLOCK, | 389 if (video_setting_ == CONTENT_SETTING_ASK) |
| 336 content::MEDIA_DEVICE_PERMISSION_DENIED); | 390 video_setting_ = response.back(); |
| 337 set_persist(true); | 391 |
| 392 if (audio_setting_ != CONTENT_SETTING_ALLOW && |
| 393 video_setting_ != CONTENT_SETTING_ALLOW) |
| 394 denial_reason_ = content::MEDIA_DEVICE_PERMISSION_DENIED; |
| 395 |
| 396 RunCallback(); |
| 338 } | 397 } |
| 339 | 398 |
| 340 PermissionRequest::IconId MediaStreamDevicesController::GetIconId() const { | 399 void MediaStreamDevicesController::AndroidOSPromptAnswered(bool allowed) { |
| 341 #if defined(OS_ANDROID) | 400 if (!allowed) { |
| 342 return IsAskingForVideo() ? IDR_INFOBAR_MEDIA_STREAM_CAMERA | 401 denial_reason_ = content::MEDIA_DEVICE_PERMISSION_DENIED; |
| 343 : IDR_INFOBAR_MEDIA_STREAM_MIC; | 402 if (audio_setting_ == CONTENT_SETTING_ALLOW) |
| 344 #else | 403 audio_setting_ = CONTENT_SETTING_BLOCK; |
| 345 return IsAskingForVideo() ? ui::kVideocamIcon : ui::kMicrophoneIcon; | 404 if (video_setting_ == CONTENT_SETTING_ALLOW) |
| 346 #endif | 405 video_setting_ = CONTENT_SETTING_BLOCK; |
| 406 } |
| 407 |
| 408 RunCallback(); |
| 347 } | 409 } |
| 348 | 410 |
| 349 base::string16 MediaStreamDevicesController::GetMessageTextFragment() const { | 411 void MediaStreamDevicesController::RequestFinishedNoPrompt() { |
| 350 int message_id = IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO_PERMISSION_FRAGMENT; | 412 RunCallback(); |
| 351 if (!IsAskingForAudio()) | |
| 352 message_id = IDS_MEDIA_CAPTURE_VIDEO_ONLY_PERMISSION_FRAGMENT; | |
| 353 else if (!IsAskingForVideo()) | |
| 354 message_id = IDS_MEDIA_CAPTURE_AUDIO_ONLY_PERMISSION_FRAGMENT; | |
| 355 return l10n_util::GetStringUTF16(message_id); | |
| 356 } | |
| 357 | |
| 358 GURL MediaStreamDevicesController::GetOrigin() const { | |
| 359 return request_.security_origin; | |
| 360 } | |
| 361 | |
| 362 void MediaStreamDevicesController::PermissionGranted() { | |
| 363 RecordPermissionAction(request_, profile_, | |
| 364 base::Bind(PermissionUmaUtil::PermissionGranted)); | |
| 365 RunCallback(GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, | |
| 366 old_audio_setting_, CONTENT_SETTING_ALLOW), | |
| 367 GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, | |
| 368 old_video_setting_, CONTENT_SETTING_ALLOW), | |
| 369 content::MEDIA_DEVICE_PERMISSION_DENIED); | |
| 370 } | |
| 371 | |
| 372 void MediaStreamDevicesController::PermissionDenied() { | |
| 373 RecordPermissionAction(request_, profile_, | |
| 374 base::Bind(PermissionUmaUtil::PermissionDenied)); | |
| 375 RunCallback(GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, | |
| 376 old_audio_setting_, CONTENT_SETTING_BLOCK), | |
| 377 GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, | |
| 378 old_video_setting_, CONTENT_SETTING_BLOCK), | |
| 379 content::MEDIA_DEVICE_PERMISSION_DENIED); | |
| 380 } | |
| 381 | |
| 382 bool MediaStreamDevicesController::ShouldShowPersistenceToggle() const { | |
| 383 return PermissionUtil::ShouldShowPersistenceToggle(); | |
| 384 } | |
| 385 | |
| 386 void MediaStreamDevicesController::Cancelled() { | |
| 387 RecordPermissionAction(request_, profile_, | |
| 388 base::Bind(PermissionUmaUtil::PermissionDismissed)); | |
| 389 RunCallback(old_audio_setting_, old_video_setting_, | |
| 390 content::MEDIA_DEVICE_PERMISSION_DISMISSED); | |
| 391 } | |
| 392 | |
| 393 void MediaStreamDevicesController::RequestFinished() { | |
| 394 delete this; | |
| 395 } | |
| 396 | |
| 397 PermissionRequestType MediaStreamDevicesController::GetPermissionRequestType() | |
| 398 const { | |
| 399 return PermissionRequestType::MEDIA_STREAM; | |
| 400 } | 413 } |
| 401 | 414 |
| 402 // static | 415 // static |
| 403 void MediaStreamDevicesController::RequestPermissionsWithDelegate( | 416 void MediaStreamDevicesController::RequestPermissionsWithDelegate( |
| 404 const content::MediaStreamRequest& request, | 417 const content::MediaStreamRequest& request, |
| 405 const content::MediaResponseCallback& callback, | 418 const content::MediaResponseCallback& callback, |
| 406 internal::PermissionPromptDelegate* delegate) { | 419 internal::PermissionPromptDelegate* delegate) { |
| 420 content::RenderFrameHost* rfh = content::RenderFrameHost::FromID( |
| 421 request.render_process_id, request.render_frame_id); |
| 407 content::WebContents* web_contents = | 422 content::WebContents* web_contents = |
| 408 content::WebContents::FromRenderFrameHost( | 423 content::WebContents::FromRenderFrameHost(rfh); |
| 409 content::RenderFrameHost::FromID(request.render_process_id, | |
| 410 request.render_frame_id)); | |
| 411 if (request.request_type == content::MEDIA_OPEN_DEVICE_PEPPER_ONLY) { | 424 if (request.request_type == content::MEDIA_OPEN_DEVICE_PEPPER_ONLY) { |
| 412 MediaPermissionRequestLogger::LogRequest( | 425 MediaPermissionRequestLogger::LogRequest( |
| 413 web_contents, request.render_process_id, request.render_frame_id, | 426 web_contents, request.render_process_id, request.render_frame_id, |
| 414 content::IsOriginSecure(request.security_origin)); | 427 content::IsOriginSecure(request.security_origin)); |
| 415 } | 428 } |
| 416 | 429 |
| 417 MediaPermissionStatus initial_permission(request); | 430 std::unique_ptr<MediaStreamDevicesController> controller( |
| 418 if (initial_permission.audio_requested() && | 431 new MediaStreamDevicesController(web_contents, request, callback)); |
| 419 !HasAvailableDevices(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, | |
| 420 request.requested_audio_device_id)) { | |
| 421 initial_permission.SetAudioBlocked(content::MEDIA_DEVICE_NO_HARDWARE); | |
| 422 } | |
| 423 | 432 |
| 424 if (initial_permission.video_requested() && | 433 #if defined(OS_ANDROID) |
| 425 !HasAvailableDevices(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, | |
| 426 request.requested_video_device_id)) { | |
| 427 initial_permission.SetVideoBlocked(content::MEDIA_DEVICE_NO_HARDWARE); | |
| 428 } | |
| 429 | |
| 430 std::unique_ptr<MediaStreamDevicesController> controller( | |
| 431 new MediaStreamDevicesController(web_contents, request, callback, | |
| 432 initial_permission)); | |
| 433 if (!controller->IsAskingForAudio() && !controller->IsAskingForVideo()) { | 434 if (!controller->IsAskingForAudio() && !controller->IsAskingForVideo()) { |
| 434 #if defined(OS_ANDROID) | |
| 435 // If either audio or video was previously allowed and Chrome no longer has | 435 // If either audio or video was previously allowed and Chrome no longer has |
| 436 // the necessary permissions, show a infobar to attempt to address this | 436 // the necessary permissions, show a infobar to attempt to address this |
| 437 // mismatch. | 437 // mismatch. |
| 438 std::vector<ContentSettingsType> content_settings_types; | 438 std::vector<ContentSettingsType> content_settings_types; |
| 439 if (controller->IsAllowedForAudio()) | 439 if (controller->IsAllowedForAudio()) |
| 440 content_settings_types.push_back(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC); | 440 content_settings_types.push_back(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC); |
| 441 | 441 |
| 442 if (controller->IsAllowedForVideo()) { | 442 if (controller->IsAllowedForVideo()) { |
| 443 content_settings_types.push_back( | 443 content_settings_types.push_back( |
| 444 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA); | 444 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA); |
| 445 } | 445 } |
| 446 if (!content_settings_types.empty() && | 446 if (!content_settings_types.empty() && |
| 447 PermissionUpdateInfoBarDelegate::ShouldShowPermissionInfobar( | 447 PermissionUpdateInfoBarDelegate::ShouldShowPermissionInfobar( |
| 448 web_contents, content_settings_types)) { | 448 web_contents, content_settings_types)) { |
| 449 PermissionUpdateInfoBarDelegate::Create( | 449 PermissionUpdateInfoBarDelegate::Create( |
| 450 web_contents, content_settings_types, | 450 web_contents, content_settings_types, |
| 451 base::Bind(&OnPermissionConflictResolved, base::Passed(&controller))); | 451 base::Bind(&AndroidOSPromptAnswered, base::Passed(&controller))); |
| 452 return; |
| 452 } | 453 } |
| 454 } |
| 453 #endif | 455 #endif |
| 454 return; | 456 |
| 457 Profile* profile = |
| 458 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
| 459 if (!controller->IsAskingForAudio() && !controller->IsAskingForVideo()) { |
| 460 controller->RequestFinishedNoPrompt(); |
| 461 } else { |
| 462 if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
| 463 switches::kEnableGroupedMediaPermissionPrompts)) { |
| 464 std::vector<ContentSettingsType> content_settings_types; |
| 465 |
| 466 if (controller->IsAskingForAudio()) |
| 467 content_settings_types.push_back(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC); |
| 468 if (controller->IsAskingForVideo()) { |
| 469 content_settings_types.push_back( |
| 470 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA); |
| 471 } |
| 472 |
| 473 LOG(ERROR) << content_settings_types.size(); |
| 474 |
| 475 PermissionManager::Get(profile)->RequestPermissions( |
| 476 content_settings_types, rfh, request.security_origin, |
| 477 request.user_gesture, |
| 478 base::Bind( |
| 479 &MediaStreamDevicesController::PromptAnsweredGroupedRequest, |
| 480 base::Passed(&controller))); |
| 481 } else { |
| 482 delegate->ShowPrompt( |
| 483 request.user_gesture, web_contents, |
| 484 base::MakeUnique<internal::MediaStreamPermissionRequest>( |
| 485 profile, controller->IsAskingForAudio(), |
| 486 controller->IsAskingForVideo(), request.security_origin, |
| 487 base::Bind(&MediaStreamDevicesController::PromptAnswered, |
| 488 base::Passed(&controller)))); |
| 489 } |
| 455 } | 490 } |
| 456 | |
| 457 delegate->ShowPrompt(request.user_gesture, web_contents, | |
| 458 std::move(controller)); | |
| 459 } | 491 } |
| 460 | 492 |
| 461 MediaStreamDevicesController::MediaStreamDevicesController( | 493 MediaStreamDevicesController::MediaStreamDevicesController( |
| 462 content::WebContents* web_contents, | 494 content::WebContents* web_contents, |
| 463 const content::MediaStreamRequest& request, | 495 const content::MediaStreamRequest& request, |
| 464 const content::MediaResponseCallback& callback, | 496 const content::MediaResponseCallback& callback) |
| 465 const MediaPermissionStatus& initial_permission) | |
| 466 : web_contents_(web_contents), request_(request), callback_(callback) { | 497 : web_contents_(web_contents), request_(request), callback_(callback) { |
| 467 profile_ = Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 498 profile_ = Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
| 468 content_settings_ = TabSpecificContentSettings::FromWebContents(web_contents); | 499 content_settings_ = TabSpecificContentSettings::FromWebContents(web_contents); |
| 469 | 500 |
| 470 content::MediaStreamRequestResult denial_reason = | 501 denial_reason_ = content::MEDIA_DEVICE_OK; |
| 471 initial_permission.denial_reason(); | 502 audio_setting_ = GetContentSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, |
| 472 old_audio_setting_ = | 503 request, &denial_reason_); |
| 473 GetContentSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, request, | 504 video_setting_ = GetContentSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, |
| 474 initial_permission.audio_requested(), | 505 request, &denial_reason_); |
| 475 initial_permission.audio_blocked(), &denial_reason); | |
| 476 old_video_setting_ = | |
| 477 GetContentSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, request, | |
| 478 initial_permission.video_requested(), | |
| 479 initial_permission.video_blocked(), &denial_reason); | |
| 480 | |
| 481 // If either setting is ask, we show the infobar. | |
| 482 if (old_audio_setting_ == CONTENT_SETTING_ASK || | |
| 483 old_video_setting_ == CONTENT_SETTING_ASK) { | |
| 484 return; | |
| 485 } | |
| 486 | |
| 487 #if defined(OS_ANDROID) | |
| 488 std::vector<ContentSettingsType> content_settings_types; | |
| 489 if (IsAllowedForAudio()) | |
| 490 content_settings_types.push_back(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC); | |
| 491 | |
| 492 if (IsAllowedForVideo()) { | |
| 493 content_settings_types.push_back(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA); | |
| 494 } | |
| 495 | |
| 496 // If the site had been previously granted the access to audio or video but | |
| 497 // Chrome is now missing the necessary permission, we need to show an infobar | |
| 498 // to resolve the difference. | |
| 499 if (!content_settings_types.empty() && | |
| 500 PermissionUpdateInfoBarDelegate::ShouldShowPermissionInfobar( | |
| 501 web_contents, content_settings_types)) { | |
| 502 return; | |
| 503 } | |
| 504 #endif | |
| 505 | |
| 506 // Otherwise we can run the callback immediately. | |
| 507 RunCallback(old_audio_setting_, old_video_setting_, denial_reason); | |
| 508 } | 506 } |
| 509 | 507 |
| 510 bool MediaStreamDevicesController::IsAllowedForAudio() const { | 508 bool MediaStreamDevicesController::IsAllowedForAudio() const { |
| 511 return old_audio_setting_ == CONTENT_SETTING_ALLOW; | 509 return audio_setting_ == CONTENT_SETTING_ALLOW; |
| 512 } | 510 } |
| 513 | 511 |
| 514 bool MediaStreamDevicesController::IsAllowedForVideo() const { | 512 bool MediaStreamDevicesController::IsAllowedForVideo() const { |
| 515 return old_video_setting_ == CONTENT_SETTING_ALLOW; | 513 return video_setting_ == CONTENT_SETTING_ALLOW; |
| 516 } | 514 } |
| 517 | 515 |
| 518 content::MediaStreamDevices MediaStreamDevicesController::GetDevices( | 516 content::MediaStreamDevices MediaStreamDevicesController::GetDevices( |
| 519 ContentSetting audio_setting, | 517 ContentSetting audio_setting, |
| 520 ContentSetting video_setting) { | 518 ContentSetting video_setting) { |
| 521 bool audio_allowed = audio_setting == CONTENT_SETTING_ALLOW; | 519 bool audio_allowed = audio_setting == CONTENT_SETTING_ALLOW; |
| 522 bool video_allowed = video_setting == CONTENT_SETTING_ALLOW; | 520 bool video_allowed = video_setting == CONTENT_SETTING_ALLOW; |
| 523 | 521 |
| 524 if (!audio_allowed && !video_allowed) | 522 if (!audio_allowed && !video_allowed) |
| 525 return content::MediaStreamDevices(); | 523 return content::MediaStreamDevices(); |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 597 // Get the default devices for the request. | 595 // Get the default devices for the request. |
| 598 MediaCaptureDevicesDispatcher::GetInstance()->GetDefaultDevicesForProfile( | 596 MediaCaptureDevicesDispatcher::GetInstance()->GetDefaultDevicesForProfile( |
| 599 profile_, audio_allowed, video_allowed, &devices); | 597 profile_, audio_allowed, video_allowed, &devices); |
| 600 break; | 598 break; |
| 601 } | 599 } |
| 602 } // switch | 600 } // switch |
| 603 | 601 |
| 604 return devices; | 602 return devices; |
| 605 } | 603 } |
| 606 | 604 |
| 607 void MediaStreamDevicesController::RunCallback( | 605 void MediaStreamDevicesController::RunCallback() { |
| 608 ContentSetting audio_setting, | |
| 609 ContentSetting video_setting, | |
| 610 content::MediaStreamRequestResult denial_reason) { | |
| 611 CHECK(!callback_.is_null()); | 606 CHECK(!callback_.is_null()); |
| 612 | 607 |
| 613 // If the kill switch is on we don't update the tab context or persist the | 608 // If the kill switch is on we don't update the tab context. |
| 614 // setting. | 609 if (denial_reason_ != content::MEDIA_DEVICE_KILL_SWITCH_ON) |
| 615 if (denial_reason != content::MEDIA_DEVICE_KILL_SWITCH_ON) { | 610 UpdateTabSpecificContentSettings(audio_setting_, video_setting_); |
| 616 if (persist()) | |
| 617 StorePermission(audio_setting, video_setting); | |
| 618 UpdateTabSpecificContentSettings(audio_setting, video_setting); | |
| 619 } | |
| 620 | 611 |
| 621 content::MediaStreamDevices devices = | 612 content::MediaStreamDevices devices = |
| 622 GetDevices(audio_setting, video_setting); | 613 GetDevices(audio_setting_, video_setting_); |
| 623 | 614 |
| 624 // If either audio or video are allowed then the callback should report | 615 // If either audio or video are allowed then the callback should report |
| 625 // success, otherwise we report |denial_reason|. | 616 // success, otherwise we report |denial_reason_|. |
| 626 content::MediaStreamRequestResult request_result = content::MEDIA_DEVICE_OK; | 617 if (audio_setting_ != CONTENT_SETTING_ALLOW && |
| 627 if (audio_setting != CONTENT_SETTING_ALLOW && | 618 video_setting_ != CONTENT_SETTING_ALLOW) { |
| 628 video_setting != CONTENT_SETTING_ALLOW) { | 619 DCHECK_NE(content::MEDIA_DEVICE_OK, denial_reason_); |
| 629 DCHECK_NE(content::MEDIA_DEVICE_OK, denial_reason); | |
| 630 request_result = denial_reason; | |
| 631 } else if (devices.empty()) { | 620 } else if (devices.empty()) { |
| 632 // Even if one of the content settings was allowed, if there are no devices | 621 // Even if one of the content settings was allowed, if there are no devices |
| 633 // at this point we still report a failure. | 622 // at this point we still report a failure. |
| 634 request_result = content::MEDIA_DEVICE_NO_HARDWARE; | 623 denial_reason_ = content::MEDIA_DEVICE_NO_HARDWARE; |
| 635 } | 624 } |
| 636 | 625 |
| 637 std::unique_ptr<content::MediaStreamUI> ui; | 626 std::unique_ptr<content::MediaStreamUI> ui; |
| 638 if (!devices.empty()) { | 627 if (!devices.empty()) { |
| 639 ui = MediaCaptureDevicesDispatcher::GetInstance() | 628 ui = MediaCaptureDevicesDispatcher::GetInstance() |
| 640 ->GetMediaStreamCaptureIndicator() | 629 ->GetMediaStreamCaptureIndicator() |
| 641 ->RegisterMediaStream(web_contents_, devices); | 630 ->RegisterMediaStream(web_contents_, devices); |
| 642 } | 631 } |
| 643 base::ResetAndReturn(&callback_).Run(devices, request_result, std::move(ui)); | 632 base::ResetAndReturn(&callback_).Run(devices, denial_reason_, std::move(ui)); |
| 644 } | |
| 645 | |
| 646 void MediaStreamDevicesController::StorePermission( | |
| 647 ContentSetting new_audio_setting, | |
| 648 ContentSetting new_video_setting) const { | |
| 649 DCHECK_CURRENTLY_ON(BrowserThread::UI); | |
| 650 DCHECK(content::IsOriginSecure(request_.security_origin) || | |
| 651 request_.request_type == content::MEDIA_OPEN_DEVICE_PEPPER_ONLY); | |
| 652 | |
| 653 if (IsAskingForAudio() && new_audio_setting != CONTENT_SETTING_ASK) { | |
| 654 HostContentSettingsMapFactory::GetForProfile(profile_) | |
| 655 ->SetContentSettingDefaultScope(request_.security_origin, GURL(), | |
| 656 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, | |
| 657 std::string(), new_audio_setting); | |
| 658 } | |
| 659 if (IsAskingForVideo() && new_video_setting != CONTENT_SETTING_ASK) { | |
| 660 HostContentSettingsMapFactory::GetForProfile(profile_) | |
| 661 ->SetContentSettingDefaultScope( | |
| 662 request_.security_origin, GURL(), | |
| 663 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, std::string(), | |
| 664 new_video_setting); | |
| 665 } | |
| 666 } | 633 } |
| 667 | 634 |
| 668 void MediaStreamDevicesController::UpdateTabSpecificContentSettings( | 635 void MediaStreamDevicesController::UpdateTabSpecificContentSettings( |
| 669 ContentSetting audio_setting, | 636 ContentSetting audio_setting, |
| 670 ContentSetting video_setting) const { | 637 ContentSetting video_setting) const { |
| 671 if (!content_settings_) | 638 if (!content_settings_) |
| 672 return; | 639 return; |
| 673 | 640 |
| 674 TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state = | 641 TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state = |
| 675 TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED; | 642 TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED; |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 707 } | 674 } |
| 708 | 675 |
| 709 content_settings_->OnMediaStreamPermissionSet( | 676 content_settings_->OnMediaStreamPermissionSet( |
| 710 request_.security_origin, microphone_camera_state, selected_audio_device, | 677 request_.security_origin, microphone_camera_state, selected_audio_device, |
| 711 selected_video_device, requested_audio_device, requested_video_device); | 678 selected_video_device, requested_audio_device, requested_video_device); |
| 712 } | 679 } |
| 713 | 680 |
| 714 ContentSetting MediaStreamDevicesController::GetContentSetting( | 681 ContentSetting MediaStreamDevicesController::GetContentSetting( |
| 715 ContentSettingsType content_type, | 682 ContentSettingsType content_type, |
| 716 const content::MediaStreamRequest& request, | 683 const content::MediaStreamRequest& request, |
| 717 bool was_requested, | |
| 718 bool was_initially_blocked, | |
| 719 content::MediaStreamRequestResult* denial_reason) const { | 684 content::MediaStreamRequestResult* denial_reason) const { |
| 720 DCHECK(content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC || | 685 DCHECK(content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC || |
| 721 content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA); | 686 content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA); |
| 722 DCHECK(!request_.security_origin.is_empty()); | 687 DCHECK(!request_.security_origin.is_empty()); |
| 723 DCHECK(content::IsOriginSecure(request_.security_origin) || | 688 DCHECK(content::IsOriginSecure(request_.security_origin) || |
| 724 request_.request_type == content::MEDIA_OPEN_DEVICE_PEPPER_ONLY); | 689 request_.request_type == content::MEDIA_OPEN_DEVICE_PEPPER_ONLY); |
| 725 if (!was_requested) { | 690 if (!ContentTypeIsRequested(content_type, request)) { |
| 726 // No denial reason set as it will have been previously set. | 691 // No denial reason set as it will have been previously set. |
| 727 return CONTENT_SETTING_DEFAULT; | 692 return CONTENT_SETTING_DEFAULT; |
| 728 } | 693 } |
| 729 | 694 |
| 730 if (was_initially_blocked) { | 695 std::string device_id; |
| 731 // No denial reason set as it will have been previously set. | 696 if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC) |
| 697 device_id = request.requested_audio_device_id; |
| 698 else |
| 699 device_id = request.requested_video_device_id; |
| 700 if (!HasAvailableDevices(content_type, device_id)) { |
| 701 *denial_reason = content::MEDIA_DEVICE_NO_HARDWARE; |
| 732 return CONTENT_SETTING_BLOCK; | 702 return CONTENT_SETTING_BLOCK; |
| 733 } | 703 } |
| 734 | 704 |
| 735 if (!IsUserAcceptAllowed(content_type)) { | 705 if (!IsUserAcceptAllowed(content_type)) { |
| 736 *denial_reason = content::MEDIA_DEVICE_PERMISSION_DENIED; | 706 *denial_reason = content::MEDIA_DEVICE_PERMISSION_DENIED; |
| 737 return CONTENT_SETTING_BLOCK; | 707 return CONTENT_SETTING_BLOCK; |
| 738 } | 708 } |
| 739 | 709 |
| 740 PermissionResult result = | 710 PermissionResult result = |
| 741 PermissionManager::Get(profile_)->GetPermissionStatus( | 711 PermissionManager::Get(profile_)->GetPermissionStatus( |
| 742 content_type, request.security_origin, | 712 content_type, request.security_origin, |
| 743 web_contents_->GetLastCommittedURL().GetOrigin()); | 713 web_contents_->GetLastCommittedURL().GetOrigin()); |
| 744 if (result.content_setting == CONTENT_SETTING_BLOCK) { | 714 if (result.content_setting == CONTENT_SETTING_BLOCK) { |
| 745 *denial_reason = (result.source == PermissionStatusSource::KILL_SWITCH) | 715 *denial_reason = (result.source == PermissionStatusSource::KILL_SWITCH) |
| 746 ? content::MEDIA_DEVICE_KILL_SWITCH_ON | 716 ? content::MEDIA_DEVICE_KILL_SWITCH_ON |
| 747 : content::MEDIA_DEVICE_PERMISSION_DENIED; | 717 : content::MEDIA_DEVICE_PERMISSION_DENIED; |
| 748 } | 718 } |
| 749 | 719 |
| 750 return result.content_setting; | 720 return result.content_setting; |
| 751 } | 721 } |
| 752 | 722 |
| 753 ContentSetting MediaStreamDevicesController::GetNewSetting( | |
| 754 ContentSettingsType content_type, | |
| 755 ContentSetting old_setting, | |
| 756 ContentSetting user_decision) const { | |
| 757 DCHECK(user_decision == CONTENT_SETTING_ALLOW || | |
| 758 user_decision == CONTENT_SETTING_BLOCK); | |
| 759 ContentSetting result = old_setting; | |
| 760 if (old_setting == CONTENT_SETTING_ASK) | |
| 761 result = user_decision; | |
| 762 return result; | |
| 763 } | |
| 764 | |
| 765 bool MediaStreamDevicesController::IsUserAcceptAllowed( | 723 bool MediaStreamDevicesController::IsUserAcceptAllowed( |
| 766 ContentSettingsType content_type) const { | 724 ContentSettingsType content_type) const { |
| 767 #if defined(OS_ANDROID) | 725 #if defined(OS_ANDROID) |
| 768 content::ContentViewCore* cvc = | 726 content::ContentViewCore* cvc = |
| 769 content::ContentViewCore::FromWebContents(web_contents_); | 727 content::ContentViewCore::FromWebContents(web_contents_); |
| 770 if (!cvc) | 728 if (!cvc) |
| 771 return false; | 729 return false; |
| 772 | 730 |
| 773 ui::WindowAndroid* window_android = cvc->GetWindowAndroid(); | 731 ui::WindowAndroid* window_android = cvc->GetWindowAndroid(); |
| 774 if (!window_android) | 732 if (!window_android) |
| 775 return false; | 733 return false; |
| 776 | 734 |
| 777 std::vector<std::string> android_permissions; | 735 std::vector<std::string> android_permissions; |
| 778 PrefServiceBridge::GetAndroidPermissionsForContentSetting( | 736 PrefServiceBridge::GetAndroidPermissionsForContentSetting( |
| 779 content_type, &android_permissions); | 737 content_type, &android_permissions); |
| 780 for (const auto& android_permission : android_permissions) { | 738 for (const auto& android_permission : android_permissions) { |
| 781 if (!window_android->HasPermission(android_permission) && | 739 if (!window_android->HasPermission(android_permission) && |
| 782 !window_android->CanRequestPermission(android_permission)) { | 740 !window_android->CanRequestPermission(android_permission)) { |
| 783 return false; | 741 return false; |
| 784 } | 742 } |
| 785 } | 743 } |
| 786 | 744 |
| 787 // Don't approve device requests if the tab was hidden. | 745 // Don't approve device requests if the tab was hidden. |
| 788 // TODO(qinmin): Add a test for this. http://crbug.com/396869. | 746 // TODO(qinmin): Add a test for this. http://crbug.com/396869. |
| 789 // TODO(raymes): Shouldn't this apply to all permissions not just audio/video? | 747 // TODO(raymes): Shouldn't this apply to all permissions not just audio/video? |
| 790 return web_contents_->GetRenderWidgetHostView()->IsShowing(); | 748 return web_contents_->GetRenderWidgetHostView()->IsShowing(); |
| 791 #endif | 749 #endif |
| 792 return true; | 750 return true; |
| 793 } | 751 } |
| OLD | NEW |