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

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

Issue 2307083002: Cleanup: move WebRTC related files from chrome/browser/media to chrome/browser/media/webrtc/ (Closed)
Patch Set: Removed file wrongly resuscitated during rebase Created 4 years, 3 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/media/media_stream_devices_controller.h"
6
7 #include <map>
8 #include <utility>
9
10 #include "base/auto_reset.h"
11 #include "base/callback_helpers.h"
12 #include "base/memory/ptr_util.h"
13 #include "base/metrics/histogram_macros.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/values.h"
16 #include "chrome/browser/content_settings/host_content_settings_map_factory.h"
17 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
18 #include "chrome/browser/media/media_capture_devices_dispatcher.h"
19 #include "chrome/browser/media/media_permission.h"
20 #include "chrome/browser/media/media_stream_capture_indicator.h"
21 #include "chrome/browser/media/media_stream_device_permissions.h"
22 #include "chrome/browser/permissions/permission_uma_util.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/ui/browser.h"
25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/common/features.h"
27 #include "chrome/common/pref_names.h"
28 #include "chrome/grit/generated_resources.h"
29 #include "chrome/grit/theme_resources.h"
30 #include "components/content_settings/core/browser/host_content_settings_map.h"
31 #include "components/content_settings/core/common/content_settings_pattern.h"
32 #include "components/pref_registry/pref_registry_syncable.h"
33 #include "components/prefs/scoped_user_pref_update.h"
34 #include "components/url_formatter/elide_url.h"
35 #include "content/public/browser/browser_thread.h"
36 #include "content/public/browser/permission_type.h"
37 #include "content/public/browser/render_frame_host.h"
38 #include "content/public/browser/render_process_host.h"
39 #include "content/public/browser/render_widget_host_view.h"
40 #include "content/public/common/media_stream_request.h"
41 #include "content/public/common/origin_util.h"
42 #include "extensions/common/constants.h"
43 #include "ui/base/l10n/l10n_util.h"
44
45 #if BUILDFLAG(ANDROID_JAVA_UI)
46 #include <vector>
47
48 #include "chrome/browser/android/preferences/pref_service_bridge.h"
49 #include "chrome/browser/permissions/permission_update_infobar_delegate_android. h"
50 #include "content/public/browser/android/content_view_core.h"
51 #include "ui/android/window_android.h"
52 #endif // BUILDFLAG(ANDROID_JAVA_UI)
53
54 using content::BrowserThread;
55
56 namespace {
57
58 // Returns true if the given ContentSettingsType is being requested in
59 // |request|.
60 bool ContentTypeIsRequested(content::PermissionType type,
61 const content::MediaStreamRequest& request) {
62 if (request.request_type == content::MEDIA_OPEN_DEVICE_PEPPER_ONLY)
63 return true;
64
65 if (type == content::PermissionType::AUDIO_CAPTURE)
66 return request.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE;
67
68 if (type == content::PermissionType::VIDEO_CAPTURE)
69 return request.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE;
70
71 return false;
72 }
73
74 using PermissionActionCallback =
75 base::Callback<void(content::PermissionType,
76 PermissionRequestGestureType,
77 const GURL&,
78 Profile*)>;
79
80 void RecordSinglePermissionAction(const content::MediaStreamRequest& request,
81 content::PermissionType permission_type,
82 Profile* profile,
83 PermissionActionCallback callback) {
84 if (ContentTypeIsRequested(permission_type, request)) {
85 // TODO(stefanocs): Pass the actual |gesture_type| once this file has been
86 // refactored into PermissionContext.
87 callback.Run(permission_type, PermissionRequestGestureType::UNKNOWN,
88 request.security_origin, profile);
89 }
90 }
91
92 // Calls |action_function| for each permission requested by |request|.
93 void RecordPermissionAction(const content::MediaStreamRequest& request,
94 Profile* profile,
95 PermissionActionCallback callback) {
96 RecordSinglePermissionAction(request, content::PermissionType::AUDIO_CAPTURE,
97 profile, callback);
98 RecordSinglePermissionAction(request, content::PermissionType::VIDEO_CAPTURE,
99 profile, callback);
100 }
101
102 // This helper class helps to measure the number of media stream requests that
103 // occur. It ensures that only one request will be recorded per navigation, per
104 // frame. TODO(raymes): Remove this when https://crbug.com/526324 is fixed.
105 class MediaPermissionRequestLogger : content::WebContentsObserver {
106 // Map of <render process id, render frame id> ->
107 // MediaPermissionRequestLogger.
108 using RequestMap = std::map<std::pair<int, int>,
109 std::unique_ptr<MediaPermissionRequestLogger>>;
110
111 public:
112 static void LogRequest(content::WebContents* contents,
113 int render_process_id,
114 int render_frame_id,
115 bool is_secure) {
116 RequestMap::key_type key =
117 std::make_pair(render_process_id, render_frame_id);
118 if (!base::ContainsKey(GetRequestMap(), key)) {
119 UMA_HISTOGRAM_BOOLEAN("Pepper.SecureOrigin.MediaStreamRequest",
120 is_secure);
121 GetRequestMap()[key] =
122 base::WrapUnique(new MediaPermissionRequestLogger(contents, key));
123 }
124 }
125
126 private:
127 MediaPermissionRequestLogger(content::WebContents* contents,
128 RequestMap::key_type key)
129 : WebContentsObserver(contents), key_(key) {}
130
131 void PageChanged(content::RenderFrameHost* render_frame_host) {
132 if (std::make_pair(render_frame_host->GetProcess()->GetID(),
133 render_frame_host->GetRoutingID()) == key_) {
134 GetRequestMap().erase(key_);
135 }
136 }
137
138 static RequestMap& GetRequestMap() {
139 CR_DEFINE_STATIC_LOCAL(RequestMap, request_map, ());
140 return request_map;
141 }
142
143 // content::WebContentsObserver overrides
144 void DidNavigateAnyFrame(
145 content::RenderFrameHost* render_frame_host,
146 const content::LoadCommittedDetails& details,
147 const content::FrameNavigateParams& params) override {
148 PageChanged(render_frame_host);
149 }
150
151 void RenderFrameDeleted(
152 content::RenderFrameHost* render_frame_host) override {
153 PageChanged(render_frame_host);
154 }
155
156 RequestMap::key_type key_;
157 };
158
159 } // namespace
160
161 MediaStreamDevicesController::MediaStreamDevicesController(
162 content::WebContents* web_contents,
163 const content::MediaStreamRequest& request,
164 const content::MediaResponseCallback& callback)
165 : web_contents_(web_contents),
166 request_(request),
167 callback_(callback),
168 persist_permission_changes_(true) {
169 if (request_.request_type == content::MEDIA_OPEN_DEVICE_PEPPER_ONLY) {
170 MediaPermissionRequestLogger::LogRequest(
171 web_contents, request.render_process_id, request.render_frame_id,
172 content::IsOriginSecure(request_.security_origin));
173 }
174 profile_ = Profile::FromBrowserContext(web_contents->GetBrowserContext());
175 content_settings_ = TabSpecificContentSettings::FromWebContents(web_contents);
176
177 content::MediaStreamRequestResult denial_reason = content::MEDIA_DEVICE_OK;
178 old_audio_setting_ = GetContentSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
179 request_, &denial_reason);
180 old_video_setting_ = GetContentSetting(
181 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, request_, &denial_reason);
182
183 // If either setting is ask, we show the infobar.
184 if (old_audio_setting_ == CONTENT_SETTING_ASK ||
185 old_video_setting_ == CONTENT_SETTING_ASK) {
186 return;
187 }
188
189 #if BUILDFLAG(ANDROID_JAVA_UI)
190 std::vector<ContentSettingsType> content_settings_types;
191 if (IsAllowedForAudio())
192 content_settings_types.push_back(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC);
193
194 if (IsAllowedForVideo()) {
195 content_settings_types.push_back(
196 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA);
197 }
198
199 // If the site had been previously granted the access to audio or video but
200 // Chrome is now missing the necessary permission, we need to show an infobar
201 // to resolve the difference.
202 if (!content_settings_types.empty() &&
203 PermissionUpdateInfoBarDelegate::ShouldShowPermissionInfobar(
204 web_contents, content_settings_types)) {
205 return;
206 }
207 #endif
208
209 // Otherwise we can run the callback immediately.
210 RunCallback(old_audio_setting_, old_video_setting_, denial_reason);
211 }
212
213 MediaStreamDevicesController::~MediaStreamDevicesController() {
214 if (!callback_.is_null()) {
215 RecordPermissionAction(request_, profile_,
216 base::Bind(PermissionUmaUtil::PermissionIgnored));
217 callback_.Run(content::MediaStreamDevices(),
218 content::MEDIA_DEVICE_FAILED_DUE_TO_SHUTDOWN,
219 std::unique_ptr<content::MediaStreamUI>());
220 }
221 }
222
223 // static
224 void MediaStreamDevicesController::RegisterProfilePrefs(
225 user_prefs::PrefRegistrySyncable* prefs) {
226 prefs->RegisterBooleanPref(prefs::kVideoCaptureAllowed, true);
227 prefs->RegisterBooleanPref(prefs::kAudioCaptureAllowed, true);
228 prefs->RegisterListPref(prefs::kVideoCaptureAllowedUrls);
229 prefs->RegisterListPref(prefs::kAudioCaptureAllowedUrls);
230 }
231
232 bool MediaStreamDevicesController::IsAllowedForAudio() const {
233 return old_audio_setting_ == CONTENT_SETTING_ALLOW;
234 }
235
236 bool MediaStreamDevicesController::IsAllowedForVideo() const {
237 return old_video_setting_ == CONTENT_SETTING_ALLOW;
238 }
239
240 bool MediaStreamDevicesController::IsAskingForAudio() const {
241 return old_audio_setting_ == CONTENT_SETTING_ASK;
242 }
243
244 bool MediaStreamDevicesController::IsAskingForVideo() const {
245 return old_video_setting_ == CONTENT_SETTING_ASK;
246 }
247
248 base::string16 MediaStreamDevicesController::GetMessageText() const {
249 int message_id = IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO;
250 if (!IsAskingForAudio())
251 message_id = IDS_MEDIA_CAPTURE_VIDEO_ONLY;
252 else if (!IsAskingForVideo())
253 message_id = IDS_MEDIA_CAPTURE_AUDIO_ONLY;
254 return l10n_util::GetStringFUTF16(
255 message_id,
256 url_formatter::FormatUrlForSecurityDisplay(
257 GetOrigin(), url_formatter::SchemeDisplay::OMIT_CRYPTOGRAPHIC));
258 }
259
260 void MediaStreamDevicesController::ForcePermissionDeniedTemporarily() {
261 base::AutoReset<bool> persist_permissions(
262 &persist_permission_changes_, false);
263 // TODO(tsergeant): Determine whether it is appropriate to record permission
264 // action metrics here, as this is a different sort of user action.
265 RunCallback(CONTENT_SETTING_BLOCK,
266 CONTENT_SETTING_BLOCK,
267 content::MEDIA_DEVICE_PERMISSION_DENIED);
268 }
269
270 int MediaStreamDevicesController::GetIconId() const {
271 if (IsAskingForVideo())
272 return IDR_INFOBAR_MEDIA_STREAM_CAMERA;
273
274 return IDR_INFOBAR_MEDIA_STREAM_MIC;
275 }
276
277 base::string16 MediaStreamDevicesController::GetMessageTextFragment() const {
278 int message_id = IDS_MEDIA_CAPTURE_AUDIO_AND_VIDEO_PERMISSION_FRAGMENT;
279 if (!IsAskingForAudio())
280 message_id = IDS_MEDIA_CAPTURE_VIDEO_ONLY_PERMISSION_FRAGMENT;
281 else if (!IsAskingForVideo())
282 message_id = IDS_MEDIA_CAPTURE_AUDIO_ONLY_PERMISSION_FRAGMENT;
283 return l10n_util::GetStringUTF16(message_id);
284 }
285
286 GURL MediaStreamDevicesController::GetOrigin() const {
287 return request_.security_origin;
288 }
289
290 void MediaStreamDevicesController::PermissionGranted() {
291 RecordPermissionAction(request_, profile_,
292 base::Bind(PermissionUmaUtil::PermissionGranted));
293 RunCallback(GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
294 old_audio_setting_, CONTENT_SETTING_ALLOW),
295 GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
296 old_video_setting_, CONTENT_SETTING_ALLOW),
297 content::MEDIA_DEVICE_PERMISSION_DENIED);
298 }
299
300 void MediaStreamDevicesController::PermissionDenied() {
301 RecordPermissionAction(request_, profile_,
302 base::Bind(PermissionUmaUtil::PermissionDenied));
303 RunCallback(GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
304 old_audio_setting_, CONTENT_SETTING_BLOCK),
305 GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
306 old_video_setting_, CONTENT_SETTING_BLOCK),
307 content::MEDIA_DEVICE_PERMISSION_DENIED);
308 }
309
310 void MediaStreamDevicesController::GroupedRequestFinished(bool audio_accepted,
311 bool video_accepted) {
312 RecordSinglePermissionAction(
313 request_, content::PermissionType::AUDIO_CAPTURE, profile_,
314 base::Bind(audio_accepted ? PermissionUmaUtil::PermissionGranted
315 : PermissionUmaUtil::PermissionDenied));
316 RecordSinglePermissionAction(
317 request_, content::PermissionType::VIDEO_CAPTURE, profile_,
318 base::Bind(video_accepted ? PermissionUmaUtil::PermissionGranted
319 : PermissionUmaUtil::PermissionDenied));
320
321 ContentSetting audio_setting =
322 audio_accepted ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
323 ContentSetting video_setting =
324 video_accepted ? CONTENT_SETTING_ALLOW : CONTENT_SETTING_BLOCK;
325 RunCallback(GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
326 old_audio_setting_, audio_setting),
327 GetNewSetting(CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA,
328 old_video_setting_, video_setting),
329 content::MEDIA_DEVICE_PERMISSION_DENIED);
330 }
331
332 void MediaStreamDevicesController::Cancelled() {
333 RecordPermissionAction(request_, profile_,
334 base::Bind(PermissionUmaUtil::PermissionDismissed));
335 RunCallback(old_audio_setting_, old_video_setting_,
336 content::MEDIA_DEVICE_PERMISSION_DISMISSED);
337 }
338
339 void MediaStreamDevicesController::RequestFinished() {
340 delete this;
341 }
342
343 PermissionRequestType MediaStreamDevicesController::GetPermissionRequestType()
344 const {
345 return PermissionRequestType::MEDIA_STREAM;
346 }
347
348 content::MediaStreamDevices MediaStreamDevicesController::GetDevices(
349 ContentSetting audio_setting,
350 ContentSetting video_setting) {
351 bool audio_allowed = audio_setting == CONTENT_SETTING_ALLOW;
352 bool video_allowed = video_setting == CONTENT_SETTING_ALLOW;
353
354 if (!audio_allowed && !video_allowed)
355 return content::MediaStreamDevices();
356
357 content::MediaStreamDevices devices;
358 switch (request_.request_type) {
359 case content::MEDIA_OPEN_DEVICE_PEPPER_ONLY: {
360 const content::MediaStreamDevice* device = NULL;
361 // For open device request, when requested device_id is empty, pick
362 // the first available of the given type. If requested device_id is
363 // not empty, return the desired device if it's available. Otherwise,
364 // return no device.
365 if (audio_allowed &&
366 request_.audio_type == content::MEDIA_DEVICE_AUDIO_CAPTURE) {
367 DCHECK_EQ(content::MEDIA_NO_SERVICE, request_.video_type);
368 if (!request_.requested_audio_device_id.empty()) {
369 device =
370 MediaCaptureDevicesDispatcher::GetInstance()
371 ->GetRequestedAudioDevice(request_.requested_audio_device_id);
372 } else {
373 device = MediaCaptureDevicesDispatcher::GetInstance()
374 ->GetFirstAvailableAudioDevice();
375 }
376 } else if (video_allowed &&
377 request_.video_type == content::MEDIA_DEVICE_VIDEO_CAPTURE) {
378 DCHECK_EQ(content::MEDIA_NO_SERVICE, request_.audio_type);
379 // Pepper API opens only one device at a time.
380 if (!request_.requested_video_device_id.empty()) {
381 device =
382 MediaCaptureDevicesDispatcher::GetInstance()
383 ->GetRequestedVideoDevice(request_.requested_video_device_id);
384 } else {
385 device = MediaCaptureDevicesDispatcher::GetInstance()
386 ->GetFirstAvailableVideoDevice();
387 }
388 }
389 if (device)
390 devices.push_back(*device);
391 break;
392 }
393 case content::MEDIA_GENERATE_STREAM: {
394 bool get_default_audio_device = audio_allowed;
395 bool get_default_video_device = video_allowed;
396
397 // Get the exact audio or video device if an id is specified.
398 if (audio_allowed && !request_.requested_audio_device_id.empty()) {
399 const content::MediaStreamDevice* audio_device =
400 MediaCaptureDevicesDispatcher::GetInstance()
401 ->GetRequestedAudioDevice(request_.requested_audio_device_id);
402 if (audio_device) {
403 devices.push_back(*audio_device);
404 get_default_audio_device = false;
405 }
406 }
407 if (video_allowed && !request_.requested_video_device_id.empty()) {
408 const content::MediaStreamDevice* video_device =
409 MediaCaptureDevicesDispatcher::GetInstance()
410 ->GetRequestedVideoDevice(request_.requested_video_device_id);
411 if (video_device) {
412 devices.push_back(*video_device);
413 get_default_video_device = false;
414 }
415 }
416
417 // If either or both audio and video devices were requested but not
418 // specified by id, get the default devices.
419 if (get_default_audio_device || get_default_video_device) {
420 MediaCaptureDevicesDispatcher::GetInstance()
421 ->GetDefaultDevicesForProfile(profile_, get_default_audio_device,
422 get_default_video_device, &devices);
423 }
424 break;
425 }
426 case content::MEDIA_DEVICE_ACCESS: {
427 // Get the default devices for the request.
428 MediaCaptureDevicesDispatcher::GetInstance()->GetDefaultDevicesForProfile(
429 profile_, audio_allowed, video_allowed, &devices);
430 break;
431 }
432 case content::MEDIA_ENUMERATE_DEVICES: {
433 // Do nothing.
434 NOTREACHED();
435 break;
436 }
437 } // switch
438
439 if (audio_allowed) {
440 HostContentSettingsMapFactory::GetForProfile(profile_)
441 ->UpdateLastUsageByPattern(
442 ContentSettingsPattern::FromURLNoWildcard(request_.security_origin),
443 ContentSettingsPattern::Wildcard(),
444 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC);
445 }
446 if (video_allowed) {
447 HostContentSettingsMapFactory::GetForProfile(profile_)
448 ->UpdateLastUsageByPattern(
449 ContentSettingsPattern::FromURLNoWildcard(request_.security_origin),
450 ContentSettingsPattern::Wildcard(),
451 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA);
452 }
453
454 return devices;
455 }
456
457 void MediaStreamDevicesController::RunCallback(
458 ContentSetting audio_setting,
459 ContentSetting video_setting,
460 content::MediaStreamRequestResult denial_reason) {
461 CHECK(!callback_.is_null());
462
463 // If the kill switch is on we don't update the tab context or persist the
464 // setting.
465 if (persist_permission_changes_ &&
466 denial_reason != content::MEDIA_DEVICE_KILL_SWITCH_ON) {
467 StorePermission(audio_setting, video_setting);
468 UpdateTabSpecificContentSettings(audio_setting, video_setting);
469 }
470
471 content::MediaStreamDevices devices =
472 GetDevices(audio_setting, video_setting);
473
474 // If either audio or video are allowed then the callback should report
475 // success, otherwise we report |denial_reason|.
476 content::MediaStreamRequestResult request_result = content::MEDIA_DEVICE_OK;
477 if (audio_setting != CONTENT_SETTING_ALLOW &&
478 video_setting != CONTENT_SETTING_ALLOW) {
479 DCHECK_NE(content::MEDIA_DEVICE_OK, denial_reason);
480 request_result = denial_reason;
481 } else if (devices.empty()) {
482 // Even if one of the content settings was allowed, if there are no devices
483 // at this point we still report a failure.
484 request_result = content::MEDIA_DEVICE_NO_HARDWARE;
485 }
486
487 std::unique_ptr<content::MediaStreamUI> ui;
488 if (!devices.empty()) {
489 ui = MediaCaptureDevicesDispatcher::GetInstance()
490 ->GetMediaStreamCaptureIndicator()
491 ->RegisterMediaStream(web_contents_, devices);
492 }
493 base::ResetAndReturn(&callback_).Run(devices, request_result, std::move(ui));
494 }
495
496 void MediaStreamDevicesController::StorePermission(
497 ContentSetting new_audio_setting,
498 ContentSetting new_video_setting) const {
499 DCHECK_CURRENTLY_ON(BrowserThread::UI);
500 DCHECK(content::IsOriginSecure(request_.security_origin) ||
501 request_.request_type == content::MEDIA_OPEN_DEVICE_PEPPER_ONLY);
502
503 if (IsAskingForAudio() && new_audio_setting != CONTENT_SETTING_ASK) {
504 HostContentSettingsMapFactory::GetForProfile(profile_)
505 ->SetContentSettingDefaultScope(request_.security_origin, GURL(),
506 CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC,
507 std::string(), new_audio_setting);
508 }
509 if (IsAskingForVideo() && new_video_setting != CONTENT_SETTING_ASK) {
510 HostContentSettingsMapFactory::GetForProfile(profile_)
511 ->SetContentSettingDefaultScope(
512 request_.security_origin, GURL(),
513 CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA, std::string(),
514 new_video_setting);
515 }
516 }
517
518 void MediaStreamDevicesController::UpdateTabSpecificContentSettings(
519 ContentSetting audio_setting,
520 ContentSetting video_setting) const {
521 if (!content_settings_)
522 return;
523
524 TabSpecificContentSettings::MicrophoneCameraState microphone_camera_state =
525 TabSpecificContentSettings::MICROPHONE_CAMERA_NOT_ACCESSED;
526 std::string selected_audio_device;
527 std::string selected_video_device;
528 std::string requested_audio_device = request_.requested_audio_device_id;
529 std::string requested_video_device = request_.requested_video_device_id;
530
531 // TODO(raymes): Why do we use the defaults here for the selected devices?
532 // Shouldn't we just use the devices that were actually selected?
533 PrefService* prefs = Profile::FromBrowserContext(
534 web_contents_->GetBrowserContext())->GetPrefs();
535 if (audio_setting != CONTENT_SETTING_DEFAULT) {
536 selected_audio_device =
537 requested_audio_device.empty()
538 ? prefs->GetString(prefs::kDefaultAudioCaptureDevice)
539 : requested_audio_device;
540 microphone_camera_state |=
541 TabSpecificContentSettings::MICROPHONE_ACCESSED |
542 (audio_setting == CONTENT_SETTING_ALLOW
543 ? 0
544 : TabSpecificContentSettings::MICROPHONE_BLOCKED);
545 }
546
547 if (video_setting != CONTENT_SETTING_DEFAULT) {
548 selected_video_device =
549 requested_video_device.empty()
550 ? prefs->GetString(prefs::kDefaultVideoCaptureDevice)
551 : requested_video_device;
552 microphone_camera_state |=
553 TabSpecificContentSettings::CAMERA_ACCESSED |
554 (video_setting == CONTENT_SETTING_ALLOW
555 ? 0
556 : TabSpecificContentSettings::CAMERA_BLOCKED);
557 }
558
559 content_settings_->OnMediaStreamPermissionSet(
560 request_.security_origin, microphone_camera_state, selected_audio_device,
561 selected_video_device, requested_audio_device, requested_video_device);
562 }
563
564 ContentSetting MediaStreamDevicesController::GetContentSetting(
565 ContentSettingsType content_type,
566 const content::MediaStreamRequest& request,
567 content::MediaStreamRequestResult* denial_reason) const {
568 DCHECK(content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC ||
569 content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA);
570
571 std::string requested_device_id;
572 if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC)
573 requested_device_id = request.requested_audio_device_id;
574 else if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA)
575 requested_device_id = request.requested_video_device_id;
576
577 if (!IsUserAcceptAllowed(content_type)) {
578 *denial_reason = content::MEDIA_DEVICE_PERMISSION_DENIED;
579 return CONTENT_SETTING_BLOCK;
580 }
581
582 content::PermissionType permission_type;
583 if (content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_MIC) {
584 permission_type = content::PermissionType::AUDIO_CAPTURE;
585 } else {
586 DCHECK(content_type == CONTENT_SETTINGS_TYPE_MEDIASTREAM_CAMERA);
587 permission_type = content::PermissionType::VIDEO_CAPTURE;
588 }
589
590 if (ContentTypeIsRequested(permission_type, request)) {
591 DCHECK(content::IsOriginSecure(request_.security_origin) ||
592 request_.request_type == content::MEDIA_OPEN_DEVICE_PEPPER_ONLY);
593 MediaPermission permission(content_type, request.security_origin,
594 web_contents_->GetLastCommittedURL().GetOrigin(), profile_);
595 return permission.GetPermissionStatusWithDeviceRequired(requested_device_id,
596 denial_reason);
597 }
598 // Return the default content setting if the device is not requested.
599 return CONTENT_SETTING_DEFAULT;
600 }
601
602 ContentSetting MediaStreamDevicesController::GetNewSetting(
603 ContentSettingsType content_type,
604 ContentSetting old_setting,
605 ContentSetting user_decision) const {
606 DCHECK(user_decision == CONTENT_SETTING_ALLOW ||
607 user_decision == CONTENT_SETTING_BLOCK);
608 ContentSetting result = old_setting;
609 if (old_setting == CONTENT_SETTING_ASK) {
610 if (user_decision == CONTENT_SETTING_ALLOW &&
611 IsUserAcceptAllowed(content_type)) {
612 result = CONTENT_SETTING_ALLOW;
613 } else if (user_decision == CONTENT_SETTING_BLOCK) {
614 result = CONTENT_SETTING_BLOCK;
615 }
616 }
617 return result;
618 }
619
620 bool MediaStreamDevicesController::IsUserAcceptAllowed(
621 ContentSettingsType content_type) const {
622 #if BUILDFLAG(ANDROID_JAVA_UI)
623 content::ContentViewCore* cvc =
624 content::ContentViewCore::FromWebContents(web_contents_);
625 if (!cvc)
626 return false;
627
628 ui::WindowAndroid* window_android = cvc->GetWindowAndroid();
629 if (!window_android)
630 return false;
631
632 std::string android_permission =
633 PrefServiceBridge::GetAndroidPermissionForContentSetting(content_type);
634 bool android_permission_blocked = false;
635 if (!android_permission.empty()) {
636 android_permission_blocked =
637 !window_android->HasPermission(android_permission) &&
638 !window_android->CanRequestPermission(android_permission);
639 }
640 if (android_permission_blocked)
641 return false;
642
643 // Don't approve device requests if the tab was hidden.
644 // TODO(qinmin): Add a test for this. http://crbug.com/396869.
645 // TODO(raymes): Shouldn't this apply to all permissions not just audio/video?
646 return web_contents_->GetRenderWidgetHostView()->IsShowing();
647 #endif
648 return true;
649 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698