blob: f6462ecc94ba5d8134a9702ef69ae3f6682f4abc [file] [log] [blame]
// 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 <memory>
#include <string>
#include "base/files/file_path.h"
#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/system/sys_info.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "build/buildflag.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browsing_data/chrome_browsing_data_remover_constants.h"
#include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
#include "chrome/browser/metrics/chrome_metrics_service_client.h"
#include "chrome/browser/metrics/chrome_metrics_services_manager_client.h"
#include "chrome/browser/metrics/testing/metrics_reporting_pref_helper.h"
#include "chrome/browser/metrics/testing/sync_metrics_test_utils.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/profiles/profile_test_util.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/sync/sync_service_factory.h"
#include "chrome/browser/sync/test/integration/secondary_account_helper.h"
#include "chrome/browser/sync/test/integration/sync_service_impl_harness.h"
#include "chrome/browser/sync/test/integration/sync_test.h"
#include "chrome/browser/unified_consent/unified_consent_service_factory.h"
#include "components/metrics/demographics/demographic_metrics_provider.h"
#include "components/metrics/demographics/demographic_metrics_test_utils.h"
#include "components/metrics_services_manager/metrics_services_manager.h"
#include "components/signin/public/base/signin_buildflags.h"
#include "components/signin/public/identity_manager/identity_manager.h"
#include "components/sync/base/features.h"
#include "components/sync/service/sync_service.h"
#include "components/sync/service/sync_service_impl.h"
#include "components/sync/service/sync_token_status.h"
#include "components/sync/test/fake_server_network_resources.h"
#include "components/ukm/ukm_recorder_observer.h"
#include "components/ukm/ukm_service.h"
#include "components/ukm/ukm_test_helper.h"
#include "components/unified_consent/unified_consent_service.h"
#include "components/version_info/version_info.h"
#include "content/public/browser/browsing_data_remover.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "content/public/test/browser_test.h"
#include "content/public/test/browser_test_utils.h"
#include "content/public/test/browsing_data_remover_test_util.h"
#include "content/public/test/navigation_handle_observer.h"
#include "content/public/test/test_navigation_observer.h"
#include "content/public/test/test_utils.h"
#include "services/metrics/public/cpp/ukm_recorder.h"
#include "services/metrics/public/cpp/ukm_source.h"
#include "services/network/test/test_network_quality_tracker.h"
#include "third_party/metrics_proto/ukm/report.pb.h"
#include "third_party/metrics_proto/user_demographics.pb.h"
#include "url/url_constants.h"
#if !BUILDFLAG(IS_ANDROID)
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/tabs/tab_enums.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "chrome/test/base/ui_test_utils.h"
#else
#include "chrome/browser/flags/android/chrome_feature_list.h"
#include "chrome/browser/flags/android/chrome_session_state.h"
#include "chrome/browser/ui/android/tab_model/tab_model.h"
#include "chrome/browser/ui/android/tab_model/tab_model_list.h"
#include "chrome/browser/ui/android/tab_model/tab_model_observer.h"
#include "chrome/test/base/android/android_browser_test.h"
#include "content/public/browser/web_contents.h"
#endif // !BUILDFLAG(IS_ANDROID)
#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID)
#include "chrome/browser/ui/profiles/profile_picker.h"
#include "chrome/browser/ui/profiles/profile_ui_test_utils.h"
#endif // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID)
namespace metrics {
namespace {
class TestTabModel;
#if !BUILDFLAG(IS_ANDROID)
typedef Browser* PlatformBrowser;
#else
typedef std::unique_ptr<TestTabModel> PlatformBrowser;
#endif // !BUILDFLAG(IS_ANDROID)
// Clears the specified data using BrowsingDataRemover.
void ClearBrowsingData(Profile* profile) {
content::BrowsingDataRemover* remover = profile->GetBrowsingDataRemover();
content::BrowsingDataRemoverCompletionObserver observer(remover);
remover->RemoveAndReply(
base::Time(), base::Time::Max(),
chrome_browsing_data_remover::DATA_TYPE_HISTORY,
content::BrowsingDataRemover::ORIGIN_TYPE_UNPROTECTED_WEB, &observer);
observer.BlockUntilCompletion();
// Make sure HistoryServiceObservers have a chance to be notified.
content::RunAllTasksUntilIdle();
}
ukm::UkmService* GetUkmService() {
return g_browser_process->GetMetricsServicesManager()->GetUkmService();
}
class TestUkmRecorderObserver : public ukm::UkmRecorderObserver {
public:
explicit TestUkmRecorderObserver(ukm::UkmRecorderImpl* ukm_recorder)
: ukm_recorder_(ukm_recorder) {
ukm_recorder_->AddUkmRecorderObserver(base::flat_set<uint64_t>(), this);
}
~TestUkmRecorderObserver() override {
ukm_recorder_->RemoveUkmRecorderObserver(this);
}
void OnEntryAdded(ukm::mojom::UkmEntryPtr entry) override {}
void OnUpdateSourceURL(ukm::SourceId source_id,
const std::vector<GURL>& urls) override {}
void OnPurgeRecordingsWithUrlScheme(const std::string& url_scheme) override {}
void OnPurge() override {}
void ExpectAllowedStateChanged(ukm::UkmConsentState expected_state) {
expected_allowed_ = expected_state;
base::RunLoop loop;
quit_closure_ = loop.QuitClosure();
loop.Run();
}
void OnUkmAllowedStateChanged(ukm::UkmConsentState allowed_state) override {
if (allowed_state == expected_allowed_) {
std::move(quit_closure_).Run();
}
}
private:
ukm::UkmConsentState expected_allowed_;
base::OnceClosure quit_closure_;
raw_ptr<ukm::UkmRecorderImpl> ukm_recorder_;
};
#if BUILDFLAG(IS_ANDROID)
// ActivityType that doesn't restore tabs on cold start.
// Any type other than kTabbed is fine.
const auto TEST_ACTIVITY_TYPE = chrome::android::ActivityType::kCustomTab;
// TestTabModel provides a means of creating a tab associated with a given
// profile. The new tab can then be added to Android's TabModelList.
class TestTabModel : public TabModel {
public:
explicit TestTabModel(Profile* profile)
: TabModel(profile, TEST_ACTIVITY_TYPE),
web_contents_(content::WebContents::Create(
content::WebContents::CreateParams(GetProfile()))) {}
~TestTabModel() override = default;
// TabModel:
int GetTabCount() const override { return 0; }
int GetActiveIndex() const override { return 0; }
base::android::ScopedJavaLocalRef<jobject> GetJavaObject() const override {
return nullptr;
}
content::WebContents* GetActiveWebContents() const override {
return web_contents_.get();
}
content::WebContents* GetWebContentsAt(int index) const override {
return nullptr;
}
TabAndroid* GetTabAt(int index) const override { return nullptr; }
void SetActiveIndex(int index) override {}
void CloseTabAt(int index) override {}
void CreateTab(TabAndroid* parent,
content::WebContents* web_contents) override {}
void HandlePopupNavigation(TabAndroid* parent,
NavigateParams* params) override {}
content::WebContents* CreateNewTabForDevTools(const GURL& url) override {
return nullptr;
}
bool IsSessionRestoreInProgress() const override { return false; }
bool IsActiveModel() const override { return false; }
void AddObserver(TabModelObserver* observer) override {}
void RemoveObserver(TabModelObserver* observer) override {}
private:
// The WebContents associated with this tab's profile.
std::unique_ptr<content::WebContents> web_contents_;
};
#endif // BUILDFLAG(IS_ANDROID)
} // namespace
// A helper object for overriding metrics enabled state.
class MetricsConsentOverride {
public:
explicit MetricsConsentOverride(bool initial_state) : state_(initial_state) {
ChromeMetricsServiceAccessor::SetMetricsAndCrashReportingForTesting(
&state_);
Update(initial_state);
}
~MetricsConsentOverride() {
ChromeMetricsServiceAccessor::SetMetricsAndCrashReportingForTesting(
nullptr);
}
void Update(bool state) {
state_ = state;
// Trigger rechecking of metrics state.
g_browser_process->GetMetricsServicesManager()->UpdateUploadPermissions(
true);
}
private:
bool state_;
};
// Test fixture that provides access to some UKM internals.
class UkmBrowserTestBase : public SyncTest {
public:
UkmBrowserTestBase() : SyncTest(SINGLE_CLIENT) {
// Explicitly enable UKM and disable metrics reporting. Disabling metrics
// reporting should affect only UMA--not UKM.
scoped_feature_list_.InitWithFeatures({ukm::kUkmFeature},
{internal::kMetricsReportingFeature});
}
UkmBrowserTestBase(const UkmBrowserTestBase&) = delete;
UkmBrowserTestBase& operator=(const UkmBrowserTestBase&) = delete;
#if !BUILDFLAG(IS_ANDROID)
ukm::UkmSource* NavigateAndGetSource(const GURL& url,
Browser* browser,
ukm::UkmTestHelper* ukm_test_helper) {
content::NavigationHandleObserver observer(
browser->tab_strip_model()->GetActiveWebContents(), url);
EXPECT_TRUE(ui_test_utils::NavigateToURL(browser, url));
const ukm::SourceId source_id = ukm::ConvertToSourceId(
observer.navigation_id(), ukm::SourceIdType::NAVIGATION_ID);
return ukm_test_helper->GetSource(source_id);
}
#endif // !BUILDFLAG(IS_ANDROID)
protected:
// Creates and returns a platform-appropriate browser for |profile|.
PlatformBrowser CreatePlatformBrowser(Profile* profile) {
#if !BUILDFLAG(IS_ANDROID)
return CreateBrowser(profile);
#else
std::unique_ptr<TestTabModel> tab_model =
std::make_unique<TestTabModel>(profile);
TabModelList::AddTabModel(tab_model.get());
EXPECT_TRUE(content::NavigateToURL(tab_model->GetActiveWebContents(),
GURL("about:blank")));
return tab_model;
#endif // !BUILDFLAG(IS_ANDROID)
}
// Creates a platform-appropriate incognito browser for |profile|.
PlatformBrowser CreateIncognitoPlatformBrowser(Profile* profile) {
EXPECT_TRUE(profile->IsOffTheRecord());
#if !BUILDFLAG(IS_ANDROID)
return CreateIncognitoBrowser(profile);
#else
return CreatePlatformBrowser(profile);
#endif // !BUILDFLAG(IS_ANDROID)
}
// Closes |browser| in a way that is appropriate for the platform.
void ClosePlatformBrowser(PlatformBrowser& browser) {
#if !BUILDFLAG(IS_ANDROID)
CloseBrowserSynchronously(browser);
#else
TabModelList::RemoveTabModel(browser.get());
browser.reset();
#endif // !BUILDFLAG(IS_ANDROID)
}
std::unique_ptr<SyncServiceImplHarness> EnableSyncForProfile(
Profile* profile) {
std::unique_ptr<SyncServiceImplHarness> harness =
test::InitializeProfileForSync(profile, GetFakeServer()->AsWeakPtr());
#if BUILDFLAG(IS_CHROMEOS_LACROS)
// Apps sync is controlled by a dedicated preference on Lacros,
// corresponding to the Apps toggle in OS Sync settings.
if (base::FeatureList::IsEnabled(syncer::kSyncChromeOSAppsToggleSharing)) {
syncer::SyncUserSettings* user_settings =
harness->service()->GetUserSettings();
// Turn on App-sync in OS Sync.
user_settings->SetAppsSyncEnabledByOs(true);
}
#endif // BUILDFLAG(IS_CHROMEOS_LACROS)
EXPECT_TRUE(harness->SetupSync());
// If unified consent is enabled, then enable url-keyed-anonymized data
// collection through the consent service.
// Note: If unfied consent is not enabled, then UKM will be enabled based on
// the history sync state.
unified_consent::UnifiedConsentService* consent_service =
UnifiedConsentServiceFactory::GetForProfile(profile);
if (consent_service) {
consent_service->SetUrlKeyedAnonymizedDataCollectionEnabled(true);
}
return harness;
}
#if !BUILDFLAG(IS_ANDROID)
Profile* CreateNonSyncProfile() {
ProfileManager* profile_manager = g_browser_process->profile_manager();
base::FilePath new_path =
profile_manager->GenerateNextProfileDirectoryPath();
Profile& profile =
profiles::testing::CreateProfileSync(profile_manager, new_path);
SetupMockGaiaResponsesForProfile(&profile);
return &profile;
}
#endif // !BUILDFLAG(IS_ANDROID)
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
class UkmBrowserTest : public UkmBrowserTestBase {
public:
UkmBrowserTest() = default;
UkmBrowserTest(const UkmBrowserTest&) = delete;
UkmBrowserTest& operator=(const UkmBrowserTest&) = delete;
#if BUILDFLAG(IS_ANDROID)
void PreRunTestOnMainThread() override {
// At some point during set-up, Android's TabModelList is populated with a
// TabModel. However, it is desirable to begin the tests with an empty
// TabModelList to avoid complicated logic in CreatePlatformBrowser.
//
// For example, if the pre-existing TabModel is not deleted and if the first
// tab created in a test is an incognito tab, then CreatePlatformBrowser
// would need to remove the pre-existing TabModel and add a new one.
// Having an empty TabModelList allows us to simply add the appropriate
// TabModel.
EXPECT_EQ(1U, TabModelList::models().size());
TabModelList::RemoveTabModel(TabModelList::models()[0]);
EXPECT_EQ(0U, TabModelList::models().size());
}
#endif // BUILDFLAG(IS_ANDROID)
};
class UkmBrowserTestWithSyncTransport : public UkmBrowserTestBase {
public:
UkmBrowserTestWithSyncTransport() = default;
UkmBrowserTestWithSyncTransport(const UkmBrowserTestWithSyncTransport&) =
delete;
UkmBrowserTestWithSyncTransport& operator=(
const UkmBrowserTestWithSyncTransport&) = delete;
void SetUpInProcessBrowserTestFixture() override {
// This is required to support (fake) secondary-account-signin (based on
// cookies) in tests. Without this, the real GaiaCookieManagerService would
// try talking to Google servers which of course wouldn't work in tests.
test_signin_client_subscription_ =
secondary_account_helper::SetUpSigninClient(&test_url_loader_factory_);
UkmBrowserTestBase::SetUpInProcessBrowserTestFixture();
}
void SetUpOnMainThread() override {
#if BUILDFLAG(IS_CHROMEOS_ASH)
secondary_account_helper::InitNetwork();
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
UkmBrowserTestBase::SetUpOnMainThread();
}
private:
base::CallbackListSubscription test_signin_client_subscription_;
};
// This tests if UKM service is enabled/disabled appropriately based on an
// input bool param. The bool reflects if metrics reporting state is
// enabled/disabled via prefs.
#if !BUILDFLAG(IS_ANDROID)
class UkmConsentParamBrowserTest : public UkmBrowserTestBase,
public testing::WithParamInterface<bool> {
public:
UkmConsentParamBrowserTest() = default;
UkmConsentParamBrowserTest(const UkmConsentParamBrowserTest&) = delete;
UkmConsentParamBrowserTest& operator=(const UkmConsentParamBrowserTest&) =
delete;
static bool IsMetricsAndCrashReportingEnabled() {
return ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled();
}
// InProcessBrowserTest overrides.
bool SetUpUserDataDirectory() override {
local_state_path_ = SetUpUserDataDirectoryForTesting(
is_metrics_reporting_enabled_initial_value());
return !local_state_path_.empty();
}
void CreatedBrowserMainParts(content::BrowserMainParts* parts) override {
InProcessBrowserTest::CreatedBrowserMainParts(parts);
// IsMetricsReportingEnabled() in non-official builds always returns false.
// Enable the official build checks so that this test can work in both
// official and non-official builds.
ChromeMetricsServiceAccessor::SetForceIsMetricsReportingEnabledPrefLookup(
true);
}
bool is_metrics_reporting_enabled_initial_value() const { return GetParam(); }
private:
base::FilePath local_state_path_;
};
#endif // !BUILDFLAG(IS_ANDROID)
// Test the reporting of the synced user's birth year and gender.
class UkmBrowserTestWithDemographics
: public UkmBrowserTestBase,
public testing::WithParamInterface<test::DemographicsTestParams> {
public:
UkmBrowserTestWithDemographics() : UkmBrowserTestBase() {
test::DemographicsTestParams param = GetParam();
if (param.enable_feature) {
scoped_feature_list_.InitWithFeatures(
// enabled_features
{kDemographicMetricsReporting,
ukm::kReportUserNoisedUserBirthYearAndGender},
// disabled_features
{});
} else {
scoped_feature_list_.InitWithFeatures(
// enabled_features
{},
// disabled_features
{kDemographicMetricsReporting,
ukm::kReportUserNoisedUserBirthYearAndGender});
}
}
UkmBrowserTestWithDemographics(const UkmBrowserTestWithDemographics&) =
delete;
UkmBrowserTestWithDemographics& operator=(
const UkmBrowserTestWithDemographics&) = delete;
PrefService* local_state() { return g_browser_process->local_state(); }
private:
base::test::ScopedFeatureList scoped_feature_list_;
};
// Make sure that UKM is disabled while an incognito window is open.
// Keep in sync with testRegularPlusIncognito in ios/chrome/browser/metrics/
// ukm_egtest.mm.
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, RegularPlusIncognitoCheck) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
PlatformBrowser browser1 = CreatePlatformBrowser(profile);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
uint64_t original_client_id = ukm_test_helper.GetClientId();
EXPECT_NE(0U, original_client_id);
Profile* incognito_profile =
profile->GetPrimaryOTRProfile(/*create_if_needed=*/true);
PlatformBrowser incognito_browser1 =
CreateIncognitoPlatformBrowser(incognito_profile);
EXPECT_FALSE(ukm_test_helper.IsRecordingEnabled());
// Opening another regular browser mustn't enable UKM.
PlatformBrowser browser2 = CreatePlatformBrowser(profile);
EXPECT_FALSE(ukm_test_helper.IsRecordingEnabled());
// Opening and closing another Incognito browser mustn't enable UKM.
PlatformBrowser incognito_browser2 =
CreateIncognitoPlatformBrowser(incognito_profile);
ClosePlatformBrowser(incognito_browser2);
EXPECT_FALSE(ukm_test_helper.IsRecordingEnabled());
ClosePlatformBrowser(browser2);
EXPECT_FALSE(ukm_test_helper.IsRecordingEnabled());
ClosePlatformBrowser(incognito_browser1);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
// Client ID should not have been reset.
EXPECT_EQ(original_client_id, ukm_test_helper.GetClientId());
ClosePlatformBrowser(browser1);
}
// Make sure opening a real window after Incognito doesn't enable UKM.
// Keep in sync with testIncognitoPlusRegular in ios/chrome/browser/metrics/
// ukm_egtest.mm.
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, IncognitoPlusRegularCheck) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
Profile* incognito_profile =
profile->GetPrimaryOTRProfile(/*create_if_needed=*/true);
PlatformBrowser incognito_browser =
CreateIncognitoPlatformBrowser(incognito_profile);
EXPECT_FALSE(ukm_test_helper.IsRecordingEnabled());
PlatformBrowser browser = CreatePlatformBrowser(profile);
EXPECT_FALSE(ukm_test_helper.IsRecordingEnabled());
ClosePlatformBrowser(incognito_browser);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
ClosePlatformBrowser(browser);
}
// Make sure that UKM is disabled while a guest profile's window is open.
#if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS)
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, RegularPlusGuestCheck) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
Browser* regular_browser = CreateBrowser(profile);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
uint64_t original_client_id = ukm_test_helper.GetClientId();
// Create browser for guest profile.
Browser* guest_browser = InProcessBrowserTest::CreateGuestBrowser();
EXPECT_FALSE(ukm_test_helper.IsRecordingEnabled());
CloseBrowserSynchronously(guest_browser);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
// Client ID should not have been reset.
EXPECT_EQ(original_client_id, ukm_test_helper.GetClientId());
CloseBrowserSynchronously(regular_browser);
}
#endif // !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_CHROMEOS)
// ProfilePicker and System profile do not exist on Chrome Ash and on Android.
#if !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID)
// Displaying the ProfilePicker implicitly creates a System Profile.
// System Profile shouldn't have any effect on the UKM Enable Status.
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, ProfilePickerCheck) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
Browser* regular_browser = CreateBrowser(profile);
ASSERT_TRUE(ukm_test_helper.IsRecordingEnabled());
// ProfilePicker creates a SystemProfile.
ProfilePicker::Show(ProfilePicker::Params::FromEntryPoint(
ProfilePicker::EntryPoint::kProfileMenuManageProfiles));
profiles::testing::WaitForPickerWidgetCreated();
Profile* system_profile =
g_browser_process->profile_manager()->GetProfileByPath(
ProfileManager::GetSystemProfilePath());
ASSERT_TRUE(system_profile);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
ProfilePicker::Hide();
profiles::testing::WaitForPickerClosed();
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
CloseBrowserSynchronously(regular_browser);
}
#endif // !BUILDFLAG(IS_CHROMEOS_ASH) && !BUILDFLAG(IS_ANDROID)
// Not applicable to Android as it doesn't have multiple profiles.
#if !BUILDFLAG(IS_ANDROID)
// Make sure that UKM is disabled while an non-sync profile's window is open.
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, OpenNonSyncCheck) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
Browser* sync_browser = CreateBrowser(profile);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
uint64_t original_client_id = ukm_test_helper.GetClientId();
EXPECT_NE(0U, original_client_id);
Profile* nonsync_profile = CreateNonSyncProfile();
Browser* nonsync_browser = CreateBrowser(nonsync_profile);
EXPECT_FALSE(ukm_test_helper.IsRecordingEnabled());
CloseBrowserSynchronously(nonsync_browser);
// TODO(crbug.com/40530708): UKM doesn't actually get re-enabled yet.
// EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
#if !BUILDFLAG(IS_CHROMEOS_ASH)
// Client ID should not have been reset.
EXPECT_EQ(original_client_id, ukm_test_helper.GetClientId());
#else
// When flag is enabled, removing MSBB consent will cause the client id to be
// reset. In this case a new profile with sync turned off is added which also
// removes consent.
EXPECT_NE(original_client_id, ukm_test_helper.GetClientId());
#endif
CloseBrowserSynchronously(sync_browser);
}
#endif // !BUILDFLAG(IS_ANDROID)
// Make sure that UKM is disabled when metrics consent is revoked.
// Keep in sync with testMetricsConsent in ios/chrome/browser/metrics/
// ukm_egtest.mm.
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, MetricsConsentCheck) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
PlatformBrowser browser = CreatePlatformBrowser(profile);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
uint64_t original_client_id = ukm_test_helper.GetClientId();
EXPECT_NE(0U, original_client_id);
// Make sure there is a persistent log.
ukm_test_helper.BuildAndStoreLog();
EXPECT_TRUE(ukm_test_helper.HasUnsentLogs());
metrics_consent.Update(false);
EXPECT_FALSE(ukm_test_helper.IsRecordingEnabled());
EXPECT_FALSE(ukm_test_helper.HasUnsentLogs());
metrics_consent.Update(true);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
// Client ID should have been reset.
EXPECT_NE(original_client_id, ukm_test_helper.GetClientId());
ClosePlatformBrowser(browser);
}
#if !BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, LogProtoData) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
Browser* sync_browser = CreateBrowser(profile);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
uint64_t original_client_id = ukm_test_helper.GetClientId();
EXPECT_NE(0U, original_client_id);
// Make sure there is a persistent log.
ukm_test_helper.BuildAndStoreLog();
EXPECT_TRUE(ukm_test_helper.HasUnsentLogs());
// Check log contents.
std::unique_ptr<ukm::Report> report = ukm_test_helper.GetUkmReport();
EXPECT_EQ(original_client_id, report->client_id());
// Note: The version number reported in the proto may have a suffix, such as
// "-64-devel", so use use StartsWith() rather than checking for equality.
EXPECT_TRUE(base::StartsWith(report->system_profile().app_version(),
version_info::GetVersionNumber(),
base::CompareCase::SENSITIVE));
EXPECT_EQ(base::SysInfo::HardwareModelName(),
report->system_profile().hardware().hardware_class());
CloseBrowserSynchronously(sync_browser);
}
#endif // !BUILDFLAG(IS_ANDROID)
// TODO(crbug.com/40103988): Add the remaining test cases.
// Keep this test in sync with testUKMDemographicsReportingWithFeatureEnabled
// and testUKMDemographicsReportingWithFeatureDisabled in
// ios/chrome/browser/metrics/demographics_egtest.mm.
IN_PROC_BROWSER_TEST_P(UkmBrowserTestWithDemographics,
AddSyncedUserBirthYearAndGenderToProtoData) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
test::DemographicsTestParams param = GetParam();
MetricsConsentOverride metrics_consent(true);
base::HistogramTester histogram;
const base::Time now = base::Time::Now();
test::UpdateNetworkTime(now, g_browser_process->network_time_tracker());
const int test_birth_year = test::GetMaximumEligibleBirthYear(now);
const UserDemographicsProto::Gender test_gender =
UserDemographicsProto::GENDER_FEMALE;
// Add the test synced user birth year and gender priority prefs to the sync
// server data.
test::AddUserBirthYearAndGenderToSyncServer(GetFakeServer()->AsWeakPtr(),
test_birth_year, test_gender);
Profile* test_profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(test_profile);
// Make sure that there is only one Profile to allow reporting the user's
// birth year and gender.
ASSERT_EQ(1, num_clients());
PlatformBrowser browser = CreatePlatformBrowser(test_profile);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
uint64_t original_client_id = ukm_test_helper.GetClientId();
EXPECT_NE(0U, original_client_id);
// Log UKM metrics report.
ukm_test_helper.BuildAndStoreLog();
EXPECT_TRUE(ukm_test_helper.HasUnsentLogs());
// Check the log's content.
std::unique_ptr<ukm::Report> report = ukm_test_helper.GetUkmReport();
if (param.expect_reported_demographics) {
EXPECT_EQ(test::GetNoisedBirthYear(local_state(), test_birth_year),
report->user_demographics().birth_year());
EXPECT_EQ(test_gender, report->user_demographics().gender());
} else {
EXPECT_FALSE(report->has_user_demographics());
}
#if !BUILDFLAG(IS_CHROMEOS)
// Sign out the user to revoke all refresh tokens. This prevents any posted
// tasks from successfully fetching an access token during the tear-down
// phase and crashing on a DCHECK. See crbug/1102746 for more details.
harness->SignOutPrimaryAccount();
#endif // !BUILDFLAG(IS_CHROMEOS)
ClosePlatformBrowser(browser);
}
#if BUILDFLAG(IS_CHROMEOS_ASH)
// Cannot test for the enabled feature on Chrome OS because there are always
// multiple profiles.
static const auto kDemographicsTestParams = testing::Values(
test::DemographicsTestParams{/*enable_feature=*/false,
/*expect_reported_demographics=*/false});
#else
static const auto kDemographicsTestParams = testing::Values(
test::DemographicsTestParams{/*enable_feature=*/false,
/*expect_reported_demographics=*/false},
test::DemographicsTestParams{/*enable_feature=*/true,
/*expect_reported_demographics=*/true});
#endif
INSTANTIATE_TEST_SUITE_P(,
UkmBrowserTestWithDemographics,
kDemographicsTestParams);
// Verifies that network provider attaches effective connection type correctly
// to the UKM report.
#if !BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, NetworkProviderPopulatesSystemProfile) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
// Override network quality to 2G. This should cause the
// |max_effective_connection_type| in the system profile to be set to 2G.
g_browser_process->network_quality_tracker()
->ReportEffectiveConnectionTypeForTesting(
net::EFFECTIVE_CONNECTION_TYPE_2G);
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
Browser* sync_browser = CreateBrowser(profile);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
uint64_t original_client_id = ukm_test_helper.GetClientId();
EXPECT_NE(0U, original_client_id);
// Override network quality to 4G. This should cause the
// |max_effective_connection_type| in the system profile to be set to 4G.
g_browser_process->network_quality_tracker()
->ReportEffectiveConnectionTypeForTesting(
net::EFFECTIVE_CONNECTION_TYPE_4G);
// Make sure there is a persistent log.
ukm_test_helper.BuildAndStoreLog();
EXPECT_TRUE(ukm_test_helper.HasUnsentLogs());
// Check log contents.
std::unique_ptr<ukm::Report> report = ukm_test_helper.GetUkmReport();
EXPECT_EQ(SystemProfileProto::Network::EFFECTIVE_CONNECTION_TYPE_2G,
report->system_profile().network().min_effective_connection_type());
EXPECT_EQ(SystemProfileProto::Network::EFFECTIVE_CONNECTION_TYPE_4G,
report->system_profile().network().max_effective_connection_type());
CloseBrowserSynchronously(sync_browser);
}
#endif // !BUILDFLAG(IS_ANDROID)
// Make sure that providing consent doesn't enable UKM when sync is disabled.
// Keep in sync with testConsentAddedButNoSync in ios/chrome/browser/metrics/
// ukm_egtest.mm and consentAddedButNoSyncCheck in chrome/android/javatests/src/
// org/chromium/chrome/browser/sync/UkmTest.java.
// Flaky on Android crbug.com/1096400
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_ConsentAddedButNoSyncCheck DISABLED_ConsentAddedButNoSyncCheck
#else
#define MAYBE_ConsentAddedButNoSyncCheck ConsentAddedButNoSyncCheck
#endif
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, MAYBE_ConsentAddedButNoSyncCheck) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
MetricsConsentOverride metrics_consent(false);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
PlatformBrowser browser = CreatePlatformBrowser(profile);
EXPECT_FALSE(ukm_test_helper.IsRecordingEnabled());
metrics_consent.Update(true);
EXPECT_FALSE(ukm_test_helper.IsRecordingEnabled());
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
g_browser_process->GetMetricsServicesManager()->UpdateUploadPermissions(true);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
ClosePlatformBrowser(browser);
}
// Make sure that extension URLs are disabled when an open sync window
// disables it.
#if !BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, SingleDisableExtensionsSyncCheck) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
Browser* sync_browser = CreateBrowser(profile);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
EXPECT_TRUE(ukm_test_helper.IsExtensionRecordingEnabled());
uint64_t original_client_id = ukm_test_helper.GetClientId();
EXPECT_NE(0U, original_client_id);
ASSERT_TRUE(
harness->DisableSyncForType(syncer::UserSelectableType::kExtensions));
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
EXPECT_FALSE(ukm_test_helper.IsExtensionRecordingEnabled());
ASSERT_TRUE(
harness->EnableSyncForType(syncer::UserSelectableType::kExtensions));
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
EXPECT_TRUE(ukm_test_helper.IsExtensionRecordingEnabled());
// Client ID should not be reset.
EXPECT_EQ(original_client_id, ukm_test_helper.GetClientId());
CloseBrowserSynchronously(sync_browser);
}
#endif // !BUILDFLAG(IS_ANDROID)
// Make sure that extension URLs are disabled when any open sync window
// disables it.
#if !BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, MultiDisableExtensionsSyncCheck) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
MetricsConsentOverride metrics_consent(true);
Profile* profile1 = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness1 =
EnableSyncForProfile(profile1);
Browser* browser1 = CreateBrowser(profile1);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
uint64_t original_client_id = ukm_test_helper.GetClientId();
EXPECT_NE(0U, original_client_id);
Profile* profile2 = CreateNonSyncProfile();
std::unique_ptr<SyncServiceImplHarness> harness2 =
EnableSyncForProfile(profile2);
Browser* browser2 = CreateBrowser(profile2);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
EXPECT_TRUE(ukm_test_helper.IsExtensionRecordingEnabled());
#if !BUILDFLAG(IS_CHROMEOS_ASH)
EXPECT_EQ(original_client_id, ukm_test_helper.GetClientId());
#else
// If the feature is enabled, then the client id will have been reset. The
// client id is reset when the second profile is initially created without any
// sync preferences enabled or MSBB. With the feature, any consent on to off
// change for MSBB or App Sync will cause the client id to reset.
EXPECT_NE(original_client_id, ukm_test_helper.GetClientId());
original_client_id = ukm_test_helper.GetClientId();
#endif
ASSERT_TRUE(
harness2->DisableSyncForType(syncer::UserSelectableType::kExtensions));
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
EXPECT_FALSE(ukm_test_helper.IsExtensionRecordingEnabled());
ASSERT_TRUE(
harness2->EnableSyncForType(syncer::UserSelectableType::kExtensions));
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
EXPECT_TRUE(ukm_test_helper.IsExtensionRecordingEnabled());
EXPECT_EQ(original_client_id, ukm_test_helper.GetClientId());
CloseBrowserSynchronously(browser2);
CloseBrowserSynchronously(browser1);
}
#endif // !BUILDFLAG(IS_ANDROID)
#if !BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, LogsTabId) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
ASSERT_TRUE(embedded_test_server()->Start());
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
Browser* sync_browser = CreateBrowser(profile);
const ukm::UkmSource* first_source =
NavigateAndGetSource(embedded_test_server()->GetURL("/title1.html"),
sync_browser, &ukm_test_helper);
// Tab ids are incremented starting from 1. Since we started a new sync
// browser, this is the second tab.
EXPECT_EQ(2, first_source->navigation_data().tab_id);
// Ensure the tab id is constant in a single tab.
const ukm::UkmSource* second_source =
NavigateAndGetSource(embedded_test_server()->GetURL("/title2.html"),
sync_browser, &ukm_test_helper);
EXPECT_EQ(first_source->navigation_data().tab_id,
second_source->navigation_data().tab_id);
// Add a new tab, it should get a new tab id.
chrome::NewTab(sync_browser);
const ukm::UkmSource* third_source =
NavigateAndGetSource(embedded_test_server()->GetURL("/title3.html"),
sync_browser, &ukm_test_helper);
EXPECT_EQ(3, third_source->navigation_data().tab_id);
}
#endif // !BUILDFLAG(IS_ANDROID)
#if !BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, LogsPreviousSourceId) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
ASSERT_TRUE(embedded_test_server()->Start());
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
Browser* sync_browser = CreateBrowser(profile);
const ukm::UkmSource* first_source =
NavigateAndGetSource(embedded_test_server()->GetURL("/title1.html"),
sync_browser, &ukm_test_helper);
const ukm::UkmSource* second_source =
NavigateAndGetSource(embedded_test_server()->GetURL("/title2.html"),
sync_browser, &ukm_test_helper);
EXPECT_EQ(first_source->id(),
second_source->navigation_data().previous_source_id);
// Open a new tab with window.open.
content::WebContents* opener =
sync_browser->tab_strip_model()->GetActiveWebContents();
GURL new_tab_url = embedded_test_server()->GetURL("/title3.html");
content::TestNavigationObserver waiter(new_tab_url);
waiter.StartWatchingNewWebContents();
EXPECT_TRUE(content::ExecJs(
opener, content::JsReplace("window.open($1)", new_tab_url)));
waiter.Wait();
EXPECT_NE(opener, sync_browser->tab_strip_model()->GetActiveWebContents());
ukm::SourceId new_id = sync_browser->tab_strip_model()
->GetActiveWebContents()
->GetPrimaryMainFrame()
->GetPageUkmSourceId();
ukm::UkmSource* new_tab_source = ukm_test_helper.GetSource(new_id);
EXPECT_NE(nullptr, new_tab_source);
EXPECT_EQ(ukm::kInvalidSourceId,
new_tab_source->navigation_data().previous_source_id);
// Subsequent navigations within the tab should get a previous_source_id field
// set.
const ukm::UkmSource* subsequent_source =
NavigateAndGetSource(embedded_test_server()->GetURL("/title3.html"),
sync_browser, &ukm_test_helper);
EXPECT_EQ(new_tab_source->id(),
subsequent_source->navigation_data().previous_source_id);
}
#endif // !BUILDFLAG(IS_ANDROID)
#if !BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, LogsOpenerSource) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
ASSERT_TRUE(embedded_test_server()->Start());
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
Browser* sync_browser = CreateBrowser(profile);
const ukm::UkmSource* first_source =
NavigateAndGetSource(embedded_test_server()->GetURL("/title1.html"),
sync_browser, &ukm_test_helper);
// This tab was not opened by another tab, so it should not have an opener
// id.
EXPECT_EQ(ukm::kInvalidSourceId,
first_source->navigation_data().opener_source_id);
// Open a new tab with window.open.
content::WebContents* opener =
sync_browser->tab_strip_model()->GetActiveWebContents();
GURL new_tab_url = embedded_test_server()->GetURL("/title2.html");
content::TestNavigationObserver waiter(new_tab_url);
waiter.StartWatchingNewWebContents();
EXPECT_TRUE(content::ExecJs(
opener, content::JsReplace("window.open($1)", new_tab_url)));
waiter.Wait();
EXPECT_NE(opener, sync_browser->tab_strip_model()->GetActiveWebContents());
ukm::SourceId new_id = sync_browser->tab_strip_model()
->GetActiveWebContents()
->GetPrimaryMainFrame()
->GetPageUkmSourceId();
ukm::UkmSource* new_tab_source = ukm_test_helper.GetSource(new_id);
EXPECT_NE(nullptr, new_tab_source);
EXPECT_EQ(first_source->id(),
new_tab_source->navigation_data().opener_source_id);
// Subsequent navigations within the tab should not get an opener set.
const ukm::UkmSource* subsequent_source =
NavigateAndGetSource(embedded_test_server()->GetURL("/title3.html"),
sync_browser, &ukm_test_helper);
EXPECT_EQ(ukm::kInvalidSourceId,
subsequent_source->navigation_data().opener_source_id);
}
#endif // !BUILDFLAG(IS_ANDROID)
// ChromeOS doesn't have the concept of sign-out so this test doesn't make sense
// there.
//
// Flaky on Android: https://crbug.com/1096047.
//
// Make sure that UKM is disabled when the profile signs out of Sync.
// Keep in sync with testSingleSyncSignout in ios/chrome/browser/metrics/
// ukm_egtest.mm and singleSyncSignoutCheck in chrome/android/javatests/src/org/
// chromium/chrome/browser/sync/UkmTest.java.
#if !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, SingleSyncSignoutCheck) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
PlatformBrowser browser = CreatePlatformBrowser(profile);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
uint64_t original_client_id = ukm_test_helper.GetClientId();
EXPECT_NE(0U, original_client_id);
harness->SignOutPrimaryAccount();
EXPECT_FALSE(ukm_test_helper.IsRecordingEnabled());
EXPECT_NE(original_client_id, ukm_test_helper.GetClientId());
ClosePlatformBrowser(browser);
}
#endif // !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_ANDROID)
// ChromeOS doesn't have the concept of sign-out so this test doesn't make sense
// there. Android doesn't have multiple profiles.
#if !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_ANDROID)
// Make sure that UKM is disabled when any profile signs out of Sync.
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, MultiSyncSignoutCheck) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
MetricsConsentOverride metrics_consent(true);
Profile* profile1 = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness1 =
EnableSyncForProfile(profile1);
Browser* browser1 = CreateBrowser(profile1);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
uint64_t original_client_id = ukm_test_helper.GetClientId();
EXPECT_NE(0U, original_client_id);
Profile* profile2 = CreateNonSyncProfile();
std::unique_ptr<SyncServiceImplHarness> harness2 =
EnableSyncForProfile(profile2);
Browser* browser2 = CreateBrowser(profile2);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
EXPECT_EQ(original_client_id, ukm_test_helper.GetClientId());
harness2->SignOutPrimaryAccount();
EXPECT_FALSE(ukm_test_helper.IsRecordingEnabled());
EXPECT_NE(original_client_id, ukm_test_helper.GetClientId());
CloseBrowserSynchronously(browser2);
CloseBrowserSynchronously(browser1);
}
#endif // !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_ANDROID)
// Make sure that if history/sync services weren't available when we tried to
// attach listeners, UKM is not enabled.
#if !BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, ServiceListenerInitFailedCheck) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
MetricsConsentOverride metrics_consent(true);
ChromeMetricsServiceClient::SetNotificationListenerSetupFailedForTesting(
true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
Browser* sync_browser = CreateBrowser(profile);
EXPECT_FALSE(ukm_test_helper.IsRecordingEnabled());
CloseBrowserSynchronously(sync_browser);
}
#endif // !BUILDFLAG(IS_ANDROID)
// Make sure that UKM is not affected by MetricsReporting Feature (sampling).
#if !BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, MetricsReportingCheck) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
// Need to set the Metrics Default to OPT_OUT to trigger MetricsReporting.
PrefService* local_state = g_browser_process->local_state();
ForceRecordMetricsReportingDefaultState(local_state,
EnableMetricsDefault::OPT_OUT);
// Verify that kMetricsReportingFeature is disabled (i.e. other metrics
// services will be sampled out).
EXPECT_FALSE(
base::FeatureList::IsEnabled(internal::kMetricsReportingFeature));
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
Browser* sync_browser = CreateBrowser(profile);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
CloseBrowserSynchronously(sync_browser);
}
#endif // !BUILDFLAG(IS_ANDROID)
// Make sure that pending data is deleted when user deletes history.
//
// Keep in sync with testHistoryDelete in ios/chrome/browser/metrics/
// ukm_egtest.mm and testHistoryDeleteCheck in chrome/android/javatests/src/org/
// chromium/chrome/browser/metrics/UkmTest.java.
//
// Flaky on Android: https://crbug.com/1131541.
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_HistoryDeleteCheck DISABLED_HistoryDeleteCheck
#else
#define MAYBE_HistoryDeleteCheck HistoryDeleteCheck
#endif
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, MAYBE_HistoryDeleteCheck) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
PlatformBrowser browser = CreatePlatformBrowser(profile);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
uint64_t original_client_id = ukm_test_helper.GetClientId();
EXPECT_NE(0U, original_client_id);
const ukm::SourceId kDummySourceId = 0x54321;
ukm_test_helper.RecordSourceForTesting(kDummySourceId);
EXPECT_TRUE(ukm_test_helper.HasSource(kDummySourceId));
ClearBrowsingData(profile);
// Other sources may already have been recorded since the data was cleared,
// but the dummy source should be gone.
EXPECT_FALSE(ukm_test_helper.HasSource(kDummySourceId));
// Client ID should NOT be reset.
EXPECT_EQ(original_client_id, ukm_test_helper.GetClientId());
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
ClosePlatformBrowser(browser);
}
// On ChromeOS, the test profile starts with a primary account already set, so
// this test doesn't apply.
#if !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(UkmBrowserTestWithSyncTransport,
NotEnabledForSecondaryAccountSync) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
MetricsConsentOverride metrics_consent(true);
// Signing in (without granting sync consent or explicitly setting up Sync)
// should trigger starting the Sync machinery in standalone transport mode.
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
test::InitializeProfileForSync(profile, GetFakeServer()->AsWeakPtr());
syncer::SyncService* sync_service =
SyncServiceFactory::GetForProfile(profile);
secondary_account_helper::SignInUnconsentedAccount(
profile, &test_url_loader_factory_, "secondary_user@email.com");
ASSERT_NE(syncer::SyncService::TransportState::DISABLED,
sync_service->GetTransportState());
ASSERT_TRUE(harness->AwaitSyncTransportActive());
ASSERT_EQ(syncer::SyncService::TransportState::ACTIVE,
sync_service->GetTransportState());
ASSERT_FALSE(sync_service->IsSyncFeatureEnabled());
// History Sync is not active.
ASSERT_FALSE(sync_service->GetActiveDataTypes().Has(syncer::HISTORY));
ASSERT_FALSE(sync_service->GetActiveDataTypes().Has(
syncer::HISTORY_DELETE_DIRECTIVES));
EXPECT_FALSE(ukm_test_helper.IsRecordingEnabled());
}
#endif // !BUILDFLAG(IS_CHROMEOS) && !BUILDFLAG(IS_ANDROID)
#if !BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_P(UkmConsentParamBrowserTest, GroupPolicyConsentCheck) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
// Note we are not using the synthetic MetricsConsentOverride since we are
// testing directly from prefs.
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
Browser* sync_browser = CreateBrowser(profile);
// The input param controls whether we set the prefs related to group policy
// enabled or not. Based on its value, we should report the same value for
// both if reporting is enabled and if UKM service is enabled.
bool is_enabled = is_metrics_reporting_enabled_initial_value();
EXPECT_EQ(is_enabled,
UkmConsentParamBrowserTest::IsMetricsAndCrashReportingEnabled());
EXPECT_EQ(is_enabled, ukm_test_helper.IsRecordingEnabled());
CloseBrowserSynchronously(sync_browser);
}
#endif // !BUILDFLAG(IS_ANDROID)
#if !BUILDFLAG(IS_ANDROID)
// Verify UKM is enabled/disabled for both potential settings of group policy.
INSTANTIATE_TEST_SUITE_P(UkmConsentParamBrowserTests,
UkmConsentParamBrowserTest,
testing::Bool());
#endif // !BUILDFLAG(IS_ANDROID)
// Verify that sources kept alive in-memory will be discarded by UKM service in
// one reporting cycle after the web contents are destroyed when the tab is
// closed or when the user navigated away in the same tab.
#if !BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, EvictObsoleteSources) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
Browser* sync_browser = CreateBrowser(profile);
ASSERT_TRUE(embedded_test_server()->Start());
ukm::SourceId source_id1 = ukm::kInvalidSourceId;
ukm::SourceId source_id2 = ukm::kInvalidSourceId;
const std::vector<GURL> test_urls = {
embedded_test_server()->GetURL("/title1.html"),
embedded_test_server()->GetURL("/title2.html"),
embedded_test_server()->GetURL("/title3.html")};
// Open a blank new tab.
ASSERT_TRUE(AddTabAtIndexToBrowser(sync_browser, 1, GURL(url::kAboutBlankURL),
ui::PAGE_TRANSITION_TYPED, true));
// Gather source id from the NavigationHandle assigned to navigations that
// start with the expected URL.
content::NavigationHandleObserver tab_1_observer(
sync_browser->tab_strip_model()->GetActiveWebContents(), test_urls[0]);
// Navigate to a test URL in this new tab.
ASSERT_TRUE(ui_test_utils::NavigateToURL(sync_browser, test_urls[0]));
// Get the source id associated to the last committed navigation, which could
// differ from the id from WebContents for example if the site executes a
// same-document navigation (e.g. history.pushState/replaceState). This
// navigation source id is the one marked as obsolete by UKM recorder.
source_id1 = ukm::ConvertToSourceId(tab_1_observer.navigation_id(),
ukm::SourceIdType::NAVIGATION_ID);
// The UKM report contains this newly-created source.
ukm_test_helper.BuildAndStoreLog();
std::unique_ptr<ukm::Report> report = ukm_test_helper.GetUkmReport();
bool has_source_id1 = false;
bool has_source_id2 = false;
for (const auto& s : report->sources()) {
has_source_id1 |= s.id() == source_id1;
has_source_id2 |= s.id() == source_id2;
}
EXPECT_TRUE(has_source_id1);
EXPECT_FALSE(has_source_id2);
// Navigate to another URL in a new tab.
ASSERT_TRUE(AddTabAtIndexToBrowser(sync_browser, 2, GURL(url::kAboutBlankURL),
ui::PAGE_TRANSITION_TYPED, true));
content::NavigationHandleObserver tab_2_observer(
sync_browser->tab_strip_model()->GetActiveWebContents(), test_urls[1]);
ASSERT_TRUE(ui_test_utils::NavigateToURL(sync_browser, test_urls[1]));
source_id2 = ukm::ConvertToSourceId(tab_2_observer.navigation_id(),
ukm::SourceIdType::NAVIGATION_ID);
// The next report should again contain source 1 because the tab is still
// alive, and also source 2 associated to the new tab that has just been
// opened.
ukm_test_helper.BuildAndStoreLog();
report = ukm_test_helper.GetUkmReport();
has_source_id1 = false;
has_source_id2 = false;
for (const auto& s : report->sources()) {
has_source_id1 |= s.id() == source_id1;
has_source_id2 |= s.id() == source_id2;
}
EXPECT_TRUE(has_source_id1);
EXPECT_TRUE(has_source_id2);
// Close the tab corresponding to source 1, this should mark source 1 as
// obsolete. Next report will still contain source 1 because we might have
// associated entries before it was closed.
sync_browser->tab_strip_model()->CloseWebContentsAt(
1, TabCloseTypes::CLOSE_NONE);
ukm_test_helper.BuildAndStoreLog();
report = ukm_test_helper.GetUkmReport();
has_source_id1 = false;
has_source_id2 = false;
for (const auto& s : report->sources()) {
has_source_id1 |= s.id() == source_id1;
has_source_id2 |= s.id() == source_id2;
}
EXPECT_TRUE(has_source_id1);
EXPECT_TRUE(has_source_id2);
// Navigate to a new URL in the current tab, this will mark source 2 that was
// in the current tab as obsolete.
ASSERT_TRUE(ui_test_utils::NavigateToURL(sync_browser, test_urls[2]));
// The previous report was the last one that could potentially contain entries
// for source 1. Source 1 is thus no longer included in future reports. This
// report will still contain source 2 because we might have associated entries
// since the last report.
ukm_test_helper.BuildAndStoreLog();
report = ukm_test_helper.GetUkmReport();
has_source_id1 = false;
has_source_id2 = false;
for (const auto& s : report->sources()) {
has_source_id1 |= s.id() == source_id1;
has_source_id2 |= s.id() == source_id2;
}
EXPECT_FALSE(has_source_id1);
EXPECT_TRUE(has_source_id2);
// Neither source 1 or source 2 is alive anymore.
ukm_test_helper.BuildAndStoreLog();
report = ukm_test_helper.GetUkmReport();
has_source_id1 = false;
has_source_id2 = false;
for (const auto& s : report->sources()) {
has_source_id1 |= s.id() == source_id1;
has_source_id2 |= s.id() == source_id2;
}
EXPECT_FALSE(has_source_id1);
EXPECT_FALSE(has_source_id2);
CloseBrowserSynchronously(sync_browser);
}
#endif // !BUILDFLAG(IS_ANDROID)
// Verify that correct sources are marked as obsolete when same-document
// navigation happens.
#if !BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(UkmBrowserTest,
MarkObsoleteSourcesSameDocumentNavigation) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
Browser* sync_browser = CreateBrowser(profile);
ASSERT_TRUE(embedded_test_server()->Start());
// First navigation.
const ukm::SourceId source_id1 =
NavigateAndGetSource(embedded_test_server()->GetURL("/title1.html"),
sync_browser, &ukm_test_helper)
->id();
EXPECT_FALSE(ukm_test_helper.IsSourceObsolete(source_id1));
// Cross-document navigation where the previous navigation is cross-document.
const ukm::SourceId source_id2 =
NavigateAndGetSource(embedded_test_server()->GetURL("/title2.html"),
sync_browser, &ukm_test_helper)
->id();
EXPECT_TRUE(ukm_test_helper.IsSourceObsolete(source_id1));
EXPECT_FALSE(ukm_test_helper.IsSourceObsolete(source_id2));
// Same-document navigation where the previous navigation is cross-document.
const ukm::SourceId source_id3 =
NavigateAndGetSource(embedded_test_server()->GetURL("/title2.html#a"),
sync_browser, &ukm_test_helper)
->id();
EXPECT_TRUE(ukm_test_helper.IsSourceObsolete(source_id1));
EXPECT_FALSE(ukm_test_helper.IsSourceObsolete(source_id2));
EXPECT_FALSE(ukm_test_helper.IsSourceObsolete(source_id3));
// Same-document navigation where the previous navigation is same-document.
const ukm::SourceId source_id4 =
NavigateAndGetSource(embedded_test_server()->GetURL("/title2.html#b"),
sync_browser, &ukm_test_helper)
->id();
EXPECT_TRUE(ukm_test_helper.IsSourceObsolete(source_id1));
EXPECT_FALSE(ukm_test_helper.IsSourceObsolete(source_id2));
EXPECT_TRUE(ukm_test_helper.IsSourceObsolete(source_id3));
EXPECT_FALSE(ukm_test_helper.IsSourceObsolete(source_id4));
// Cross-document navigation where the previous navigation is same-document.
NavigateAndGetSource(embedded_test_server()->GetURL("/title1.html"),
sync_browser, &ukm_test_helper)
->id();
EXPECT_TRUE(ukm_test_helper.IsSourceObsolete(source_id1));
EXPECT_TRUE(ukm_test_helper.IsSourceObsolete(source_id2));
EXPECT_TRUE(ukm_test_helper.IsSourceObsolete(source_id3));
EXPECT_TRUE(ukm_test_helper.IsSourceObsolete(source_id4));
}
#endif // !BUILDFLAG(IS_ANDROID)
// Verify that sources are not marked as obsolete by a new navigation that does
// not commit.
#if !BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, NotMarkSourcesIfNavigationNotCommitted) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
Browser* sync_browser = CreateBrowser(profile);
ASSERT_TRUE(embedded_test_server()->Start());
// An example navigation that commits.
const GURL test_url_with_commit =
embedded_test_server()->GetURL("/title1.html");
// An example of a navigation returning "204 No Content" which does not commit
// (i.e. the WebContents stays at the existing URL).
const GURL test_url_no_commit =
embedded_test_server()->GetURL("/page204.html");
// Get the source id from the committed navigation.
const ukm::SourceId source_id =
NavigateAndGetSource(test_url_with_commit, sync_browser, &ukm_test_helper)
->id();
// Initial default state.
EXPECT_FALSE(ukm_test_helper.IsSourceObsolete(source_id));
// New navigation did not commit, thus the source should still be kept alive.
ASSERT_TRUE(ui_test_utils::NavigateToURL(sync_browser, test_url_no_commit));
EXPECT_FALSE(ukm_test_helper.IsSourceObsolete(source_id));
}
#endif // !BUILDFLAG(IS_ANDROID)
#if !BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, DebugUiRenders) {
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
PlatformBrowser browser = CreatePlatformBrowser(profile);
ukm::UkmService* ukm_service(GetUkmService());
EXPECT_TRUE(ukm_service->IsSamplingConfigured());
// chrome://ukm
const GURL debug_url(content::GetWebUIURLString(content::kChromeUIUkmHost));
content::TestNavigationObserver waiter(debug_url);
waiter.WatchExistingWebContents();
EXPECT_TRUE(ui_test_utils::NavigateToURL(browser, debug_url));
waiter.WaitForNavigationFinished();
}
#endif // !BUILDFLAG(IS_ANDROID)
#if !BUILDFLAG(IS_ANDROID)
IN_PROC_BROWSER_TEST_F(UkmBrowserTest, AllowedStateChanged) {
ukm::UkmTestHelper ukm_test_helper(GetUkmService());
MetricsConsentOverride metrics_consent(true);
Profile* test_profile = ProfileManager::GetLastUsedProfileIfLoaded();
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(test_profile);
CreatePlatformBrowser(test_profile);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
EXPECT_TRUE(g_browser_process->GetMetricsServicesManager()
->IsUkmAllowedForAllProfiles());
TestUkmRecorderObserver observer(GetUkmService());
unified_consent::UnifiedConsentService* consent_service =
UnifiedConsentServiceFactory::GetForProfile(test_profile);
consent_service->SetUrlKeyedAnonymizedDataCollectionEnabled(false);
#if !BUILDFLAG(IS_CHROMEOS_ASH)
EXPECT_FALSE(ukm_test_helper.IsRecordingEnabled());
EXPECT_FALSE(g_browser_process->GetMetricsServicesManager()
->IsUkmAllowedForAllProfiles());
// Expect nothing to be consented to.
observer.ExpectAllowedStateChanged(ukm::UkmConsentState());
#else
// ChromeOS has a different behavior compared to other platforms.
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
EXPECT_TRUE(g_browser_process->GetMetricsServicesManager()
->IsUkmAllowedForAllProfiles());
observer.ExpectAllowedStateChanged(ukm::UkmConsentState({ukm::APPS}));
#endif
consent_service->SetUrlKeyedAnonymizedDataCollectionEnabled(true);
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
EXPECT_TRUE(g_browser_process->GetMetricsServicesManager()
->IsUkmAllowedForAllProfiles());
observer.ExpectAllowedStateChanged(ukm::UkmConsentState::All());
}
#endif // !BUILDFLAG(IS_ANDROID)
#if BUILDFLAG(IS_CHROMEOS_ASH)
class UkmBrowserTestForAppConsent : public UkmBrowserTestBase {
public:
UkmBrowserTestForAppConsent() = default;
};
IN_PROC_BROWSER_TEST_F(UkmBrowserTestForAppConsent, MetricsClientEnablement) {
ukm::UkmService* ukm_service = GetUkmService();
ukm::UkmTestHelper ukm_test_helper(ukm_service);
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
unified_consent::UnifiedConsentService* consent_service =
UnifiedConsentServiceFactory::GetForProfile(profile);
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
// All consents are on.
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
EXPECT_TRUE(ukm_service->recording_enabled(ukm::MSBB));
EXPECT_TRUE(ukm_service->recording_enabled(ukm::EXTENSIONS));
EXPECT_TRUE(ukm_service->recording_enabled(ukm::APPS));
// Turn off MSBB consent.
consent_service->SetUrlKeyedAnonymizedDataCollectionEnabled(false);
// Still have AppKM consent.
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
EXPECT_FALSE(ukm_service->recording_enabled(ukm::MSBB));
EXPECT_FALSE(ukm_service->recording_enabled(ukm::EXTENSIONS));
EXPECT_TRUE(ukm_service->recording_enabled(ukm::APPS));
// Turn off App-sync.
auto* user_settings = harness->service()->GetUserSettings();
auto registered_os_sync_types =
user_settings->GetRegisteredSelectableOsTypes();
registered_os_sync_types.Remove(syncer::UserSelectableOsType::kOsApps);
user_settings->SetSelectedOsTypes(false, registered_os_sync_types);
// UKM recording is now disabled since MSBB and App-sync consent
// has been removed.
EXPECT_FALSE(ukm_test_helper.IsRecordingEnabled());
EXPECT_FALSE(ukm_service->recording_enabled(ukm::MSBB));
EXPECT_FALSE(ukm_service->recording_enabled(ukm::EXTENSIONS));
EXPECT_FALSE(ukm_service->recording_enabled(ukm::APPS));
}
IN_PROC_BROWSER_TEST_F(UkmBrowserTestForAppConsent,
ClientIdResetWhenConsentRemoved) {
ukm::UkmService* ukm_service = GetUkmService();
ukm::UkmTestHelper ukm_test_helper(ukm_service);
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
unified_consent::UnifiedConsentService* consent_service =
UnifiedConsentServiceFactory::GetForProfile(profile);
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
const auto original_client_id = ukm_test_helper.GetClientId();
EXPECT_NE(0ul, original_client_id);
// All consents are on.
EXPECT_TRUE(ukm_test_helper.IsRecordingEnabled());
EXPECT_TRUE(ukm_service->recording_enabled(ukm::MSBB));
EXPECT_TRUE(ukm_service->recording_enabled(ukm::EXTENSIONS));
EXPECT_TRUE(ukm_service->recording_enabled(ukm::APPS));
// Turn off MSBB consent.
consent_service->SetUrlKeyedAnonymizedDataCollectionEnabled(false);
EXPECT_FALSE(ukm_service->recording_enabled(ukm::MSBB));
// Client ID should reset when MSBB is disabled.
const auto app_sync_client_id = ukm_test_helper.GetClientId();
EXPECT_NE(original_client_id, app_sync_client_id);
// Turn off app sync.
auto* user_settings = harness->service()->GetUserSettings();
auto registered_os_sync_types =
user_settings->GetRegisteredSelectableOsTypes();
registered_os_sync_types.Remove(syncer::UserSelectableOsType::kOsApps);
user_settings->SetSelectedOsTypes(false, registered_os_sync_types);
EXPECT_FALSE(ukm_service->recording_enabled(ukm::APPS));
// Client ID should reset when app sync is disable.
const auto final_client_id = ukm_test_helper.GetClientId();
EXPECT_NE(app_sync_client_id, final_client_id);
}
IN_PROC_BROWSER_TEST_F(UkmBrowserTestForAppConsent,
EnsurePurgeOnConsentChange) {
ukm::UkmService* ukm_service = GetUkmService();
ukm::UkmTestHelper ukm_test_helper(ukm_service);
MetricsConsentOverride metrics_consent(true);
Profile* profile = ProfileManager::GetLastUsedProfileIfLoaded();
unified_consent::UnifiedConsentService* consent_service =
UnifiedConsentServiceFactory::GetForProfile(profile);
std::unique_ptr<SyncServiceImplHarness> harness =
EnableSyncForProfile(profile);
Browser* sync_browser = CreateBrowser(profile);
ASSERT_TRUE(embedded_test_server()->Start());
const std::vector<GURL> test_urls = {
embedded_test_server()->GetURL("/title1.html"),
embedded_test_server()->GetURL("/title2.html"),
embedded_test_server()->GetURL("/title3.html")};
// Verify all consents are enabled.
EXPECT_TRUE(ukm_service->recording_enabled(ukm::MSBB));
EXPECT_TRUE(ukm_service->recording_enabled(ukm::EXTENSIONS));
EXPECT_TRUE(ukm_service->recording_enabled(ukm::APPS));
int tab_index = 1;
// Generate MSBB ukm entries by navigating to some test webpages.
for (const auto& url : test_urls) {
ASSERT_TRUE(AddTabAtIndexToBrowser(sync_browser, tab_index++,
GURL(url::kAboutBlankURL),
ui::PAGE_TRANSITION_TYPED, true));
NavigateAndGetSource(url, sync_browser, &ukm_test_helper);
}
// Revoke MSBB consent.
consent_service->SetUrlKeyedAnonymizedDataCollectionEnabled(false);
// Verify that MSBB consent was revoked.
EXPECT_FALSE(ukm_service->recording_enabled(ukm::MSBB));
EXPECT_FALSE(ukm_service->recording_enabled(ukm::EXTENSIONS));
EXPECT_TRUE(ukm_service->recording_enabled(ukm::APPS));
ukm_test_helper.BuildAndStoreLog();
const std::unique_ptr<ukm::Report> report = ukm_test_helper.GetUkmReport();
// Verify that the only sources in the report are APP_ID.
// NOTE(crbug/1395143): It was noticed that there was an APP_ID source
// generated despite not being explicitly created. No entries are associated
// with it though.
for (int i = 0; i < report->sources_size(); ++i) {
const auto id = report->sources(i).id();
EXPECT_EQ(ukm::GetSourceIdType(id), ukm::SourceIdType::APP_ID);
}
}
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
} // namespace metrics