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 |