blob: bc39911116cbf1d67667b21cd56868516680f602 [file] [log] [blame]
// Copyright 2017 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/ukm/observers/sync_disable_observer.h"
#include "base/observer_list.h"
#include "components/sync/driver/sync_token_status.h"
#include "components/sync/driver/test_sync_service.h"
#include "components/sync/engine/cycle/sync_cycle_snapshot.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "components/unified_consent/feature.h"
#include "components/unified_consent/pref_names.h"
#include "components/unified_consent/scoped_unified_consent.h"
#include "components/unified_consent/unified_consent_service.h"
#include "testing/gtest/include/gtest/gtest.h"
using unified_consent::ScopedUnifiedConsent;
using unified_consent::UnifiedConsentFeatureState;
namespace ukm {
namespace {
class MockSyncService : public syncer::TestSyncService {
public:
MockSyncService() {
SetTransportState(TransportState::INITIALIZING);
SetLastCycleSnapshot(syncer::SyncCycleSnapshot());
}
~MockSyncService() override { Shutdown(); }
void SetStatus(bool has_passphrase, bool history_enabled, bool active) {
SetTransportState(active ? TransportState::ACTIVE
: TransportState::INITIALIZING);
SetIsUsingSecondaryPassphrase(has_passphrase);
SetPreferredDataTypes(
history_enabled
? syncer::ModelTypeSet(syncer::HISTORY_DELETE_DIRECTIVES)
: syncer::ModelTypeSet());
// It doesn't matter what exactly we set here, it's only relevant that the
// SyncCycleSnapshot is initialized at all.
SetLastCycleSnapshot(syncer::SyncCycleSnapshot(
syncer::ModelNeutralState(), syncer::ProgressMarkerMap(), false, 0, 0,
0, true, 0, base::Time::Now(), base::Time::Now(),
std::vector<int>(syncer::ModelType::NUM_ENTRIES, 0),
std::vector<int>(syncer::ModelType::NUM_ENTRIES, 0),
sync_pb::SyncEnums::UNKNOWN_ORIGIN, base::TimeDelta::FromMinutes(1),
false));
NotifyObserversOfStateChanged();
}
void SetAuthError(GoogleServiceAuthError::State error_state) {
syncer::TestSyncService::SetAuthError(GoogleServiceAuthError(error_state));
NotifyObserversOfStateChanged();
}
void Shutdown() override {
for (auto& observer : observers_) {
observer.OnSyncShutdown(this);
}
}
private:
// syncer::TestSyncService:
void AddObserver(syncer::SyncServiceObserver* observer) override {
observers_.AddObserver(observer);
}
void RemoveObserver(syncer::SyncServiceObserver* observer) override {
observers_.RemoveObserver(observer);
}
void NotifyObserversOfStateChanged() {
for (auto& observer : observers_) {
observer.OnStateChanged(this);
}
}
// The list of observers of the SyncService state.
base::ObserverList<syncer::SyncServiceObserver>::Unchecked observers_;
DISALLOW_COPY_AND_ASSIGN(MockSyncService);
};
class TestSyncDisableObserver : public SyncDisableObserver {
public:
TestSyncDisableObserver() : purged_(false), notified_(false) {}
~TestSyncDisableObserver() override {}
bool ResetPurged() {
bool was_purged = purged_;
purged_ = false;
return was_purged;
}
bool ResetNotified() {
bool notified = notified_;
notified_ = false;
return notified;
}
private:
// SyncDisableObserver:
void OnSyncPrefsChanged(bool must_purge) override {
notified_ = true;
purged_ = purged_ || must_purge;
}
bool purged_;
bool notified_;
DISALLOW_COPY_AND_ASSIGN(TestSyncDisableObserver);
};
class SyncDisableObserverTest : public testing::Test {
public:
SyncDisableObserverTest() {}
void RegisterUrlKeyedAnonymizedDataCollectionPref(
sync_preferences::TestingPrefServiceSyncable& prefs) {
unified_consent::UnifiedConsentService::RegisterPrefs(prefs.registry());
}
void SetUrlKeyedAnonymizedDataCollectionEnabled(PrefService* prefs,
bool enabled) {
DCHECK(unified_consent::IsUnifiedConsentFeatureEnabled());
prefs->SetBoolean(
unified_consent::prefs::kUrlKeyedAnonymizedDataCollectionEnabled,
enabled);
}
private:
DISALLOW_COPY_AND_ASSIGN(SyncDisableObserverTest);
};
} // namespace
TEST_F(SyncDisableObserverTest, NoProfiles) {
TestSyncDisableObserver observer;
EXPECT_FALSE(observer.SyncStateAllowsUkm());
EXPECT_FALSE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
}
TEST_F(SyncDisableObserverTest, NotActive) {
MockSyncService sync;
sync.SetStatus(false, true, false);
sync_preferences::TestingPrefServiceSyncable prefs;
RegisterUrlKeyedAnonymizedDataCollectionPref(prefs);
TestSyncDisableObserver observer;
observer.ObserveServiceForSyncDisables(&sync, &prefs);
EXPECT_FALSE(observer.SyncStateAllowsUkm());
EXPECT_FALSE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
}
TEST_F(SyncDisableObserverTest, OneEnabled_UnifiedConsentDisabled) {
ScopedUnifiedConsent scoped_unified_consent(
UnifiedConsentFeatureState::kDisabled);
TestSyncDisableObserver observer;
MockSyncService sync;
sync.SetStatus(false, true, true);
observer.ObserveServiceForSyncDisables(&sync, nullptr);
EXPECT_TRUE(observer.SyncStateAllowsUkm());
EXPECT_TRUE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
}
TEST_F(SyncDisableObserverTest, OneEnabled_UnifiedConsentEnabled) {
ScopedUnifiedConsent scoped_unified_consent(
UnifiedConsentFeatureState::kEnabled);
sync_preferences::TestingPrefServiceSyncable prefs;
RegisterUrlKeyedAnonymizedDataCollectionPref(prefs);
SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs, true);
MockSyncService sync;
for (bool has_passphrase : {true, false}) {
for (bool history_enabled : {true, false}) {
TestSyncDisableObserver observer;
sync.SetStatus(has_passphrase, history_enabled, /*active=*/true);
observer.ObserveServiceForSyncDisables(&sync, &prefs);
EXPECT_TRUE(observer.SyncStateAllowsUkm());
EXPECT_TRUE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
}
}
}
TEST_F(SyncDisableObserverTest, Passphrased_UnifiedConsentDisabled) {
ScopedUnifiedConsent scoped_unified_consent(
UnifiedConsentFeatureState::kDisabled);
MockSyncService sync;
sync.SetStatus(true, true, true);
TestSyncDisableObserver observer;
observer.ObserveServiceForSyncDisables(&sync, nullptr);
EXPECT_FALSE(observer.SyncStateAllowsUkm());
EXPECT_FALSE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
}
TEST_F(SyncDisableObserverTest, HistoryDisabled_UnifiedConsentDisabled) {
ScopedUnifiedConsent scoped_unified_consent(
UnifiedConsentFeatureState::kDisabled);
TestSyncDisableObserver observer;
MockSyncService sync;
sync.SetStatus(false, false, true);
observer.ObserveServiceForSyncDisables(&sync, nullptr);
EXPECT_FALSE(observer.SyncStateAllowsUkm());
EXPECT_FALSE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
}
TEST_F(SyncDisableObserverTest, AuthError_UnifiedConsentDisabled) {
ScopedUnifiedConsent scoped_unified_consent(
UnifiedConsentFeatureState::kDisabled);
TestSyncDisableObserver observer;
MockSyncService sync;
sync.SetStatus(false, true, true);
observer.ObserveServiceForSyncDisables(&sync, nullptr);
EXPECT_TRUE(observer.SyncStateAllowsUkm());
sync.SetAuthError(GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
EXPECT_FALSE(observer.SyncStateAllowsUkm());
sync.SetAuthError(GoogleServiceAuthError::NONE);
EXPECT_TRUE(observer.SyncStateAllowsUkm());
}
TEST_F(SyncDisableObserverTest, MixedProfiles1_UnifiedConsentDisabled) {
ScopedUnifiedConsent scoped_unified_consent(
UnifiedConsentFeatureState::kDisabled);
TestSyncDisableObserver observer;
MockSyncService sync1;
sync1.SetStatus(false, false, true);
observer.ObserveServiceForSyncDisables(&sync1, nullptr);
MockSyncService sync2;
sync2.SetStatus(false, true, true);
observer.ObserveServiceForSyncDisables(&sync2, nullptr);
EXPECT_FALSE(observer.SyncStateAllowsUkm());
EXPECT_FALSE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
}
TEST_F(SyncDisableObserverTest, MixedProfiles2_UnifiedConsentDisabled) {
ScopedUnifiedConsent scoped_unified_consent(
UnifiedConsentFeatureState::kDisabled);
TestSyncDisableObserver observer;
MockSyncService sync1;
sync1.SetStatus(false, true, true);
observer.ObserveServiceForSyncDisables(&sync1, nullptr);
EXPECT_TRUE(observer.ResetNotified());
MockSyncService sync2;
sync2.SetStatus(false, false, true);
observer.ObserveServiceForSyncDisables(&sync2, nullptr);
EXPECT_FALSE(observer.SyncStateAllowsUkm());
EXPECT_TRUE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
sync2.Shutdown();
EXPECT_TRUE(observer.SyncStateAllowsUkm());
EXPECT_TRUE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
}
TEST_F(SyncDisableObserverTest, MixedProfiles_UnifiedConsentEnabled) {
ScopedUnifiedConsent scoped_unified_consent(
UnifiedConsentFeatureState::kEnabled);
sync_preferences::TestingPrefServiceSyncable prefs1;
RegisterUrlKeyedAnonymizedDataCollectionPref(prefs1);
sync_preferences::TestingPrefServiceSyncable prefs2;
RegisterUrlKeyedAnonymizedDataCollectionPref(prefs2);
TestSyncDisableObserver observer;
MockSyncService sync1;
SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs1, false);
observer.ObserveServiceForSyncDisables(&sync1, &prefs1);
MockSyncService sync2;
SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs2, true);
observer.ObserveServiceForSyncDisables(&sync2, &prefs2);
EXPECT_FALSE(observer.SyncStateAllowsUkm());
EXPECT_FALSE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
}
TEST_F(SyncDisableObserverTest, TwoEnabled_UnifiedConsentDisabled) {
ScopedUnifiedConsent scoped_unified_consent(
UnifiedConsentFeatureState::kDisabled);
TestSyncDisableObserver observer;
MockSyncService sync1;
sync1.SetStatus(false, true, true);
observer.ObserveServiceForSyncDisables(&sync1, nullptr);
EXPECT_TRUE(observer.ResetNotified());
MockSyncService sync2;
sync2.SetStatus(false, true, true);
observer.ObserveServiceForSyncDisables(&sync2, nullptr);
EXPECT_TRUE(observer.SyncStateAllowsUkm());
EXPECT_FALSE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
}
TEST_F(SyncDisableObserverTest, TwoEnabled_UnifiedConsentEnabled) {
ScopedUnifiedConsent scoped_unified_consent(
UnifiedConsentFeatureState::kEnabled);
sync_preferences::TestingPrefServiceSyncable prefs1;
RegisterUrlKeyedAnonymizedDataCollectionPref(prefs1);
sync_preferences::TestingPrefServiceSyncable prefs2;
RegisterUrlKeyedAnonymizedDataCollectionPref(prefs2);
TestSyncDisableObserver observer;
MockSyncService sync1;
SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs1, true);
observer.ObserveServiceForSyncDisables(&sync1, &prefs1);
EXPECT_TRUE(observer.ResetNotified());
MockSyncService sync2;
SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs2, true);
observer.ObserveServiceForSyncDisables(&sync2, &prefs2);
EXPECT_TRUE(observer.SyncStateAllowsUkm());
EXPECT_FALSE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
}
TEST_F(SyncDisableObserverTest, OneAddRemove_UnifiedConsentDisabled) {
ScopedUnifiedConsent scoped_unified_consent(
UnifiedConsentFeatureState::kDisabled);
TestSyncDisableObserver observer;
MockSyncService sync;
observer.ObserveServiceForSyncDisables(&sync, nullptr);
EXPECT_FALSE(observer.SyncStateAllowsUkm());
EXPECT_FALSE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
sync.SetStatus(false, true, true);
EXPECT_TRUE(observer.SyncStateAllowsUkm());
EXPECT_TRUE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
sync.Shutdown();
EXPECT_FALSE(observer.SyncStateAllowsUkm());
EXPECT_TRUE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
}
TEST_F(SyncDisableObserverTest, OneAddRemove_UnifiedConsentEnabled) {
ScopedUnifiedConsent scoped_unified_consent(
UnifiedConsentFeatureState::kEnabled);
sync_preferences::TestingPrefServiceSyncable prefs;
RegisterUrlKeyedAnonymizedDataCollectionPref(prefs);
TestSyncDisableObserver observer;
MockSyncService sync;
observer.ObserveServiceForSyncDisables(&sync, &prefs);
EXPECT_FALSE(observer.SyncStateAllowsUkm());
EXPECT_FALSE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs, true);
EXPECT_TRUE(observer.SyncStateAllowsUkm());
EXPECT_TRUE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
sync.Shutdown();
EXPECT_FALSE(observer.SyncStateAllowsUkm());
EXPECT_TRUE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
}
TEST_F(SyncDisableObserverTest, PurgeOnDisable_UnifiedConsentDisabled) {
ScopedUnifiedConsent scoped_unified_consent(
UnifiedConsentFeatureState::kDisabled);
TestSyncDisableObserver observer;
MockSyncService sync;
sync.SetStatus(false, true, true);
observer.ObserveServiceForSyncDisables(&sync, nullptr);
EXPECT_TRUE(observer.SyncStateAllowsUkm());
EXPECT_TRUE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
sync.SetStatus(false, false, true);
EXPECT_FALSE(observer.SyncStateAllowsUkm());
EXPECT_TRUE(observer.ResetNotified());
EXPECT_TRUE(observer.ResetPurged());
sync.Shutdown();
EXPECT_FALSE(observer.SyncStateAllowsUkm());
EXPECT_FALSE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
}
TEST_F(SyncDisableObserverTest, PurgeOnDisable_UnifiedConsentEnabled) {
ScopedUnifiedConsent scoped_unified_consent(
UnifiedConsentFeatureState::kEnabled);
sync_preferences::TestingPrefServiceSyncable prefs;
RegisterUrlKeyedAnonymizedDataCollectionPref(prefs);
TestSyncDisableObserver observer;
MockSyncService sync;
SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs, true);
observer.ObserveServiceForSyncDisables(&sync, &prefs);
EXPECT_TRUE(observer.SyncStateAllowsUkm());
EXPECT_TRUE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs, false);
EXPECT_FALSE(observer.SyncStateAllowsUkm());
EXPECT_TRUE(observer.ResetNotified());
EXPECT_TRUE(observer.ResetPurged());
sync.Shutdown();
EXPECT_FALSE(observer.SyncStateAllowsUkm());
EXPECT_FALSE(observer.ResetNotified());
EXPECT_FALSE(observer.ResetPurged());
}
} // namespace ukm