Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(652)

Side by Side Diff: chrome/browser/media/webrtc/media_stream_devices_controller.cc

Issue 2706813004: Move logic to show permission prompts into MediaStreamDevicesController (Closed)
Patch Set: Move logic to show permission prompts into MediaStreamDevicesController Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 26 matching lines...) Expand all
37 #include "content/public/browser/render_widget_host_view.h" 37 #include "content/public/browser/render_widget_host_view.h"
38 #include "content/public/common/media_stream_request.h" 38 #include "content/public/common/media_stream_request.h"
39 #include "content/public/common/origin_util.h" 39 #include "content/public/common/origin_util.h"
40 #include "extensions/common/constants.h" 40 #include "extensions/common/constants.h"
41 #include "ui/base/l10n/l10n_util.h" 41 #include "ui/base/l10n/l10n_util.h"
42 42
43 #if defined(OS_ANDROID) 43 #if defined(OS_ANDROID)
44 #include <vector> 44 #include <vector>
45 45
46 #include "chrome/browser/android/preferences/pref_service_bridge.h" 46 #include "chrome/browser/android/preferences/pref_service_bridge.h"
47 #include "chrome/browser/media/webrtc/media_stream_infobar_delegate_android.h"
48 #include "chrome/browser/permissions/permission_dialog_delegate.h"
47 #include "chrome/browser/permissions/permission_update_infobar_delegate_android. h" 49 #include "chrome/browser/permissions/permission_update_infobar_delegate_android. h"
48 #include "chrome/grit/theme_resources.h" 50 #include "chrome/grit/theme_resources.h"
49 #include "content/public/browser/android/content_view_core.h" 51 #include "content/public/browser/android/content_view_core.h"
50 #include "ui/android/window_android.h" 52 #include "ui/android/window_android.h"
51 #else // !defined(OS_ANDROID) 53 #else // !defined(OS_ANDROID)
54 #include "chrome/browser/permissions/permission_request_manager.h"
52 #include "ui/vector_icons/vector_icons.h" 55 #include "ui/vector_icons/vector_icons.h"
53 #endif 56 #endif
54 57
55 using content::BrowserThread; 58 using content::BrowserThread;
56 59
57 namespace { 60 namespace {
58 61
59 // Returns true if the given ContentSettingsType is being requested in 62 // Returns true if the given ContentSettingsType is being requested in
60 // |request|. 63 // |request|.
61 bool ContentTypeIsRequested(ContentSettingsType type, 64 bool ContentTypeIsRequested(ContentSettingsType type,
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 // Calls |action_function| for each permission requested by |request|. 96 // Calls |action_function| for each permission requested by |request|.
94 void RecordPermissionAction(const content::MediaStreamRequest& request, 97 void RecordPermissionAction(const content::MediaStreamRequest& request,
95 Profile* profile, 98 Profile* profile,
96 PermissionActionCallback callback) { 99 PermissionActionCallback callback) {
97 RecordSinglePermissionAction(request, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, 100 RecordSinglePermissionAction(request, CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
98 profile, callback); 101 profile, callback);
99 RecordSinglePermissionAction( 102 RecordSinglePermissionAction(
100 request, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, profile, callback); 103 request, CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, profile, callback);
101 } 104 }
102 105
106 #if defined(OS_ANDROID)
107 // Callback for the permission update infobar when the site and Chrome
108 // permissions are mismatched on Android.
109 void OnPermissionConflictResolved(
110 std::unique_ptr<MediaStreamDevicesController> controller,
111 bool allowed) {
112 if (allowed)
113 controller->PermissionGranted();
114 else
115 controller->ForcePermissionDeniedTemporarily();
116 }
117
118 #endif // defined(OS_ANDROID)
119
103 // This helper class helps to measure the number of media stream requests that 120 // This helper class helps to measure the number of media stream requests that
104 // occur. It ensures that only one request will be recorded per navigation, per 121 // occur. It ensures that only one request will be recorded per navigation, per
105 // frame. TODO(raymes): Remove this when https://crbug.com/526324 is fixed. 122 // frame. TODO(raymes): Remove this when https://crbug.com/526324 is fixed.
106 class MediaPermissionRequestLogger : content::WebContentsObserver { 123 class MediaPermissionRequestLogger : content::WebContentsObserver {
107 // Map of <render process id, render frame id> -> 124 // Map of <render process id, render frame id> ->
108 // MediaPermissionRequestLogger. 125 // MediaPermissionRequestLogger.
109 using RequestMap = std::map<std::pair<int, int>, 126 using RequestMap = std::map<std::pair<int, int>,
110 std::unique_ptr<MediaPermissionRequestLogger>>; 127 std::unique_ptr<MediaPermissionRequestLogger>>;
111 128
112 public: 129 public:
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
151 void RenderFrameDeleted( 168 void RenderFrameDeleted(
152 content::RenderFrameHost* render_frame_host) override { 169 content::RenderFrameHost* render_frame_host) override {
153 PageChanged(render_frame_host); 170 PageChanged(render_frame_host);
154 } 171 }
155 172
156 RequestMap::key_type key_; 173 RequestMap::key_type key_;
157 }; 174 };
158 175
159 } // namespace 176 } // namespace
160 177
161 MediaStreamDevicesController::MediaStreamDevicesController( 178 // static
179 void MediaStreamDevicesController::RequestPermissions(
162 content::WebContents* web_contents, 180 content::WebContents* web_contents,
163 const content::MediaStreamRequest& request, 181 const content::MediaStreamRequest& request,
164 const content::MediaResponseCallback& callback) 182 const content::MediaResponseCallback& callback) {
165 : web_contents_(web_contents), 183 std::unique_ptr<MediaStreamDevicesController> controller(
166 request_(request), 184 new MediaStreamDevicesController(web_contents, request, callback));
167 callback_(callback) { 185 if (!controller->IsAskingForAudio() && !controller->IsAskingForVideo()) {
168 if (request_.request_type == content::MEDIA_OPEN_DEVICE_PEPPER_ONLY) { 186 #if defined(OS_ANDROID)
169 MediaPermissionRequestLogger::LogRequest( 187 // If either audio or video was previously allowed and Chrome no longer has
170 web_contents, request.render_process_id, request.render_frame_id, 188 // the necessary permissions, show a infobar to attempt to address this
171 content::IsOriginSecure(request_.security_origin)); 189 // mismatch.
172 } 190 std::vector<ContentSettingsType> content_settings_types;
173 profile_ = Profile::FromBrowserContext(web_contents->GetBrowserContext()); 191 if (controller->IsAllowedForAudio())
174 content_settings_ = TabSpecificContentSettings::FromWebContents(web_contents); 192 content_settings_types.push_back(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC);
175 193
176 content::MediaStreamRequestResult denial_reason = content::MEDIA_DEVICE_OK; 194 if (controller->IsAllowedForVideo()) {
177 old_audio_setting_ = GetContentSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC, 195 content_settings_types.push_back(
178 request_, &denial_reason); 196 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA);
179 old_video_setting_ = GetContentSetting( 197 }
180 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, request_, &denial_reason); 198 if (!content_settings_types.empty() &&
181 199 PermissionUpdateInfoBarDelegate::ShouldShowPermissionInfobar(
182 // If either setting is ask, we show the infobar. 200 web_contents, content_settings_types)) {
183 if (old_audio_setting_ == CONTENT_SETTING_ASK || 201 PermissionUpdateInfoBarDelegate::Create(
184 old_video_setting_ == CONTENT_SETTING_ASK) { 202 web_contents, content_settings_types,
203 base::Bind(&OnPermissionConflictResolved, base::Passed(&controller)));
204 }
205 #endif
185 return; 206 return;
186 } 207 }
187 208
188 #if defined(OS_ANDROID) 209 #if defined(OS_ANDROID)
189 std::vector<ContentSettingsType> content_settings_types; 210 PermissionUmaUtil::RecordPermissionPromptShown(
190 if (IsAllowedForAudio()) 211 controller->GetPermissionRequestType(),
191 content_settings_types.push_back(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC); 212 PermissionUtil::GetGestureType(request.user_gesture));
192 213 if (PermissionDialogDelegate::ShouldShowDialog(request.user_gesture)) {
193 if (IsAllowedForVideo()) { 214 PermissionDialogDelegate::CreateMediaStreamDialog(
194 content_settings_types.push_back( 215 web_contents, request.user_gesture, std::move(controller));
195 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA); 216 } else {
217 MediaStreamInfoBarDelegateAndroid::Create(
218 web_contents, request.user_gesture, std::move(controller));
196 } 219 }
197 220 #else
198 // If the site had been previously granted the access to audio or video but 221 PermissionRequestManager* permission_request_manager =
199 // Chrome is now missing the necessary permission, we need to show an infobar 222 PermissionRequestManager::FromWebContents(web_contents);
200 // to resolve the difference. 223 if (permission_request_manager)
201 if (!content_settings_types.empty() && 224 permission_request_manager->AddRequest(controller.release());
202 PermissionUpdateInfoBarDelegate::ShouldShowPermissionInfobar(
203 web_contents, content_settings_types)) {
204 return;
205 }
206 #endif 225 #endif
207
208 // Otherwise we can run the callback immediately.
209 RunCallback(old_audio_setting_, old_video_setting_, denial_reason);
210 }
211
212 MediaStreamDevicesController::~MediaStreamDevicesController() {
213 if (!callback_.is_null()) {
214 RecordPermissionAction(request_, profile_,
215 base::Bind(PermissionUmaUtil::PermissionIgnored));
216 callback_.Run(content::MediaStreamDevices(),
217 content::MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN,
218 std::unique_ptr<content::MediaStreamUI>());
219 }
220 } 226 }
221 227
222 // static 228 // static
223 void MediaStreamDevicesController::RegisterProfilePrefs( 229 void MediaStreamDevicesController::RegisterProfilePrefs(
224 user_prefs::PrefRegistrySyncable* prefs) { 230 user_prefs::PrefRegistrySyncable* prefs) {
225 prefs->RegisterBooleanPref(prefs::kVideoCaptureAllowed, true); 231 prefs->RegisterBooleanPref(prefs::kVideoCaptureAllowed, true);
226 prefs->RegisterBooleanPref(prefs::kAudioCaptureAllowed, true); 232 prefs->RegisterBooleanPref(prefs::kAudioCaptureAllowed, true);
227 prefs->RegisterListPref(prefs::kVideoCaptureAllowedUrls); 233 prefs->RegisterListPref(prefs::kVideoCaptureAllowedUrls);
228 prefs->RegisterListPref(prefs::kAudioCaptureAllowedUrls); 234 prefs->RegisterListPref(prefs::kAudioCaptureAllowedUrls);
229 } 235 }
230 236
231 bool MediaStreamDevicesController::IsAllowedForAudio() const { 237 MediaStreamDevicesController::~MediaStreamDevicesController() {
232 return old_audio_setting_ == CONTENT_SETTING_ALLOW; 238 if (!callback_.is_null()) {
233 } 239 RecordPermissionAction(request_, profile_,
234 240 base::Bind(PermissionUmaUtil::PermissionIgnored));
235 bool MediaStreamDevicesController::IsAllowedForVideo() const { 241 callback_.Run(content::MediaStreamDevices(),
236 return old_video_setting_ == CONTENT_SETTING_ALLOW; 242 content::MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN,
243 std::unique_ptr<content::MediaStreamUI>());
244 }
237 } 245 }
238 246
239 bool MediaStreamDevicesController::IsAskingForAudio() const { 247 bool MediaStreamDevicesController::IsAskingForAudio() const {
240 return old_audio_setting_ == CONTENT_SETTING_ASK; 248 return old_audio_setting_ == CONTENT_SETTING_ASK;
241 } 249 }
242 250
243 bool MediaStreamDevicesController::IsAskingForVideo() const { 251 bool MediaStreamDevicesController::IsAskingForVideo() const {
244 return old_video_setting_ == CONTENT_SETTING_ASK; 252 return old_video_setting_ == CONTENT_SETTING_ASK;
245 } 253 }
246 254
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
321 329
322 void MediaStreamDevicesController::RequestFinished() { 330 void MediaStreamDevicesController::RequestFinished() {
323 delete this; 331 delete this;
324 } 332 }
325 333
326 PermissionRequestType MediaStreamDevicesController::GetPermissionRequestType() 334 PermissionRequestType MediaStreamDevicesController::GetPermissionRequestType()
327 const { 335 const {
328 return PermissionRequestType::MEDIA_STREAM; 336 return PermissionRequestType::MEDIA_STREAM;
329 } 337 }
330 338
339 MediaStreamDevicesController::MediaStreamDevicesController(
340 content::WebContents* web_contents,
341 const content::MediaStreamRequest& request,
342 const content::MediaResponseCallback& callback)
343 : web_contents_(web_contents), request_(request), callback_(callback) {
344 if (request_.request_type == content::MEDIA_OPEN_DEVICE_PEPPER_ONLY) {
345 MediaPermissionRequestLogger::LogRequest(
346 web_contents, request.render_process_id, request.render_frame_id,
347 content::IsOriginSecure(request_.security_origin));
348 }
349 profile_ = Profile::FromBrowserContext(web_contents->GetBrowserContext());
350 content_settings_ = TabSpecificContentSettings::FromWebContents(web_contents);
351
352 content::MediaStreamRequestResult denial_reason = content::MEDIA_DEVICE_OK;
353 old_audio_setting_ = GetContentSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
354 request_, &denial_reason);
355 old_video_setting_ = GetContentSetting(
356 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, request_, &denial_reason);
357
358 // If either setting is ask, we show the infobar.
359 if (old_audio_setting_ == CONTENT_SETTING_ASK ||
360 old_video_setting_ == CONTENT_SETTING_ASK) {
361 return;
362 }
363
364 #if defined(OS_ANDROID)
365 std::vector<ContentSettingsType> content_settings_types;
366 if (IsAllowedForAudio())
367 content_settings_types.push_back(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC);
368
369 if (IsAllowedForVideo()) {
370 content_settings_types.push_back(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA);
371 }
372
373 // If the site had been previously granted the access to audio or video but
374 // Chrome is now missing the necessary permission, we need to show an infobar
375 // to resolve the difference.
376 if (!content_settings_types.empty() &&
377 PermissionUpdateInfoBarDelegate::ShouldShowPermissionInfobar(
378 web_contents, content_settings_types)) {
379 return;
380 }
381 #endif
382
383 // Otherwise we can run the callback immediately.
384 RunCallback(old_audio_setting_, old_video_setting_, denial_reason);
385 }
386
387 bool MediaStreamDevicesController::IsAllowedForAudio() const {
388 return old_audio_setting_ == CONTENT_SETTING_ALLOW;
389 }
390
391 bool MediaStreamDevicesController::IsAllowedForVideo() const {
392 return old_video_setting_ == CONTENT_SETTING_ALLOW;
393 }
394
331 content::MediaStreamDevices MediaStreamDevicesController::GetDevices( 395 content::MediaStreamDevices MediaStreamDevicesController::GetDevices(
332 ContentSetting audio_setting, 396 ContentSetting audio_setting,
333 ContentSetting video_setting) { 397 ContentSetting video_setting) {
334 bool audio_allowed = audio_setting == CONTENT_SETTING_ALLOW; 398 bool audio_allowed = audio_setting == CONTENT_SETTING_ALLOW;
335 bool video_allowed = video_setting == CONTENT_SETTING_ALLOW; 399 bool video_allowed = video_setting == CONTENT_SETTING_ALLOW;
336 400
337 if (!audio_allowed && !video_allowed) 401 if (!audio_allowed && !video_allowed)
338 return content::MediaStreamDevices(); 402 return content::MediaStreamDevices();
339 403
340 content::MediaStreamDevices devices; 404 content::MediaStreamDevices devices;
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
595 } 659 }
596 } 660 }
597 661
598 // Don't approve device requests if the tab was hidden. 662 // Don't approve device requests if the tab was hidden.
599 // TODO(qinmin): Add a test for this. http://crbug.com/396869. 663 // TODO(qinmin): Add a test for this. http://crbug.com/396869.
600 // TODO(raymes): Shouldn't this apply to all permissions not just audio/video? 664 // TODO(raymes): Shouldn't this apply to all permissions not just audio/video?
601 return web_contents_->GetRenderWidgetHostView()->IsShowing(); 665 return web_contents_->GetRenderWidgetHostView()->IsShowing();
602 #endif 666 #endif
603 return true; 667 return true;
604 } 668 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698