chromium/components/ukm/observers/ukm_consent_state_observer_unittest.cc

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/ukm/observers/ukm_consent_state_observer.h"

#include "base/observer_list.h"
#include "base/test/scoped_feature_list.h"
#include "components/sync/engine/cycle/sync_cycle_snapshot.h"
#include "components/sync/protocol/sync_enums.pb.h"
#include "components/sync/service/sync_token_status.h"
#include "components/sync/test/test_sync_service.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "components/unified_consent/pref_names.h"
#include "components/unified_consent/unified_consent_service.h"
#include "testing/gtest/include/gtest/gtest.h"

#if BUILDFLAG(IS_CHROMEOS)
#include "chromeos/components/kiosk/kiosk_test_utils.h"  // nogncheck
#include "chromeos/components/mgs/managed_guest_session_test_utils.h"
#endif  // BUILDFLAG(IS_CHROMEOS)

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "components/user_manager/fake_user_manager.h"
#include "components/user_manager/scoped_user_manager.h"
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

namespace ukm {

namespace {

class MockSyncService : public syncer::TestSyncService {};

class TestUkmConsentStateObserver : public UkmConsentStateObserver {};

class UkmConsentStateObserverTest : public testing::TestWithParam<bool> {};

}  // namespace

TEST_F(UkmConsentStateObserverTest, NoProfiles) {}

TEST_F(UkmConsentStateObserverTest, NotActive) {}

TEST_F(UkmConsentStateObserverTest, OneEnabled) {}

TEST_F(UkmConsentStateObserverTest, MixedProfiles) {}

TEST_F(UkmConsentStateObserverTest, TwoEnabled) {}

TEST_F(UkmConsentStateObserverTest, OneAddRemove) {}

TEST_F(UkmConsentStateObserverTest, PurgeOnDisable) {}

TEST_F(UkmConsentStateObserverTest, NoInitialUkmConsentState) {}

#if BUILDFLAG(IS_CHROMEOS_ASH)
TEST_F(UkmConsentStateObserverTest, VerifyConsentStates) {
  sync_preferences::TestingPrefServiceSyncable prefs;
  RegisterUrlKeyedAnonymizedDataCollectionPref(prefs);
  TestUkmConsentStateObserver observer;
  MockSyncService sync;
  // Disable app sync consent.
  sync.SetAppSync(false);

  // Enable MSBB consent.
  SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs, /*enabled=*/true);
  observer.StartObserving(&sync, &prefs);

  UkmConsentState state = observer.GetUkmConsentState();

  EXPECT_TRUE(observer.IsUkmAllowedForAllProfiles());
  // MSBB and Extensions are enabled while App Sync is disabled.
  EXPECT_TRUE(state.Has(MSBB));
  EXPECT_TRUE(state.Has(EXTENSIONS));
  EXPECT_FALSE(state.Has(APPS));

  // UKM is enabled and the consent state was changed. Purge will not happen
  // because UKM was enabled not disabled.
  EXPECT_TRUE(observer.ResetNotified());
  EXPECT_FALSE(observer.ResetPurged());

  // Turn on app sync.
  sync.SetAppSync(true);
  state = observer.GetUkmConsentState();

  // Verify that the these values remain unchanged with App-sync enablement.
  EXPECT_TRUE(observer.IsUkmAllowedForAllProfiles());
  EXPECT_TRUE(state.Has(MSBB));
  EXPECT_TRUE(state.Has(EXTENSIONS));
  EXPECT_TRUE(observer.ResetNotified());
  EXPECT_FALSE(observer.ResetPurged());

  // Check for the updated consent propagated correctly.
  EXPECT_TRUE(state.Has(APPS));

  // Turn off MSBB.
  SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs, /*enabled=*/false);

  state = observer.GetUkmConsentState();

  // UKM will remain allowed.
  EXPECT_TRUE(observer.IsUkmAllowedForAllProfiles());
  // MSBB should be off.
  EXPECT_FALSE(state.Has(MSBB));
  // Extensions should be off, implicitly.
  EXPECT_FALSE(state.Has(EXTENSIONS));
  // App sync will stay on.
  EXPECT_TRUE(state.Has(APPS));
  EXPECT_TRUE(observer.ResetNotified());
  // UKM is still allowed, total purge is not triggered.
  EXPECT_FALSE(observer.ResetPurged());

  // Finally, turn off app sync.
  sync.SetAppSync(false);

  state = observer.GetUkmConsentState();
  // All consents should be off.
  EXPECT_FALSE(state.Has(MSBB));
  EXPECT_FALSE(state.Has(EXTENSIONS));
  EXPECT_FALSE(state.Has(APPS));
  EXPECT_TRUE(observer.ResetNotified());

  // All UKM consent is turned off, total purge will be triggered.
  EXPECT_TRUE(observer.ResetPurged());
}

