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

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

Powered by Google App Engine
This is Rietveld 408576698