| Index: chrome/browser/chromeos/attestation/platform_verification_flow.cc
|
| diff --git a/chrome/browser/chromeos/attestation/platform_verification_flow.cc b/chrome/browser/chromeos/attestation/platform_verification_flow.cc
|
| index cbbc50cf6e75349f37a01b20d69a95432ca5e9a4..77f93f50c6c98bf84cf3df481c4961cb435e6bba 100644
|
| --- a/chrome/browser/chromeos/attestation/platform_verification_flow.cc
|
| +++ b/chrome/browser/chromeos/attestation/platform_verification_flow.cc
|
| @@ -14,7 +14,9 @@
|
| #include "chrome/browser/chromeos/login/user.h"
|
| #include "chrome/browser/chromeos/login/user_manager.h"
|
| #include "chrome/browser/chromeos/settings/cros_settings.h"
|
| +#include "chrome/browser/content_settings/host_content_settings_map.h"
|
| #include "chrome/browser/profiles/profile.h"
|
| +#include "chrome/common/content_settings_pattern.h"
|
| #include "chrome/common/pref_names.h"
|
| #include "chromeos/attestation/attestation_flow.h"
|
| #include "chromeos/cryptohome/async_method_caller.h"
|
| @@ -26,9 +28,12 @@
|
| #include "content/public/browser/browser_thread.h"
|
| #include "content/public/browser/user_metrics.h"
|
| #include "content/public/browser/web_contents.h"
|
| +#include "content/public/common/url_constants.h"
|
|
|
| namespace {
|
|
|
| +const char kDefaultHttpsPort[] = "443";
|
| +
|
| // A callback method to handle DBus errors.
|
| void DBusCallback(const base::Callback<void(bool)>& on_success,
|
| const base::Closure& on_failure,
|
| @@ -61,7 +66,6 @@ class DefaultDelegate : public PlatformVerificationFlow::Delegate {
|
| virtual ~DefaultDelegate() {}
|
|
|
| virtual void ShowConsentPrompt(
|
| - PlatformVerificationFlow::ConsentType type,
|
| content::WebContents* web_contents,
|
| const PlatformVerificationFlow::Delegate::ConsentCallback& callback)
|
| OVERRIDE {
|
| @@ -79,6 +83,7 @@ PlatformVerificationFlow::PlatformVerificationFlow()
|
| user_manager_(UserManager::Get()),
|
| delegate_(NULL),
|
| testing_prefs_(NULL),
|
| + testing_content_settings_(NULL),
|
| weak_factory_(this) {
|
| DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| scoped_ptr<ServerProxy> attestation_ca_client(new AttestationCAClient());
|
| @@ -103,6 +108,7 @@ PlatformVerificationFlow::PlatformVerificationFlow(
|
| user_manager_(user_manager),
|
| delegate_(delegate),
|
| testing_prefs_(NULL),
|
| + testing_content_settings_(NULL),
|
| weak_factory_(this) {
|
| DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| }
|
| @@ -116,6 +122,11 @@ void PlatformVerificationFlow::ChallengePlatformKey(
|
| const std::string& challenge,
|
| const ChallengeCallback& callback) {
|
| DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
| + if (!GetURL(web_contents).is_valid()) {
|
| + LOG(WARNING) << "PlatformVerificationFlow: Invalid URL.";
|
| + ReportError(callback, INTERNAL_ERROR);
|
| + return;
|
| + }
|
| if (!IsAttestationEnabled(web_contents)) {
|
| LOG(INFO) << "PlatformVerificationFlow: Feature disabled.";
|
| ReportError(callback, POLICY_REJECTED);
|
| @@ -138,12 +149,23 @@ void PlatformVerificationFlow::CheckConsent(content::WebContents* web_contents,
|
| const std::string& challenge,
|
| const ChallengeCallback& callback,
|
| bool attestation_enrolled) {
|
| - ConsentType consent_type = CONSENT_TYPE_NONE;
|
| - if (!attestation_enrolled || IsFirstUse(web_contents)) {
|
| - consent_type = CONSENT_TYPE_ATTESTATION;
|
| - } else if (IsAlwaysAskRequired(web_contents)) {
|
| - consent_type = CONSENT_TYPE_ALWAYS;
|
| + PrefService* pref_service = GetPrefs(web_contents);
|
| + if (!pref_service) {
|
| + LOG(ERROR) << "Failed to get user prefs.";
|
| + ReportError(callback, INTERNAL_ERROR);
|
| + return;
|
| }
|
| + bool consent_required = (
|
| + // Consent required if attestation has never been enrolled on this device.
|
| + !attestation_enrolled ||
|
| + // Consent required if this is the first use of attestation for content
|
| + // protection on this device.
|
| + !pref_service->GetBoolean(prefs::kRAConsentFirstTime) ||
|
| + // Consent required if consent has never been given for this domain.
|
| + !GetDomainPref(GetContentSettings(web_contents),
|
| + GetURL(web_contents),
|
| + NULL));
|
| +
|
| Delegate::ConsentCallback consent_callback = base::Bind(
|
| &PlatformVerificationFlow::OnConsentResponse,
|
| weak_factory_.GetWeakPtr(),
|
| @@ -151,14 +173,11 @@ void PlatformVerificationFlow::CheckConsent(content::WebContents* web_contents,
|
| service_id,
|
| challenge,
|
| callback,
|
| - consent_type);
|
| - if (consent_type == CONSENT_TYPE_NONE) {
|
| + consent_required);
|
| + if (consent_required)
|
| + delegate_->ShowConsentPrompt(web_contents, consent_callback);
|
| + else
|
| consent_callback.Run(CONSENT_RESPONSE_NONE);
|
| - } else {
|
| - delegate_->ShowConsentPrompt(consent_type,
|
| - web_contents,
|
| - consent_callback);
|
| - }
|
| }
|
|
|
| void PlatformVerificationFlow::RegisterProfilePrefs(
|
| @@ -166,12 +185,6 @@ void PlatformVerificationFlow::RegisterProfilePrefs(
|
| prefs->RegisterBooleanPref(prefs::kRAConsentFirstTime,
|
| false,
|
| user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
|
| - prefs->RegisterDictionaryPref(
|
| - prefs::kRAConsentDomains,
|
| - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
|
| - prefs->RegisterBooleanPref(prefs::kRAConsentAlways,
|
| - false,
|
| - user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
|
| }
|
|
|
| void PlatformVerificationFlow::OnConsentResponse(
|
| @@ -179,16 +192,16 @@ void PlatformVerificationFlow::OnConsentResponse(
|
| const std::string& service_id,
|
| const std::string& challenge,
|
| const ChallengeCallback& callback,
|
| - ConsentType consent_type,
|
| + bool consent_required,
|
| ConsentResponse consent_response) {
|
| - if (consent_type != CONSENT_TYPE_NONE) {
|
| + if (consent_required) {
|
| if (consent_response == CONSENT_RESPONSE_NONE) {
|
| // No user response - do not proceed and do not modify any settings.
|
| LOG(WARNING) << "PlatformVerificationFlow: No response from user.";
|
| ReportError(callback, USER_REJECTED);
|
| return;
|
| }
|
| - if (!UpdateSettings(web_contents, consent_type, consent_response)) {
|
| + if (!UpdateSettings(web_contents, consent_response)) {
|
| ReportError(callback, INTERNAL_ERROR);
|
| return;
|
| }
|
| @@ -289,7 +302,10 @@ const GURL& PlatformVerificationFlow::GetURL(
|
| content::WebContents* web_contents) {
|
| if (!testing_url_.is_empty())
|
| return testing_url_;
|
| - return web_contents->GetLastCommittedURL();
|
| + const GURL& url = web_contents->GetLastCommittedURL();
|
| + if (!url.is_valid())
|
| + return web_contents->GetVisibleURL();
|
| + return url;
|
| }
|
|
|
| User* PlatformVerificationFlow::GetUser(content::WebContents* web_contents) {
|
| @@ -299,6 +315,14 @@ User* PlatformVerificationFlow::GetUser(content::WebContents* web_contents) {
|
| Profile::FromBrowserContext(web_contents->GetBrowserContext()));
|
| }
|
|
|
| +HostContentSettingsMap* PlatformVerificationFlow::GetContentSettings(
|
| + content::WebContents* web_contents) {
|
| + if (testing_content_settings_)
|
| + return testing_content_settings_;
|
| + return Profile::FromBrowserContext(web_contents->GetBrowserContext())->
|
| + GetHostContentSettingsMap();
|
| +}
|
| +
|
| bool PlatformVerificationFlow::IsAttestationEnabled(
|
| content::WebContents* web_contents) {
|
| // Check the device policy for the feature.
|
| @@ -322,92 +346,77 @@ bool PlatformVerificationFlow::IsAttestationEnabled(
|
|
|
| // Check the user preference for this domain.
|
| bool enabled_for_domain = false;
|
| - bool found = GetDomainPref(web_contents, &enabled_for_domain);
|
| + bool found = GetDomainPref(GetContentSettings(web_contents),
|
| + GetURL(web_contents),
|
| + &enabled_for_domain);
|
| return (!found || enabled_for_domain);
|
| }
|
|
|
| -bool PlatformVerificationFlow::IsFirstUse(content::WebContents* web_contents) {
|
| - PrefService* pref_service = GetPrefs(web_contents);
|
| - if (!pref_service) {
|
| - LOG(ERROR) << "Failed to get user prefs.";
|
| - return true;
|
| - }
|
| - return !pref_service->GetBoolean(prefs::kRAConsentFirstTime);
|
| -}
|
| -
|
| -bool PlatformVerificationFlow::IsAlwaysAskRequired(
|
| - content::WebContents* web_contents) {
|
| - PrefService* pref_service = GetPrefs(web_contents);
|
| - if (!pref_service) {
|
| - LOG(ERROR) << "Failed to get user prefs.";
|
| - return true;
|
| - }
|
| - if (!pref_service->GetBoolean(prefs::kRAConsentAlways))
|
| - return false;
|
| - // Show the consent UI if the user has not already explicitly allowed or
|
| - // denied for this domain.
|
| - return !GetDomainPref(web_contents, NULL);
|
| -}
|
| -
|
| bool PlatformVerificationFlow::UpdateSettings(
|
| content::WebContents* web_contents,
|
| - ConsentType consent_type,
|
| ConsentResponse consent_response) {
|
| PrefService* pref_service = GetPrefs(web_contents);
|
| if (!pref_service) {
|
| LOG(ERROR) << "Failed to get user prefs.";
|
| return false;
|
| }
|
| - if (consent_type == CONSENT_TYPE_ATTESTATION) {
|
| - if (consent_response == CONSENT_RESPONSE_DENY) {
|
| - pref_service->SetBoolean(prefs::kEnableDRM, false);
|
| - } else if (consent_response == CONSENT_RESPONSE_ALLOW) {
|
| - pref_service->SetBoolean(prefs::kRAConsentFirstTime, true);
|
| - RecordDomainConsent(web_contents, true);
|
| - } else if (consent_response == CONSENT_RESPONSE_ALWAYS_ASK) {
|
| - pref_service->SetBoolean(prefs::kRAConsentFirstTime, true);
|
| - pref_service->SetBoolean(prefs::kRAConsentAlways, true);
|
| - RecordDomainConsent(web_contents, true);
|
| - }
|
| - } else if (consent_type == CONSENT_TYPE_ALWAYS) {
|
| - bool allowed = (consent_response == CONSENT_RESPONSE_ALLOW ||
|
| - consent_response == CONSENT_RESPONSE_ALWAYS_ASK);
|
| - RecordDomainConsent(web_contents, allowed);
|
| - }
|
| + pref_service->SetBoolean(prefs::kRAConsentFirstTime, true);
|
| + RecordDomainConsent(GetContentSettings(web_contents),
|
| + GetURL(web_contents),
|
| + (consent_response == CONSENT_RESPONSE_ALLOW));
|
| return true;
|
| }
|
|
|
| bool PlatformVerificationFlow::GetDomainPref(
|
| - content::WebContents* web_contents,
|
| + HostContentSettingsMap* content_settings,
|
| + const GURL& url,
|
| bool* pref_value) {
|
| - PrefService* pref_service = GetPrefs(web_contents);
|
| - CHECK(pref_service);
|
| - base::DictionaryValue::Iterator iter(
|
| - *pref_service->GetDictionary(prefs::kRAConsentDomains));
|
| - const GURL& url = GetURL(web_contents);
|
| - while (!iter.IsAtEnd()) {
|
| - if (url.DomainIs(iter.key().c_str())) {
|
| - if (pref_value) {
|
| - if (!iter.value().GetAsBoolean(pref_value)) {
|
| - LOG(ERROR) << "Unexpected pref type.";
|
| - *pref_value = false;
|
| - }
|
| - }
|
| - return true;
|
| - }
|
| - iter.Advance();
|
| - }
|
| - return false;
|
| + CHECK(content_settings);
|
| + CHECK(url.is_valid());
|
| + ContentSetting setting = content_settings->GetContentSetting(
|
| + url,
|
| + url,
|
| + CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER,
|
| + std::string());
|
| + if (setting != CONTENT_SETTING_ALLOW && setting != CONTENT_SETTING_BLOCK)
|
| + return false;
|
| + if (pref_value)
|
| + *pref_value = (setting == CONTENT_SETTING_ALLOW);
|
| + return true;
|
| }
|
|
|
| void PlatformVerificationFlow::RecordDomainConsent(
|
| - content::WebContents* web_contents,
|
| + HostContentSettingsMap* content_settings,
|
| + const GURL& url,
|
| bool allow_domain) {
|
| - PrefService* pref_service = GetPrefs(web_contents);
|
| - CHECK(pref_service);
|
| - DictionaryPrefUpdate updater(pref_service, prefs::kRAConsentDomains);
|
| - const GURL& url = GetURL(web_contents);
|
| - updater->SetBoolean(url.host(), allow_domain);
|
| + CHECK(content_settings);
|
| + CHECK(url.is_valid());
|
| + // Build a pattern to represent scheme and host.
|
| + scoped_ptr<ContentSettingsPattern::BuilderInterface> builder(
|
| + ContentSettingsPattern::CreateBuilder(false));
|
| + builder->WithScheme(url.scheme())
|
| + ->WithDomainWildcard()
|
| + ->WithHost(url.host())
|
| + ->WithPathWildcard();
|
| + if (!url.port().empty())
|
| + builder->WithPort(url.port());
|
| + else if (url.SchemeIs(content::kHttpsScheme))
|
| + builder->WithPort(kDefaultHttpsPort);
|
| + else if (url.SchemeIs(content::kHttpScheme))
|
| + builder->WithPortWildcard();
|
| + ContentSettingsPattern pattern = builder->Build();
|
| + if (pattern.IsValid()) {
|
| + ContentSetting setting = allow_domain ? CONTENT_SETTING_ALLOW
|
| + : CONTENT_SETTING_BLOCK;
|
| + content_settings->SetContentSetting(
|
| + pattern,
|
| + pattern,
|
| + CONTENT_SETTINGS_TYPE_PROTECTED_MEDIA_IDENTIFIER,
|
| + std::string(),
|
| + setting);
|
| + } else {
|
| + LOG(WARNING) << "Not recording action: invalid URL pattern";
|
| + }
|
| }
|
|
|
| } // namespace attestation
|
|
|