TEST_F(UkmConsentStateObserverTest, VerifyConflictingProfilesRevokesConsent) {
  sync_preferences::TestingPrefServiceSyncable prefs1;
  RegisterUrlKeyedAnonymizedDataCollectionPref(prefs1);
  sync_preferences::TestingPrefServiceSyncable prefs2;
  RegisterUrlKeyedAnonymizedDataCollectionPref(prefs2);

  // Add Profile 1 with MSBB consent but not App Sync.
  TestUkmConsentStateObserver observer;
  MockSyncService sync1;
  sync1.SetAppSync(false);
  SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs1, /*enabled=*/true);
  observer.StartObserving(&sync1, &prefs1);
  EXPECT_TRUE(observer.ResetNotified());
  EXPECT_FALSE(observer.ResetPurged());
  const UkmConsentState consent_state = observer.GetUkmConsentState();
  EXPECT_TRUE(consent_state.Has(MSBB));
  EXPECT_FALSE(consent_state.Has(APPS));

  // Add Profile 2 with App Sync consent but not MSBB.
  MockSyncService sync2;
  sync2.SetAppSync(true);
  SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs2, /*enabled=*/false);
  observer.StartObserving(&sync2, &prefs2);
  EXPECT_TRUE(observer.ResetNotified());

  // Consents of MSBB and App-sync for each profile conflicts with either other
  // resulting in all types of consent being false.
  // MSBB is off because Profile 1 consents but Profile 2 doesn't.
  // APP sync is off because Profile 2 consents but Profile 1 doesn't.
  UkmConsentState state = observer.GetUkmConsentState();
  EXPECT_FALSE(observer.IsUkmAllowedForAllProfiles());
  EXPECT_FALSE(state.Has(MSBB));
  EXPECT_FALSE(state.Has(EXTENSIONS));
  EXPECT_FALSE(state.Has(APPS));
  EXPECT_FALSE(observer.ResetPurged());
}

#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

#if BUILDFLAG(IS_CHROMEOS)

// Test consent state for kiosk.
class KioskUkmConsentStateObserverTest : public UkmConsentStateObserverTest {
 public:
  bool is_ukm_collection_enabled() const { return GetParam(); }
};

TEST_P(KioskUkmConsentStateObserverTest, VerifyDefaultConsent) {
  // Enter Kiosk session.
#if BUILDFLAG(IS_CHROMEOS_ASH)
  user_manager::ScopedUserManager user_manager(
      std::make_unique<user_manager::FakeUserManager>());
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
  chromeos::SetUpFakeKioskSession();

  sync_preferences::TestingPrefServiceSyncable prefs;
  RegisterUrlKeyedAnonymizedDataCollectionPref(prefs);
  TestUkmConsentStateObserver observer;
  MockSyncService sync;
  // Disable app sync consent.
  sync.SetAppSync(false);

  // Enable MSBB consent.
  SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs,
                                             is_ukm_collection_enabled());
  observer.StartObserving(&sync, &prefs);

  UkmConsentState state = observer.GetUkmConsentState();

  EXPECT_EQ(is_ukm_collection_enabled(), observer.IsUkmAllowedForAllProfiles());
  // MSBB and Extensions are enabled while App Sync is disabled.
  EXPECT_EQ(is_ukm_collection_enabled(), state.Has(MSBB));
  EXPECT_EQ(is_ukm_collection_enabled(), state.Has(APPS));
}

INSTANTIATE_TEST_SUITE_P(KioskUkmConsentStateObserverTest,
                         KioskUkmConsentStateObserverTest,
                         ::testing::Bool());

// Test consent state for managed guest session (MGS).
class MgsUkmConsentStateObserverTest : public UkmConsentStateObserverTest {
 public:
  bool is_ukm_collection_enabled() const { return GetParam(); }

 private:
  chromeos::FakeManagedGuestSession managed_guest_session;
};

TEST_P(MgsUkmConsentStateObserverTest, VerifyAppsOnlyConsent) {
  sync_preferences::TestingPrefServiceSyncable prefs;
  RegisterUrlKeyedAnonymizedDataCollectionPref(prefs);
  TestUkmConsentStateObserver observer;
  MockSyncService sync;
  // Disable app sync consent.
  sync.SetAppSync(false);

  SetUrlKeyedAnonymizedDataCollectionEnabled(&prefs,
                                             is_ukm_collection_enabled());
  observer.StartObserving(&sync, &prefs);

  UkmConsentState state = observer.GetUkmConsentState();

  // MGS should report AppKM if policy is enabled.
  EXPECT_EQ(is_ukm_collection_enabled(), state.Has(APPS));
  EXPECT_EQ(false, state.Has(MSBB));
}

INSTANTIATE_TEST_SUITE_P(MgsUkmConsentStateObserverTest,
                         MgsUkmConsentStateObserverTest,
                         ::testing::Bool());

#endif  // BUILDFLAG(IS_CHROMEOS)

}  // namespace ukm