blob: 3f8d01f75f5135caa255d240bca1e88d1ecfca9e [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_PRIVACY_SANDBOX_PRIVACY_SANDBOX_SETTINGS_H_
#define CHROME_BROWSER_PRIVACY_SANDBOX_PRIVACY_SANDBOX_SETTINGS_H_
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
#include "base/optional.h"
#include "base/scoped_observation.h"
#include "base/time/time.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/policy/core/common/policy_service.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/sync/driver/sync_service.h"
#include "components/sync/driver/sync_service_observer.h"
#include "net/cookies/cookie_constants.h"
class HostContentSettingsMap;
class PrefService;
namespace content_settings {
class CookieSettings;
}
namespace url {
class Origin;
}
// A service which acts as a intermediary between Privacy Sandbox APIs and the
// preferences and content settings which define when they are allowed to be
// accessed.
// TODO (crbug.com/1154686): Move this and other Privacy Sandbox items into
// components.
class PrivacySandboxSettings : public KeyedService,
public policy::PolicyService::Observer,
public syncer::SyncServiceObserver,
public signin::IdentityManager::Observer {
public:
class Observer {
public:
virtual void OnFlocDataAccessibleSinceUpdated() = 0;
};
PrivacySandboxSettings(HostContentSettingsMap* host_content_settings_map,
content_settings::CookieSettings* cookie_settings,
PrefService* pref_service,
policy::PolicyService* policy_service,
syncer::SyncService* sync_service,
signin::IdentityManager* identity_manager);
~PrivacySandboxSettings() override;
// Returns true when the privacy sandbox settings feature is enabled, and at
// least one of the privacy sandbox APIs is also enabled. This function,
// rather than direct inspection of the feature itself, should be used to
// determine if the privacy sandbox is available to users.
// TODO(crbug.com/1174572) Remove this when one API is fully launched.
static bool PrivacySandboxSettingsFunctional();
// Determines whether FLoC is allowable in a particular context.
// |top_frame_origin| is used to check for content settings which could both
// affect 1P and 3P contexts.
bool IsFlocAllowed(const GURL& url,
const base::Optional<url::Origin>& top_frame_origin) const;
// Returns the point in time from which history is eligible to be used when
// calculating a user's FLoC ID. Reset when a user clears all cookies, or
// when the browser restarts with "Clear on exit" enabled. The returned time
// will have been fuzzed for local privacy, and so may be in the future, in
// which case no history is eligible.
base::Time FlocDataAccessibleSince() const;
// Determines whether Conversion Measurement is allowable in a particular
// context. Should be called at both impression & conversion. At each of these
// points |top_frame_origin| is the same as either the impression origin or
// the conversion origin respectively.
bool IsConversionMeasurementAllowed(
const url::Origin& top_frame_origin,
const url::Origin& reporting_origin) const;
// Called before sending the associated conversion report to
// |reporting_origin|. Re-checks that |reporting_origin| is allowable as a 3P
// on both |impression_origin| and |conversion_origin|.
bool ShouldSendConversionReport(const url::Origin& impression_origin,
const url::Origin& conversion_origin,
const url::Origin& reporting_origin) const;
// Determine whether |auction_party| can register an interest group, or sell /
// buy in an auction, on |top_frame_origin|.
bool IsFledgeAllowed(const url::Origin& top_frame_origin,
const GURL& auction_party);
// Filter |auction_parties| down to those that may participate as a buyer for
// auctions run on |top_frame_origin|. Logically equivalent to calling
// IsFledgeAllowed() for each element of |auction_parties|.
std::vector<GURL> FilterFledgeAllowedParties(
const url::Origin& top_frame_origin,
const std::vector<GURL>& auction_parties);
// Used by FLoC to determine whether the FLoC calculation can start in general
// and whether the FLoC ID can be queried. If the sandbox experiment is
// disabled, this check is equivalent to
// |!cookie_settings_->ShouldBlockThirdPartyCookies()|; but if the experiment
// is enabled, this will check prefs::kPrivacySandboxApisEnabled instead.
bool IsPrivacySandboxAllowed();
// Used by the UI to check if the API is enabled. Unlike the method above,
// this method only checks the pref directly.
bool IsPrivacySandboxEnabled();
// Returns whether the state of the API is managed.
bool IsPrivacySandboxManaged();
// Gets invoked by the UI when the user manually changed the state of the API.
void SetPrivacySandboxEnabled(bool enabled);
// Called when there's a broad cookies clearing action. For example, this
// should be called on "Clear browsing data", but shouldn't be called on the
// Clear-Site-Data header, as it's restricted to a specific site.
void OnCookiesCleared();
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
// KeyedService:
void Shutdown() override;
// policy::PolicyService::Observer:
void OnPolicyUpdated(const policy::PolicyNamespace& ns,
const policy::PolicyMap& previous,
const policy::PolicyMap& current) override;
// syncer::SyncServiceObserver:
void OnStateChanged(syncer::SyncService* sync) override;
void OnSyncCycleCompleted(syncer::SyncService* sync) override;
// signin::IdentityManager::Observer:
// TODO(crbug.com/1167680): This is only required to capture failure scenarios
// that affect sync, yet aren't reported via SyncServiceObserver.
void OnErrorStateOfRefreshTokenUpdatedForAccount(
const CoreAccountInfo& account_info,
const GoogleServiceAuthError& error) override;
protected:
friend class PrivacySandboxSettingsTest;
FRIEND_TEST_ALL_PREFIXES(PrivacySandboxSettingsTest, ReconciliationOutcome);
FRIEND_TEST_ALL_PREFIXES(PrivacySandboxSettingsTest,
ImmediateReconciliationNoSync);
FRIEND_TEST_ALL_PREFIXES(PrivacySandboxSettingsTest,
ImmediateReconciliationSyncComplete);
FRIEND_TEST_ALL_PREFIXES(PrivacySandboxSettingsTest,
ImmediateReconciliationPersistentSyncError);
FRIEND_TEST_ALL_PREFIXES(PrivacySandboxSettingsTest,
ImmediateReconciliationNoDisable);
FRIEND_TEST_ALL_PREFIXES(PrivacySandboxSettingsTest,
DelayedReconciliationSyncSuccess);
FRIEND_TEST_ALL_PREFIXES(PrivacySandboxSettingsTest,
DelayedReconciliationSyncFailure);
FRIEND_TEST_ALL_PREFIXES(PrivacySandboxSettingsTest,
DelayedReconciliationIdentityFailure);
FRIEND_TEST_ALL_PREFIXES(PrivacySandboxSettingsTest,
DelayedReconciliationSyncIssueThenManaged);
FRIEND_TEST_ALL_PREFIXES(PrivacySandboxSettingsTest,
NoReconciliationAlreadyRun);
FRIEND_TEST_ALL_PREFIXES(PrivacySandboxSettingsTest,
NoReconciliationSandboxSettingsDisabled);
FRIEND_TEST_ALL_PREFIXES(PrivacySandboxSettingsTest,
MetricsLoggingOccursCorrectly);
/**
* Contains all possible privacy sandbox states, recorded on startup.
*
* These values are persisted to logs. Entries should not be renumbered and
* numeric values should never be reused.
*
* Must be kept in sync with the SettingsPrivacySandboxEnabled enum in
* histograms/enums.xml and privacy_sandbox_settings_unittest.cc.
*/
enum class SettingsPrivacySandboxEnabled {
kPSEnabledAllowAll = 0,
kPSEnabledBlock3P = 1,
kPSEnabledBlockAll = 2,
kPSDisabledAllowAll = 3,
kPSDisabledBlock3P = 4,
kPSDisabledBlockAll = 5,
kPSDisabledPolicyBlock3P = 6,
kPSDisabledPolicyBlockAll = 7,
// Add values above this line with a corresponding label in
// tools/metrics/histograms/enums.xml
kMaxValue = kPSDisabledPolicyBlockAll,
};
// Determines based on the current features, preferences and provided
// |cookie_settings| whether Privacy Sandbox APIs are generally allowable for
// |url| on |top_frame_origin|. Individual APIs may perform additional checks
// for allowability (such as incognito) ontop of this. |cookie_settings| is
// provided as a parameter to allow callers to cache it between calls.
bool IsPrivacySandboxAllowedForContext(
const GURL& url,
const base::Optional<url::Origin>& top_frame_origin,
const ContentSettingsForOneType& cookie_settings) const;
// Inspects the current sync state and settings to determine if the Privacy
// Sandbox prefs should be reconciled. Calls ReconcilePrivacySandbox()
// immediately if appropriate, or may register sync and identity observers to
// call ReconcilePrivacySandbox() later as appropriate.
void MaybeReconcilePrivacySandboxPref();
// Selectively disable the Privacy Sandbox preference based on the local and
// synced state. Reconcilliation is only performed once per synced profile.
// As the sandbox is default enabled, reconcilliation will only ever opt a
// user out of the sandbox.
void ReconcilePrivacySandboxPref();
// Stops any observation of services being performed by this class.
void StopObserving();
// Helper function to actually make the metrics call for
// LogPrivacySandboxState.
void RecordPrivacySandboxHistogram(SettingsPrivacySandboxEnabled state);
// Logs the state of the privacy sandbox and cookie settings. Called once per
// profile startup.
void LogPrivacySandboxState();
private:
base::ObserverList<Observer>::Unchecked observers_;
HostContentSettingsMap* host_content_settings_map_;
content_settings::CookieSettings* cookie_settings_;
PrefService* pref_service_;
policy::PolicyService* policy_service_;
syncer::SyncService* sync_service_;
signin::IdentityManager* identity_manager_;
base::ScopedObservation<syncer::SyncService, syncer::SyncServiceObserver>
sync_service_observer_{this};
base::ScopedObservation<signin::IdentityManager,
signin::IdentityManager::Observer>
identity_manager_observer_{this};
// A manual record of whether policy_service_ is being observerd.
// Unfortunately PolicyService does not support scoped observers.
bool policy_service_observed_ = false;
};
#endif // CHROME_BROWSER_PRIVACY_SANDBOX_PRIVACY_SANDBOX_SETTINGS_H_