| 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/media_stream_devices_controller.h" | 5 #include "chrome/browser/media/media_stream_devices_controller.h" |
| 6 | 6 |
| 7 #include "base/auto_reset.h" | 7 #include "base/auto_reset.h" |
| 8 #include "base/callback_helpers.h" | 8 #include "base/callback_helpers.h" |
| 9 #include "base/containers/scoped_ptr_map.h" | 9 #include "base/containers/scoped_ptr_map.h" |
| 10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| 11 #include "base/prefs/scoped_user_pref_update.h" | 11 #include "base/prefs/scoped_user_pref_update.h" |
| 12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
| 13 #include "base/values.h" | 13 #include "base/values.h" |
| 14 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" | 14 #include "chrome/browser/content_settings/host_content_settings_map_factory.h" |
| 15 #include "chrome/browser/content_settings/tab_specific_content_settings.h" | 15 #include "chrome/browser/content_settings/tab_specific_content_settings.h" |
| 16 #include "chrome/browser/media/media_capture_devices_dispatcher.h" | 16 #include "chrome/browser/media/media_capture_devices_dispatcher.h" |
| 17 #include "chrome/browser/media/media_permission.h" | 17 #include "chrome/browser/media/media_permission.h" |
| 18 #include "chrome/browser/media/media_stream_capture_indicator.h" | 18 #include "chrome/browser/media/media_stream_capture_indicator.h" |
| 19 #include "chrome/browser/media/media_stream_device_permissions.h" | 19 #include "chrome/browser/media/media_stream_device_permissions.h" |
| 20 #include "chrome/browser/permissions/permission_uma_util.h" |
| 20 #include "chrome/browser/profiles/profile.h" | 21 #include "chrome/browser/profiles/profile.h" |
| 21 #include "chrome/browser/ui/browser.h" | 22 #include "chrome/browser/ui/browser.h" |
| 22 #include "chrome/common/chrome_switches.h" | 23 #include "chrome/common/chrome_switches.h" |
| 23 #include "chrome/common/pref_names.h" | 24 #include "chrome/common/pref_names.h" |
| 24 #include "chrome/grit/generated_resources.h" | 25 #include "chrome/grit/generated_resources.h" |
| 25 #include "components/content_settings/core/browser/host_content_settings_map.h" | 26 #include "components/content_settings/core/browser/host_content_settings_map.h" |
| 26 #include "components/content_settings/core/common/content_settings_pattern.h" | 27 #include "components/content_settings/core/common/content_settings_pattern.h" |
| 27 #include "components/pref_registry/pref_registry_syncable.h" | 28 #include "components/pref_registry/pref_registry_syncable.h" |
| 28 #include "content/public/browser/browser_thread.h" | 29 #include "content/public/browser/browser_thread.h" |
| 29 #include "content/public/browser/render_frame_host.h" | 30 #include "content/public/browser/render_frame_host.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 41 #include "chrome/browser/android/preferences/pref_service_bridge.h" | 42 #include "chrome/browser/android/preferences/pref_service_bridge.h" |
| 42 #include "chrome/browser/permissions/permission_update_infobar_delegate_android.
h" | 43 #include "chrome/browser/permissions/permission_update_infobar_delegate_android.
h" |
| 43 #include "content/public/browser/android/content_view_core.h" | 44 #include "content/public/browser/android/content_view_core.h" |
| 44 #include "ui/android/window_android.h" | 45 #include "ui/android/window_android.h" |
| 45 #endif // OS_ANDROID | 46 #endif // OS_ANDROID |
| 46 | 47 |
| 47 using content::BrowserThread; | 48 using content::BrowserThread; |
| 48 | 49 |
| 49 namespace { | 50 namespace { |
| 50 | 51 |
| 51 enum DevicePermissionActions { | |
| 52 kAllowHttps = 0, | |
| 53 kAllowHttp, | |
| 54 kDeny, | |
| 55 kCancel, | |
| 56 kPermissionActionsMax // Must always be last! | |
| 57 }; | |
| 58 | |
| 59 // Returns true if the given ContentSettingsType is being requested in | 52 // Returns true if the given ContentSettingsType is being requested in |
| 60 // |request|. | 53 // |request|. |
| 61 bool ContentTypeIsRequested(ContentSettingsType type, | 54 bool ContentTypeIsRequested(ContentSettingsType type, |
| 62 const content::MediaStreamRequest& request) { | 55 const content::MediaStreamRequest& request) { |
| 63 if (request.request_type == content::MEDIA_OPEN_DEVICE_PEPPER_ONLY) | 56 if (request.request_type == content::MEDIA_OPEN_DEVICE_PEPPER_ONLY) |
| 64 return true; | 57 return true; |
| 65 | 58 |
| 66 if (type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC) | 59 if (type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC) |
| 67 return request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE; | 60 return request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE; |
| 68 | 61 |
| 69 if (type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA) | 62 if (type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA) |
| 70 return request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE; | 63 return request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE; |
| 71 | 64 |
| 72 return false; | 65 return false; |
| 73 } | 66 } |
| 74 | 67 |
| 68 using PermissionActionCallback = |
| 69 base::Callback<void(ContentSettingsType, const GURL&)>; |
| 70 |
| 71 // Calls |action_function| for each permission requested by |request|. |
| 72 void RecordPermissionAction(const content::MediaStreamRequest& request, |
| 73 PermissionActionCallback callback) { |
| 74 if (ContentTypeIsRequested(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, |
| 75 request)) { |
| 76 callback.Run(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, |
| 77 request.security_origin); |
| 78 } |
| 79 if (ContentTypeIsRequested(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, request)) { |
| 80 callback.Run(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, |
| 81 request.security_origin); |
| 82 } |
| 83 } |
| 84 |
| 75 // This helper class helps to measure the number of media stream requests that | 85 // This helper class helps to measure the number of media stream requests that |
| 76 // occur. It ensures that only one request will be recorded per navigation, per | 86 // occur. It ensures that only one request will be recorded per navigation, per |
| 77 // frame. TODO(raymes): Remove this when https://crbug.com/526324 is fixed. | 87 // frame. TODO(raymes): Remove this when https://crbug.com/526324 is fixed. |
| 78 class MediaPermissionRequestLogger : content::WebContentsObserver { | 88 class MediaPermissionRequestLogger : content::WebContentsObserver { |
| 79 // Map of <render process id, render frame id> -> | 89 // Map of <render process id, render frame id> -> |
| 80 // MediaPermissionRequestLogger. | 90 // MediaPermissionRequestLogger. |
| 81 using RequestMap = | 91 using RequestMap = |
| 82 base::ScopedPtrMap<std::pair<int, int>, | 92 base::ScopedPtrMap<std::pair<int, int>, |
| 83 scoped_ptr<MediaPermissionRequestLogger>>; | 93 scoped_ptr<MediaPermissionRequestLogger>>; |
| 84 | 94 |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 179 return; | 189 return; |
| 180 } | 190 } |
| 181 #endif | 191 #endif |
| 182 | 192 |
| 183 // Otherwise we can run the callback immediately. | 193 // Otherwise we can run the callback immediately. |
| 184 RunCallback(old_audio_setting_, old_video_setting_, denial_reason); | 194 RunCallback(old_audio_setting_, old_video_setting_, denial_reason); |
| 185 } | 195 } |
| 186 | 196 |
| 187 MediaStreamDevicesController::~MediaStreamDevicesController() { | 197 MediaStreamDevicesController::~MediaStreamDevicesController() { |
| 188 if (!callback_.is_null()) { | 198 if (!callback_.is_null()) { |
| 199 RecordPermissionAction( |
| 200 request_, base::Bind(PermissionUmaUtil::PermissionIgnored)); |
| 189 callback_.Run(content::MediaStreamDevices(), | 201 callback_.Run(content::MediaStreamDevices(), |
| 190 content::MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN, | 202 content::MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN, |
| 191 scoped_ptr<content::MediaStreamUI>()); | 203 scoped_ptr<content::MediaStreamUI>()); |
| 192 } | 204 } |
| 193 } | 205 } |
| 194 | 206 |
| 195 // static | 207 // static |
| 196 void MediaStreamDevicesController::RegisterProfilePrefs( | 208 void MediaStreamDevicesController::RegisterProfilePrefs( |
| 197 user_prefs::PrefRegistrySyncable* prefs) { | 209 user_prefs::PrefRegistrySyncable* prefs) { |
| 198 prefs->RegisterBooleanPref(prefs::kVideoCaptureAllowed, true); | 210 prefs->RegisterBooleanPref(prefs::kVideoCaptureAllowed, true); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 217 return old_video_setting_ == CONTENT_SETTING_ASK; | 229 return old_video_setting_ == CONTENT_SETTING_ASK; |
| 218 } | 230 } |
| 219 | 231 |
| 220 const std::string& MediaStreamDevicesController::GetSecurityOriginSpec() const { | 232 const std::string& MediaStreamDevicesController::GetSecurityOriginSpec() const { |
| 221 return request_.security_origin.spec(); | 233 return request_.security_origin.spec(); |
| 222 } | 234 } |
| 223 | 235 |
| 224 void MediaStreamDevicesController::ForcePermissionDeniedTemporarily() { | 236 void MediaStreamDevicesController::ForcePermissionDeniedTemporarily() { |
| 225 base::AutoReset<bool> persist_permissions( | 237 base::AutoReset<bool> persist_permissions( |
| 226 &persist_permission_changes_, false); | 238 &persist_permission_changes_, false); |
| 227 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions", | 239 // TODO(tsergeant): Determine whether it is appropriate to record permission |
| 228 kDeny, kPermissionActionsMax); | 240 // action metrics here, as this is a different sort of user action. |
| 229 RunCallback(CONTENT_SETTING_BLOCK, | 241 RunCallback(CONTENT_SETTING_BLOCK, |
| 230 CONTENT_SETTING_BLOCK, | 242 CONTENT_SETTING_BLOCK, |
| 231 content::MEDIA_DEVICE_PERMISSION_DENIED); | 243 content::MEDIA_DEVICE_PERMISSION_DENIED); |
| 232 } | 244 } |
| 233 | 245 |
| 234 int MediaStreamDevicesController::GetIconId() const { | 246 int MediaStreamDevicesController::GetIconId() const { |
| 235 if (IsAskingForVideo()) | 247 if (IsAskingForVideo()) |
| 236 return IDR_INFOBAR_MEDIA_STREAM_CAMERA; | 248 return IDR_INFOBAR_MEDIA_STREAM_CAMERA; |
| 237 | 249 |
| 238 return IDR_INFOBAR_MEDIA_STREAM_MIC; | 250 return IDR_INFOBAR_MEDIA_STREAM_MIC; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 259 | 271 |
| 260 bool MediaStreamDevicesController::HasUserGesture() const { | 272 bool MediaStreamDevicesController::HasUserGesture() const { |
| 261 return request_.user_gesture; | 273 return request_.user_gesture; |
| 262 } | 274 } |
| 263 | 275 |
| 264 GURL MediaStreamDevicesController::GetRequestingHostname() const { | 276 GURL MediaStreamDevicesController::GetRequestingHostname() const { |
| 265 return request_.security_origin; | 277 return request_.security_origin; |
| 266 } | 278 } |
| 267 | 279 |
| 268 void MediaStreamDevicesController::PermissionGranted() { | 280 void MediaStreamDevicesController::PermissionGranted() { |
| 269 GURL origin(GetSecurityOriginSpec()); | 281 RecordPermissionAction( |
| 270 if (content::IsOriginSecure(origin)) { | 282 request_, base::Bind(PermissionUmaUtil::PermissionGranted)); |
| 271 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions", | |
| 272 kAllowHttps, kPermissionActionsMax); | |
| 273 } else { | |
| 274 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions", | |
| 275 kAllowHttp, kPermissionActionsMax); | |
| 276 } | |
| 277 RunCallback(GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, | 283 RunCallback(GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, |
| 278 old_audio_setting_, CONTENT_SETTING_ALLOW), | 284 old_audio_setting_, CONTENT_SETTING_ALLOW), |
| 279 GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, | 285 GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, |
| 280 old_video_setting_, CONTENT_SETTING_ALLOW), | 286 old_video_setting_, CONTENT_SETTING_ALLOW), |
| 281 content::MEDIA_DEVICE_PERMISSION_DENIED); | 287 content::MEDIA_DEVICE_PERMISSION_DENIED); |
| 282 } | 288 } |
| 283 | 289 |
| 284 void MediaStreamDevicesController::PermissionDenied() { | 290 void MediaStreamDevicesController::PermissionDenied() { |
| 285 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions", | 291 RecordPermissionAction( |
| 286 kDeny, kPermissionActionsMax); | 292 request_, base::Bind(PermissionUmaUtil::PermissionDenied)); |
| 287 RunCallback(GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, | 293 RunCallback(GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, |
| 288 old_audio_setting_, CONTENT_SETTING_BLOCK), | 294 old_audio_setting_, CONTENT_SETTING_BLOCK), |
| 289 GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, | 295 GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, |
| 290 old_video_setting_, CONTENT_SETTING_BLOCK), | 296 old_video_setting_, CONTENT_SETTING_BLOCK), |
| 291 content::MEDIA_DEVICE_PERMISSION_DENIED); | 297 content::MEDIA_DEVICE_PERMISSION_DENIED); |
| 292 } | 298 } |
| 293 | 299 |
| 294 void MediaStreamDevicesController::Cancelled() { | 300 void MediaStreamDevicesController::Cancelled() { |
| 295 UMA_HISTOGRAM_ENUMERATION("Media.DevicePermissionActions", | 301 RecordPermissionAction( |
| 296 kCancel, kPermissionActionsMax); | 302 request_, base::Bind(PermissionUmaUtil::PermissionDismissed)); |
| 297 RunCallback(old_audio_setting_, old_video_setting_, | 303 RunCallback(old_audio_setting_, old_video_setting_, |
| 298 content::MEDIA_DEVICE_PERMISSION_DISMISSED); | 304 content::MEDIA_DEVICE_PERMISSION_DISMISSED); |
| 299 } | 305 } |
| 300 | 306 |
| 301 void MediaStreamDevicesController::RequestFinished() { | 307 void MediaStreamDevicesController::RequestFinished() { |
| 302 delete this; | 308 delete this; |
| 303 } | 309 } |
| 304 | 310 |
| 305 content::MediaStreamDevices MediaStreamDevicesController::GetDevices( | 311 content::MediaStreamDevices MediaStreamDevicesController::GetDevices( |
| 306 ContentSetting audio_setting, | 312 ContentSetting audio_setting, |
| (...skipping 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 596 if (android_permission_blocked) | 602 if (android_permission_blocked) |
| 597 return false; | 603 return false; |
| 598 | 604 |
| 599 // Don't approve device requests if the tab was hidden. | 605 // Don't approve device requests if the tab was hidden. |
| 600 // TODO(qinmin): Add a test for this. http://crbug.com/396869. | 606 // TODO(qinmin): Add a test for this. http://crbug.com/396869. |
| 601 // TODO(raymes): Shouldn't this apply to all permissions not just audio/video? | 607 // TODO(raymes): Shouldn't this apply to all permissions not just audio/video? |
| 602 return web_contents_->GetRenderWidgetHostView()->IsShowing(); | 608 return web_contents_->GetRenderWidgetHostView()->IsShowing(); |
| 603 #endif | 609 #endif |
| 604 return true; | 610 return true; |
| 605 } | 611 } |
| OLD | NEW |