blob: 04e2bef96a0ef699c5c2e6ff472fbfd525842960 [file] [log] [blame]
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/privacy_sandbox/privacy_sandbox_service.h"
#include "base/feature_list.h"
#include "base/memory/raw_ptr.h"
#include "base/test/bind.h"
#include "base/test/gtest_util.h"
#include "base/test/icu_test_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/metrics/user_action_tester.h"
#include "base/test/scoped_feature_list.h"
#include "build/branding_buildflags.h"
#include "chrome/browser/content_settings/cookie_settings_factory.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/first_party_sets/first_party_sets_policy_service.h"
#include "chrome/browser/first_party_sets/scoped_mock_first_party_sets_handler.h"
#include "chrome/browser/policy/policy_test_utils.h"
#include "chrome/browser/privacy_sandbox/privacy_sandbox_settings_factory.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/common/chrome_features.h"
#include "chrome/test/base/testing_profile.h"
#include "components/browsing_topics/test_util.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/content_settings_types.h"
#include "components/content_settings/core/common/pref_names.h"
#include "components/content_settings/core/test/content_settings_mock_provider.h"
#include "components/content_settings/core/test/content_settings_test_utils.h"
#include "components/policy/core/common/mock_policy_service.h"
#include "components/policy/policy_constants.h"
#include "components/privacy_sandbox/mock_privacy_sandbox_settings.h"
#include "components/privacy_sandbox/privacy_sandbox_features.h"
#include "components/privacy_sandbox/privacy_sandbox_prefs.h"
#include "components/privacy_sandbox/privacy_sandbox_settings_impl.h"
#include "components/privacy_sandbox/privacy_sandbox_test_util.h"
#include "components/profile_metrics/browser_profile_type.h"
#include "components/signin/public/identity_manager/account_info.h"
#include "components/signin/public/identity_manager/identity_test_environment.h"
#include "components/strings/grit/components_strings.h"
#include "components/sync/base/user_selectable_type.h"
#include "components/sync/test/test_sync_service.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/browser/first_party_sets_handler.h"
#include "content/public/browser/interest_group_manager.h"
#include "content/public/common/content_features.h"
#include "content/public/test/browser_task_environment.h"
#include "net/base/schemeful_site.h"
#include "net/first_party_sets/first_party_set_entry.h"
#include "net/first_party_sets/first_party_set_entry_override.h"
#include "net/first_party_sets/first_party_sets_context_config.h"
#include "net/first_party_sets/global_first_party_sets.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/features.h"
#include "url/origin.h"
#if !BUILDFLAG(IS_ANDROID)
#include "chrome/browser/ui/hats/mock_trust_safety_sentiment_service.h"
#endif
#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h"
#include "chromeos/ash/components/login/login_state/scoped_test_public_session_login_state.h"
#endif
#if BUILDFLAG(IS_CHROMEOS_LACROS)
#include "chromeos/crosapi/mojom/crosapi.mojom.h"
#include "chromeos/startup/browser_init_params.h"
#endif
namespace {
using browsing_topics::Topic;
using privacy_sandbox::CanonicalTopic;
using testing::ElementsAre;
using PromptAction = PrivacySandboxService::PromptAction;
using PromptSuppressedReason = PrivacySandboxService::PromptSuppressedReason;
using PromptType = PrivacySandboxService::PromptType;
// C++20 introduces the "using enum" construct, which significantly reduces the
// required verbosity here. C++20 is support is coming to Chromium
// (crbug.com/1284275), with Mac / Windows / Linux support at the time of
// writing.
// TODO (crbug.com/1401686): Replace groups with commented lines when C++20 is
// supported.
// using enum privacy_sandbox_test_util::TestState;
using privacy_sandbox_test_util::StateKey;
constexpr auto kHasCurrentTopics = StateKey::kHasCurrentTopics;
constexpr auto kHasBlockedTopics = StateKey::kHasBlockedTopics;
constexpr auto kAdvanceClockBy = StateKey::kAdvanceClockBy;
constexpr auto kActiveTopicsConsent = StateKey::kActiveTopicsConsent;
// using enum privacy_sandbox_test_util::InputKey;
using privacy_sandbox_test_util::InputKey;
constexpr auto kTopicsToggleNewValue = InputKey::kTopicsToggleNewValue;
constexpr auto kTopFrameOrigin = InputKey::kTopFrameOrigin;
constexpr auto kAdMeasurementReportingOrigin =
InputKey::kAdMeasurementReportingOrigin;
constexpr auto kFledgeAuctionPartyOrigin = InputKey::kFledgeAuctionPartyOrigin;
// using enum privacy_sandbox_test_util::TestOutput;
using privacy_sandbox_test_util::OutputKey;
constexpr auto kTopicsConsentGiven = OutputKey::kTopicsConsentGiven;
constexpr auto kTopicsConsentLastUpdateReason =
OutputKey::kTopicsConsentLastUpdateReason;
constexpr auto kTopicsConsentLastUpdateTime =
OutputKey::kTopicsConsentLastUpdateTime;
constexpr auto kTopicsConsentStringIdentifiers =
OutputKey::kTopicsConsentStringIdentifiers;
using privacy_sandbox_test_util::MultipleInputKeys;
using privacy_sandbox_test_util::MultipleOutputKeys;
using privacy_sandbox_test_util::MultipleStateKeys;
using privacy_sandbox_test_util::SiteDataExceptions;
using privacy_sandbox_test_util::TestCase;
using privacy_sandbox_test_util::TestInput;
using privacy_sandbox_test_util::TestOutput;
using privacy_sandbox_test_util::TestState;
const char kFirstPartySetsStateHistogram[] = "Settings.FirstPartySets.State";
const char kPrivacySandboxStartupHistogram[] =
"Settings.PrivacySandbox.StartupState";
const base::Version kFirstPartySetsVersion("1.2.3");
constexpr int kTestTaxonomyVersion = 1;
class TestPrivacySandboxService
: public privacy_sandbox_test_util::PrivacySandboxServiceTestInterface {
public:
explicit TestPrivacySandboxService(PrivacySandboxService* service)
: service_(service) {}
// PrivacySandboxServiceTestInterface
void TopicsToggleChanged(bool new_value) const override {
service_->TopicsToggleChanged(new_value);
}
void SetTopicAllowed(privacy_sandbox::CanonicalTopic topic,
bool allowed) override {
service_->SetTopicAllowed(topic, allowed);
}
bool TopicsHasActiveConsent() const override {
return service_->TopicsHasActiveConsent();
}
privacy_sandbox::TopicsConsentUpdateSource TopicsConsentLastUpdateSource()
const override {
return service_->TopicsConsentLastUpdateSource();
}
base::Time TopicsConsentLastUpdateTime() const override {
return service_->TopicsConsentLastUpdateTime();
}
std::string TopicsConsentLastUpdateText() const override {
return service_->TopicsConsentLastUpdateText();
}
void ForceChromeBuildForTests(bool force_chrome_build) const override {
service_->ForceChromeBuildForTests(force_chrome_build);
}
int GetRequiredPromptType() const override {
return static_cast<int>(service_->GetRequiredPromptType());
}
void PromptActionOccurred(int action) const override {
service_->PromptActionOccurred(static_cast<PromptAction>(action));
}
private:
raw_ptr<PrivacySandboxService> service_;
};
class TestInterestGroupManager : public content::InterestGroupManager {
public:
void SetInterestGroupDataKeys(
const std::vector<InterestGroupDataKey>& data_keys) {
data_keys_ = data_keys;
}
// content::InterestGroupManager:
void GetAllInterestGroupJoiningOrigins(
base::OnceCallback<void(std::vector<url::Origin>)> callback) override {
NOTREACHED();
}
void GetAllInterestGroupDataKeys(
base::OnceCallback<void(std::vector<InterestGroupDataKey>)> callback)
override {
std::move(callback).Run(data_keys_);
}
void RemoveInterestGroupsByDataKey(InterestGroupDataKey data_key,
base::OnceClosure callback) override {
NOTREACHED();
}
private:
std::vector<InterestGroupDataKey> data_keys_;
};
struct PromptTestState {
bool consent_required;
bool old_api_pref;
bool new_api_pref;
bool notice_displayed;
bool consent_decision_made;
bool confirmation_not_shown;
};
struct ExpectedPromptOutput {
bool dcheck_failure;
PrivacySandboxService::PromptType prompt_type;
bool new_api_pref;
};
struct PromptTestCase {
PromptTestState test_setup;
ExpectedPromptOutput expected_output;
};
std::vector<PromptTestCase> kPromptTestCases = {
{{/*consent_required=*/false, /*old_api_pref=*/false,
/*new_api_pref=*/false,
/*notice_displayed=*/false, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/true, /*old_api_pref=*/false,
/*new_api_pref=*/false,
/*notice_displayed=*/false, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/false, /*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNotice,
/*new_api_pref=*/false}},
{{/*consent_required=*/true, /*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kConsent,
/*new_api_pref=*/false}},
{{/*consent_required=*/false, /*old_api_pref=*/false,
/*new_api_pref=*/true,
/*notice_displayed=*/false, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/true, /*old_api_pref=*/false,
/*new_api_pref=*/true,
/*notice_displayed=*/false, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/false, /*old_api_pref=*/true,
/*new_api_pref=*/true,
/*notice_displayed=*/false, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNotice,
/*new_api_pref=*/true}},
{{/*consent_required=*/true, /*old_api_pref=*/true,
/*new_api_pref=*/true,
/*notice_displayed=*/false, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kConsent,
/*new_api_pref=*/true}},
{{/*consent_required=*/false, /*old_api_pref=*/false,
/*new_api_pref=*/false,
/*notice_displayed=*/true, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/true, /*old_api_pref=*/false,
/*new_api_pref=*/false,
/*notice_displayed=*/true, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/false, /*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/true, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/true, /*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/true, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/false, /*old_api_pref=*/false,
/*new_api_pref=*/true,
/*notice_displayed=*/true, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/true, /*old_api_pref=*/false,
/*new_api_pref=*/true,
/*notice_displayed=*/true, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kConsent,
/*new_api_pref=*/false}},
{{/*consent_required=*/false, /*old_api_pref=*/true,
/*new_api_pref=*/true,
/*notice_displayed=*/true, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/true, /*old_api_pref=*/true,
/*new_api_pref=*/true,
/*notice_displayed=*/true, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kConsent,
/*new_api_pref=*/false}},
{{/*consent_required=*/false, /*old_api_pref=*/false,
/*new_api_pref=*/false,
/*notice_displayed=*/false, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/true, /*old_api_pref=*/false,
/*new_api_pref=*/false,
/*notice_displayed=*/false, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/false, /*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/true, /*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/false, /*old_api_pref=*/false,
/*new_api_pref=*/true,
/*notice_displayed=*/false, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/true, /*old_api_pref=*/false,
/*new_api_pref=*/true,
/*notice_displayed=*/false, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/false, /*old_api_pref=*/true,
/*new_api_pref=*/true,
/*notice_displayed=*/false, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/true, /*old_api_pref=*/true,
/*new_api_pref=*/true,
/*notice_displayed=*/false, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/false, /*old_api_pref=*/false,
/*new_api_pref=*/false,
/*notice_displayed=*/true, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/true, /*old_api_pref=*/false,
/*new_api_pref=*/false,
/*notice_displayed=*/true, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/false, /*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/true, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/true, /*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/true, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/false, /*old_api_pref=*/false,
/*new_api_pref=*/true,
/*notice_displayed=*/true, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/true, /*old_api_pref=*/false,
/*new_api_pref=*/true,
/*notice_displayed=*/true, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/false, /*old_api_pref=*/true,
/*new_api_pref=*/true,
/*notice_displayed=*/true, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/true, /*old_api_pref=*/true,
/*new_api_pref=*/true,
/*notice_displayed=*/true, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/false},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/false, /*old_api_pref=*/false,
/*new_api_pref=*/false,
/*notice_displayed=*/false, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/true, /*old_api_pref=*/false,
/*new_api_pref=*/false,
/*notice_displayed=*/false, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/false, /*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/true, /*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/false, /*old_api_pref=*/false,
/*new_api_pref=*/true,
/*notice_displayed=*/false, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/true, /*old_api_pref=*/false,
/*new_api_pref=*/true,
/*notice_displayed=*/false, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/false, /*old_api_pref=*/true,
/*new_api_pref=*/true,
/*notice_displayed=*/false, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/true, /*old_api_pref=*/true,
/*new_api_pref=*/true,
/*notice_displayed=*/false, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/false, /*old_api_pref=*/false,
/*new_api_pref=*/false,
/*notice_displayed=*/true, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/true, /*old_api_pref=*/false,
/*new_api_pref=*/false,
/*notice_displayed=*/true, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/false, /*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/true, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/true, /*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/true, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/false, /*old_api_pref=*/false,
/*new_api_pref=*/true,
/*notice_displayed=*/true, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/true, /*old_api_pref=*/false,
/*new_api_pref=*/true,
/*notice_displayed=*/true, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/false, /*old_api_pref=*/true,
/*new_api_pref=*/true,
/*notice_displayed=*/true, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/true, /*old_api_pref=*/true,
/*new_api_pref=*/true,
/*notice_displayed=*/true, /*consent_decision_made=*/false,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/false, /*old_api_pref=*/false,
/*new_api_pref=*/false,
/*notice_displayed=*/false, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/true, /*old_api_pref=*/false,
/*new_api_pref=*/false,
/*notice_displayed=*/false, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/false, /*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/true, /*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/false, /*old_api_pref=*/false,
/*new_api_pref=*/true,
/*notice_displayed=*/false, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/true, /*old_api_pref=*/false,
/*new_api_pref=*/true,
/*notice_displayed=*/false, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/false, /*old_api_pref=*/true,
/*new_api_pref=*/true,
/*notice_displayed=*/false, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/true, /*old_api_pref=*/true,
/*new_api_pref=*/true,
/*notice_displayed=*/false, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/false, /*old_api_pref=*/false,
/*new_api_pref=*/false,
/*notice_displayed=*/true, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/true, /*old_api_pref=*/false,
/*new_api_pref=*/false,
/*notice_displayed=*/true, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/false, /*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/true, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/true, /*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/true, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/false}},
{{/*consent_required=*/false, /*old_api_pref=*/false,
/*new_api_pref=*/true,
/*notice_displayed=*/true, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/true, /*old_api_pref=*/false,
/*new_api_pref=*/true,
/*notice_displayed=*/true, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/false, /*old_api_pref=*/true,
/*new_api_pref=*/true,
/*notice_displayed=*/true, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
{{/*consent_required=*/true, /*old_api_pref=*/true,
/*new_api_pref=*/true,
/*notice_displayed=*/true, /*consent_decision_made=*/true,
/*confirmation_not_shown=*/true},
{/*dcheck_failure=*/false,
/*prompt_type=*/PrivacySandboxService::PromptType::kNone,
/*new_api_pref=*/true}},
};
void SetupPromptTestState(
base::test::ScopedFeatureList* feature_list,
sync_preferences::TestingPrefServiceSyncable* pref_service,
const PromptTestState& test_state) {
feature_list->Reset();
feature_list->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings3,
{{"consent-required", test_state.consent_required ? "true" : "false"},
{"notice-required", !test_state.consent_required ? "true" : "false"}});
pref_service->SetUserPref(
prefs::kPrivacySandboxApisEnabled,
std::make_unique<base::Value>(test_state.old_api_pref));
pref_service->SetUserPref(
prefs::kPrivacySandboxApisEnabledV2,
std::make_unique<base::Value>(test_state.new_api_pref));
pref_service->SetUserPref(
prefs::kPrivacySandboxNoticeDisplayed,
std::make_unique<base::Value>(test_state.notice_displayed));
pref_service->SetUserPref(
prefs::kPrivacySandboxConsentDecisionMade,
std::make_unique<base::Value>(test_state.consent_decision_made));
pref_service->SetUserPref(
prefs::kPrivacySandboxNoConfirmationSandboxDisabled,
std::make_unique<base::Value>(test_state.confirmation_not_shown));
}
// Remove any user preference settings for First Party Set related preferences,
// returning them to their default value.
void ClearFpsUserPrefs(
sync_preferences::TestingPrefServiceSyncable* pref_service) {
pref_service->RemoveUserPref(prefs::kPrivacySandboxFirstPartySetsEnabled);
pref_service->RemoveUserPref(
prefs::kPrivacySandboxFirstPartySetsDataAccessAllowedInitialized);
}
// Remove any user preference settings for Anti-abuse related preferences,
// returning them to their default value.
void ResetAntiAbuseSettings(
sync_preferences::TestingPrefServiceSyncable* pref_service,
HostContentSettingsMap* host_content_settings_map) {
pref_service->RemoveUserPref(prefs::kPrivacySandboxAntiAbuseInitialized);
host_content_settings_map->SetDefaultContentSetting(
ContentSettingsType::ANTI_ABUSE, CONTENT_SETTING_ALLOW);
}
std::vector<int> GetTopicsSettingsStringIdentifiers(bool did_consent,
bool has_current_topics,
bool has_blocked_topics) {
if (did_consent && !has_blocked_topics) {
return {IDS_SETTINGS_TOPICS_PAGE_TITLE,
IDS_SETTINGS_TOPICS_PAGE_TOGGLE_LABEL,
IDS_SETTINGS_TOPICS_PAGE_TOGGLE_SUB_LABEL,
IDS_SETTINGS_TOPICS_PAGE_CURRENT_TOPICS_HEADING,
IDS_SETTINGS_TOPICS_PAGE_CURRENT_TOPICS_DESCRIPTION_CANONICAL,
IDS_SETTINGS_TOPICS_PAGE_CURRENT_TOPICS_DESCRIPTION_DISABLED,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_HEADING,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_BULLET_1,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_BULLET_2,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_BULLET_3,
IDS_SETTINGS_TOPICS_PAGE_BLOCKED_TOPICS_HEADING,
IDS_SETTINGS_TOPICS_PAGE_BLOCKED_TOPICS_DESCRIPTION_EMPTY,
IDS_SETTINGS_TOPICS_PAGE_FOOTER_CANONICAL};
} else if (did_consent && has_blocked_topics) {
return {IDS_SETTINGS_TOPICS_PAGE_TITLE,
IDS_SETTINGS_TOPICS_PAGE_TOGGLE_LABEL,
IDS_SETTINGS_TOPICS_PAGE_TOGGLE_SUB_LABEL,
IDS_SETTINGS_TOPICS_PAGE_CURRENT_TOPICS_HEADING,
IDS_SETTINGS_TOPICS_PAGE_CURRENT_TOPICS_DESCRIPTION_CANONICAL,
IDS_SETTINGS_TOPICS_PAGE_CURRENT_TOPICS_DESCRIPTION_DISABLED,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_HEADING,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_BULLET_1,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_BULLET_2,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_BULLET_3,
IDS_SETTINGS_TOPICS_PAGE_BLOCKED_TOPICS_HEADING,
IDS_SETTINGS_TOPICS_PAGE_BLOCKED_TOPICS_DESCRIPTION,
IDS_SETTINGS_TOPICS_PAGE_FOOTER_CANONICAL};
} else if (!did_consent && has_current_topics && has_blocked_topics) {
return {IDS_SETTINGS_TOPICS_PAGE_TITLE,
IDS_SETTINGS_TOPICS_PAGE_TOGGLE_LABEL,
IDS_SETTINGS_TOPICS_PAGE_TOGGLE_SUB_LABEL,
IDS_SETTINGS_TOPICS_PAGE_CURRENT_TOPICS_HEADING,
IDS_SETTINGS_TOPICS_PAGE_CURRENT_TOPICS_DESCRIPTION_CANONICAL,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_HEADING,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_BULLET_1,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_BULLET_2,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_BULLET_3,
IDS_SETTINGS_TOPICS_PAGE_BLOCKED_TOPICS_HEADING,
IDS_SETTINGS_TOPICS_PAGE_BLOCKED_TOPICS_DESCRIPTION,
IDS_SETTINGS_TOPICS_PAGE_FOOTER_CANONICAL};
} else if (!did_consent && has_current_topics && !has_blocked_topics) {
return {IDS_SETTINGS_TOPICS_PAGE_TITLE,
IDS_SETTINGS_TOPICS_PAGE_TOGGLE_LABEL,
IDS_SETTINGS_TOPICS_PAGE_TOGGLE_SUB_LABEL,
IDS_SETTINGS_TOPICS_PAGE_CURRENT_TOPICS_HEADING,
IDS_SETTINGS_TOPICS_PAGE_CURRENT_TOPICS_DESCRIPTION_CANONICAL,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_HEADING,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_BULLET_1,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_BULLET_2,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_BULLET_3,
IDS_SETTINGS_TOPICS_PAGE_BLOCKED_TOPICS_HEADING,
IDS_SETTINGS_TOPICS_PAGE_BLOCKED_TOPICS_DESCRIPTION_EMPTY,
IDS_SETTINGS_TOPICS_PAGE_FOOTER_CANONICAL};
} else if (!did_consent && !has_current_topics && has_blocked_topics) {
return {IDS_SETTINGS_TOPICS_PAGE_TITLE,
IDS_SETTINGS_TOPICS_PAGE_TOGGLE_LABEL,
IDS_SETTINGS_TOPICS_PAGE_TOGGLE_SUB_LABEL,
IDS_SETTINGS_TOPICS_PAGE_CURRENT_TOPICS_HEADING,
IDS_SETTINGS_TOPICS_PAGE_CURRENT_TOPICS_DESCRIPTION_CANONICAL,
IDS_SETTINGS_TOPICS_PAGE_CURRENT_TOPICS_DESCRIPTION_EMPTY,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_HEADING,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_BULLET_1,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_BULLET_2,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_BULLET_3,
IDS_SETTINGS_TOPICS_PAGE_BLOCKED_TOPICS_HEADING,
IDS_SETTINGS_TOPICS_PAGE_BLOCKED_TOPICS_DESCRIPTION,
IDS_SETTINGS_TOPICS_PAGE_FOOTER_CANONICAL};
} else if (!did_consent && !has_current_topics && !has_blocked_topics) {
return {IDS_SETTINGS_TOPICS_PAGE_TITLE,
IDS_SETTINGS_TOPICS_PAGE_TOGGLE_LABEL,
IDS_SETTINGS_TOPICS_PAGE_TOGGLE_SUB_LABEL,
IDS_SETTINGS_TOPICS_PAGE_CURRENT_TOPICS_HEADING,
IDS_SETTINGS_TOPICS_PAGE_CURRENT_TOPICS_DESCRIPTION_CANONICAL,
IDS_SETTINGS_TOPICS_PAGE_CURRENT_TOPICS_DESCRIPTION_EMPTY,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_HEADING,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_BULLET_1,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_BULLET_2,
IDS_SETTINGS_TOPICS_PAGE_LEARN_MORE_BULLET_3,
IDS_SETTINGS_TOPICS_PAGE_BLOCKED_TOPICS_HEADING,
IDS_SETTINGS_TOPICS_PAGE_BLOCKED_TOPICS_DESCRIPTION_EMPTY,
IDS_SETTINGS_TOPICS_PAGE_FOOTER_CANONICAL};
}
NOTREACHED() << "Invalid topics settings consent state";
return {};
}
std::vector<int> GetTopicsConfirmationStringIdentifiers() {
return {IDS_PRIVACY_SANDBOX_M1_CONSENT_TITLE,
IDS_PRIVACY_SANDBOX_M1_CONSENT_DESCRIPTION_1,
IDS_PRIVACY_SANDBOX_M1_CONSENT_DESCRIPTION_2,
IDS_PRIVACY_SANDBOX_M1_CONSENT_DESCRIPTION_3,
IDS_PRIVACY_SANDBOX_M1_CONSENT_DESCRIPTION_4,
IDS_PRIVACY_SANDBOX_M1_CONSENT_LEARN_MORE_EXPAND_LABEL,
IDS_PRIVACY_SANDBOX_M1_CONSENT_LEARN_MORE_BULLET_1,
IDS_PRIVACY_SANDBOX_M1_CONSENT_LEARN_MORE_BULLET_2,
IDS_PRIVACY_SANDBOX_M1_CONSENT_LEARN_MORE_BULLET_3,
IDS_PRIVACY_SANDBOX_M1_CONSENT_LEARN_MORE_LINK};
}
} // namespace
class PrivacySandboxServiceTest : public testing::Test {
public:
PrivacySandboxServiceTest()
: browser_task_environment_(
base::test::TaskEnvironment::TimeSource::MOCK_TIME) {}
void SetUp() override {
InitializeFeaturesBeforeStart();
CreateService();
base::RunLoop run_loop;
first_party_sets_policy_service_.WaitForFirstInitCompleteForTesting(
run_loop.QuitClosure());
run_loop.Run();
first_party_sets_policy_service_.ResetForTesting();
}
virtual void InitializeFeaturesBeforeStart() {}
virtual std::unique_ptr<
privacy_sandbox_test_util::MockPrivacySandboxSettingsDelegate>
CreateMockDelegate() {
auto mock_delegate = std::make_unique<testing::NiceMock<
privacy_sandbox_test_util::MockPrivacySandboxSettingsDelegate>>();
mock_delegate->SetUpIsPrivacySandboxRestrictedResponse(
/*restricted=*/false);
return mock_delegate;
}
void CreateService() {
auto mock_delegate = CreateMockDelegate();
mock_delegate_ = mock_delegate.get();
privacy_sandbox_settings_ =
std::make_unique<privacy_sandbox::PrivacySandboxSettingsImpl>(
std::move(mock_delegate), host_content_settings_map(),
cookie_settings(), prefs());
#if !BUILDFLAG(IS_ANDROID)
mock_sentiment_service_ =
std::make_unique<::testing::NiceMock<MockTrustSafetySentimentService>>(
profile());
#endif
privacy_sandbox_service_ = std::make_unique<PrivacySandboxService>(
privacy_sandbox_settings(), cookie_settings(), profile()->GetPrefs(),
test_interest_group_manager(), GetProfileType(),
browsing_data_remover(), host_content_settings_map(),
#if !BUILDFLAG(IS_ANDROID)
mock_sentiment_service(),
#endif
mock_browsing_topics_service(), first_party_sets_policy_service());
}
virtual profile_metrics::BrowserProfileType GetProfileType() {
return profile_metrics::BrowserProfileType::kRegular;
}
void ConfirmRequiredPromptType(
PrivacySandboxService::PromptType prompt_type) {
// The required prompt type should never change between successive calls to
// GetRequiredPromptType.
EXPECT_EQ(prompt_type, privacy_sandbox_service()->GetRequiredPromptType());
}
TestingProfile* profile() { return &profile_; }
PrivacySandboxService* privacy_sandbox_service() {
return privacy_sandbox_service_.get();
}
privacy_sandbox::PrivacySandboxSettings* privacy_sandbox_settings() {
return privacy_sandbox_settings_.get();
}
base::test::ScopedFeatureList* feature_list() { return &feature_list_; }
sync_preferences::TestingPrefServiceSyncable* prefs() {
return profile()->GetTestingPrefService();
}
HostContentSettingsMap* host_content_settings_map() {
return HostContentSettingsMapFactory::GetForProfile(profile());
}
content_settings::CookieSettings* cookie_settings() {
return CookieSettingsFactory::GetForProfile(profile()).get();
}
TestInterestGroupManager* test_interest_group_manager() {
return &test_interest_group_manager_;
}
content::BrowsingDataRemover* browsing_data_remover() {
return profile()->GetBrowsingDataRemover();
}
browsing_topics::MockBrowsingTopicsService* mock_browsing_topics_service() {
return &mock_browsing_topics_service_;
}
privacy_sandbox_test_util::MockPrivacySandboxSettingsDelegate*
mock_delegate() {
return mock_delegate_;
}
first_party_sets::ScopedMockFirstPartySetsHandler&
mock_first_party_sets_handler() {
return mock_first_party_sets_handler_;
}
first_party_sets::FirstPartySetsPolicyService*
first_party_sets_policy_service() {
return &first_party_sets_policy_service_;
}
content::BrowserTaskEnvironment* browser_task_environment() {
return &browser_task_environment_;
}
#if !BUILDFLAG(IS_ANDROID)
MockTrustSafetySentimentService* mock_sentiment_service() {
return mock_sentiment_service_.get();
}
#endif
private:
content::BrowserTaskEnvironment browser_task_environment_;
TestingProfile profile_;
base::test::ScopedFeatureList feature_list_;
TestInterestGroupManager test_interest_group_manager_;
browsing_topics::MockBrowsingTopicsService mock_browsing_topics_service_;
raw_ptr<privacy_sandbox_test_util::MockPrivacySandboxSettingsDelegate>
mock_delegate_;
first_party_sets::ScopedMockFirstPartySetsHandler
mock_first_party_sets_handler_;
first_party_sets::FirstPartySetsPolicyService
first_party_sets_policy_service_ =
first_party_sets::FirstPartySetsPolicyService(
profile_.GetOriginalProfile());
#if !BUILDFLAG(IS_ANDROID)
std::unique_ptr<MockTrustSafetySentimentService> mock_sentiment_service_;
#endif
std::unique_ptr<privacy_sandbox::PrivacySandboxSettings>
privacy_sandbox_settings_;
std::unique_ptr<PrivacySandboxService> privacy_sandbox_service_;
};
TEST_F(PrivacySandboxServiceTest, GetFledgeJoiningEtldPlusOne) {
// Confirm that the set of FLEDGE origins which were top-frame for FLEDGE join
// actions is correctly converted into a list of eTLD+1s.
using FledgeTestCase =
std::pair<std::vector<url::Origin>, std::vector<std::string>>;
// Items which map to the same eTLD+1 should be coalesced into a single entry.
FledgeTestCase test_case_1 = {
{url::Origin::Create(GURL("https://www.example.com")),
url::Origin::Create(GURL("https://example.com:8080")),
url::Origin::Create(GURL("http://www.example.com"))},
{"example.com"}};
// eTLD's should return the host instead, this is relevant for sites which
// are themselves on the PSL, e.g. github.io.
FledgeTestCase test_case_2 = {
{
url::Origin::Create(GURL("https://co.uk")),
url::Origin::Create(GURL("http://co.uk")),
url::Origin::Create(GURL("http://example.co.uk")),
},
{"co.uk", "example.co.uk"}};
// IP addresses should also return the host.
FledgeTestCase test_case_3 = {
{
url::Origin::Create(GURL("https://192.168.1.2")),
url::Origin::Create(GURL("https://192.168.1.2:8080")),
url::Origin::Create(GURL("https://192.168.1.3:8080")),
},
{"192.168.1.2", "192.168.1.3"}};
// Results should be alphabetically ordered.
FledgeTestCase test_case_4 = {{
url::Origin::Create(GURL("https://d.com")),
url::Origin::Create(GURL("https://b.com")),
url::Origin::Create(GURL("https://a.com")),
url::Origin::Create(GURL("https://c.com")),
},
{"a.com", "b.com", "c.com", "d.com"}};
std::vector<FledgeTestCase> test_cases = {test_case_1, test_case_2,
test_case_3, test_case_4};
for (const auto& origins_to_expected : test_cases) {
std::vector<content::InterestGroupManager::InterestGroupDataKey> data_keys;
base::ranges::transform(
origins_to_expected.first, std::back_inserter(data_keys),
[](const auto& origin) {
return content::InterestGroupManager::InterestGroupDataKey{
url::Origin::Create(GURL("https://embedded.com")), origin};
});
test_interest_group_manager()->SetInterestGroupDataKeys(data_keys);
bool callback_called = false;
auto callback = base::BindLambdaForTesting(
[&](std::vector<std::string> items_for_display) {
ASSERT_EQ(items_for_display.size(),
origins_to_expected.second.size());
for (size_t i = 0; i < items_for_display.size(); i++) {
EXPECT_EQ(origins_to_expected.second[i], items_for_display[i]);
}
callback_called = true;
});
privacy_sandbox_service()->GetFledgeJoiningEtldPlusOneForDisplay(callback);
EXPECT_TRUE(callback_called);
}
}
TEST_F(PrivacySandboxServiceTest, GetFledgeBlockedEtldPlusOne) {
// Confirm that blocked FLEDGE top frame eTLD+1's are correctly produced
// for display.
const std::vector<std::string> sites = {"google.com", "example.com",
"google.com.au"};
for (const auto& site : sites) {
privacy_sandbox_settings()->SetFledgeJoiningAllowed(site, false);
}
// Sites should be returned in lexographical order.
auto returned_sites =
privacy_sandbox_service()->GetBlockedFledgeJoiningTopFramesForDisplay();
ASSERT_EQ(3u, returned_sites.size());
EXPECT_EQ(returned_sites[0], sites[1]);
EXPECT_EQ(returned_sites[1], sites[0]);
EXPECT_EQ(returned_sites[2], sites[2]);
// Settings a site back to allowed should appropriately remove it from the
// display list.
privacy_sandbox_settings()->SetFledgeJoiningAllowed("google.com", true);
returned_sites =
privacy_sandbox_service()->GetBlockedFledgeJoiningTopFramesForDisplay();
ASSERT_EQ(2u, returned_sites.size());
EXPECT_EQ(returned_sites[0], sites[1]);
EXPECT_EQ(returned_sites[1], sites[2]);
}
TEST_F(PrivacySandboxServiceTest, PromptActionUpdatesRequiredPrompt) {
// Confirm that when the service is informed a prompt action occurred, it
// correctly adjusts the required prompt type and Privacy Sandbox pref.
// Consent accepted:
SetupPromptTestState(feature_list(), prefs(),
{/*consent_required=*/true,
/*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false,
/*consent_decision_made=*/false,
/*confirmation_not_shown=*/false});
EXPECT_EQ(PrivacySandboxService::PromptType::kConsent,
privacy_sandbox_service()->GetRequiredPromptType());
EXPECT_FALSE(prefs()->GetBoolean(prefs::kPrivacySandboxApisEnabledV2));
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kConsentAccepted);
EXPECT_EQ(PrivacySandboxService::PromptType::kNone,
privacy_sandbox_service()->GetRequiredPromptType());
EXPECT_TRUE(prefs()->GetBoolean(prefs::kPrivacySandboxApisEnabledV2));
EXPECT_TRUE(prefs()->GetBoolean(prefs::kPrivacySandboxConsentDecisionMade));
// Consent declined:
SetupPromptTestState(feature_list(), prefs(),
{/*consent_required=*/true,
/*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false,
/*consent_decision_made=*/false,
/*confirmation_not_shown=*/false});
EXPECT_EQ(PrivacySandboxService::PromptType::kConsent,
privacy_sandbox_service()->GetRequiredPromptType());
EXPECT_FALSE(prefs()->GetBoolean(prefs::kPrivacySandboxApisEnabledV2));
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kConsentDeclined);
EXPECT_EQ(PrivacySandboxService::PromptType::kNone,
privacy_sandbox_service()->GetRequiredPromptType());
EXPECT_FALSE(prefs()->GetBoolean(prefs::kPrivacySandboxApisEnabledV2));
EXPECT_TRUE(prefs()->GetBoolean(prefs::kPrivacySandboxConsentDecisionMade));
// Notice shown:
SetupPromptTestState(feature_list(), prefs(),
{/*consent_required=*/false,
/*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false,
/*consent_decision_made=*/false,
/*confirmation_not_shown=*/false});
EXPECT_EQ(PrivacySandboxService::PromptType::kNotice,
privacy_sandbox_service()->GetRequiredPromptType());
EXPECT_FALSE(prefs()->GetBoolean(prefs::kPrivacySandboxApisEnabledV2));
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kNoticeShown);
EXPECT_EQ(PrivacySandboxService::PromptType::kNone,
privacy_sandbox_service()->GetRequiredPromptType());
EXPECT_TRUE(prefs()->GetBoolean(prefs::kPrivacySandboxApisEnabledV2));
EXPECT_TRUE(prefs()->GetBoolean(prefs::kPrivacySandboxNoticeDisplayed));
}
TEST_F(PrivacySandboxServiceTest, PromptActionsUMAActions) {
base::UserActionTester user_action_tester;
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kNoticeShown);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Settings.PrivacySandbox.Notice.Shown"));
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kNoticeOpenSettings);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Settings.PrivacySandbox.Notice.OpenedSettings"));
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kRestrictedNoticeOpenSettings);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Settings.PrivacySandbox.RestrictedNotice.OpenedSettings"));
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kNoticeAcknowledge);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Settings.PrivacySandbox.Notice.Acknowledged"));
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kNoticeDismiss);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Settings.PrivacySandbox.Notice.Dismissed"));
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kNoticeClosedNoInteraction);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Settings.PrivacySandbox.Notice.ClosedNoInteraction"));
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kConsentShown);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Settings.PrivacySandbox.Consent.Shown"));
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kConsentAccepted);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Settings.PrivacySandbox.Consent.Accepted"));
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kConsentDeclined);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Settings.PrivacySandbox.Consent.Declined"));
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kConsentMoreInfoOpened);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Settings.PrivacySandbox.Consent.LearnMoreExpanded"));
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kConsentMoreInfoClosed);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Settings.PrivacySandbox.Consent.LearnMoreClosed"));
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kConsentClosedNoDecision);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Settings.PrivacySandbox.Consent.ClosedNoInteraction"));
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kNoticeLearnMore);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Settings.PrivacySandbox.Notice.LearnMore"));
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kNoticeMoreInfoOpened);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Settings.PrivacySandbox.Notice.LearnMoreExpanded"));
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kNoticeMoreInfoClosed);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Settings.PrivacySandbox.Notice.LearnMoreClosed"));
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kConsentMoreButtonClicked);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Settings.PrivacySandbox.Consent.MoreButtonClicked"));
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kNoticeMoreButtonClicked);
EXPECT_EQ(1, user_action_tester.GetActionCount(
"Settings.PrivacySandbox.Notice.MoreButtonClicked"));
}
#if !BUILDFLAG(IS_ANDROID)
TEST_F(PrivacySandboxServiceTest, PromptActionsSentimentService) {
{
EXPECT_CALL(*mock_sentiment_service(),
InteractedWithPrivacySandbox3(testing::_))
.Times(0);
SetupPromptTestState(feature_list(), prefs(),
{/*consent_required=*/false,
/*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false,
/*consent_decision_made=*/false,
/*confirmation_not_shown=*/false});
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kNoticeShown);
}
{
EXPECT_CALL(
*mock_sentiment_service(),
InteractedWithPrivacySandbox3(TrustSafetySentimentService::FeatureArea::
kPrivacySandbox3NoticeSettings))
.Times(1);
SetupPromptTestState(feature_list(), prefs(),
{/*consent_required=*/false,
/*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false,
/*consent_decision_made=*/false,
/*confirmation_not_shown=*/false});
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kNoticeOpenSettings);
}
{
EXPECT_CALL(
*mock_sentiment_service(),
InteractedWithPrivacySandbox3(
TrustSafetySentimentService::FeatureArea::kPrivacySandbox3NoticeOk))
.Times(1);
SetupPromptTestState(feature_list(), prefs(),
{/*consent_required=*/false,
/*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false,
/*consent_decision_made=*/false,
/*confirmation_not_shown=*/false});
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kNoticeAcknowledge);
}
{
EXPECT_CALL(
*mock_sentiment_service(),
InteractedWithPrivacySandbox3(TrustSafetySentimentService::FeatureArea::
kPrivacySandbox3NoticeDismiss))
.Times(1);
SetupPromptTestState(feature_list(), prefs(),
{/*consent_required=*/false,
/*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false,
/*consent_decision_made=*/false,
/*confirmation_not_shown=*/false});
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kNoticeDismiss);
}
{
EXPECT_CALL(*mock_sentiment_service(),
InteractedWithPrivacySandbox3(testing::_))
.Times(0);
SetupPromptTestState(feature_list(), prefs(),
{/*consent_required=*/false,
/*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false,
/*consent_decision_made=*/false,
/*confirmation_not_shown=*/false});
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kNoticeClosedNoInteraction);
}
{
EXPECT_CALL(
*mock_sentiment_service(),
InteractedWithPrivacySandbox3(TrustSafetySentimentService::FeatureArea::
kPrivacySandbox3NoticeLearnMore))
.Times(1);
SetupPromptTestState(feature_list(), prefs(),
{/*consent_required=*/false,
/*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false,
/*consent_decision_made=*/false,
/*confirmation_not_shown=*/false});
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kNoticeLearnMore);
}
{
EXPECT_CALL(*mock_sentiment_service(),
InteractedWithPrivacySandbox3(testing::_))
.Times(0);
SetupPromptTestState(feature_list(), prefs(),
{/*consent_required=*/true,
/*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false,
/*consent_decision_made=*/false,
/*confirmation_not_shown=*/false});
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kConsentShown);
}
{
EXPECT_CALL(
*mock_sentiment_service(),
InteractedWithPrivacySandbox3(TrustSafetySentimentService::FeatureArea::
kPrivacySandbox3ConsentAccept))
.Times(1);
SetupPromptTestState(feature_list(), prefs(),
{/*consent_required=*/true,
/*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false,
/*consent_decision_made=*/false,
/*confirmation_not_shown=*/false});
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kConsentAccepted);
}
{
EXPECT_CALL(
*mock_sentiment_service(),
InteractedWithPrivacySandbox3(TrustSafetySentimentService::FeatureArea::
kPrivacySandbox3ConsentDecline))
.Times(1);
SetupPromptTestState(feature_list(), prefs(),
{/*consent_required=*/true,
/*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false,
/*consent_decision_made=*/false,
/*confirmation_not_shown=*/false});
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kConsentDeclined);
}
{
EXPECT_CALL(*mock_sentiment_service(),
InteractedWithPrivacySandbox3(testing::_))
.Times(0);
SetupPromptTestState(feature_list(), prefs(),
{/*consent_required=*/true,
/*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false,
/*consent_decision_made=*/false,
/*confirmation_not_shown=*/false});
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kConsentMoreInfoOpened);
}
{
EXPECT_CALL(*mock_sentiment_service(),
InteractedWithPrivacySandbox3(testing::_))
.Times(0);
SetupPromptTestState(feature_list(), prefs(),
{/*consent_required=*/true,
/*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false,
/*consent_decision_made=*/false,
/*confirmation_not_shown=*/false});
privacy_sandbox_service()->PromptActionOccurred(
PrivacySandboxService::PromptAction::kConsentClosedNoDecision);
}
}
#endif
TEST_F(PrivacySandboxServiceTest, Block3PCookieNoPrompt) {
// Confirm that when 3P cookies are blocked, that no prompt is shown.
prefs()->SetUserPref(
prefs::kCookieControlsMode,
std::make_unique<base::Value>(static_cast<int>(
content_settings::CookieControlsMode::kBlockThirdParty)));
EXPECT_EQ(PrivacySandboxService::PromptType::kNone,
privacy_sandbox_service()->GetRequiredPromptType());
// This should persist even if 3P cookies become allowed.
prefs()->SetUserPref(prefs::kCookieControlsMode,
std::make_unique<base::Value>(static_cast<int>(
content_settings::CookieControlsMode::kOff)));
EXPECT_EQ(PrivacySandboxService::PromptType::kNone,
privacy_sandbox_service()->GetRequiredPromptType());
}
TEST_F(PrivacySandboxServiceTest, BlockAllCookiesNoPrompt) {
// Confirm that when all cookies are blocked, that no prompt is shown.
cookie_settings()->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
EXPECT_EQ(PrivacySandboxService::PromptType::kNone,
privacy_sandbox_service()->GetRequiredPromptType());
// This should persist even if cookies become allowed.
cookie_settings()->SetDefaultCookieSetting(CONTENT_SETTING_ALLOW);
EXPECT_EQ(PrivacySandboxService::PromptType::kNone,
privacy_sandbox_service()->GetRequiredPromptType());
}
TEST_F(PrivacySandboxServiceTest, FledgeBlockDeletesData) {
// Allowing FLEDGE joining should not start a removal task.
privacy_sandbox_service()->SetFledgeJoiningAllowed("example.com", true);
EXPECT_EQ(0xffffffffffffffffull, // -1, indicates no last removal task.
browsing_data_remover()->GetLastUsedRemovalMaskForTesting());
// When FLEDGE joining is blocked, a removal task should be started.
privacy_sandbox_service()->SetFledgeJoiningAllowed("example.com", false);
EXPECT_EQ(content::BrowsingDataRemover::DATA_TYPE_INTEREST_GROUPS,
browsing_data_remover()->GetLastUsedRemovalMaskForTesting());
EXPECT_EQ(base::Time::Min(),
browsing_data_remover()->GetLastUsedBeginTimeForTesting());
EXPECT_EQ(content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
browsing_data_remover()->GetLastUsedOriginTypeMaskForTesting());
}
TEST_F(PrivacySandboxServiceTest, DisablingV2SandboxClearsData) {
// Confirm that when the V2 sandbox preference is disabled, a browsing data
// remover task is started and Topics Data is deleted. V1 should remain
// unaffected.
EXPECT_CALL(*mock_browsing_topics_service(), ClearAllTopicsData()).Times(0);
prefs()->SetBoolean(prefs::kPrivacySandboxApisEnabled, false);
constexpr uint64_t kNoRemovalTask = -1ull;
EXPECT_EQ(kNoRemovalTask,
browsing_data_remover()->GetLastUsedRemovalMaskForTesting());
// Enabling should not cause a removal task.
prefs()->SetBoolean(prefs::kPrivacySandboxApisEnabledV2, true);
EXPECT_EQ(kNoRemovalTask,
browsing_data_remover()->GetLastUsedRemovalMaskForTesting());
// Disabling should start a task clearing all kAPI information.
EXPECT_CALL(*mock_browsing_topics_service(), ClearAllTopicsData()).Times(1);
prefs()->SetBoolean(prefs::kPrivacySandboxApisEnabledV2, false);
EXPECT_EQ(content::BrowsingDataRemover::DATA_TYPE_PRIVACY_SANDBOX,
browsing_data_remover()->GetLastUsedRemovalMaskForTesting());
EXPECT_EQ(base::Time::Min(),
browsing_data_remover()->GetLastUsedBeginTimeForTesting());
EXPECT_EQ(content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
browsing_data_remover()->GetLastUsedOriginTypeMaskForTesting());
}
TEST_F(PrivacySandboxServiceTest, DisablingTopicsPrefClearsData) {
// Confirm that when the topics preference is disabled, topics data is
// deleted. No browsing data remover tasks are started.
EXPECT_CALL(*mock_browsing_topics_service(), ClearAllTopicsData()).Times(0);
// Enabling should not delete data.
prefs()->SetBoolean(prefs::kPrivacySandboxM1TopicsEnabled, true);
constexpr uint64_t kNoRemovalTask = -1ull;
EXPECT_EQ(kNoRemovalTask,
browsing_data_remover()->GetLastUsedRemovalMaskForTesting());
// Disabling should start delete topics data.
EXPECT_CALL(*mock_browsing_topics_service(), ClearAllTopicsData()).Times(1);
prefs()->SetBoolean(prefs::kPrivacySandboxM1TopicsEnabled, false);
EXPECT_EQ(kNoRemovalTask,
browsing_data_remover()->GetLastUsedRemovalMaskForTesting());
}
TEST_F(PrivacySandboxServiceTest, DisablingFledgePrefClearsData) {
// Confirm that when the fledge preference is disabled, a browsing data
// remover task is started. Topics data isn't deleted.
EXPECT_CALL(*mock_browsing_topics_service(), ClearAllTopicsData()).Times(0);
// Enabling should not cause a removal task.
prefs()->SetBoolean(prefs::kPrivacySandboxM1FledgeEnabled, true);
constexpr uint64_t kNoRemovalTask = -1ull;
EXPECT_EQ(kNoRemovalTask,
browsing_data_remover()->GetLastUsedRemovalMaskForTesting());
// Disabling should start a task clearing all related information.
prefs()->SetBoolean(prefs::kPrivacySandboxM1FledgeEnabled, false);
EXPECT_EQ(
content::BrowsingDataRemover::DATA_TYPE_INTEREST_GROUPS |
content::BrowsingDataRemover::DATA_TYPE_SHARED_STORAGE |
content::BrowsingDataRemover::DATA_TYPE_INTEREST_GROUPS_INTERNAL,
browsing_data_remover()->GetLastUsedRemovalMaskForTesting());
EXPECT_EQ(base::Time::Min(),
browsing_data_remover()->GetLastUsedBeginTimeForTesting());
EXPECT_EQ(content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
browsing_data_remover()->GetLastUsedOriginTypeMaskForTesting());
}
TEST_F(PrivacySandboxServiceTest, DisablingAdMeasurementePrefClearsData) {
// Confirm that when the ad measurement preference is disabled, a browsing
// data remover task is started. Topics data isn't deleted.
EXPECT_CALL(*mock_browsing_topics_service(), ClearAllTopicsData()).Times(0);
// Enabling should not cause a removal task.
prefs()->SetBoolean(prefs::kPrivacySandboxM1AdMeasurementEnabled, true);
constexpr uint64_t kNoRemovalTask = -1ull;
EXPECT_EQ(kNoRemovalTask,
browsing_data_remover()->GetLastUsedRemovalMaskForTesting());
// Disabling should start a task clearing all related information.
prefs()->SetBoolean(prefs::kPrivacySandboxM1AdMeasurementEnabled, false);
EXPECT_EQ(
content::BrowsingDataRemover::DATA_TYPE_ATTRIBUTION_REPORTING |
content::BrowsingDataRemover::DATA_TYPE_AGGREGATION_SERVICE |
content::BrowsingDataRemover::DATA_TYPE_PRIVATE_AGGREGATION_INTERNAL,
browsing_data_remover()->GetLastUsedRemovalMaskForTesting());
EXPECT_EQ(base::Time::Min(),
browsing_data_remover()->GetLastUsedBeginTimeForTesting());
EXPECT_EQ(content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB,
browsing_data_remover()->GetLastUsedOriginTypeMaskForTesting());
}
TEST_F(PrivacySandboxServiceTest, GetTopTopics) {
// Check that the service correctly de-dupes and orders top topics. Topics
// should be alphabetically ordered.
const privacy_sandbox::CanonicalTopic kFirstTopic =
privacy_sandbox::CanonicalTopic(browsing_topics::Topic(24), // "Blues"
kTestTaxonomyVersion);
const privacy_sandbox::CanonicalTopic kSecondTopic =
privacy_sandbox::CanonicalTopic(
browsing_topics::Topic(23), // "Music & audio"
kTestTaxonomyVersion);
const std::vector<privacy_sandbox::CanonicalTopic> kTopTopics = {
kSecondTopic, kSecondTopic, kFirstTopic};
EXPECT_CALL(*mock_browsing_topics_service(), GetTopTopicsForDisplay())
.WillOnce(testing::Return(kTopTopics));
auto topics = privacy_sandbox_service()->GetCurrentTopTopics();
ASSERT_EQ(2u, topics.size());
EXPECT_EQ(kFirstTopic, topics[0]);
EXPECT_EQ(kSecondTopic, topics[1]);
}
TEST_F(PrivacySandboxServiceTest, GetBlockedTopics) {
// Check that blocked topics are correctly alphabetically sorted and returned.
const privacy_sandbox::CanonicalTopic kFirstTopic =
privacy_sandbox::CanonicalTopic(browsing_topics::Topic(24), // "Blues"
kTestTaxonomyVersion);
const privacy_sandbox::CanonicalTopic kSecondTopic =
privacy_sandbox::CanonicalTopic(
browsing_topics::Topic(23), // "Music & audio"
kTestTaxonomyVersion);
// The PrivacySandboxService assumes that the PrivacySandboxSettings service
// dedupes blocked topics. Check that assumption here.
privacy_sandbox_settings()->SetTopicAllowed(kSecondTopic, false);
privacy_sandbox_settings()->SetTopicAllowed(kSecondTopic, false);
privacy_sandbox_settings()->SetTopicAllowed(kFirstTopic, false);
privacy_sandbox_settings()->SetTopicAllowed(kFirstTopic, false);
auto blocked_topics = privacy_sandbox_service()->GetBlockedTopics();
ASSERT_EQ(2u, blocked_topics.size());
EXPECT_EQ(kFirstTopic, blocked_topics[0]);
EXPECT_EQ(kSecondTopic, blocked_topics[1]);
}
TEST_F(PrivacySandboxServiceTest, SetTopicAllowed) {
const privacy_sandbox::CanonicalTopic kTestTopic =
privacy_sandbox::CanonicalTopic(browsing_topics::Topic(10),
kTestTaxonomyVersion);
EXPECT_CALL(*mock_browsing_topics_service(), ClearTopic(kTestTopic)).Times(1);
privacy_sandbox_service()->SetTopicAllowed(kTestTopic, false);
EXPECT_FALSE(privacy_sandbox_settings()->IsTopicAllowed(kTestTopic));
testing::Mock::VerifyAndClearExpectations(mock_browsing_topics_service());
EXPECT_CALL(*mock_browsing_topics_service(), ClearTopic(kTestTopic)).Times(0);
privacy_sandbox_service()->SetTopicAllowed(kTestTopic, true);
EXPECT_TRUE(privacy_sandbox_settings()->IsTopicAllowed(kTestTopic));
}
#if BUILDFLAG(IS_CHROMEOS)
TEST_F(PrivacySandboxServiceTest, DeviceLocalAccountUser) {
// No prompt should be shown if the user is associated with a device local
// account on CrOS.
SetupPromptTestState(feature_list(), prefs(),
{/*consent_required=*/true,
/*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false,
/*consent_decision_made=*/false,
/*confirmation_not_shown=*/false});
// No prompt should be shown for a public session account.
#if BUILDFLAG(IS_CHROMEOS_ASH)
ash::ScopedTestPublicSessionLoginState login_state;
#elif BUILDFLAG(IS_CHROMEOS_LACROS)
crosapi::mojom::BrowserInitParamsPtr init_params =
crosapi::mojom::BrowserInitParams::New();
init_params->session_type = crosapi::mojom::SessionType::kPublicSession;
chromeos::BrowserInitParams::SetInitParamsForTests(std::move(init_params));
#endif
EXPECT_EQ(PrivacySandboxService::PromptType::kNone,
privacy_sandbox_service()->GetRequiredPromptType());
// No prompt should be shown for a web kiosk account.
#if BUILDFLAG(IS_CHROMEOS_ASH)
ash::LoginState::Get()->SetLoggedInState(
ash::LoginState::LoggedInState::LOGGED_IN_ACTIVE,
ash::LoginState::LoggedInUserType::LOGGED_IN_USER_KIOSK);
#elif BUILDFLAG(IS_CHROMEOS_LACROS)
init_params = crosapi::mojom::BrowserInitParams::New();
init_params->session_type = crosapi::mojom::SessionType::kWebKioskSession;
chromeos::BrowserInitParams::SetInitParamsForTests(std::move(init_params));
#endif
EXPECT_EQ(PrivacySandboxService::PromptType::kNone,
privacy_sandbox_service()->GetRequiredPromptType());
// A prompt should be shown for a regular user.
#if BUILDFLAG(IS_CHROMEOS_ASH)
ash::LoginState::Get()->SetLoggedInState(
ash::LoginState::LoggedInState::LOGGED_IN_ACTIVE,
ash::LoginState::LoggedInUserType::LOGGED_IN_USER_REGULAR);
#elif BUILDFLAG(IS_CHROMEOS_LACROS)
init_params = crosapi::mojom::BrowserInitParams::New();
init_params->session_type = crosapi::mojom::SessionType::kRegularSession;
chromeos::BrowserInitParams::SetInitParamsForTests(std::move(init_params));
#endif
EXPECT_EQ(PrivacySandboxService::PromptType::kConsent,
privacy_sandbox_service()->GetRequiredPromptType());
}
#endif // BUILDFLAG(IS_CHROMEOS)
TEST_F(PrivacySandboxServiceTest, TestNoFakeTopics) {
auto* service = privacy_sandbox_service();
EXPECT_THAT(service->GetCurrentTopTopics(), testing::IsEmpty());
EXPECT_THAT(service->GetBlockedTopics(), testing::IsEmpty());
}
TEST_F(PrivacySandboxServiceTest, TestNoFakeTopicsPrefOff) {
// Sample data won't be returned for current topics when the pref is off, only
// the blocked list.
prefs()->SetUserPref(prefs::kPrivacySandboxM1TopicsEnabled,
std::make_unique<base::Value>(false));
feature_list()->InitWithFeaturesAndParameters(
{{privacy_sandbox::kPrivacySandboxSettings4,
{{privacy_sandbox::kPrivacySandboxSettings4ShowSampleDataForTesting
.name,
"true"}}}},
{});
CanonicalTopic topic3(Topic(3), kTestTaxonomyVersion);
CanonicalTopic topic4(Topic(4), kTestTaxonomyVersion);
auto* service = privacy_sandbox_service();
EXPECT_THAT(service->GetCurrentTopTopics(), testing::IsEmpty());
EXPECT_THAT(service->GetBlockedTopics(), ElementsAre(topic3, topic4));
}
TEST_F(PrivacySandboxServiceTest, TestFakeTopics) {
std::vector<base::test::FeatureRefAndParams> test_features = {
{privacy_sandbox::kPrivacySandboxSettings3,
{{privacy_sandbox::kPrivacySandboxSettings3ShowSampleDataForTesting.name,
"true"}}},
{privacy_sandbox::kPrivacySandboxSettings4,
{{privacy_sandbox::kPrivacySandboxSettings4ShowSampleDataForTesting.name,
"true"}}}};
// Sample data for current topics is only returned when the pref is on.
prefs()->SetUserPref(prefs::kPrivacySandboxM1TopicsEnabled,
std::make_unique<base::Value>(true));
for (const auto& feature : test_features) {
feature_list()->Reset();
feature_list()->InitWithFeaturesAndParameters({feature}, {});
CanonicalTopic topic1(Topic(1), kTestTaxonomyVersion);
CanonicalTopic topic2(Topic(2), kTestTaxonomyVersion);
CanonicalTopic topic3(Topic(3), kTestTaxonomyVersion);
CanonicalTopic topic4(Topic(4), kTestTaxonomyVersion);
auto* service = privacy_sandbox_service();
EXPECT_THAT(service->GetCurrentTopTopics(), ElementsAre(topic1, topic2));
EXPECT_THAT(service->GetBlockedTopics(), ElementsAre(topic3, topic4));
service->SetTopicAllowed(topic1, false);
EXPECT_THAT(service->GetCurrentTopTopics(), ElementsAre(topic2));
EXPECT_THAT(service->GetBlockedTopics(),
ElementsAre(topic1, topic3, topic4));
service->SetTopicAllowed(topic4, true);
EXPECT_THAT(service->GetCurrentTopTopics(), ElementsAre(topic2, topic4));
EXPECT_THAT(service->GetBlockedTopics(), ElementsAre(topic1, topic3));
service->SetTopicAllowed(topic1, true);
service->SetTopicAllowed(topic4, false);
EXPECT_THAT(service->GetCurrentTopTopics(), ElementsAre(topic1, topic2));
EXPECT_THAT(service->GetBlockedTopics(), ElementsAre(topic3, topic4));
}
}
TEST_F(PrivacySandboxServiceTest, PrivacySandboxPromptNoticeWaiting) {
base::HistogramTester histogram_tester;
feature_list()->Reset();
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings3, {{"notice-required", "true"}});
prefs()->SetUserPref(prefs::kPrivacySandboxNoConfirmationSandboxDisabled,
std::make_unique<base::Value>(false));
prefs()->SetUserPref(prefs::kPrivacySandboxNoticeDisplayed,
std::make_unique<base::Value>(false));
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/false,
/*block_third_party_cookies=*/false,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histogram_tester.ExpectUniqueSample(
kPrivacySandboxStartupHistogram,
PrivacySandboxService::PSStartupStates::kPromptWaiting, 1);
}
TEST_F(PrivacySandboxServiceTest,
FirstPartySetsNotRelevantMetricAllowedCookies) {
base::HistogramTester histogram_tester;
prefs()->SetUserPref(prefs::kPrivacySandboxFirstPartySetsEnabled,
std::make_unique<base::Value>(true));
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/false,
/*block_third_party_cookies=*/false,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histogram_tester.ExpectUniqueSample(
kFirstPartySetsStateHistogram,
PrivacySandboxService::FirstPartySetsState::kFpsNotRelevant, 1);
}
TEST_F(PrivacySandboxServiceTest,
FirstPartySetsNotRelevantMetricBlockedCookies) {
base::HistogramTester histogram_tester;
prefs()->SetUserPref(prefs::kPrivacySandboxFirstPartySetsEnabled,
std::make_unique<base::Value>(true));
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/true,
/*block_third_party_cookies=*/true,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_BLOCK,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histogram_tester.ExpectUniqueSample(
kFirstPartySetsStateHistogram,
PrivacySandboxService::FirstPartySetsState::kFpsNotRelevant, 1);
}
TEST_F(PrivacySandboxServiceTest, FirstPartySetsEnabledMetric) {
base::HistogramTester histogram_tester;
prefs()->SetUserPref(prefs::kPrivacySandboxFirstPartySetsEnabled,
std::make_unique<base::Value>(true));
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/true,
/*block_third_party_cookies=*/true,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histogram_tester.ExpectUniqueSample(
kFirstPartySetsStateHistogram,
PrivacySandboxService::FirstPartySetsState::kFpsEnabled, 1);
}
TEST_F(PrivacySandboxServiceTest, FirstPartySetsDisabledMetric) {
base::HistogramTester histogram_tester;
prefs()->SetUserPref(prefs::kPrivacySandboxFirstPartySetsEnabled,
std::make_unique<base::Value>(false));
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/true,
/*block_third_party_cookies=*/true,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histogram_tester.ExpectUniqueSample(
kFirstPartySetsStateHistogram,
PrivacySandboxService::FirstPartySetsState::kFpsDisabled, 1);
}
TEST_F(PrivacySandboxServiceTest, PrivacySandboxPromptConsentWaiting) {
base::HistogramTester histogram_tester;
feature_list()->Reset();
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings3,
{{"consent-required", "true" /* consent required */}});
prefs()->SetUserPref(prefs::kPrivacySandboxNoConfirmationSandboxDisabled,
std::make_unique<base::Value>(false));
prefs()->SetUserPref(prefs::kPrivacySandboxConsentDecisionMade,
std::make_unique<base::Value>(false));
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/false,
/*block_third_party_cookies=*/false,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histogram_tester.ExpectUniqueSample(
kPrivacySandboxStartupHistogram,
PrivacySandboxService::PSStartupStates::kPromptWaiting, 1);
}
TEST_F(PrivacySandboxServiceTest, PrivacySandboxV1OffDisabled) {
base::HistogramTester histogram_tester;
feature_list()->Reset();
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings3,
{{"consent-required", "false" /* consent required */}});
prefs()->SetUserPref(prefs::kPrivacySandboxNoConfirmationSandboxDisabled,
std::make_unique<base::Value>(true));
prefs()->SetUserPref(prefs::kPrivacySandboxApisEnabledV2,
std::make_unique<base::Value>(false));
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/false,
/*block_third_party_cookies=*/false,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histogram_tester.ExpectUniqueSample(
kPrivacySandboxStartupHistogram,
PrivacySandboxService::PSStartupStates::kPromptOffV1OffDisabled, 1);
}
TEST_F(PrivacySandboxServiceTest, PrivacySandboxV1OffEnabled) {
base::HistogramTester histogram_tester;
feature_list()->Reset();
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings3,
{{"consent-required", "false" /* consent required */}});
prefs()->SetUserPref(prefs::kPrivacySandboxNoConfirmationSandboxDisabled,
std::make_unique<base::Value>(true));
prefs()->SetUserPref(prefs::kPrivacySandboxApisEnabledV2,
std::make_unique<base::Value>(true));
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/true,
/*block_third_party_cookies=*/false,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histogram_tester.ExpectUniqueSample(
kPrivacySandboxStartupHistogram,
PrivacySandboxService::PSStartupStates::kPromptOffV1OffEnabled, 1);
}
TEST_F(PrivacySandboxServiceTest, PrivacySandboxRestricted) {
base::HistogramTester histogram_tester;
feature_list()->Reset();
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings3,
{{"consent-required", "false" /* consent required */}});
prefs()->SetUserPref(prefs::kPrivacySandboxNoConfirmationSandboxRestricted,
std::make_unique<base::Value>(true));
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/false,
/*block_third_party_cookies=*/false,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histogram_tester.ExpectUniqueSample(
kPrivacySandboxStartupHistogram,
PrivacySandboxService::PSStartupStates::kPromptOffRestricted, 1);
}
TEST_F(PrivacySandboxServiceTest, PrivacySandboxManagedEnabled) {
base::HistogramTester histogram_tester;
feature_list()->Reset();
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings3,
{{"consent-required", "false" /* consent required */}});
prefs()->SetUserPref(prefs::kPrivacySandboxNoConfirmationSandboxManaged,
std::make_unique<base::Value>(true));
prefs()->SetUserPref(prefs::kPrivacySandboxApisEnabledV2,
std::make_unique<base::Value>(true));
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/true,
/*block_third_party_cookies=*/false,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histogram_tester.ExpectUniqueSample(
kPrivacySandboxStartupHistogram,
PrivacySandboxService::PSStartupStates::kPromptOffManagedEnabled, 1);
}
TEST_F(PrivacySandboxServiceTest, PrivacySandboxManagedDisabled) {
base::HistogramTester histogram_tester;
feature_list()->Reset();
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings3,
{{"consent-required", "false" /* consent required */}});
prefs()->SetUserPref(prefs::kPrivacySandboxNoConfirmationSandboxManaged,
std::make_unique<base::Value>(true));
prefs()->SetUserPref(prefs::kPrivacySandboxApisEnabledV2,
std::make_unique<base::Value>(false));
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/false,
/*block_third_party_cookies=*/false,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histogram_tester.ExpectUniqueSample(
kPrivacySandboxStartupHistogram,
PrivacySandboxService::PSStartupStates::kPromptOffManagedDisabled, 1);
}
TEST_F(PrivacySandboxServiceTest, PrivacySandbox3PCOffEnabled) {
base::HistogramTester histogram_tester;
feature_list()->Reset();
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings3,
{{"consent-required", "false" /* consent required */}});
prefs()->SetUserPref(
prefs::kPrivacySandboxNoConfirmationThirdPartyCookiesBlocked,
std::make_unique<base::Value>(true));
prefs()->SetUserPref(prefs::kPrivacySandboxApisEnabledV2,
std::make_unique<base::Value>(true));
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/true,
/*block_third_party_cookies=*/true,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histogram_tester.ExpectUniqueSample(
kPrivacySandboxStartupHistogram,
PrivacySandboxService::PSStartupStates::kPromptOff3PCOffEnabled, 1);
}
TEST_F(PrivacySandboxServiceTest, PrivacySandbox3PCOffDisabled) {
base::HistogramTester histogram_tester;
feature_list()->Reset();
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings3,
{{"consent-required", "false" /* consent required */}});
prefs()->SetUserPref(
prefs::kPrivacySandboxNoConfirmationThirdPartyCookiesBlocked,
std::make_unique<base::Value>(true));
prefs()->SetUserPref(prefs::kPrivacySandboxApisEnabledV2,
std::make_unique<base::Value>(false));
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/false,
/*block_third_party_cookies=*/true,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histogram_tester.ExpectUniqueSample(
kPrivacySandboxStartupHistogram,
PrivacySandboxService::PSStartupStates::kPromptOff3PCOffDisabled, 1);
}
TEST_F(PrivacySandboxServiceTest, PrivacySandboxConsentEnabled) {
base::HistogramTester histogram_tester;
feature_list()->Reset();
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings3,
{{"consent-required", "true" /* consent required */}});
prefs()->SetUserPref(prefs::kPrivacySandboxNoConfirmationSandboxDisabled,
std::make_unique<base::Value>(false));
prefs()->SetUserPref(prefs::kPrivacySandboxConsentDecisionMade,
std::make_unique<base::Value>(true));
prefs()->SetUserPref(prefs::kPrivacySandboxApisEnabledV2,
std::make_unique<base::Value>(true));
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/true,
/*block_third_party_cookies=*/false,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histogram_tester.ExpectUniqueSample(
kPrivacySandboxStartupHistogram,
PrivacySandboxService::PSStartupStates::kConsentShownEnabled, 1);
}
TEST_F(PrivacySandboxServiceTest, PrivacySandboxConsentDisabled) {
base::HistogramTester histogram_tester;
feature_list()->Reset();
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings3,
{{"consent-required", "true" /* consent required */}});
prefs()->SetUserPref(prefs::kPrivacySandboxNoConfirmationSandboxDisabled,
std::make_unique<base::Value>(false));
prefs()->SetUserPref(prefs::kPrivacySandboxConsentDecisionMade,
std::make_unique<base::Value>(true));
prefs()->SetUserPref(prefs::kPrivacySandboxApisEnabledV2,
std::make_unique<base::Value>(false));
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/false,
/*block_third_party_cookies=*/false,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histogram_tester.ExpectUniqueSample(
kPrivacySandboxStartupHistogram,
PrivacySandboxService::PSStartupStates::kConsentShownDisabled, 1);
}
TEST_F(PrivacySandboxServiceTest, PrivacySandboxNoticeEnabled) {
base::HistogramTester histogram_tester;
feature_list()->Reset();
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings3,
{{"notice-required", "true" /* consent required */}});
prefs()->SetUserPref(prefs::kPrivacySandboxNoConfirmationSandboxDisabled,
std::make_unique<base::Value>(false));
prefs()->SetUserPref(prefs::kPrivacySandboxNoticeDisplayed,
std::make_unique<base::Value>(true));
prefs()->SetUserPref(prefs::kPrivacySandboxApisEnabledV2,
std::make_unique<base::Value>(true));
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/true,
/*block_third_party_cookies=*/false,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histogram_tester.ExpectUniqueSample(
kPrivacySandboxStartupHistogram,
PrivacySandboxService::PSStartupStates::kNoticeShownEnabled, 1);
}
TEST_F(PrivacySandboxServiceTest, PrivacySandboxNoticeDisabled) {
base::HistogramTester histogram_tester;
feature_list()->Reset();
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings3,
{{"notice-required", "true" /* consent required */}});
prefs()->SetUserPref(prefs::kPrivacySandboxNoConfirmationSandboxDisabled,
std::make_unique<base::Value>(false));
prefs()->SetUserPref(prefs::kPrivacySandboxNoticeDisplayed,
std::make_unique<base::Value>(true));
prefs()->SetUserPref(prefs::kPrivacySandboxApisEnabledV2,
std::make_unique<base::Value>(false));
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/false,
/*block_third_party_cookies=*/false,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histogram_tester.ExpectUniqueSample(
kPrivacySandboxStartupHistogram,
PrivacySandboxService::PSStartupStates::kNoticeShownDisabled, 1);
}
TEST_F(PrivacySandboxServiceTest, PrivacySandboxManuallyControlledEnabled) {
base::HistogramTester histogram_tester;
prefs()->SetUserPref(prefs::kPrivacySandboxApisEnabledV2,
std::make_unique<base::Value>(true));
prefs()->SetUserPref(prefs::kPrivacySandboxNoConfirmationManuallyControlled,
std::make_unique<base::Value>(true));
CreateService();
histogram_tester.ExpectUniqueSample(kPrivacySandboxStartupHistogram,
PrivacySandboxService::PSStartupStates::
kPromptOffManuallyControlledEnabled,
1);
}
TEST_F(PrivacySandboxServiceTest, PrivacySandboxManuallyControlledDisabled) {
base::HistogramTester histogram_tester;
prefs()->SetUserPref(prefs::kPrivacySandboxApisEnabledV2,
std::make_unique<base::Value>(false));
prefs()->SetUserPref(prefs::kPrivacySandboxNoConfirmationManuallyControlled,
std::make_unique<base::Value>(true));
CreateService();
histogram_tester.ExpectUniqueSample(kPrivacySandboxStartupHistogram,
PrivacySandboxService::PSStartupStates::
kPromptOffManuallyControlledDisabled,
1);
}
TEST_F(PrivacySandboxServiceTest, PrivacySandboxNoPromptDisabled) {
base::HistogramTester histogram_tester;
prefs()->SetUserPref(prefs::kPrivacySandboxApisEnabledV2,
std::make_unique<base::Value>(false));
CreateService();
histogram_tester.ExpectUniqueSample(
kPrivacySandboxStartupHistogram,
PrivacySandboxService::PSStartupStates::kNoPromptRequiredDisabled, 1);
}
TEST_F(PrivacySandboxServiceTest, PrivacySandboxNoPromptEnabled) {
base::HistogramTester histogram_tester;
prefs()->SetUserPref(prefs::kPrivacySandboxApisEnabledV2,
std::make_unique<base::Value>(true));
CreateService();
histogram_tester.ExpectUniqueSample(
kPrivacySandboxStartupHistogram,
PrivacySandboxService::PSStartupStates::kNoPromptRequiredEnabled, 1);
}
TEST_F(PrivacySandboxServiceTest, MetricsLoggingOccursCorrectly) {
base::HistogramTester histograms;
const std::string histogram_name = "Settings.PrivacySandbox.Enabled";
// The histogram should start off empty.
histograms.ExpectTotalCount(histogram_name, 0);
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/true,
/*block_third_party_cookies=*/false,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histograms.ExpectTotalCount(histogram_name, 1);
histograms.ExpectBucketCount(
histogram_name,
static_cast<int>(PrivacySandboxService::SettingsPrivacySandboxEnabled::
kPSEnabledAllowAll),
1);
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/true,
/*block_third_party_cookies=*/true,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histograms.ExpectTotalCount(histogram_name, 2);
histograms.ExpectBucketCount(
histogram_name,
static_cast<int>(PrivacySandboxService::SettingsPrivacySandboxEnabled::
kPSEnabledBlock3P),
1);
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/true,
/*block_third_party_cookies=*/true,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_BLOCK,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histograms.ExpectTotalCount(histogram_name, 3);
histograms.ExpectBucketCount(
histogram_name,
static_cast<int>(PrivacySandboxService::SettingsPrivacySandboxEnabled::
kPSEnabledBlockAll),
1);
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/false,
/*block_third_party_cookies=*/false,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histograms.ExpectTotalCount(histogram_name, 4);
histograms.ExpectBucketCount(
histogram_name,
static_cast<int>(PrivacySandboxService::SettingsPrivacySandboxEnabled::
kPSDisabledAllowAll),
1);
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/false,
/*block_third_party_cookies=*/true,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histograms.ExpectTotalCount(histogram_name, 5);
histograms.ExpectBucketCount(
histogram_name,
static_cast<int>(PrivacySandboxService::SettingsPrivacySandboxEnabled::
kPSDisabledBlock3P),
1);
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/false,
/*block_third_party_cookies=*/true,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_BLOCK,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
histograms.ExpectTotalCount(histogram_name, 6);
histograms.ExpectBucketCount(
histogram_name,
static_cast<int>(PrivacySandboxService::PrivacySandboxService::
SettingsPrivacySandboxEnabled::kPSDisabledBlockAll),
1);
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/false,
/*block_third_party_cookies=*/true,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_BLOCK,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/ContentSetting::CONTENT_SETTING_BLOCK,
/*managed_cookie_exceptions=*/{});
CreateService();
histograms.ExpectTotalCount(histogram_name, 7);
histograms.ExpectBucketCount(
histogram_name,
static_cast<int>(PrivacySandboxService::SettingsPrivacySandboxEnabled::
kPSDisabledPolicyBlockAll),
1);
}
TEST_F(PrivacySandboxServiceTest, SampleFpsData) {
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxFirstPartySetsUI,
{{"use-sample-sets", "true"}});
prefs()->SetUserPref(
prefs::kCookieControlsMode,
std::make_unique<base::Value>(static_cast<int>(
content_settings::CookieControlsMode::kBlockThirdParty)));
prefs()->SetBoolean(prefs::kPrivacySandboxFirstPartySetsEnabled, true);
EXPECT_EQ(u"google.com",
privacy_sandbox_service()->GetFirstPartySetOwnerForDisplay(
GURL("https://mail.google.com.au")));
EXPECT_EQ(u"google.com",
privacy_sandbox_service()->GetFirstPartySetOwnerForDisplay(
GURL("https://youtube.com")));
EXPECT_EQ(u"münchen.de",
privacy_sandbox_service()->GetFirstPartySetOwnerForDisplay(
GURL("https://muenchen.de")));
EXPECT_EQ(absl::nullopt,
privacy_sandbox_service()->GetFirstPartySetOwnerForDisplay(
GURL("https://example.com")));
}
TEST_F(PrivacySandboxServiceTest,
GetFirstPartySetOwner_SimulatedFpsData_DisabledWhen3pcAllowed) {
GURL associate1_gurl("https://associate1.test");
net::SchemefulSite primary_site(GURL("https://primary.test"));
net::SchemefulSite associate1_site(associate1_gurl);
// Create Global First-Party Sets with the following set:
// { primary: "https://primary.test",
// associatedSites: ["https://associate1.test"}
net::GlobalFirstPartySets global_sets(
kFirstPartySetsVersion,
{{associate1_site,
{net::FirstPartySetEntry(primary_site, net::SiteType::kAssociated,
0)}}},
{});
// Simulate 3PC are allowed while:
// - FPS pref is enabled
// - FPS backend Feature is enabled
// - FPS UI Feature is enabled
feature_list()->InitWithFeatures(
{privacy_sandbox::kPrivacySandboxFirstPartySetsUI,
features::kFirstPartySets},
{});
CreateService();
ClearFpsUserPrefs(prefs());
prefs()->SetUserPref(prefs::kCookieControlsMode,
std::make_unique<base::Value>(static_cast<int>(
content_settings::CookieControlsMode::kOff)));
prefs()->SetUserPref(prefs::kPrivacySandboxFirstPartySetsEnabled,
std::make_unique<base::Value>(true));
mock_first_party_sets_handler().SetGlobalSets(global_sets.Clone());
first_party_sets_policy_service()->InitForTesting();
// We shouldn't get associate1's owner since FPS is disabled.
EXPECT_EQ(privacy_sandbox_service()->GetFirstPartySetOwner(associate1_gurl),
absl::nullopt);
}
TEST_F(PrivacySandboxServiceTest,
GetFirstPartySetOwner_SimulatedFpsData_DisabledWhenAllCookiesBlocked) {
GURL associate1_gurl("https://associate1.test");
net::SchemefulSite primary_site(GURL("https://primary.test"));
net::SchemefulSite associate1_site(associate1_gurl);
// Create Global First-Party Sets with the following set:
// { primary: "https://primary.test",
// associatedSites: ["https://associate1.test"}
net::GlobalFirstPartySets global_sets(
kFirstPartySetsVersion,
{{associate1_site,
{net::FirstPartySetEntry(primary_site, net::SiteType::kAssociated,
0)}}},
{});
// Simulate all cookies are blocked while:
// - FPS pref is enabled
// - FPS backend Feature is enabled
// - FPS UI Feature is enabled
feature_list()->InitWithFeatures(
{privacy_sandbox::kPrivacySandboxFirstPartySetsUI,
features::kFirstPartySets},
{});
prefs()->SetUserPref(
prefs::kCookieControlsMode,
std::make_unique<base::Value>(static_cast<int>(
content_settings::CookieControlsMode::kBlockThirdParty)));
cookie_settings()->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
CreateService();
ClearFpsUserPrefs(prefs());
prefs()->SetUserPref(prefs::kPrivacySandboxFirstPartySetsEnabled,
std::make_unique<base::Value>(true));
mock_first_party_sets_handler().SetGlobalSets(global_sets.Clone());
first_party_sets_policy_service()->InitForTesting();
// We shouldn't get associate1's owner since FPS is disabled.
EXPECT_EQ(privacy_sandbox_service()->GetFirstPartySetOwner(associate1_gurl),
absl::nullopt);
}
TEST_F(PrivacySandboxServiceTest,
GetFirstPartySetOwner_SimulatedFpsData_DisabledByFpsUiFeature) {
GURL associate1_gurl("https://associate1.test");
net::SchemefulSite primary_site(GURL("https://primary.test"));
net::SchemefulSite associate1_site(associate1_gurl);
// Create Global First-Party Sets with the following set:
// { primary: "https://primary.test",
// associatedSites: ["https://associate1.test"}
net::GlobalFirstPartySets global_sets(
kFirstPartySetsVersion,
{{associate1_site,
{net::FirstPartySetEntry(primary_site, net::SiteType::kAssociated,
0)}}},
{});
// Simulate FPS UI feature disabled while:
// - FPS pref is enabled
// - FPS backend Feature is enabled
// - 3PC are being blocked
feature_list()->InitWithFeatures(
{features::kFirstPartySets},
{privacy_sandbox::kPrivacySandboxFirstPartySetsUI});
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/true,
/*block_third_party_cookies=*/true,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
ClearFpsUserPrefs(prefs());
prefs()->SetUserPref(prefs::kPrivacySandboxFirstPartySetsEnabled,
std::make_unique<base::Value>(true));
mock_first_party_sets_handler().SetGlobalSets(global_sets.Clone());
first_party_sets_policy_service()->InitForTesting();
// We shouldn't get associate1's owner since FPS is disabled.
EXPECT_EQ(privacy_sandbox_service()->GetFirstPartySetOwner(associate1_gurl),
absl::nullopt);
}
TEST_F(PrivacySandboxServiceTest,
GetFirstPartySetOwner_SimulatedFpsData_DisabledByFpsFeature) {
GURL associate1_gurl("https://associate1.test");
net::SchemefulSite primary_site(GURL("https://primary.test"));
net::SchemefulSite associate1_site(associate1_gurl);
// Create Global First-Party Sets with the following set:
// { primary: "https://primary.test",
// associatedSites: ["https://associate1.test"}
net::GlobalFirstPartySets global_sets(
kFirstPartySetsVersion,
{{associate1_site,
{net::FirstPartySetEntry(primary_site, net::SiteType::kAssociated,
0)}}},
{});
// Simulate FPS backend feature disabled while:
// - FPS pref is enabled
// - FPS UI Feature is enabled
// - 3PC are being blocked
feature_list()->InitWithFeatures(
{privacy_sandbox::kPrivacySandboxFirstPartySetsUI},
{features::kFirstPartySets});
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/true,
/*block_third_party_cookies=*/true,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
ClearFpsUserPrefs(prefs());
prefs()->SetUserPref(prefs::kPrivacySandboxFirstPartySetsEnabled,
std::make_unique<base::Value>(true));
mock_first_party_sets_handler().SetGlobalSets(global_sets.Clone());
first_party_sets_policy_service()->InitForTesting();
// We shouldn't get associate1's owner since FPS is disabled.
EXPECT_EQ(privacy_sandbox_service()->GetFirstPartySetOwner(associate1_gurl),
absl::nullopt);
}
TEST_F(PrivacySandboxServiceTest,
GetFirstPartySetOwner_SimulatedFpsData_DisabledByFpsPref) {
GURL associate1_gurl("https://associate1.test");
net::SchemefulSite primary_site(GURL("https://primary.test"));
net::SchemefulSite associate1_site(associate1_gurl);
// Create Global First-Party Sets with the following set:
// { primary: "https://primary.test",
// associatedSites: ["https://associate1.test"}
net::GlobalFirstPartySets global_sets(
kFirstPartySetsVersion,
{{associate1_site,
{net::FirstPartySetEntry(primary_site, net::SiteType::kAssociated,
0)}}},
{});
// Simulate FPS pref disabled while:
// - FPS UI Feature is enabled
// - FPS backend Feature is enabled
// - 3PC are being blocked
feature_list()->InitWithFeatures(
{features::kFirstPartySets,
privacy_sandbox::kPrivacySandboxFirstPartySetsUI},
{});
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/true,
/*block_third_party_cookies=*/true,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
ClearFpsUserPrefs(prefs());
prefs()->SetUserPref(prefs::kPrivacySandboxFirstPartySetsEnabled,
std::make_unique<base::Value>(false));
mock_first_party_sets_handler().SetGlobalSets(global_sets.Clone());
first_party_sets_policy_service()->InitForTesting();
// We shouldn't get associate1's owner since FPS is disabled.
EXPECT_EQ(privacy_sandbox_service()->GetFirstPartySetOwner(associate1_gurl),
absl::nullopt);
}
TEST_F(PrivacySandboxServiceTest,
SimulatedFpsData_FpsEnabled_WithoutGlobalSets) {
GURL primary_gurl("https://primary.test");
GURL associate1_gurl("https://associate1.test");
GURL associate2_gurl("https://associate2.test");
net::SchemefulSite primary_site(primary_gurl);
net::SchemefulSite associate1_site(associate1_gurl);
net::SchemefulSite associate2_site(associate2_gurl);
// Set up state that fully enables the First-Party Sets for UI; blocking 3PC,
// and enabling the FPS UI and backend features and the FPS enabled pref.
feature_list()->InitWithFeatures(
{features::kFirstPartySets,
privacy_sandbox::kPrivacySandboxFirstPartySetsUI},
{});
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/true,
/*block_third_party_cookies=*/true,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
ClearFpsUserPrefs(prefs());
prefs()->SetUserPref(prefs::kPrivacySandboxFirstPartySetsEnabled,
std::make_unique<base::Value>(true));
// Verify `GetFirstPartySetOwner` returns empty if FPS is enabled but the
// Global sets are not ready yet.
EXPECT_EQ(privacy_sandbox_service()->GetFirstPartySetOwner(associate1_gurl),
absl::nullopt);
EXPECT_EQ(privacy_sandbox_service()->GetFirstPartySetOwner(associate2_gurl),
absl::nullopt);
}
TEST_F(PrivacySandboxServiceTest,
SimulatedFpsData_FpsEnabled_WithGlobalSetsAndProfileSets) {
GURL primary_gurl("https://primary.test");
GURL associate1_gurl("https://associate1.test");
GURL associate2_gurl("https://associate2.test");
net::SchemefulSite primary_site(primary_gurl);
net::SchemefulSite associate1_site(associate1_gurl);
net::SchemefulSite associate2_site(associate2_gurl);
// Set up state that fully enables the First-Party Sets for UI; blocking 3PC,
// and enabling the FPS UI and backend features and the FPS enabled pref.
feature_list()->InitWithFeatures(
{features::kFirstPartySets,
privacy_sandbox::kPrivacySandboxFirstPartySetsUI},
{});
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/true,
/*block_third_party_cookies=*/true,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
ClearFpsUserPrefs(prefs());
prefs()->SetUserPref(prefs::kPrivacySandboxFirstPartySetsEnabled,
std::make_unique<base::Value>(true));
// Simulate that the Global First-Party Sets are ready with the following set:
// { primary: "https://primary.test",
// associatedSites: ["https://associate1.test", "https://associate2.test"] }
mock_first_party_sets_handler().SetGlobalSets(net::GlobalFirstPartySets(
kFirstPartySetsVersion,
{{associate1_site,
{net::FirstPartySetEntry(primary_site, net::SiteType::kAssociated, 0)}},
{associate2_site,
{net::FirstPartySetEntry(primary_site, net::SiteType::kAssociated,
1)}}},
{}));
// Simulate that associate2 is removed from the Global First-Party Sets for
// this profile.
mock_first_party_sets_handler().SetContextConfig(
net::FirstPartySetsContextConfig(
{{net::SchemefulSite(GURL("https://associate2.test")),
net::FirstPartySetEntryOverride()}}));
first_party_sets_policy_service()->InitForTesting();
// Verify that primary owns associate1, but no longer owns associate2.
EXPECT_EQ(
privacy_sandbox_service()->GetFirstPartySetOwner(associate1_gurl).value(),
primary_site);
EXPECT_EQ(privacy_sandbox_service()->GetFirstPartySetOwner(associate2_gurl),
absl::nullopt);
}
TEST_F(PrivacySandboxServiceTest, FpsPrefInit) {
// Check that the init of the FPS pref occurs correctly.
ClearFpsUserPrefs(prefs());
prefs()->SetUserPref(
prefs::kCookieControlsMode,
std::make_unique<base::Value>(static_cast<int>(
content_settings::CookieControlsMode::kBlockThirdParty)));
// Whilst the FPS UI is not available, the pref should not be init.
feature_list()->InitAndDisableFeature(
privacy_sandbox::kPrivacySandboxFirstPartySetsUI);
CreateService();
EXPECT_TRUE(prefs()->GetBoolean(prefs::kPrivacySandboxFirstPartySetsEnabled));
EXPECT_FALSE(prefs()->GetBoolean(
prefs::kPrivacySandboxFirstPartySetsDataAccessAllowedInitialized));
// If the UI is available, the user blocks 3PC, and the pref has not been
// previously init, it should be.
ClearFpsUserPrefs(prefs());
feature_list()->Reset();
feature_list()->InitAndEnableFeature(
privacy_sandbox::kPrivacySandboxFirstPartySetsUI);
CreateService();
EXPECT_FALSE(
prefs()->GetBoolean(prefs::kPrivacySandboxFirstPartySetsEnabled));
EXPECT_TRUE(prefs()->GetBoolean(
prefs::kPrivacySandboxFirstPartySetsDataAccessAllowedInitialized));
// Once the pref has been init, it should not be re-init, and updated user
// cookie settings should not impact it.
ClearFpsUserPrefs(prefs());
prefs()->SetUserPref(prefs::kCookieControlsMode,
std::make_unique<base::Value>(static_cast<int>(
content_settings::CookieControlsMode::kOff)));
CreateService();
EXPECT_TRUE(prefs()->GetBoolean(prefs::kPrivacySandboxFirstPartySetsEnabled));
EXPECT_TRUE(prefs()->GetBoolean(
prefs::kPrivacySandboxFirstPartySetsDataAccessAllowedInitialized));
prefs()->SetUserPref(
prefs::kCookieControlsMode,
std::make_unique<base::Value>(static_cast<int>(
content_settings::CookieControlsMode::kBlockThirdParty)));
CreateService();
EXPECT_TRUE(prefs()->GetBoolean(prefs::kPrivacySandboxFirstPartySetsEnabled));
EXPECT_TRUE(prefs()->GetBoolean(
prefs::kPrivacySandboxFirstPartySetsDataAccessAllowedInitialized));
// Blocking all cookies should also init the FPS pref to off.
ClearFpsUserPrefs(prefs());
prefs()->SetUserPref(prefs::kCookieControlsMode,
std::make_unique<base::Value>(static_cast<int>(
content_settings::CookieControlsMode::kOff)));
cookie_settings()->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
CreateService();
EXPECT_FALSE(
prefs()->GetBoolean(prefs::kPrivacySandboxFirstPartySetsEnabled));
EXPECT_TRUE(prefs()->GetBoolean(
prefs::kPrivacySandboxFirstPartySetsDataAccessAllowedInitialized));
}
TEST_F(PrivacySandboxServiceTest, UsesFpsSampleSetsWhenProvided) {
// Confirm that when the FPS sample sets are provided, they are used to answer
// First-Party Sets queries instead of the actual sets.
// Set up state that fully enables the First-Party Sets for UI; blocking
// 3PC, and enabling the FPS UI and backend features and the FPS enabled pref.
//
// Note: this indicates that the sample sets should be used.
feature_list()->InitWithFeaturesAndParameters(
/*enabled_features=*/{{features::kFirstPartySets, {}},
{privacy_sandbox::kPrivacySandboxFirstPartySetsUI,
{{"use-sample-sets", "true"}}}},
/*disabled_features=*/{});
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/true,
/*block_third_party_cookies=*/true,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
ClearFpsUserPrefs(prefs());
prefs()->SetUserPref(prefs::kPrivacySandboxFirstPartySetsEnabled,
std::make_unique<base::Value>(true));
// Simulate that the Global First-Party Sets are ready with the following
// set:
// { primary: "https://youtube-primary.test",
// associatedSites: ["https://youtube.com"]
// }
net::SchemefulSite youtube_primary_site(GURL("https://youtube-primary.test"));
GURL youtube_gurl("https://youtube.com");
net::SchemefulSite youtube_site(youtube_gurl);
mock_first_party_sets_handler().SetGlobalSets(net::GlobalFirstPartySets(
kFirstPartySetsVersion,
{{youtube_site,
{net::FirstPartySetEntry(youtube_primary_site,
net::SiteType::kAssociated, 0)}}},
{}));
// Simulate that https://google.de is moved into a new First-Party Set for
// this profile.
mock_first_party_sets_handler().SetContextConfig(
net::FirstPartySetsContextConfig(
{{net::SchemefulSite(GURL("https://google.de")),
net::FirstPartySetEntryOverride(net::FirstPartySetEntry(
net::SchemefulSite(GURL("https://new-primary.test")),
net::SiteType::kAssociated, 0))}}));
first_party_sets_policy_service()->InitForTesting();
// Expect queries to be resolved based on the FPS sample sets.
EXPECT_GT(privacy_sandbox_service()->GetSampleFirstPartySets().size(), 0u);
EXPECT_EQ(privacy_sandbox_service()->GetFirstPartySetOwner(
GURL("https://youtube.com")),
net::SchemefulSite(GURL("https://google.com")));
EXPECT_TRUE(privacy_sandbox_service()->IsPartOfManagedFirstPartySet(
net::SchemefulSite(GURL("https://googlesource.com"))));
EXPECT_FALSE(privacy_sandbox_service()->IsPartOfManagedFirstPartySet(
net::SchemefulSite(GURL("https://google.de"))));
feature_list()->Reset();
feature_list()->InitWithFeatures(
{features::kFirstPartySets,
privacy_sandbox::kPrivacySandboxFirstPartySetsUI},
{});
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/true,
/*block_third_party_cookies=*/true,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
ClearFpsUserPrefs(prefs());
prefs()->SetUserPref(prefs::kPrivacySandboxFirstPartySetsEnabled,
std::make_unique<base::Value>(true));
// Expect queries to be resolved based on the FPS backend.
EXPECT_EQ(privacy_sandbox_service()->GetSampleFirstPartySets().size(), 0u);
EXPECT_EQ(privacy_sandbox_service()->GetFirstPartySetOwner(youtube_gurl),
youtube_primary_site);
EXPECT_FALSE(privacy_sandbox_service()->IsPartOfManagedFirstPartySet(
net::SchemefulSite(GURL("https://googlesource.com"))));
EXPECT_TRUE(privacy_sandbox_service()->IsPartOfManagedFirstPartySet(
net::SchemefulSite(GURL("https://google.de"))));
}
TEST_F(PrivacySandboxServiceTest, AntiAbuseContentSettingInit) {
// Check that the init of the Anti-abuse pref occurs correctly.
ResetAntiAbuseSettings(prefs(), host_content_settings_map());
prefs()->SetUserPref(
prefs::kCookieControlsMode,
std::make_unique<base::Value>(static_cast<int>(
content_settings::CookieControlsMode::kBlockThirdParty)));
// If the user blocks 3PC, and the pref has not been previously init, it
// should be.
ResetAntiAbuseSettings(prefs(), host_content_settings_map());
CreateService();
EXPECT_EQ(host_content_settings_map()->GetDefaultContentSetting(
ContentSettingsType::ANTI_ABUSE, nullptr),
CONTENT_SETTING_BLOCK);
EXPECT_TRUE(prefs()->GetBoolean(prefs::kPrivacySandboxAntiAbuseInitialized));
// Once the setting has been init, it should not be re-init, and updated user
// cookie settings should not impact it.
ResetAntiAbuseSettings(prefs(), host_content_settings_map());
prefs()->SetUserPref(prefs::kCookieControlsMode,
std::make_unique<base::Value>(static_cast<int>(
content_settings::CookieControlsMode::kOff)));
CreateService();
EXPECT_EQ(host_content_settings_map()->GetDefaultContentSetting(
ContentSettingsType::ANTI_ABUSE, nullptr),
CONTENT_SETTING_ALLOW);
EXPECT_TRUE(prefs()->GetBoolean(prefs::kPrivacySandboxAntiAbuseInitialized));
prefs()->SetUserPref(
prefs::kCookieControlsMode,
std::make_unique<base::Value>(static_cast<int>(
content_settings::CookieControlsMode::kBlockThirdParty)));
CreateService();
EXPECT_EQ(host_content_settings_map()->GetDefaultContentSetting(
ContentSettingsType::ANTI_ABUSE, nullptr),
CONTENT_SETTING_ALLOW);
EXPECT_TRUE(prefs()->GetBoolean(prefs::kPrivacySandboxAntiAbuseInitialized));
// Blocking all cookies should also init the Anti-abuse setting to blocked.
ResetAntiAbuseSettings(prefs(), host_content_settings_map());
prefs()->SetUserPref(prefs::kCookieControlsMode,
std::make_unique<base::Value>(static_cast<int>(
content_settings::CookieControlsMode::kOff)));
cookie_settings()->SetDefaultCookieSetting(CONTENT_SETTING_BLOCK);
CreateService();
EXPECT_EQ(host_content_settings_map()->GetDefaultContentSetting(
ContentSettingsType::ANTI_ABUSE, nullptr),
CONTENT_SETTING_BLOCK);
EXPECT_TRUE(prefs()->GetBoolean(prefs::kPrivacySandboxAntiAbuseInitialized));
}
class PrivacySandboxServiceTestNonRegularProfile
: public PrivacySandboxServiceTest {
profile_metrics::BrowserProfileType GetProfileType() override {
return profile_metrics::BrowserProfileType::kSystem;
}
};
TEST_F(PrivacySandboxServiceTestNonRegularProfile, NoMetricsRecorded) {
// Check that non-regular profiles do not record metrics.
base::HistogramTester histograms;
const std::string histogram_name = "Settings.PrivacySandbox.Enabled";
privacy_sandbox_test_util::SetupTestState(
prefs(), host_content_settings_map(),
/*privacy_sandbox_enabled=*/true,
/*block_third_party_cookies=*/false,
/*default_cookie_setting=*/ContentSetting::CONTENT_SETTING_ALLOW,
/*user_cookie_exceptions=*/{},
/*managed_cookie_setting=*/privacy_sandbox_test_util::kNoSetting,
/*managed_cookie_exceptions=*/{});
CreateService();
// The histogram should remain empty.
histograms.ExpectTotalCount(histogram_name, 0);
}
TEST_F(PrivacySandboxServiceTestNonRegularProfile, NoPromptRequired) {
CreateService();
// Non-regular profiles should never have a prompt shown.
SetupPromptTestState(feature_list(), prefs(),
{/*consent_required=*/true,
/*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false,
/*consent_decision_made=*/false,
/*confirmation_not_shown=*/false});
EXPECT_EQ(PrivacySandboxService::PromptType::kNone,
privacy_sandbox_service()->GetRequiredPromptType());
SetupPromptTestState(feature_list(), prefs(),
{/*consent_required=*/false,
/*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false,
/*consent_decision_made=*/false,
/*confirmation_not_shown=*/false});
EXPECT_EQ(PrivacySandboxService::PromptType::kNone,
privacy_sandbox_service()->GetRequiredPromptType());
}
class PrivacySandboxServicePromptTestBase {
public:
PrivacySandboxServicePromptTestBase() {
privacy_sandbox::RegisterProfilePrefs(prefs()->registry());
}
#if BUILDFLAG(IS_CHROMEOS_ASH)
void SetUp() {
user_manager_ = std::make_unique<ash::FakeChromeUserManager>();
user_manager_->Initialize();
}
void TearDown() {
// Clean up user manager.
user_manager_->Shutdown();
user_manager_->Destroy();
user_manager_.reset();
}
#endif
protected:
base::test::ScopedFeatureList* feature_list() { return &feature_list_; }
sync_preferences::TestingPrefServiceSyncable* prefs() {
return &pref_service_;
}
privacy_sandbox_test_util::MockPrivacySandboxSettings*
privacy_sandbox_settings() {
return &privacy_sandbox_settings_;
}
private:
base::test::ScopedFeatureList feature_list_;
#if BUILDFLAG(IS_CHROMEOS_ASH)
std::unique_ptr<ash::FakeChromeUserManager> user_manager_;
#endif
sync_preferences::TestingPrefServiceSyncable pref_service_;
privacy_sandbox_test_util::MockPrivacySandboxSettings
privacy_sandbox_settings_;
};
class PrivacySandboxServicePromptTest
: public PrivacySandboxServicePromptTestBase,
public testing::Test {
#if BUILDFLAG(IS_CHROMEOS_ASH)
public:
void SetUp() override { PrivacySandboxServicePromptTestBase::SetUp(); }
void TearDown() override { PrivacySandboxServicePromptTestBase::TearDown(); }
#endif
};
TEST_F(PrivacySandboxServicePromptTest, RestrictedPrompt) {
// Confirm that when the Privacy Sandbox is restricted, that no prompt is
// shown.
SetupPromptTestState(feature_list(), prefs(),
{/*consent_required=*/true,
/*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false,
/*consent_decision_made=*/false,
/*confirmation_not_shown=*/false});
EXPECT_CALL(*privacy_sandbox_settings(), IsPrivacySandboxRestricted())
.Times(1)
.WillOnce(testing::Return(true));
EXPECT_EQ(
PrivacySandboxService::PromptType::kNone,
PrivacySandboxService::GetRequiredPromptTypeInternal(
prefs(), profile_metrics::BrowserProfileType::kRegular,
privacy_sandbox_settings(), /*third_party_cookies_blocked=*/false));
// After being restricted, even if the restriction is removed, no prompt
// should be shown. No call should even need to be made to see if the
// sandbox is still restricted.
EXPECT_CALL(*privacy_sandbox_settings(), IsPrivacySandboxRestricted())
.Times(0);
EXPECT_EQ(
PrivacySandboxService::PromptType::kNone,
PrivacySandboxService::GetRequiredPromptTypeInternal(
prefs(), profile_metrics::BrowserProfileType::kRegular,
privacy_sandbox_settings(), /*third_party_cookies_blocked=*/false));
}
TEST_F(PrivacySandboxServicePromptTest, ManagedNoPrompt) {
// Confirm that when the Privacy Sandbox is managed, that no prompt is
// shown.
SetupPromptTestState(feature_list(), prefs(),
{/*consent_required=*/true,
/*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false,
/*consent_decision_made=*/false,
/*confirmation_not_shown=*/false});
prefs()->SetManagedPref(prefs::kPrivacySandboxApisEnabledV2,
base::Value(true));
EXPECT_EQ(
PrivacySandboxService::PromptType::kNone,
PrivacySandboxService::GetRequiredPromptTypeInternal(
prefs(), profile_metrics::BrowserProfileType::kRegular,
privacy_sandbox_settings(), /*third_party_cookies_blocked=*/false));
// This should persist even if the preference becomes unmanaged.
prefs()->RemoveManagedPref(prefs::kPrivacySandboxApisEnabledV2);
EXPECT_EQ(
PrivacySandboxService::PromptType::kNone,
PrivacySandboxService::GetRequiredPromptTypeInternal(
prefs(), profile_metrics::BrowserProfileType::kRegular,
privacy_sandbox_settings(), /*third_party_cookies_blocked=*/false));
}
TEST_F(PrivacySandboxServicePromptTest, ManuallyControlledNoPrompt) {
// Confirm that if the Privacy Sandbox V2 is manually controlled by the user,
// that no prompt is shown.
SetupPromptTestState(feature_list(), prefs(),
{/*consent_required=*/true,
/*old_api_pref=*/true,
/*new_api_pref=*/false,
/*notice_displayed=*/false,
/*consent_decision_made=*/false,
/*confirmation_not_shown=*/false});
prefs()->SetUserPref(prefs::kPrivacySandboxManuallyControlledV2,
base::Value(true));
EXPECT_EQ(
PrivacySandboxService::PromptType::kNone,
PrivacySandboxService::GetRequiredPromptTypeInternal(
prefs(), profile_metrics::BrowserProfileType::kRegular,
privacy_sandbox_settings(), /*third_party_cookies_blocked=*/false));
}
TEST_F(PrivacySandboxServicePromptTest, NoParamNoPrompt) {
// Confirm that if neither the consent or notice parameter is set, no prompt
// is required.
EXPECT_EQ(
PrivacySandboxService::PromptType::kNone,
PrivacySandboxService::GetRequiredPromptTypeInternal(
prefs(), profile_metrics::BrowserProfileType::kRegular,
privacy_sandbox_settings(), /*third_party_cookies_blocked=*/false));
}
class PrivacySandboxServiceDeathTest
: public PrivacySandboxServicePromptTestBase,
public testing::TestWithParam<int> {
#if BUILDFLAG(IS_CHROMEOS_ASH)
public:
void SetUp() override { PrivacySandboxServicePromptTestBase::SetUp(); }
void TearDown() override { PrivacySandboxServicePromptTestBase::TearDown(); }
#endif
};
TEST_P(PrivacySandboxServiceDeathTest, GetRequiredPromptType) {
const auto& test_case = kPromptTestCases[GetParam()];
privacy_sandbox_settings()->SetUpDefaultResponse();
testing::Message scope_message;
scope_message << "consent_required:" << test_case.test_setup.consent_required
<< " old_api_pref:" << test_case.test_setup.old_api_pref
<< " new_api_pref:" << test_case.test_setup.new_api_pref
<< " notice_displayed:" << test_case.test_setup.notice_displayed
<< " consent_decision_made:"
<< test_case.test_setup.consent_decision_made
<< " confirmation_not_shown:"
<< test_case.test_setup.confirmation_not_shown;
SCOPED_TRACE(scope_message);
SetupPromptTestState(feature_list(), prefs(), test_case.test_setup);
if (test_case.expected_output.dcheck_failure) {
EXPECT_DCHECK_DEATH(
PrivacySandboxService::GetRequiredPromptTypeInternal(
prefs(), profile_metrics::BrowserProfileType::kRegular,
privacy_sandbox_settings(), /*third_party_cookies_blocked=*/false);
);
return;
}
// Returned prompt type should never change between successive calls.
EXPECT_EQ(
test_case.expected_output.prompt_type,
PrivacySandboxService::GetRequiredPromptTypeInternal(
prefs(), profile_metrics::BrowserProfileType::kRegular,
privacy_sandbox_settings(), /*third_party_cookies_blocked=*/false));
EXPECT_EQ(
test_case.expected_output.prompt_type,
PrivacySandboxService::GetRequiredPromptTypeInternal(
prefs(), profile_metrics::BrowserProfileType::kRegular,
privacy_sandbox_settings(), /*third_party_cookies_blocked=*/false));
EXPECT_EQ(test_case.expected_output.new_api_pref,
prefs()->GetBoolean(prefs::kPrivacySandboxApisEnabledV2));
// The old Privacy Sandbox pref should never change from the initial test
// state.
EXPECT_EQ(test_case.test_setup.old_api_pref,
prefs()->GetBoolean(prefs::kPrivacySandboxApisEnabled));
}
INSTANTIATE_TEST_SUITE_P(PrivacySandboxServiceDeathTestInstance,
PrivacySandboxServiceDeathTest,
testing::Range(0, 64));
using PrivacySandboxServiceTestCoverageTest = testing::Test;
TEST_F(PrivacySandboxServiceTestCoverageTest, PromptTestCoverage) {
// Confirm that the set of prompt test cases exhaustively covers all possible
// combinations of input.
std::set<int> test_case_properties;
for (const auto& test_case : kPromptTestCases) {
int test_case_property = 0;
test_case_property |= test_case.test_setup.consent_required ? 1 << 0 : 0;
test_case_property |= test_case.test_setup.old_api_pref ? 1 << 1 : 0;
test_case_property |= test_case.test_setup.new_api_pref ? 1 << 2 : 0;
test_case_property |= test_case.test_setup.notice_displayed ? 1 << 3 : 0;
test_case_property |=
test_case.test_setup.consent_decision_made ? 1 << 4 : 0;
test_case_property |=
test_case.test_setup.confirmation_not_shown ? 1 << 5 : 0;
test_case_properties.insert(test_case_property);
}
EXPECT_EQ(test_case_properties.size(), kPromptTestCases.size());
EXPECT_EQ(64u, test_case_properties.size());
}
class PrivacySandboxServiceM1Test : public PrivacySandboxServiceTest {
public:
void InitializeFeaturesBeforeStart() override {
feature_list()->InitAndEnableFeature(
privacy_sandbox::kPrivacySandboxSettings4);
}
protected:
void RunTestCase(const TestState& test_state,
const TestInput& test_input,
const TestOutput& test_output) {
auto user_provider = std::make_unique<content_settings::MockProvider>();
auto* user_provider_raw = user_provider.get();
auto managed_provider = std::make_unique<content_settings::MockProvider>();
auto* managed_provider_raw = managed_provider.get();
content_settings::TestUtils::OverrideProvider(
host_content_settings_map(), std::move(user_provider),
HostContentSettingsMap::PREF_PROVIDER);
content_settings::TestUtils::OverrideProvider(
host_content_settings_map(), std::move(managed_provider),
HostContentSettingsMap::POLICY_PROVIDER);
auto service_wrapper = TestPrivacySandboxService(privacy_sandbox_service());
privacy_sandbox_test_util::RunTestCase(
browser_task_environment(), prefs(), host_content_settings_map(),
mock_delegate(), mock_browsing_topics_service(),
privacy_sandbox_settings(), &service_wrapper, user_provider_raw,
managed_provider_raw, TestCase(test_state, test_input, test_output));
}
void DisablePrivacySandboxPromptEnabledPolicy() {
prefs()->SetManagedPref(
prefs::kPrivacySandboxM1PromptSuppressed,
base::Value(static_cast<int>(
PrivacySandboxService::PromptSuppressedReason::kPolicy)));
}
};
TEST_F(PrivacySandboxServiceM1Test, TopicsConsentDefault) {
RunTestCase(
TestState{}, TestInput{},
TestOutput{{kTopicsConsentGiven, false},
{kTopicsConsentLastUpdateReason,
privacy_sandbox::TopicsConsentUpdateSource::kDefaultValue},
{kTopicsConsentLastUpdateTime, base::Time()},
{kTopicsConsentStringIdentifiers, std::vector<int>()}});
}
TEST_F(PrivacySandboxServiceM1Test, TopicsConsentSettings_EnableWithBlocked) {
// Note that when testing for enabling topics, there can never have been
// current topics in prod code.
RunTestCase(
TestState{{kActiveTopicsConsent, false},
{kHasCurrentTopics, false},
{kHasBlockedTopics, true},
{kAdvanceClockBy, base::Hours(1)}},
TestInput{
{kTopicsToggleNewValue, true},
},
TestOutput{
{kTopicsConsentGiven, true},
{kTopicsConsentLastUpdateReason,
privacy_sandbox::TopicsConsentUpdateSource::kSettings},
{kTopicsConsentLastUpdateTime, base::Time::Now() + base::Hours(1)},
{kTopicsConsentStringIdentifiers,
GetTopicsSettingsStringIdentifiers(/*did_consent=*/true,
/*has_current_topics=*/false,
/*has_blocked_topics=*/true)},
});
}
TEST_F(PrivacySandboxServiceM1Test, TopicsConsentSettings_EnableNoBlocked) {
RunTestCase(
TestState{{kActiveTopicsConsent, false},
{kHasCurrentTopics, false},
{kHasBlockedTopics, false},
{kAdvanceClockBy, base::Hours(1)}},
TestInput{
{kTopicsToggleNewValue, true},
},
TestOutput{
{kTopicsConsentGiven, true},
{kTopicsConsentLastUpdateReason,
privacy_sandbox::TopicsConsentUpdateSource::kSettings},
{kTopicsConsentLastUpdateTime, base::Time::Now() + base::Hours(1)},
{kTopicsConsentStringIdentifiers,
GetTopicsSettingsStringIdentifiers(/*did_consent=*/true,
/*has_current_topics=*/false,
/*has_blocked_topics=*/false)},
});
}
TEST_F(PrivacySandboxServiceM1Test,
TopicsConsentSettings_DisableCurrentAndBlocked) {
RunTestCase(
TestState{{kActiveTopicsConsent, true},
{kHasCurrentTopics, true},
{kHasBlockedTopics, true},
{kAdvanceClockBy, base::Hours(1)}},
TestInput{
{kTopicsToggleNewValue, false},
},
TestOutput{
{kTopicsConsentGiven, false},
{kTopicsConsentLastUpdateReason,
privacy_sandbox::TopicsConsentUpdateSource::kSettings},
{kTopicsConsentLastUpdateTime, base::Time::Now() + base::Hours(1)},
{kTopicsConsentStringIdentifiers,
GetTopicsSettingsStringIdentifiers(/*did_consent=*/false,
/*has_current_topics=*/true,
/*has_blocked_topics=*/true)},
});
}
TEST_F(PrivacySandboxServiceM1Test, TopicsConsentSettings_DisableBlockedOnly) {
RunTestCase(
TestState{{kActiveTopicsConsent, true},
{kHasCurrentTopics, false},
{kHasBlockedTopics, true},
{kAdvanceClockBy, base::Hours(1)}},
TestInput{
{kTopicsToggleNewValue, false},
},
TestOutput{
{kTopicsConsentGiven, false},
{kTopicsConsentLastUpdateReason,
privacy_sandbox::TopicsConsentUpdateSource::kSettings},
{kTopicsConsentLastUpdateTime, base::Time::Now() + base::Hours(1)},
{kTopicsConsentStringIdentifiers,
GetTopicsSettingsStringIdentifiers(/*did_consent=*/false,
/*has_current_topics=*/false,
/*has_blocked_topics=*/true)},
});
}
TEST_F(PrivacySandboxServiceM1Test, TopicsConsentSettings_DisableCurrentOnly) {
RunTestCase(
TestState{{kActiveTopicsConsent, true},
{kHasCurrentTopics, true},
{kHasBlockedTopics, false},
{kAdvanceClockBy, base::Hours(1)}},
TestInput{
{kTopicsToggleNewValue, false},
},
TestOutput{
{kTopicsConsentGiven, false},
{kTopicsConsentLastUpdateReason,
privacy_sandbox::TopicsConsentUpdateSource::kSettings},
{kTopicsConsentLastUpdateTime, base::Time::Now() + base::Hours(1)},
{kTopicsConsentStringIdentifiers,
GetTopicsSettingsStringIdentifiers(/*did_consent=*/false,
/*has_current_topics=*/true,
/*has_blocked_topics=*/false)},
});
}
TEST_F(PrivacySandboxServiceM1Test,
TopicsConsentSettings_DisableNoCurrentNoBlocked) {
RunTestCase(
TestState{{kActiveTopicsConsent, true},
{kHasCurrentTopics, false},
{kHasBlockedTopics, false},
{kAdvanceClockBy, base::Hours(1)}},
TestInput{
{kTopicsToggleNewValue, false},
},
TestOutput{
{kTopicsConsentGiven, false},
{kTopicsConsentLastUpdateReason,
privacy_sandbox::TopicsConsentUpdateSource::kSettings},
{kTopicsConsentLastUpdateTime, base::Time::Now() + base::Hours(1)},
{kTopicsConsentStringIdentifiers,
GetTopicsSettingsStringIdentifiers(/*did_consent=*/false,
/*has_current_topics=*/false,
/*has_blocked_topics=*/false)},
});
}
TEST_F(PrivacySandboxServiceM1Test,
RecordPrivacySandbox4StartupMetrics_PromptSuppressed_Explicitly) {
base::HistogramTester histogram_tester;
const std::string privacy_sandbox_prompt_startup_histogram =
"Settings.PrivacySandbox.PromptStartupState";
prefs()->SetInteger(
prefs::kPrivacySandboxM1PromptSuppressed,
static_cast<int>(
PrivacySandboxService::PromptSuppressedReason::kRestricted));
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
privacy_sandbox_prompt_startup_histogram,
static_cast<int>(PrivacySandboxService::PromptStartupState::
kPromptNotShownDueToPrivacySandboxRestricted),
/*expected_count=*/1);
prefs()->SetInteger(
prefs::kPrivacySandboxM1PromptSuppressed,
static_cast<int>(PrivacySandboxService::PromptSuppressedReason::
kThirdPartyCookiesBlocked));
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
privacy_sandbox_prompt_startup_histogram,
static_cast<int>(PrivacySandboxService::PromptStartupState::
kPromptNotShownDueTo3PCBlocked),
/*expected_count=*/1);
prefs()->SetInteger(
prefs::kPrivacySandboxM1PromptSuppressed,
static_cast<int>(PrivacySandboxService::PromptSuppressedReason::
kTrialsConsentDeclined));
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
privacy_sandbox_prompt_startup_histogram,
static_cast<int>(PrivacySandboxService::PromptStartupState::
kPromptNotShownDueToTrialConsentDeclined),
/*expected_count=*/1);
prefs()->SetInteger(
prefs::kPrivacySandboxM1PromptSuppressed,
static_cast<int>(PrivacySandboxService::PromptSuppressedReason::
kTrialsDisabledAfterNotice));
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
privacy_sandbox_prompt_startup_histogram,
static_cast<int>(PrivacySandboxService::PromptStartupState::
kPromptNotShownDueToTrialsDisabledAfterNoticeShown),
/*expected_count=*/1);
prefs()->SetInteger(
prefs::kPrivacySandboxM1PromptSuppressed,
static_cast<int>(PrivacySandboxService::PromptSuppressedReason::kPolicy));
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
privacy_sandbox_prompt_startup_histogram,
static_cast<int>(PrivacySandboxService::PromptStartupState::
kPromptNotShownDueToManagedState),
/*expected_count=*/1);
prefs()->SetInteger(
prefs::kPrivacySandboxM1PromptSuppressed,
static_cast<int>(PrivacySandboxService::PromptSuppressedReason::
kNoticeShownToGuardian));
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
privacy_sandbox_prompt_startup_histogram,
static_cast<int>(PrivacySandboxService::PromptStartupState::
kRestrictedNoticeNotShownDueToNoticeShownToGuardian),
/*expected_count=*/1);
}
TEST_F(PrivacySandboxServiceM1Test,
RecordPrivacySandbox4StartupMetrics_PromptSuppressed_Implicitly) {
base::HistogramTester histogram_tester;
const std::string privacy_sandbox_prompt_startup_histogram =
"Settings.PrivacySandbox.PromptStartupState";
// Ensure prompt not suppressed.
prefs()->SetInteger(
prefs::kPrivacySandboxM1PromptSuppressed,
static_cast<int>(PrivacySandboxService::PromptSuppressedReason::kNone));
// Disable one of the K-APIs.
prefs()->SetManagedPref(prefs::kPrivacySandboxM1TopicsEnabled,
base::Value(false));
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
privacy_sandbox_prompt_startup_histogram,
static_cast<int>(PrivacySandboxService::PromptStartupState::
kPromptNotShownDueToManagedState),
/*expected_count=*/1);
}
TEST_F(PrivacySandboxServiceM1Test,
RecordPrivacySandbox4StartupMetrics_PromptNotSuppressed_EEA) {
base::HistogramTester histogram_tester;
const std::string privacy_sandbox_prompt_startup_histogram =
"Settings.PrivacySandbox.PromptStartupState";
// Ensure prompt not suppressed.
prefs()->SetInteger(
prefs::kPrivacySandboxM1PromptSuppressed,
static_cast<int>(PrivacySandboxService::PromptSuppressedReason::kNone));
base::test::ScopedFeatureList feature_list_consent_required;
std::map<std::string, std::string> consent_required_feature_param = {
{std::string(
privacy_sandbox::kPrivacySandboxSettings4ConsentRequiredName),
"true"},
{std::string(privacy_sandbox::kPrivacySandboxSettings4NoticeRequiredName),
"false"}};
feature_list_consent_required.InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings4,
consent_required_feature_param);
// Not consented
prefs()->SetBoolean(prefs::kPrivacySandboxM1ConsentDecisionMade, false);
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
privacy_sandbox_prompt_startup_histogram,
static_cast<int>(
PrivacySandboxService::PromptStartupState::kEEAConsentPromptWaiting),
/*expected_count=*/1);
// Consent decision made and notice acknowledged.
prefs()->SetBoolean(prefs::kPrivacySandboxM1ConsentDecisionMade, true);
prefs()->SetBoolean(prefs::kPrivacySandboxM1EEANoticeAcknowledged, true);
// With topics enabled.
prefs()->SetBoolean(prefs::kPrivacySandboxM1TopicsEnabled, true);
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
privacy_sandbox_prompt_startup_histogram,
static_cast<int>(PrivacySandboxService::PromptStartupState::
kEEAFlowCompletedWithTopicsAccepted),
/*expected_count=*/1);
// With topics disabled.
prefs()->SetBoolean(prefs::kPrivacySandboxM1TopicsEnabled, false);
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
privacy_sandbox_prompt_startup_histogram,
static_cast<int>(PrivacySandboxService::PromptStartupState::
kEEAFlowCompletedWithTopicsDeclined),
/*expected_count=*/1);
// Consent decision made but notice was not acknowledged.
prefs()->SetBoolean(prefs::kPrivacySandboxM1EEANoticeAcknowledged, false);
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
privacy_sandbox_prompt_startup_histogram,
static_cast<int>(
PrivacySandboxService::PromptStartupState::kEEANoticePromptWaiting),
/*expected_count=*/1);
}
TEST_F(PrivacySandboxServiceM1Test,
RecordPrivacySandbox4StartupMetrics_PromptNotSuppressed_ROW) {
base::HistogramTester histogram_tester;
const std::string privacy_sandbox_prompt_startup_histogram =
"Settings.PrivacySandbox.PromptStartupState";
// Ensure prompt not suppressed.
prefs()->SetInteger(
prefs::kPrivacySandboxM1PromptSuppressed,
static_cast<int>(PrivacySandboxService::PromptSuppressedReason::kNone));
base::test::ScopedFeatureList feature_list_notice_required;
std::map<std::string, std::string> notice_required_feature_param = {
{std::string(
privacy_sandbox::kPrivacySandboxSettings4ConsentRequiredName),
"false"},
{std::string(privacy_sandbox::kPrivacySandboxSettings4NoticeRequiredName),
"true"}};
feature_list_notice_required.InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings4, notice_required_feature_param);
// Notice flow not completed.
prefs()->SetBoolean(prefs::kPrivacySandboxM1RowNoticeAcknowledged, false);
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
privacy_sandbox_prompt_startup_histogram,
static_cast<int>(
PrivacySandboxService::PromptStartupState::kROWNoticePromptWaiting),
/*expected_count=*/1);
// Notice flow completed.
prefs()->SetBoolean(prefs::kPrivacySandboxM1RowNoticeAcknowledged, true);
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
privacy_sandbox_prompt_startup_histogram,
static_cast<int>(
PrivacySandboxService::PromptStartupState::kROWNoticeFlowCompleted),
/*expected_count=*/1);
}
TEST_F(PrivacySandboxServiceM1Test, RecordPrivacySandbox4StartupMetrics_APIs) {
// Each test for the APIs are scoped below to ensure we start with a clean
// HistogramTester as each call to `RecordPrivacySandbox4StartupMetrics` emits
// histograms for all APIs.
// Topics
{
base::HistogramTester histogram_tester;
prefs()->SetBoolean(prefs::kPrivacySandboxM1TopicsEnabled, true);
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount("Settings.PrivacySandbox.Topics.Enabled",
static_cast<int>(true),
/*expected_count=*/1);
prefs()->SetBoolean(prefs::kPrivacySandboxM1TopicsEnabled, false);
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount("Settings.PrivacySandbox.Topics.Enabled",
static_cast<int>(false),
/*expected_count=*/1);
}
// Fledge
{
base::HistogramTester histogram_tester;
prefs()->SetBoolean(prefs::kPrivacySandboxM1FledgeEnabled, true);
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount("Settings.PrivacySandbox.Fledge.Enabled",
static_cast<int>(true),
/*expected_count=*/1);
prefs()->SetBoolean(prefs::kPrivacySandboxM1FledgeEnabled, false);
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount("Settings.PrivacySandbox.Fledge.Enabled",
static_cast<int>(false),
/*expected_count=*/1);
}
// Ad measurement
{
base::HistogramTester histogram_tester;
prefs()->SetBoolean(prefs::kPrivacySandboxM1AdMeasurementEnabled, true);
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
"Settings.PrivacySandbox.AdMeasurement.Enabled", static_cast<int>(true),
/*expected_count=*/1);
prefs()->SetBoolean(prefs::kPrivacySandboxM1AdMeasurementEnabled, false);
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
"Settings.PrivacySandbox.AdMeasurement.Enabled",
static_cast<int>(false),
/*expected_count=*/1);
}
}
class PrivacySandboxServiceM1RestrictedNoticeTest
: public PrivacySandboxServiceM1Test {
public:
void InitializeFeaturesBeforeStart() override {
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings4,
{{"notice-required", "true"}, {"restricted-notice", "true"}});
}
};
TEST_F(PrivacySandboxServiceM1RestrictedNoticeTest,
RestrictedPromptActionsUpdatePrefs) {
// Prompt acknowledge action should update the prefs accordingly.
RunTestCase(
TestState{{StateKey::kM1AdMeasurementEnabledUserPrefValue, false},
{StateKey::kM1RestrictedNoticeAcknowledged, false}},
TestInput{{InputKey::kPromptAction,
static_cast<int>(PromptAction::kRestrictedNoticeAcknowledge)}},
TestOutput{{OutputKey::kM1AdMeasurementEnabled, true},
{OutputKey::kM1RestrictedNoticeAcknowledged, true}});
// Open settings action should update the prefs accordingly.
RunTestCase(TestState{{StateKey::kM1AdMeasurementEnabledUserPrefValue, false},
{StateKey::kM1RestrictedNoticeAcknowledged, false}},
TestInput{{InputKey::kPromptAction,
static_cast<int>(
PromptAction::kRestrictedNoticeOpenSettings)}},
TestOutput{{OutputKey::kM1AdMeasurementEnabled, true},
{OutputKey::kM1RestrictedNoticeAcknowledged, true}});
}
class PrivacySandboxServiceM1DelayCreation
: public PrivacySandboxServiceM1Test {
public:
void SetUp() override {
// Prevent service from being created by base class.
}
};
TEST_F(PrivacySandboxServiceM1DelayCreation,
UnrestrictedRemainsEnabledWithConsent) {
prefs()->SetBoolean(prefs::kPrivacySandboxM1TopicsEnabled, true);
prefs()->SetBoolean(prefs::kPrivacySandboxM1FledgeEnabled, true);
prefs()->SetBoolean(prefs::kPrivacySandboxM1AdMeasurementEnabled, true);
prefs()->SetBoolean(prefs::kPrivacySandboxTopicsConsentGiven, true);
prefs()->SetTime(prefs::kPrivacySandboxTopicsConsentLastUpdateTime,
base::Time::Now());
prefs()->SetInteger(
prefs::kPrivacySandboxTopicsConsentLastUpdateReason,
static_cast<int>(
privacy_sandbox::TopicsConsentUpdateSource::kConfirmation));
prefs()->SetString(prefs::kPrivacySandboxTopicsConsentTextAtLastUpdate,
"foo");
CreateService();
EXPECT_TRUE(prefs()->GetBoolean(prefs::kPrivacySandboxM1TopicsEnabled));
EXPECT_TRUE(prefs()->GetBoolean(prefs::kPrivacySandboxM1FledgeEnabled));
EXPECT_TRUE(
prefs()->GetBoolean(prefs::kPrivacySandboxM1AdMeasurementEnabled));
EXPECT_TRUE(prefs()->GetBoolean(prefs::kPrivacySandboxTopicsConsentGiven));
EXPECT_EQ(
base::Time::Now(),
prefs()->GetTime(prefs::kPrivacySandboxTopicsConsentLastUpdateTime));
EXPECT_EQ(privacy_sandbox::TopicsConsentUpdateSource::kConfirmation,
static_cast<privacy_sandbox::TopicsConsentUpdateSource>(
prefs()->GetInteger(
prefs::kPrivacySandboxTopicsConsentLastUpdateReason)));
EXPECT_EQ("foo", prefs()->GetString(
prefs::kPrivacySandboxTopicsConsentTextAtLastUpdate));
}
TEST_F(PrivacySandboxServiceM1DelayCreation,
PromptSuppressReasonClearedWhenRestrictedNoticeEnabled) {
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings4,
{{"restricted-notice", "true"}});
prefs()->SetInteger(
prefs::kPrivacySandboxM1PromptSuppressed,
static_cast<int>(
PrivacySandboxService::PromptSuppressedReason::kRestricted));
CreateService();
EXPECT_EQ(
static_cast<int>(PrivacySandboxService::PromptSuppressedReason::kNone),
prefs()->GetValue(prefs::kPrivacySandboxM1PromptSuppressed));
}
TEST_F(PrivacySandboxServiceM1DelayCreation,
PromptSuppressReasonNotClearedWhenRestrictedNoticeDisabled) {
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings4,
{{"restricted-notice", "false"}});
prefs()->SetInteger(
prefs::kPrivacySandboxM1PromptSuppressed,
static_cast<int>(
PrivacySandboxService::PromptSuppressedReason::kRestricted));
CreateService();
EXPECT_EQ(static_cast<int>(
PrivacySandboxService::PromptSuppressedReason::kRestricted),
prefs()->GetValue(prefs::kPrivacySandboxM1PromptSuppressed));
}
class PrivacySandboxServiceM1DelayCreationRestricted
: public PrivacySandboxServiceM1DelayCreation {
public:
std::unique_ptr<privacy_sandbox_test_util::MockPrivacySandboxSettingsDelegate>
CreateMockDelegate() override {
auto mock_delegate = std::make_unique<testing::NiceMock<
privacy_sandbox_test_util::MockPrivacySandboxSettingsDelegate>>();
mock_delegate->SetUpIsPrivacySandboxRestrictedResponse(
/*restricted=*/true);
return mock_delegate;
}
};
TEST_F(PrivacySandboxServiceM1DelayCreationRestricted,
RestrictedDisablesAndClearsConsent) {
prefs()->SetBoolean(prefs::kPrivacySandboxM1TopicsEnabled, true);
prefs()->SetBoolean(prefs::kPrivacySandboxM1FledgeEnabled, true);
prefs()->SetBoolean(prefs::kPrivacySandboxM1AdMeasurementEnabled, true);
prefs()->SetBoolean(prefs::kPrivacySandboxTopicsConsentGiven, true);
prefs()->SetTime(prefs::kPrivacySandboxTopicsConsentLastUpdateTime,
base::Time::Now());
prefs()->SetInteger(
prefs::kPrivacySandboxTopicsConsentLastUpdateReason,
static_cast<int>(
privacy_sandbox::TopicsConsentUpdateSource::kConfirmation));
prefs()->SetString(prefs::kPrivacySandboxTopicsConsentTextAtLastUpdate,
"foo");
CreateService();
EXPECT_FALSE(prefs()->GetBoolean(prefs::kPrivacySandboxM1TopicsEnabled));
EXPECT_FALSE(prefs()->GetBoolean(prefs::kPrivacySandboxM1FledgeEnabled));
EXPECT_FALSE(
prefs()->GetBoolean(prefs::kPrivacySandboxM1AdMeasurementEnabled));
EXPECT_FALSE(prefs()->GetBoolean(prefs::kPrivacySandboxTopicsConsentGiven));
EXPECT_EQ(
base::Time(),
prefs()->GetTime(prefs::kPrivacySandboxTopicsConsentLastUpdateTime));
EXPECT_EQ(privacy_sandbox::TopicsConsentUpdateSource::kDefaultValue,
static_cast<privacy_sandbox::TopicsConsentUpdateSource>(
prefs()->GetInteger(
prefs::kPrivacySandboxTopicsConsentLastUpdateReason)));
EXPECT_EQ("", prefs()->GetString(
prefs::kPrivacySandboxTopicsConsentTextAtLastUpdate));
}
TEST_F(PrivacySandboxServiceM1DelayCreationRestricted,
RestrictedEnabledDoesntClearAdMeasurementPref) {
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings4,
{{"restricted-notice", "true"}});
prefs()->SetBoolean(prefs::kPrivacySandboxM1TopicsEnabled, true);
prefs()->SetBoolean(prefs::kPrivacySandboxM1FledgeEnabled, true);
prefs()->SetBoolean(prefs::kPrivacySandboxM1AdMeasurementEnabled, true);
CreateService();
EXPECT_FALSE(prefs()->GetBoolean(prefs::kPrivacySandboxM1TopicsEnabled));
EXPECT_FALSE(prefs()->GetBoolean(prefs::kPrivacySandboxM1FledgeEnabled));
EXPECT_TRUE(
prefs()->GetBoolean(prefs::kPrivacySandboxM1AdMeasurementEnabled));
}
class PrivacySandboxServiceM1PromptTest : public PrivacySandboxServiceM1Test {
public:
void InitializeFeaturesBeforeStart() override {
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings4,
{{"consent-required", "true"}, {"notice-required", "false"}});
}
};
TEST_F(PrivacySandboxServiceM1PromptTest, PrivacySandboxCorrectPromptVersion) {
// Depending on the feature enabled, a different prompt type may occur.
// Trials
feature_list()->Reset();
feature_list()->InitWithFeaturesAndParameters(
{{privacy_sandbox::kPrivacySandboxSettings3,
{{"force-show-consent-for-testing", "true"}}}},
{privacy_sandbox::kPrivacySandboxSettings4});
RunTestCase(TestState({}), TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{{OutputKey::kPromptType,
static_cast<int>(PromptType::kConsent)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)}});
// M1
feature_list()->Reset();
feature_list()->InitWithFeaturesAndParameters(
{{privacy_sandbox::kPrivacySandboxSettings4,
{{"force-show-consent-for-testing", "true"}}}},
{privacy_sandbox::kPrivacySandboxSettings3});
RunTestCase(TestState({}), TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{{OutputKey::kPromptType,
static_cast<int>(PromptType::kM1Consent)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)}});
}
#if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
TEST_F(PrivacySandboxServiceM1PromptTest, NonChromeBuildPrompt) {
// A case that will normally show a prompt will not if is a non-Chrome build.
RunTestCase(
TestState{{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)}},
TestInput{{InputKey::kForceChromeBuild, false}},
TestOutput{{OutputKey::kPromptType, static_cast<int>(PromptType::kNone)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)}});
}
#endif
TEST_F(PrivacySandboxServiceM1PromptTest, ThirdPartyCookiesBlocked) {
// If third party cookies are blocked, set the suppressed reason as
// kThirdPartyCookiesBlocked and return kNone.
RunTestCase(
TestState{{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{StateKey::kCookieControlsModeUserPrefValue,
content_settings::CookieControlsMode::kBlockThirdParty}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{{OutputKey::kPromptType, static_cast<int>(PromptType::kNone)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(
PromptSuppressedReason::kThirdPartyCookiesBlocked)}});
}
TEST_F(PrivacySandboxServiceM1PromptTest, RestrictedPrompt) {
// If the Privacy Sandbox is restricted, no prompt is shown.
RunTestCase(
TestState{{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{StateKey::kIsRestrictedAccount, true}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{{OutputKey::kPromptType,
static_cast<int>(PrivacySandboxService::PromptType::kNone)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kRestricted)}});
// After being restricted, even if the restriction is removed, no prompt
// should be shown. No call should even need to be made to see if the
// sandbox is still restricted.
RunTestCase(
TestState{{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kRestricted)},
{StateKey::kIsRestrictedAccount, false}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{{OutputKey::kPromptType,
static_cast<int>(PrivacySandboxService::PromptType::kNone)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kRestricted)}});
}
#if !BUILDFLAG(IS_ANDROID)
TEST_F(PrivacySandboxServiceM1PromptTest, PromptActionsSentimentService) {
// Settings both consent and notice to be true so that we can loop through all
// cases interacting with the sentiment service cleanly, without breaking
// DCHECKs. Other tests / code paths check that PromptActionOccurred is
// working correctly based on notice and consent, and assert that only one is
// enabled.
feature_list()->Reset();
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings4,
{{"consent-required", "true"},
{"notice-required", "true"},
{"restricted-notice", "true"}});
std::map<PromptAction, TrustSafetySentimentService::FeatureArea>
expected_feature_areas;
expected_feature_areas = {
{PromptAction::kNoticeOpenSettings,
TrustSafetySentimentService::FeatureArea::
kPrivacySandbox4NoticeSettings},
{PromptAction::kNoticeAcknowledge,
TrustSafetySentimentService::FeatureArea::kPrivacySandbox4NoticeOk},
{PromptAction::kConsentAccepted,
TrustSafetySentimentService::FeatureArea::kPrivacySandbox4ConsentAccept},
{PromptAction::kConsentDeclined,
TrustSafetySentimentService::FeatureArea::
kPrivacySandbox4ConsentDecline}};
for (int enum_value = 0;
enum_value <= static_cast<int>(PromptAction::kMaxValue); ++enum_value) {
auto prompt_action = static_cast<PromptAction>(enum_value);
if (expected_feature_areas.count(prompt_action)) {
EXPECT_CALL(
*mock_sentiment_service(),
InteractedWithPrivacySandbox4(expected_feature_areas[prompt_action]))
.Times(1);
} else {
EXPECT_CALL(*mock_sentiment_service(),
InteractedWithPrivacySandbox4(testing::_))
.Times(0);
}
privacy_sandbox_service()->PromptActionOccurred(prompt_action);
testing::Mock::VerifyAndClearExpectations(mock_sentiment_service());
}
}
#endif
class PrivacySandboxServiceM1ConsentPromptTest
: public PrivacySandboxServiceM1PromptTest {};
TEST_F(PrivacySandboxServiceM1ConsentPromptTest, SuppressedConsent) {
// A case that will normally show a consent will not if there is any
// suppression reason.
for (int suppressed_reason = static_cast<int>(PromptSuppressedReason::kNone);
suppressed_reason <= static_cast<int>(PromptSuppressedReason::kMaxValue);
++suppressed_reason) {
bool suppressed =
suppressed_reason != static_cast<int>(PromptSuppressedReason::kNone);
auto expected_prompt =
suppressed ? PromptType::kNone : PromptType::kM1Consent;
RunTestCase(
TestState{{StateKey::kM1PromptSuppressedReason, suppressed_reason},
{StateKey::kIsRestrictedAccount, false}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{{OutputKey::kPromptType, static_cast<int>(expected_prompt)},
{OutputKey::kM1PromptSuppressedReason, suppressed_reason}});
}
}
TEST_F(PrivacySandboxServiceM1ConsentPromptTest, TrialsConsentDeclined) {
// If a previous consent decision was made to decline the privacy sandbox
// (privacy_sandbox.apis_enabled_v2 is false), set kTrialsConsentDeclined
// as suppressed reason and return kNone.
RunTestCase(
TestState{{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{StateKey::kTrialsConsentDecisionMade, true}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{
{OutputKey::kPromptType, static_cast<int>(PromptType::kNone)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kTrialsConsentDeclined)}});
}
TEST_F(PrivacySandboxServiceM1ConsentPromptTest, M1ConsentDecisionNotMade) {
// If m1 consent required, and decision has not been made, return
// kM1Consent.
RunTestCase(TestState{{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{StateKey::kM1ConsentDecisionMade, false}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{{OutputKey::kPromptType,
static_cast<int>(PromptType::kM1Consent)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)}});
}
TEST_F(PrivacySandboxServiceM1ConsentPromptTest,
M1ConsentDecisionMadeAndEEANoticeNotAcknowledged) {
// If m1 consent decision has been made and the eea notice has not been
// acknowledged, return kM1NoticeEEA.
RunTestCase(TestState{{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{StateKey::kM1ConsentDecisionMade, true}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{{OutputKey::kPromptType,
static_cast<int>(PromptType::kM1NoticeEEA)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)}});
}
TEST_F(PrivacySandboxServiceM1ConsentPromptTest,
M1ConsentDecisionMadeAndEEANoticeAcknowledged) {
// If m1 consent decision has been made and the eea notice has been
// acknowledged, return kNone.
RunTestCase(
TestState{{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{StateKey::kM1ConsentDecisionMade, true},
{StateKey::kM1EEANoticeAcknowledged, true}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{{OutputKey::kPromptType, static_cast<int>(PromptType::kNone)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)}});
}
TEST_F(PrivacySandboxServiceM1ConsentPromptTest, ROWNoticeAckTopicsDisabled) {
// If the user saw the ROW notice, and then disable Topics from settings, and
// is now in EEA, they should not see a prompt.
RunTestCase(
TestState{{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{StateKey::kM1RowNoticeAcknowledged, true},
{StateKey::kM1TopicsEnabledUserPrefValue, false}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{
{OutputKey::kPromptType, static_cast<int>(PromptType::kNone)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(
PromptSuppressedReason::
kROWFlowCompletedAndTopicsDisabledBeforeEEAMigration)}});
}
TEST_F(PrivacySandboxServiceM1ConsentPromptTest, PromptAction_ConsentAccepted) {
// Confirm that when the service is informed that the consent prompt was
// accepted, it correctly adjusts the Privacy Sandbox prefs.
RunTestCase(
TestState{{kActiveTopicsConsent, false},
{kAdvanceClockBy, base::Hours(1)}},
TestInput{{InputKey::kPromptAction,
static_cast<int>(PromptAction::kConsentAccepted)}},
TestOutput{
{OutputKey::kM1ConsentDecisionMade, true},
{OutputKey::kM1TopicsEnabled, true},
{OutputKey::kTopicsConsentGiven, true},
{OutputKey::kTopicsConsentLastUpdateReason,
privacy_sandbox::TopicsConsentUpdateSource::kConfirmation},
{kTopicsConsentLastUpdateTime, base::Time::Now() + base::Hours(1)},
{kTopicsConsentStringIdentifiers,
GetTopicsConfirmationStringIdentifiers()}});
}
TEST_F(PrivacySandboxServiceM1ConsentPromptTest, PromptAction_ConsentDeclined) {
// Confirm that when the service is informed that the consent prompt was
// declined, it correctly adjusts the Privacy Sandbox prefs.
RunTestCase(
TestState{{kActiveTopicsConsent, true},
{kAdvanceClockBy, base::Hours(1)}},
TestInput{{InputKey::kPromptAction,
static_cast<int>(PromptAction::kConsentDeclined)}},
TestOutput{
{OutputKey::kM1ConsentDecisionMade, true},
{OutputKey::kM1TopicsEnabled, false},
{OutputKey::kTopicsConsentGiven, false},
{OutputKey::kTopicsConsentLastUpdateReason,
privacy_sandbox::TopicsConsentUpdateSource::kConfirmation},
{kTopicsConsentLastUpdateTime, base::Time::Now() + base::Hours(1)},
{kTopicsConsentStringIdentifiers,
GetTopicsConfirmationStringIdentifiers()}});
}
TEST_F(PrivacySandboxServiceM1ConsentPromptTest,
PromptAction_EEANoticeAcknowledged) {
// Confirm that when the service is informed that the eea notice was
// acknowledged, it correctly adjusts the Privacy Sandbox prefs.
RunTestCase(TestState{{StateKey::kM1ConsentDecisionMade, true},
{StateKey::kM1EEANoticeAcknowledged, false}},
TestInput{{InputKey::kPromptAction,
static_cast<int>(PromptAction::kNoticeAcknowledge)}},
TestOutput{{OutputKey::kM1EEANoticeAcknowledged, true},
{OutputKey::kM1FledgeEnabled, true},
{OutputKey::kM1AdMeasurementEnabled, true}});
RunTestCase(
TestState{{StateKey::kM1ConsentDecisionMade, true},
{StateKey::kM1EEANoticeAcknowledged, false}},
TestInput{{InputKey::kPromptAction,
static_cast<int>(PromptAction::kNoticeOpenSettings)}},
TestOutput{{OutputKey::kM1EEANoticeAcknowledged, true},
{OutputKey::kM1FledgeEnabled, true},
{OutputKey::kM1AdMeasurementEnabled, true},
{OutputKey::kTopicsConsentGiven, false},
{OutputKey::kTopicsConsentLastUpdateReason,
privacy_sandbox::TopicsConsentUpdateSource::kDefaultValue}});
}
TEST_F(PrivacySandboxServiceM1ConsentPromptTest,
PromptAction_EEANoticeAcknowledged_ROWNoticeAcknowledged) {
// Confirm that if the user has already acknowledged an ROW notice, that the
// EEA notice does not attempt to re-enable APIs. This is important for the
// ROW -> EEA upgrade flow, where the user may have already visited settings.
RunTestCase(TestState{{StateKey::kM1ConsentDecisionMade, true},
{StateKey::kM1EEANoticeAcknowledged, false},
{StateKey::kM1RowNoticeAcknowledged, true}},
TestInput{{InputKey::kPromptAction,
static_cast<int>(PromptAction::kNoticeAcknowledge)}},
TestOutput{{OutputKey::kM1EEANoticeAcknowledged, true},
{OutputKey::kM1FledgeEnabled, false},
{OutputKey::kM1AdMeasurementEnabled, false}});
}
class PrivacySandboxServiceM1NoticePromptTest
: public PrivacySandboxServiceM1PromptTest {
public:
void InitializeFeaturesBeforeStart() override {
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings4,
{{"consent-required", "false"}, {"notice-required", "true"}});
}
};
TEST_F(PrivacySandboxServiceM1NoticePromptTest, SuppressedNotice) {
// A case that will normally show a notice will not if there is any
// suppression reason.
for (int suppressed_reason = static_cast<int>(PromptSuppressedReason::kNone);
suppressed_reason <= static_cast<int>(PromptSuppressedReason::kMaxValue);
++suppressed_reason) {
bool suppressed =
suppressed_reason != static_cast<int>(PromptSuppressedReason::kNone);
auto expected_prompt =
suppressed ? PromptType::kNone : PromptType::kM1NoticeROW;
RunTestCase(
TestState{{StateKey::kM1PromptSuppressedReason, suppressed_reason}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{{OutputKey::kPromptType, static_cast<int>(expected_prompt)},
{OutputKey::kM1PromptSuppressedReason, suppressed_reason}});
}
}
TEST_F(PrivacySandboxServiceM1NoticePromptTest, TrialsDisabledAfterNotice) {
// If a previous notice was shown and then the privacy sandbox was disabled
// after (privacy_sandbox.apis_enabled_v2 is false), set
// kTrialsDisabledAfterNotice as suppressed reason and return kNone.
RunTestCase(
TestState{{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{StateKey::kTrialsNoticeDisplayed, true}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{{OutputKey::kPromptType, static_cast<int>(PromptType::kNone)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(
PromptSuppressedReason::kTrialsDisabledAfterNotice)}});
}
TEST_F(PrivacySandboxServiceM1NoticePromptTest, M1NoticeNotAcknowledged) {
// If m1 notice required, and the row notice has not been acknowledged, return
// kM1NoticeROW.
RunTestCase(TestState{{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{StateKey::kM1RowNoticeAcknowledged, false}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{{OutputKey::kPromptType,
static_cast<int>(PromptType::kM1NoticeROW)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)}});
}
TEST_F(PrivacySandboxServiceM1NoticePromptTest, M1NoticeAcknowledged) {
// If m1 notice required, and the row notice has been acknowledged, return
// kNone.
RunTestCase(
TestState{{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{StateKey::kM1RowNoticeAcknowledged, true}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{{OutputKey::kPromptType, static_cast<int>(PromptType::kNone)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)}});
}
TEST_F(PrivacySandboxServiceM1NoticePromptTest, M1EEAFlowInterrupted) {
// If a user has migrated from EEA to ROW and has already completed the eea
// consent but not yet acknowledged the notice, return kM1NoticeROW.
RunTestCase(TestState{{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{StateKey::kM1ConsentDecisionMade, true},
{StateKey::kM1EEANoticeAcknowledged, false}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{{OutputKey::kPromptType,
static_cast<int>(PromptType::kM1NoticeROW)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)}});
}
TEST_F(PrivacySandboxServiceM1NoticePromptTest, M1EEAFlowCompleted) {
// If a user has migrated from EEA to ROW and has already completed the eea
// flow, set kEEAFlowCompleted as suppressed reason return kNone.
RunTestCase(
TestState{{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{StateKey::kM1ConsentDecisionMade, true},
{StateKey::kM1EEANoticeAcknowledged, true}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{
{OutputKey::kPromptType, static_cast<int>(PromptType::kNone)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(
PromptSuppressedReason::kEEAFlowCompletedBeforeRowMigration)}});
}
TEST_F(PrivacySandboxServiceM1NoticePromptTest,
PromptAction_RowNoticeAcknowledged) {
// Confirm that when the service is informed that the row notice was
// acknowledged, it correctly adjusts the Privacy Sandbox prefs.
RunTestCase(TestState{},
TestInput{{InputKey::kPromptAction,
static_cast<int>(PromptAction::kNoticeAcknowledge)}},
TestOutput{{OutputKey::kM1RowNoticeAcknowledged, true},
{OutputKey::kM1TopicsEnabled, true},
{OutputKey::kM1FledgeEnabled, true},
{OutputKey::kM1AdMeasurementEnabled, true},
{OutputKey::kTopicsConsentGiven, false}});
}
TEST_F(PrivacySandboxServiceM1NoticePromptTest, PromptAction_OpenSettings) {
// Confirm that when the service is informed that the row notice was
// acknowledged, it correctly adjusts the Privacy Sandbox prefs.
RunTestCase(TestState{},
TestInput{{InputKey::kPromptAction,
static_cast<int>(PromptAction::kNoticeOpenSettings)}},
TestOutput{{OutputKey::kM1RowNoticeAcknowledged, true},
{OutputKey::kM1TopicsEnabled, true},
{OutputKey::kM1FledgeEnabled, true},
{OutputKey::kM1AdMeasurementEnabled, true},
{OutputKey::kTopicsConsentGiven, false}});
}
TEST_F(PrivacySandboxServiceM1Test, DisablePrivacySandboxPromptPolicy) {
// Disable the prompt via policy and check the returned prompt type is kNone.
RunTestCase(
TestState{{StateKey::kM1PromptDisabledByPolicy,
static_cast<int>(
PrivacySandboxService::PromptSuppressedReason::kPolicy)}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{
{OutputKey::kPromptType, static_cast<int>(PromptType::kNone)}});
}
TEST_F(PrivacySandboxServiceM1Test, DisablePrivacySandboxTopicsPolicy) {
// Disable the Topics api via policy and check the returned prompt type is
// kNone and topics is not allowed.
RunTestCase(
TestState{{StateKey::kM1TopicsDisabledByPolicy, true}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{{OutputKey::kPromptType, static_cast<int>(PromptType::kNone)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{OutputKey::kIsTopicsAllowed, false}});
}
TEST_F(PrivacySandboxServiceM1Test, DisablePrivacySandboxFledgePolicy) {
// Disable the Fledge api via policy and check the returned prompt type is
// kNone and fledge is not allowed.
RunTestCase(
TestState{{StateKey::kM1FledgeDisabledByPolicy, true}},
TestInput{
{InputKey::kForceChromeBuild, true},
{kTopFrameOrigin, url::Origin::Create(GURL("https://top-frame.com"))},
{kFledgeAuctionPartyOrigin,
url::Origin::Create(GURL("https://embedded.com"))}},
TestOutput{{OutputKey::kPromptType, static_cast<int>(PromptType::kNone)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{OutputKey::kIsFledgeAllowed, false}});
}
TEST_F(PrivacySandboxServiceM1Test, DisablePrivacySandboxAdMeasurementPolicy) {
// Disable the ad measurement api via policy and check the returned prompt
// type is kNone and the api is not allowed.
RunTestCase(
TestState{{StateKey::kM1AdMesaurementDisabledByPolicy, true}},
TestInput{
{kTopFrameOrigin, url::Origin::Create(GURL("https://top-frame.com"))},
{kAdMeasurementReportingOrigin,
url::Origin::Create(GURL("https://embedded.com"))},
{InputKey::kForceChromeBuild, true}},
TestOutput{{OutputKey::kPromptType, static_cast<int>(PromptType::kNone)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{OutputKey::kIsAttributionReportingAllowed, false}});
}
// TODO(crbug.com/1428506): consider parameterizing other tests for the various
// feature flags, particularly `kPrivacySandboxSettings4RestrictedNotice`.
class PrivacySandboxServiceM1RestrictedNoticePromptTest
: public PrivacySandboxServiceM1PromptTest {
public:
std::unique_ptr<privacy_sandbox_test_util::MockPrivacySandboxSettingsDelegate>
CreateMockDelegate() override {
auto mock_delegate = std::make_unique<testing::NiceMock<
privacy_sandbox_test_util::MockPrivacySandboxSettingsDelegate>>();
mock_delegate->SetUpIsSubjectToM1NoticeRestrictedResponse(
/*is_subject_to_restricted_notice=*/true);
return mock_delegate;
}
void InitializeFeaturesBeforeStart() override {
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings4,
{{"consent-required", "false"},
{"notice-required", "true"},
{privacy_sandbox::kPrivacySandboxSettings4RestrictedNotice.name,
"true"}});
}
};
TEST_F(PrivacySandboxServiceM1RestrictedNoticePromptTest, RestrictedNotice) {
// Ensure that kM1NoticeRestricted is returned when configured to do so.
RunTestCase(TestState{{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{StateKey::kTrialsNoticeDisplayed, false}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{{OutputKey::kPromptType,
static_cast<int>(PromptType::kM1NoticeRestricted)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)}});
}
TEST_F(PrivacySandboxServiceM1RestrictedNoticePromptTest,
RestrictedNoticeAlreadyAcknowledged) {
// If the user already acknowledged the notice, don't show it, or the ROW
// notice, again.
RunTestCase(
TestState{{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{StateKey::kTrialsNoticeDisplayed, false},
{StateKey::kM1RestrictedNoticeAcknowledged, true}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{{OutputKey::kPromptType, static_cast<int>(PromptType::kNone)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)}});
}
TEST_F(PrivacySandboxServiceM1RestrictedNoticePromptTest,
ROWNoticeAlreadyAcknowledged) {
// If the user already acknowledged a different notice, don't show it again.
RunTestCase(
TestState{{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{StateKey::kTrialsNoticeDisplayed, false},
{StateKey::kM1RowNoticeAcknowledged, true}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{{OutputKey::kPromptType, static_cast<int>(PromptType::kNone)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)}});
}
TEST_F(PrivacySandboxServiceM1RestrictedNoticePromptTest,
EEANoticeAlreadyAcknowledged) {
// If the user already acknowledged a different notice, don't show the
// restricted notice again. Ensure the existing suppression reason is
// respected.
RunTestCase(
TestState{{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{StateKey::kTrialsNoticeDisplayed, false},
{StateKey::kM1ConsentDecisionMade, true},
{StateKey::kM1EEANoticeAcknowledged, true}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{
{OutputKey::kPromptType, static_cast<int>(PromptType::kNone)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(
PromptSuppressedReason::kEEAFlowCompletedBeforeRowMigration)}});
}
TEST_F(PrivacySandboxServiceM1RestrictedNoticePromptTest,
RecordPrivacySandbox4StartupMetrics_PromptNotSuppressed) {
base::HistogramTester histogram_tester;
const std::string privacy_sandbox_prompt_startup_histogram =
"Settings.PrivacySandbox.PromptStartupState";
// Ensure prompt not suppressed.
prefs()->SetInteger(
prefs::kPrivacySandboxM1PromptSuppressed,
static_cast<int>(PrivacySandboxService::PromptSuppressedReason::kNone));
base::test::ScopedFeatureList feature_list_notice_required;
std::map<std::string, std::string> notice_required_feature_param = {
{std::string(
privacy_sandbox::kPrivacySandboxSettings4ConsentRequiredName),
"false"},
{std::string(privacy_sandbox::kPrivacySandboxSettings4NoticeRequiredName),
"true"}};
feature_list_notice_required.InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings4, notice_required_feature_param);
// Notice flow not completed.
prefs()->SetBoolean(prefs::kPrivacySandboxM1RestrictedNoticeAcknowledged,
false);
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
privacy_sandbox_prompt_startup_histogram,
static_cast<int>(PrivacySandboxService::PromptStartupState::
kRestrictedNoticePromptWaiting),
/*expected_count=*/1);
// Notice flow completed.
prefs()->SetBoolean(prefs::kPrivacySandboxM1RestrictedNoticeAcknowledged,
true);
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
privacy_sandbox_prompt_startup_histogram,
static_cast<int>(PrivacySandboxService::PromptStartupState::
kRestrictedNoticeFlowCompleted),
/*expected_count=*/1);
// ROW flow completed, which implies no restricted prompt.
prefs()->SetBoolean(prefs::kPrivacySandboxM1RestrictedNoticeAcknowledged,
false);
prefs()->SetBoolean(prefs::kPrivacySandboxM1RowNoticeAcknowledged, true);
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
privacy_sandbox_prompt_startup_histogram,
static_cast<int>(
PrivacySandboxService::PromptStartupState::
kRestrictedNoticeNotShownDueToFullNoticeAcknowledged),
/*expected_count=*/1);
// EAA flow completed, which implies no restricted prompt.
prefs()->SetBoolean(prefs::kPrivacySandboxM1RestrictedNoticeAcknowledged,
false);
prefs()->SetBoolean(prefs::kPrivacySandboxM1EEANoticeAcknowledged, true);
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
privacy_sandbox_prompt_startup_histogram,
static_cast<int>(
PrivacySandboxService::PromptStartupState::
kRestrictedNoticeNotShownDueToFullNoticeAcknowledged),
// One when the ROW notice acknowledged pref was set, plus the latest
// call.
/*expected_count=*/2);
}
TEST_F(PrivacySandboxServiceM1RestrictedNoticePromptTest,
RecordPrivacySandbox4StartupMetrics_GraduationFlow) {
const std::string privacy_sandbox_prompt_startup_histogram =
"Settings.PrivacySandbox.PromptStartupState";
// Ensure prompt not suppressed.
prefs()->SetInteger(
prefs::kPrivacySandboxM1PromptSuppressed,
static_cast<int>(PrivacySandboxService::PromptSuppressedReason::kNone));
// Restricted Notice flow NOT completed & user ready for graduation.
{
base::HistogramTester histogram_tester;
prefs()->SetBoolean(prefs::kPrivacySandboxM1RestrictedNoticeAcknowledged,
false);
// User waiting for graduation
prefs()->SetBoolean(prefs::kPrivacySandboxM1Restricted, true);
prefs()->SetBoolean(prefs::kPrivacySandboxM1Unrestricted, true);
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
privacy_sandbox_prompt_startup_histogram,
static_cast<int>(
PrivacySandboxService::PromptStartupState::
kWaitingForGraduationRestrictedNoticeFlowNotCompleted),
/*expected_count=*/1);
}
// Restricted Notice flow completed & user ready for graduation.
{
base::HistogramTester histogram_tester;
prefs()->SetBoolean(prefs::kPrivacySandboxM1RestrictedNoticeAcknowledged,
true);
// User waiting for graduation
prefs()->SetBoolean(prefs::kPrivacySandboxM1Restricted, true);
prefs()->SetBoolean(prefs::kPrivacySandboxM1Unrestricted, true);
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
privacy_sandbox_prompt_startup_histogram,
static_cast<int>(
PrivacySandboxService::PromptStartupState::
kWaitingForGraduationRestrictedNoticeFlowCompleted),
/*expected_count=*/1);
}
// Restricted Notice flow completed & user NOT ready for graduation.
{
base::HistogramTester histogram_tester;
prefs()->SetBoolean(prefs::kPrivacySandboxM1RestrictedNoticeAcknowledged,
true);
// User NOT waiting for graduation
prefs()->SetBoolean(prefs::kPrivacySandboxM1Restricted, true);
prefs()->SetBoolean(prefs::kPrivacySandboxM1Unrestricted, false);
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
privacy_sandbox_prompt_startup_histogram,
static_cast<int>(PrivacySandboxService::PromptStartupState::
kRestrictedNoticeFlowCompleted),
/*expected_count=*/1);
}
// Restricted Notice flow NOT completed & user NOT ready for graduation.
{
base::HistogramTester histogram_tester;
prefs()->SetBoolean(prefs::kPrivacySandboxM1RestrictedNoticeAcknowledged,
false);
// User NOT waiting for graduation
prefs()->SetBoolean(prefs::kPrivacySandboxM1Restricted, true);
prefs()->SetBoolean(prefs::kPrivacySandboxM1Unrestricted, false);
privacy_sandbox_service()->RecordPrivacySandbox4StartupMetrics();
histogram_tester.ExpectBucketCount(
privacy_sandbox_prompt_startup_histogram,
static_cast<int>(PrivacySandboxService::PromptStartupState::
kRestrictedNoticePromptWaiting),
/*expected_count=*/1);
}
}
TEST_F(PrivacySandboxServiceM1RestrictedNoticePromptTest,
RestrictedNoticeAcknowledged) {
// Ensure that Ad measurement pref is not re-enabled if user disabled it
// after acknowledging the restricted notice.
RunTestCase(
TestState{{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{StateKey::kM1RestrictedNoticeAcknowledged, true},
{StateKey::kM1AdMeasurementEnabledUserPrefValue, false}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{{OutputKey::kPromptType,
static_cast<int>(PrivacySandboxService::PromptType::kNone)},
{OutputKey::kM1AdMeasurementEnabled, false},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)}});
}
class PrivacySandboxServiceM1RestrictedNoticeShownToGuardianTest
: public PrivacySandboxServiceM1PromptTest {
public:
std::unique_ptr<privacy_sandbox_test_util::MockPrivacySandboxSettingsDelegate>
CreateMockDelegate() override {
auto mock_delegate = std::make_unique<testing::NiceMock<
privacy_sandbox_test_util::MockPrivacySandboxSettingsDelegate>>();
mock_delegate->SetUpIsPrivacySandboxRestrictedResponse(
/*restricted=*/true);
return mock_delegate;
}
void InitializeFeaturesBeforeStart() override {
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings4,
{{"consent-required", "false"},
{"notice-required", "true"},
{privacy_sandbox::kPrivacySandboxSettings4RestrictedNotice.name,
"true"}});
}
};
TEST_F(PrivacySandboxServiceM1RestrictedNoticeShownToGuardianTest,
NotSubjectToNoticeButIsRestricted) {
// Ensure that kNoticeShownToGuardian, with no prompt, is returned in the
// event that the user is not subject to the m1 notice restricted prompt.
// Ensure measurements API is enabled for these users.
RunTestCase(
TestState{{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{StateKey::kTrialsNoticeDisplayed, false}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{
{OutputKey::kPromptType, static_cast<int>(PromptType::kNone)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNoticeShownToGuardian)},
{OutputKey::kM1AdMeasurementEnabled, true}});
}
TEST_F(PrivacySandboxServiceM1RestrictedNoticeShownToGuardianTest,
NotSubjectToNoticeButIsRestrictedWithAdMeasurementDisabled) {
// Ensure that Ad measurement pref is not re-enabled if user disabled it
// after the notice was suppressed due to kNoticeShownToGuardian.
RunTestCase(
TestState{
{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNoticeShownToGuardian)},
{StateKey::kM1AdMeasurementEnabledUserPrefValue, false}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{
{OutputKey::kPromptType,
static_cast<int>(PrivacySandboxService::PromptType::kNone)},
{OutputKey::kM1AdMeasurementEnabled, false},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNoticeShownToGuardian)}});
}
class PrivacySandboxServiceM1RestrictedNoticeEnabledNoRestrictionsTest
: public PrivacySandboxServiceM1PromptTest {
public:
std::unique_ptr<privacy_sandbox_test_util::MockPrivacySandboxSettingsDelegate>
CreateMockDelegate() override {
auto mock_delegate = std::make_unique<testing::NiceMock<
privacy_sandbox_test_util::MockPrivacySandboxSettingsDelegate>>();
mock_delegate->SetUpIsPrivacySandboxRestrictedResponse(
/*restricted=*/false);
mock_delegate->SetUpIsSubjectToM1NoticeRestrictedResponse(
/*is_subject_to_restricted_notice=*/false);
return mock_delegate;
}
void InitializeFeaturesBeforeStart() override {
feature_list()->InitAndEnableFeatureWithParameters(
privacy_sandbox::kPrivacySandboxSettings4,
{{"consent-required", "false"},
{"notice-required", "true"},
{privacy_sandbox::kPrivacySandboxSettings4RestrictedNotice.name,
"true"}});
}
};
TEST_F(PrivacySandboxServiceM1RestrictedNoticeEnabledNoRestrictionsTest,
VerifyPromptType) {
// The restricted notice feature is enabled, but the account is not subject to
// the restrictions, and the privacy sandbox is not otherwise restricted. The
// ROW notice is still applicable, however.
RunTestCase(TestState{{StateKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)},
{StateKey::kTrialsNoticeDisplayed, false}},
TestInput{{InputKey::kForceChromeBuild, true}},
TestOutput{{OutputKey::kPromptType,
static_cast<int>(PromptType::kM1NoticeROW)},
{OutputKey::kM1PromptSuppressedReason,
static_cast<int>(PromptSuppressedReason::kNone)}});
}