Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / media / protected_media_identifier_permission_context.cc
blob756a8eee96ee444f022abe52ca0adb77f0464169
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 "content/public/browser/browser_thread.h"
13 #include "content/public/browser/user_metrics.h"
14 #include "content/public/browser/web_contents.h"
15 #if defined(OS_CHROMEOS)
16 #include <utility>
18 #include "chrome/browser/chromeos/attestation/platform_verification_dialog.h"
19 #include "chrome/browser/chromeos/settings/cros_settings.h"
20 #include "chromeos/chromeos_switches.h"
21 #include "chromeos/settings/cros_settings_names.h"
22 #include "components/pref_registry/pref_registry_syncable.h"
23 #include "components/user_prefs/user_prefs.h"
24 #include "ui/views/widget/widget.h"
25 #elif !defined(OS_ANDROID)
26 #error This file currently only supports Chrome OS and Android.
27 #endif
29 #if defined(OS_CHROMEOS)
30 using chromeos::attestation::PlatformVerificationDialog;
31 #endif
33 ProtectedMediaIdentifierPermissionContext::
34 ProtectedMediaIdentifierPermissionContext(Profile* profile)
35 : PermissionContextBase(profile,
36 CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER)
37 #if defined(OS_CHROMEOS)
39 weak_factory_(this)
40 #endif
44 ProtectedMediaIdentifierPermissionContext::
45 ~ProtectedMediaIdentifierPermissionContext() {
48 void ProtectedMediaIdentifierPermissionContext::RequestPermission(
49 content::WebContents* web_contents,
50 const PermissionRequestID& id,
51 const GURL& requesting_origin,
52 bool user_gesture,
53 const BrowserPermissionCallback& callback) {
54 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
56 GURL embedding_origin = web_contents->GetLastCommittedURL().GetOrigin();
58 DVLOG(1) << __FUNCTION__ << ": (" << requesting_origin.spec() << ", "
59 << embedding_origin.spec() << ")";
61 ContentSetting content_setting =
62 GetPermissionStatus(requesting_origin, embedding_origin);
64 if (content_setting == CONTENT_SETTING_ALLOW ||
65 content_setting == CONTENT_SETTING_BLOCK) {
66 NotifyPermissionSet(id, requesting_origin, embedding_origin, callback,
67 false /* persist */, content_setting);
68 return;
71 DCHECK_EQ(CONTENT_SETTING_ASK, content_setting);
73 #if defined(OS_CHROMEOS)
74 // Since the dialog is modal, we only support one prompt per |web_contents|.
75 // Reject the new one if there is already one pending. See
76 // http://crbug.com/447005
77 if (pending_requests_.count(web_contents)) {
78 callback.Run(CONTENT_SETTING_ASK);
79 return;
82 // On ChromeOS, we don't use PermissionContextBase::RequestPermission() which
83 // uses the standard permission infobar/bubble UI. See http://crbug.com/454847
84 // Instead, we show the existing platform verification UI.
85 // TODO(xhwang): Remove when http://crbug.com/454847 is fixed.
86 views::Widget* widget = PlatformVerificationDialog::ShowDialog(
87 web_contents, requesting_origin,
88 base::Bind(&ProtectedMediaIdentifierPermissionContext::
89 OnPlatformVerificationConsentResponse,
90 weak_factory_.GetWeakPtr(), web_contents, id,
91 requesting_origin, embedding_origin, callback));
92 pending_requests_.insert(
93 std::make_pair(web_contents, std::make_pair(widget, id)));
94 #else
95 PermissionContextBase::RequestPermission(web_contents, id, requesting_origin,
96 user_gesture, callback);
97 #endif
100 ContentSetting ProtectedMediaIdentifierPermissionContext::GetPermissionStatus(
101 const GURL& requesting_origin,
102 const GURL& embedding_origin) const {
103 DVLOG(1) << __FUNCTION__ << ": (" << requesting_origin.spec() << ", "
104 << embedding_origin.spec() << ")";
106 if (!requesting_origin.is_valid() || !embedding_origin.is_valid() ||
107 !IsProtectedMediaIdentifierEnabled()) {
108 return CONTENT_SETTING_BLOCK;
111 ContentSetting content_setting = PermissionContextBase::GetPermissionStatus(
112 requesting_origin, embedding_origin);
113 DCHECK(content_setting == CONTENT_SETTING_ALLOW ||
114 content_setting == CONTENT_SETTING_BLOCK ||
115 content_setting == CONTENT_SETTING_ASK);
117 return content_setting;
120 void ProtectedMediaIdentifierPermissionContext::CancelPermissionRequest(
121 content::WebContents* web_contents,
122 const PermissionRequestID& id) {
123 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
125 #if defined(OS_CHROMEOS)
126 PendingRequestMap::iterator request = pending_requests_.find(web_contents);
127 if (request == pending_requests_.end() || (request->second.second != id))
128 return;
130 views::Widget* widget = request->second.first;
131 pending_requests_.erase(request);
133 // If |web_contents| is being destroyed, |widget| could be invalid. No need to
134 // manually close it here. Otherwise, close the |widget| here.
135 // OnPlatformVerificationConsentResponse() will be fired during this process,
136 // but since |web_contents| is removed from |pending_requests_|, the callback
137 // will simply be dropped.
138 if (!web_contents->IsBeingDestroyed())
139 widget->Close();
140 #else
141 PermissionContextBase::CancelPermissionRequest(web_contents, id);
142 #endif
145 void ProtectedMediaIdentifierPermissionContext::UpdateTabContext(
146 const PermissionRequestID& id,
147 const GURL& requesting_frame,
148 bool allowed) {
149 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
151 // WebContents may have gone away.
152 TabSpecificContentSettings* content_settings =
153 TabSpecificContentSettings::GetForFrame(id.render_process_id(),
154 id.render_frame_id());
155 if (content_settings) {
156 content_settings->OnProtectedMediaIdentifierPermissionSet(
157 requesting_frame.GetOrigin(), allowed);
161 bool
162 ProtectedMediaIdentifierPermissionContext::IsRestrictedToSecureOrigins() const {
163 return false;
166 // TODO(xhwang): We should consolidate the "protected content" related pref
167 // across platforms.
168 bool ProtectedMediaIdentifierPermissionContext::
169 IsProtectedMediaIdentifierEnabled() const {
170 #if defined(OS_CHROMEOS)
171 // Platform verification is not allowed in incognito or guest mode.
172 if (profile()->IsOffTheRecord() || profile()->IsGuestSession()) {
173 DVLOG(1) << "Protected media identifier disabled in incognito or guest "
174 "mode.";
175 return false;
178 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
179 if (command_line->HasSwitch(chromeos::switches::kSystemDevMode) &&
180 !command_line->HasSwitch(chromeos::switches::kAllowRAInDevMode)) {
181 DVLOG(1) << "Protected media identifier disabled in dev mode.";
182 return false;
185 // This could be disabled by the device policy or by user's master switch.
186 bool enabled_for_device = false;
187 if (!chromeos::CrosSettings::Get()->GetBoolean(
188 chromeos::kAttestationForContentProtectionEnabled,
189 &enabled_for_device) ||
190 !enabled_for_device ||
191 !profile()->GetPrefs()->GetBoolean(prefs::kEnableDRM)) {
192 DVLOG(1) << "Protected media identifier disabled by the user or by device "
193 "policy.";
194 return false;
196 #endif
198 return true;
201 #if defined(OS_CHROMEOS)
202 void ProtectedMediaIdentifierPermissionContext::
203 OnPlatformVerificationConsentResponse(
204 content::WebContents* web_contents,
205 const PermissionRequestID& id,
206 const GURL& requesting_origin,
207 const GURL& embedding_origin,
208 const BrowserPermissionCallback& callback,
209 PlatformVerificationDialog::ConsentResponse response) {
210 // The request may have been canceled. Drop the callback in that case.
211 PendingRequestMap::iterator request = pending_requests_.find(web_contents);
212 if (request == pending_requests_.end())
213 return;
215 DCHECK(request->second.second == id);
216 pending_requests_.erase(request);
218 ContentSetting content_setting = CONTENT_SETTING_ASK;
219 bool persist = false; // Whether the ContentSetting should be saved.
220 switch (response) {
221 case PlatformVerificationDialog::CONSENT_RESPONSE_NONE:
222 content_setting = CONTENT_SETTING_ASK;
223 persist = false;
224 break;
225 case PlatformVerificationDialog::CONSENT_RESPONSE_ALLOW:
226 VLOG(1) << "Platform verification accepted by user.";
227 content::RecordAction(
228 base::UserMetricsAction("PlatformVerificationAccepted"));
229 content_setting = CONTENT_SETTING_ALLOW;
230 persist = true;
231 break;
232 case PlatformVerificationDialog::CONSENT_RESPONSE_DENY:
233 VLOG(1) << "Platform verification denied by user.";
234 content::RecordAction(
235 base::UserMetricsAction("PlatformVerificationRejected"));
236 content_setting = CONTENT_SETTING_BLOCK;
237 persist = true;
238 break;
241 NotifyPermissionSet(
242 id, requesting_origin, embedding_origin, callback,
243 persist, content_setting);
245 #endif