Don't show supervised user as "already on this device" while they're being imported.
[chromium-blink-merge.git] / chrome / browser / media / protected_media_identifier_permission_context.cc
blob3b1f047b82e3c303044838d73de4f1459c1900d7
1 // Copyright 2013 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.
5 #include "chrome/browser/media/protected_media_identifier_permission_context.h"
7 #include "base/command_line.h"
8 #include "base/prefs/pref_service.h"
9 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/common/pref_names.h"
12 #include "components/content_settings/core/common/permission_request_id.h"
13 #include "content/public/browser/browser_thread.h"
14 #include "content/public/browser/user_metrics.h"
15 #include "content/public/browser/web_contents.h"
16 #if defined(OS_CHROMEOS)
17 #include <utility>
19 #include "chrome/browser/chromeos/attestation/platform_verification_dialog.h"
20 #include "chrome/browser/chromeos/settings/cros_settings.h"
21 #include "chromeos/chromeos_switches.h"
22 #include "chromeos/settings/cros_settings_names.h"
23 #include "components/pref_registry/pref_registry_syncable.h"
24 #include "components/user_prefs/user_prefs.h"
25 #include "ui/views/widget/widget.h"
26 #elif defined(OS_ANDROID)
27 #include "media/base/media_switches.h"
28 #else
29 #error This file currently only supports Chrome OS and Android.
30 #endif
32 #if defined(OS_CHROMEOS)
33 using chromeos::attestation::PlatformVerificationDialog;
34 #endif
36 ProtectedMediaIdentifierPermissionContext::
37 ProtectedMediaIdentifierPermissionContext(Profile* profile)
38 : PermissionContextBase(profile,
39 CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER)
40 #if defined(OS_CHROMEOS)
42 weak_factory_(this)
43 #endif
47 ProtectedMediaIdentifierPermissionContext::
48 ~ProtectedMediaIdentifierPermissionContext() {
51 void ProtectedMediaIdentifierPermissionContext::RequestPermission(
52 content::WebContents* web_contents,
53 const PermissionRequestID& id,
54 const GURL& requesting_origin,
55 bool user_gesture,
56 const BrowserPermissionCallback& callback) {
57 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
59 GURL embedding_origin = web_contents->GetLastCommittedURL().GetOrigin();
61 DVLOG(1) << __FUNCTION__ << ": (" << requesting_origin.spec() << ", "
62 << embedding_origin.spec() << ")";
64 ContentSetting content_setting =
65 GetPermissionStatus(requesting_origin, embedding_origin);
67 if (content_setting == CONTENT_SETTING_ALLOW ||
68 content_setting == CONTENT_SETTING_BLOCK) {
69 NotifyPermissionSet(id, requesting_origin, embedding_origin, callback,
70 false /* persist */, content_setting);
71 return;
74 DCHECK_EQ(CONTENT_SETTING_ASK, content_setting);
76 #if defined(OS_CHROMEOS)
77 // Since the dialog is modal, we only support one prompt per |web_contents|.
78 // Reject the new one if there is already one pending. See
79 // http://crbug.com/447005
80 if (pending_requests_.count(web_contents)) {
81 callback.Run(CONTENT_SETTING_ASK);
82 return;
85 // On ChromeOS, we don't use PermissionContextBase::RequestPermission() which
86 // uses the standard permission infobar/bubble UI. See http://crbug.com/454847
87 // Instead, we show the existing platform verification UI.
88 // TODO(xhwang): Remove when http://crbug.com/454847 is fixed.
89 views::Widget* widget = PlatformVerificationDialog::ShowDialog(
90 web_contents, requesting_origin,
91 base::Bind(&ProtectedMediaIdentifierPermissionContext::
92 OnPlatformVerificationConsentResponse,
93 weak_factory_.GetWeakPtr(), web_contents, id,
94 requesting_origin, embedding_origin, callback));
95 pending_requests_.insert(
96 std::make_pair(web_contents, std::make_pair(widget, id)));
97 #else
98 DCHECK(!base::CommandLine::ForCurrentProcess()->HasSwitch(
99 switches::kDisableInfobarForProtectedMediaIdentifier));
100 PermissionContextBase::RequestPermission(web_contents, id, requesting_origin,
101 user_gesture, callback);
102 #endif
105 ContentSetting ProtectedMediaIdentifierPermissionContext::GetPermissionStatus(
106 const GURL& requesting_origin,
107 const GURL& embedding_origin) const {
108 DVLOG(1) << __FUNCTION__ << ": (" << requesting_origin.spec() << ", "
109 << embedding_origin.spec() << ")";
111 if (!requesting_origin.is_valid() || !embedding_origin.is_valid() ||
112 !IsProtectedMediaIdentifierEnabled()) {
113 return CONTENT_SETTING_BLOCK;
116 ContentSetting content_setting = PermissionContextBase::GetPermissionStatus(
117 requesting_origin, embedding_origin);
118 DCHECK(content_setting == CONTENT_SETTING_ALLOW ||
119 content_setting == CONTENT_SETTING_BLOCK ||
120 content_setting == CONTENT_SETTING_ASK);
122 #if defined(OS_ANDROID)
123 // When kDisableInfobarForProtectedMediaIdentifier is enabled, do not "ask"
124 // the user and always "allow".
125 if (content_setting == CONTENT_SETTING_ASK &&
126 base::CommandLine::ForCurrentProcess()->HasSwitch(
127 switches::kDisableInfobarForProtectedMediaIdentifier)) {
128 content_setting = CONTENT_SETTING_ALLOW;
130 #endif
132 return content_setting;
135 void ProtectedMediaIdentifierPermissionContext::CancelPermissionRequest(
136 content::WebContents* web_contents,
137 const PermissionRequestID& id) {
138 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
140 #if defined(OS_CHROMEOS)
141 PendingRequestMap::iterator request = pending_requests_.find(web_contents);
142 if (request == pending_requests_.end() || !request->second.second.Equals(id))
143 return;
145 views::Widget* widget = request->second.first;
146 pending_requests_.erase(request);
148 // If |web_contents| is being destroyed, |widget| could be invalid. No need to
149 // manually close it here. Otherwise, close the |widget| here.
150 // OnPlatformVerificationConsentResponse() will be fired during this process,
151 // but since |web_contents| is removed from |pending_requests_|, the callback
152 // will simply be dropped.
153 if (!web_contents->IsBeingDestroyed())
154 widget->Close();
155 #else
156 PermissionContextBase::CancelPermissionRequest(web_contents, id);
157 #endif
160 void ProtectedMediaIdentifierPermissionContext::UpdateTabContext(
161 const PermissionRequestID& id,
162 const GURL& requesting_frame,
163 bool allowed) {
164 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
166 // WebContents may have gone away.
167 TabSpecificContentSettings* content_settings =
168 TabSpecificContentSettings::Get(id.render_process_id(),
169 id.render_view_id());
170 if (content_settings) {
171 content_settings->OnProtectedMediaIdentifierPermissionSet(
172 requesting_frame.GetOrigin(), allowed);
176 // TODO(xhwang): We should consolidate the "protected content" related pref
177 // across platforms.
178 bool ProtectedMediaIdentifierPermissionContext::
179 IsProtectedMediaIdentifierEnabled() const {
180 #if defined(OS_CHROMEOS)
181 // Platform verification is not allowed in incognito or guest mode.
182 if (profile()->IsOffTheRecord() || profile()->IsGuestSession()) {
183 DVLOG(1) << "Protected media identifier disabled in incognito or guest "
184 "mode.";
185 return false;
188 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
189 if (command_line->HasSwitch(chromeos::switches::kSystemDevMode) &&
190 !command_line->HasSwitch(chromeos::switches::kAllowRAInDevMode)) {
191 DVLOG(1) << "Protected media identifier disabled in dev mode.";
192 return false;
195 // This could be disabled by the device policy or by user's master switch.
196 bool enabled_for_device = false;
197 if (!chromeos::CrosSettings::Get()->GetBoolean(
198 chromeos::kAttestationForContentProtectionEnabled,
199 &enabled_for_device) ||
200 !enabled_for_device ||
201 !profile()->GetPrefs()->GetBoolean(prefs::kEnableDRM)) {
202 DVLOG(1) << "Protected media identifier disabled by the user or by device "
203 "policy.";
204 return false;
206 #endif
208 return true;
211 #if defined(OS_CHROMEOS)
212 void ProtectedMediaIdentifierPermissionContext::
213 OnPlatformVerificationConsentResponse(
214 content::WebContents* web_contents,
215 const PermissionRequestID& id,
216 const GURL& requesting_origin,
217 const GURL& embedding_origin,
218 const BrowserPermissionCallback& callback,
219 PlatformVerificationDialog::ConsentResponse response) {
220 // The request may have been canceled. Drop the callback in that case.
221 PendingRequestMap::iterator request = pending_requests_.find(web_contents);
222 if (request == pending_requests_.end())
223 return;
225 DCHECK(request->second.second.Equals(id));
226 pending_requests_.erase(request);
228 ContentSetting content_setting = CONTENT_SETTING_ASK;
229 bool persist = false; // Whether the ContentSetting should be saved.
230 switch (response) {
231 case PlatformVerificationDialog::CONSENT_RESPONSE_NONE:
232 content_setting = CONTENT_SETTING_ASK;
233 persist = false;
234 break;
235 case PlatformVerificationDialog::CONSENT_RESPONSE_ALLOW:
236 VLOG(1) << "Platform verification accepted by user.";
237 content::RecordAction(
238 base::UserMetricsAction("PlatformVerificationAccepted"));
239 content_setting = CONTENT_SETTING_ALLOW;
240 persist = true;
241 break;
242 case PlatformVerificationDialog::CONSENT_RESPONSE_DENY:
243 VLOG(1) << "Platform verification denied by user.";
244 content::RecordAction(
245 base::UserMetricsAction("PlatformVerificationRejected"));
246 content_setting = CONTENT_SETTING_BLOCK;
247 persist = true;
248 break;
251 NotifyPermissionSet(
252 id, requesting_origin, embedding_origin, callback,
253 persist, content_setting);
255 #endif