blob: 9beba00d83f72a218fc71795f35fe7cadac217a2 [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.
#ifndef COMPONENTS_PRIVACY_SANDBOX_PRIVACY_SANDBOX_TEST_UTIL_H_
#define COMPONENTS_PRIVACY_SANDBOX_PRIVACY_SANDBOX_TEST_UTIL_H_
#include <set>
#include <string>
#include "components/browsing_topics/test_util.h"
#include "components/content_settings/core/browser/cookie_settings.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/test/content_settings_mock_provider.h"
#include "components/privacy_sandbox/privacy_sandbox_attestations/privacy_sandbox_attestations.h"
#include "components/privacy_sandbox/privacy_sandbox_prefs.h"
#include "components/privacy_sandbox/privacy_sandbox_settings.h"
#include "components/privacy_sandbox/tpcd_experiment_eligibility.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "url/origin.h"
namespace sync_preferences {
class TestingPrefServiceSyncable;
}
class HostContentSettingsMap;
namespace privacy_sandbox_test_util {
class PrivacySandboxServiceTestInterface {
public:
virtual void TopicsToggleChanged(bool new_value) const = 0;
virtual void SetTopicAllowed(privacy_sandbox::CanonicalTopic topic,
bool allowed) = 0;
virtual bool TopicsHasActiveConsent() const = 0;
virtual privacy_sandbox::TopicsConsentUpdateSource
TopicsConsentLastUpdateSource() const = 0;
virtual base::Time TopicsConsentLastUpdateTime() const = 0;
virtual std::string TopicsConsentLastUpdateText() const = 0;
virtual void ForceChromeBuildForTests(bool force_chrome_build) const = 0;
virtual int GetRequiredPromptType() const = 0;
virtual void PromptActionOccurred(int action) const = 0;
};
class MockPrivacySandboxObserver
: public privacy_sandbox::PrivacySandboxSettings::Observer {
public:
MockPrivacySandboxObserver();
~MockPrivacySandboxObserver();
MOCK_METHOD(void, OnTopicsDataAccessibleSinceUpdated, (), (override));
MOCK_METHOD1(OnFirstPartySetsEnabledChanged, void(bool));
};
class MockPrivacySandboxSettingsDelegate
: public privacy_sandbox::PrivacySandboxSettings::Delegate {
public:
MockPrivacySandboxSettingsDelegate();
~MockPrivacySandboxSettingsDelegate() override;
void SetUpIsPrivacySandboxRestrictedResponse(bool restricted) {
ON_CALL(*this, IsPrivacySandboxRestricted).WillByDefault([=]() {
return restricted;
});
}
void SetUpIsPrivacySandboxCurrentlyUnrestrictedResponse(bool unrestricted) {
ON_CALL(*this, IsPrivacySandboxCurrentlyUnrestricted).WillByDefault([=]() {
return unrestricted;
});
}
void SetUpIsIncognitoProfileResponse(bool incognito) {
ON_CALL(*this, IsIncognitoProfile).WillByDefault([=]() {
return incognito;
});
}
void SetUpHasAppropriateTopicsConsentResponse(bool has_appropriate_consent) {
ON_CALL(*this, HasAppropriateTopicsConsent).WillByDefault([=]() {
return has_appropriate_consent;
});
}
void SetUpIsSubjectToM1NoticeRestrictedResponse(
bool is_subject_to_restricted_notice) {
ON_CALL(*this, IsSubjectToM1NoticeRestricted).WillByDefault([=]() {
return is_subject_to_restricted_notice;
});
}
void SetUpIsCookieDeprecationExperimentEligibleResponse(bool eligible) {
ON_CALL(*this, IsCookieDeprecationExperimentEligible).WillByDefault([=]() {
return eligible;
});
}
void SetUpGetCookieDeprecationExperimentCurrentEligibility(
privacy_sandbox::TpcdExperimentEligibility::Reason eligibility_reason) {
ON_CALL(*this, GetCookieDeprecationExperimentCurrentEligibility)
.WillByDefault([=]() {
return privacy_sandbox::TpcdExperimentEligibility(eligibility_reason);
});
}
void SetUpIsCookieDeprecationLabelAllowedResponse(bool allowed) {
ON_CALL(*this, IsCookieDeprecationLabelAllowed).WillByDefault([=]() {
return allowed;
});
}
void SetUpAreThirdPartyCookiesBlockedByCookieDeprecationExperimentResponse(
bool result) {
ON_CALL(*this, AreThirdPartyCookiesBlockedByCookieDeprecationExperiment)
.WillByDefault([=]() { return result; });
}
MOCK_METHOD(bool, IsPrivacySandboxRestricted, (), (const, override));
MOCK_METHOD(bool,
IsPrivacySandboxCurrentlyUnrestricted,
(),
(const, override));
MOCK_METHOD(bool, IsIncognitoProfile, (), (const, override));
MOCK_METHOD(bool, HasAppropriateTopicsConsent, (), (const, override));
MOCK_METHOD(bool, IsSubjectToM1NoticeRestricted, (), (const, override));
MOCK_METHOD(bool,
IsCookieDeprecationExperimentEligible,
(),
(const, override));
MOCK_METHOD(privacy_sandbox::TpcdExperimentEligibility,
GetCookieDeprecationExperimentCurrentEligibility,
(),
(const, override));
MOCK_METHOD(bool, IsCookieDeprecationLabelAllowed, (), (const, override));
MOCK_METHOD(bool,
AreThirdPartyCookiesBlockedByCookieDeprecationExperiment,
(),
(const, override));
};
// A declarative test case is a collection of key value pairs, which each define
// some property of the test, such as the state of the profile, the input, or
// expected output.
// Defines the state of the profile prior to testing.
enum class StateKey {
kM1TopicsEnabledUserPrefValue = 1,
kCookieControlsModeUserPrefValue = 2,
kSiteDataUserDefault = 3,
kSiteDataUserExceptions = 4,
kM1FledgeEnabledUserPrefValue = 5,
kM1AdMeasurementEnabledUserPrefValue = 6,
kIsIncognito = 7,
kIsRestrictedAccount = 8,
kHasCurrentTopics = 9,
kHasBlockedTopics = 10,
kAdvanceClockBy = 11,
kActiveTopicsConsent = 12,
kTrialsConsentDecisionMade = 14,
kTrialsNoticeDisplayed = 15,
kM1ConsentDecisionPreviouslyMade = 16,
kM1EEANoticePreviouslyAcknowledged = 17,
kM1RowNoticePreviouslyAcknowledged = 18,
kM1PromptPreviouslySuppressedReason = 19,
kM1PromptDisabledByPolicy = 20,
kM1TopicsDisabledByPolicy = 21,
kM1FledgeDisabledByPolicy = 22,
kM1AdMesaurementDisabledByPolicy = 23,
kHasAppropriateTopicsConsent = 24,
kM1RestrictedNoticePreviouslyAcknowledged = 25,
kAttestationsMap = 26,
kBlockFledgeJoiningForEtldplus1 = 27,
};
// Defines the input to the functions under test.
enum class InputKey {
kTopFrameOrigin = 1,
kTopicsURL = 2,
kFledgeAuctionPartyOrigin = 3,
kAdMeasurementReportingOrigin = 4,
kAdMeasurementSourceOrigin = 5,
kAdMeasurementDestinationOrigin = 6,
kAccessingOrigin = 7,
kTopicsToggleNewValue = 8,
kForceChromeBuild = 9,
kPromptAction = 10,
kEventReportingDestinationOrigin = 11,
kOutSharedStorageDebugMessage = 12,
kOutSharedStorageSelectURLDebugMessage = 13,
};
// Defines the expected output of the functions under test, when the profile is
// setup as per defined state, and they are provided the defined inputs.
enum class OutputKey {
kIsTopicsAllowed = 1,
kIsTopicsAllowedForContext = 2,
kIsAttributionReportingAllowed = 4,
kMaySendAttributionReport = 5,
kIsSharedStorageAllowed = 6,
kIsSharedStorageSelectURLAllowed = 7,
kIsPrivateAggregationAllowed = 8,
kIsTopicsAllowedMetric = 9,
kIsTopicsAllowedForContextMetric = 10,
kIsAttributionReportingAllowedMetric = 12,
kMaySendAttributionReportMetric = 13,
kIsSharedStorageAllowedMetric = 14,
kIsSharedStorageSelectURLAllowedMetric = 15,
kIsPrivateAggregationAllowedMetric = 16,
kTopicsConsentGiven = 17,
kTopicsConsentLastUpdateReason = 18,
kTopicsConsentLastUpdateTime = 19,
kTopicsConsentStringIdentifiers = 20,
kPromptType = 21,
kM1PromptSuppressedReason = 22,
kM1ConsentDecisionMade = 23,
kM1EEANoticeAcknowledged = 24,
kM1RowNoticeAcknowledged = 25,
kM1TopicsEnabled = 26,
kM1FledgeEnabled = 27,
kM1AdMeasurementEnabled = 28,
kIsAttributionReportingEverAllowed = 29,
kIsAttributionReportingEverAllowedMetric = 30,
kM1RestrictedNoticeAcknowledged = 31,
kIsEventReportingDestinationAttestedForFledge = 32,
kIsEventReportingDestinationAttestedForSharedStorage = 33,
kIsEventReportingDestinationAttestedForFledgeMetric = 34,
kIsEventReportingDestinationAttestedForSharedStorageMetric = 35,
kIsFledgeJoinAllowed = 36,
kIsFledgeLeaveAllowed = 37,
kIsFledgeUpdateAllowed = 38,
kIsFledgeSellAllowed = 39,
kIsFledgeBuyAllowed = 40,
kIsFledgeJoinAllowedMetric = 41,
kIsFledgeLeaveAllowedMetric = 42,
kIsFledgeUpdateAllowedMetric = 43,
kIsFledgeSellAllowedMetric = 44,
kIsFledgeBuyAllowedMetric = 45,
kIsCookieDeprecationLabelAllowedForContext = 46,
kIsPrivateAggregationDebugModeAllowed = 47,
kIsSharedStorageAllowedDebugMessage = 48,
kIsSharedStorageSelectURLAllowedDebugMessage = 49,
};
// To allow multiple input keys to map to the same value, without having to
// redeclare every such relationship, additional types are defined here. The
// result is that `TestKey` can represent 1:1 and many:1 key value
// relationships.
template <typename T>
using MultipleKeys = std::set<T>;
using MultipleStateKeys = MultipleKeys<StateKey>;
using MultipleInputKeys = MultipleKeys<InputKey>;
using MultipleOutputKeys = MultipleKeys<OutputKey>;
template <typename T>
using TestKey = absl::variant<T, MultipleKeys<T>>;
using SiteDataException = std::pair<std::string, ContentSetting>;
using SiteDataExceptions = std::vector<SiteDataException>;
// Although each part of the test case (state, input, output) uses different
// key types, the set of value types associated with those keys is shared, and
// represented by this variant. When accessing keys, the test util will expect
// a particular value type, and will error otherwise.
using TestCaseItemValue = absl::variant<
bool,
std::string,
std::string*,
url::Origin,
GURL,
content_settings::CookieControlsMode,
SiteDataExceptions,
ContentSetting,
int,
base::Time,
base::TimeDelta,
privacy_sandbox::TopicsConsentUpdateSource,
std::vector<int>,
std::optional<privacy_sandbox::PrivacySandboxAttestationsMap>>;
using TestState = std::map<TestKey<StateKey>, TestCaseItemValue>;
using TestInput = std::map<TestKey<InputKey>, TestCaseItemValue>;
using TestOutput = std::map<TestKey<OutputKey>, TestCaseItemValue>;
using TestCase = std::tuple<TestState, TestInput, TestOutput>;
// Define an additional content setting value to simulate an unmanaged default
// content setting.
const ContentSetting kNoSetting = static_cast<ContentSetting>(-1);
struct CookieContentSettingException {
std::string primary_pattern;
std::string secondary_pattern;
ContentSetting content_setting;
};
// Setup and run the provided test case.
void RunTestCase(
content::BrowserTaskEnvironment* task_environment,
sync_preferences::TestingPrefServiceSyncable* testing_pref_service,
HostContentSettingsMap* host_content_settings_map,
MockPrivacySandboxSettingsDelegate* mock_delegate,
browsing_topics::MockBrowsingTopicsService* mock_browsing_topics_service,
privacy_sandbox::PrivacySandboxSettings* privacy_sandbox_settings,
PrivacySandboxServiceTestInterface* privacy_sandbox_service,
content_settings::MockProvider* user_content_setting_provider,
content_settings::MockProvider* managed_content_setting_provider,
const TestCase& test_case);
// Applies the state defined by `key`, `value` to the provided profile
// components. This is only exposed for access via the TestUtil unittest.
// Use `RunTestCase()` exclusively elsewhere.
void ApplyTestState(
StateKey key,
const TestCaseItemValue& value,
content::BrowserTaskEnvironment* task_environment,
sync_preferences::TestingPrefServiceSyncable* testing_pref_service,
HostContentSettingsMap* map,
MockPrivacySandboxSettingsDelegate* mock_delegate,
PrivacySandboxServiceTestInterface* privacy_sandbox_service,
browsing_topics::MockBrowsingTopicsService* mock_browsing_topics_service,
privacy_sandbox::PrivacySandboxSettings* privacy_sandbox_settings,
content_settings::MockProvider* user_content_setting_provider,
content_settings::MockProvider* managed_content_setting_provider);
// Some input is not directly passed to the function under test, and so must
// be run in advance of checking output. When input is provided directly to
// and output function, it is handled in `CheckOutput()`. This is only exposed
// for access via the TestUtil unit test. Use `RunTestCase()` exclusively
// elsewhere.
void ProvideInput(const std::pair<InputKey, TestCaseItemValue>& input,
PrivacySandboxServiceTestInterface* privacy_sandbox_service);
// Checks that the output of functions defined in `output`, when provided with
// appropriate entries from `input` is as expected. This is only exposed for
// access via the TestUtil unit test. Use `RunTestCase()` exclusively elsewhere.
void CheckOutput(
const std::map<InputKey, TestCaseItemValue>& input,
const std::pair<OutputKey, TestCaseItemValue>& output,
privacy_sandbox::PrivacySandboxSettings* privacy_sandbox_settings,
PrivacySandboxServiceTestInterface* privacy_sandbox_service,
sync_preferences::TestingPrefServiceSyncable* testing_pref_service);
} // namespace privacy_sandbox_test_util
#endif // COMPONENTS_PRIVACY_SANDBOX_PRIVACY_SANDBOX_TEST_UTIL_H_