| // Copyright 2019 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. |
| |
| #import "ios/chrome/browser/metrics/ios_chrome_metrics_service_client.h" |
| |
| #include <string> |
| |
| #include "base/compiler_specific.h" |
| #include "base/metrics/persistent_histogram_allocator.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "build/branding_buildflags.h" |
| #include "components/metrics/client_info.h" |
| #include "components/metrics/metrics_service.h" |
| #include "components/metrics/metrics_state_manager.h" |
| #include "components/metrics/metrics_switches.h" |
| #include "components/metrics/test/test_enabled_state_provider.h" |
| #include "components/metrics/unsent_log_store.h" |
| #include "components/prefs/testing_pref_service.h" |
| #include "components/ukm/ukm_service.h" |
| #include "ios/chrome/browser/browser_state/test_chrome_browser_state.h" |
| #include "ios/chrome/browser/browser_state/test_chrome_browser_state_manager.h" |
| #include "ios/chrome/test/ios_chrome_scoped_testing_chrome_browser_state_manager.h" |
| #include "ios/web/public/test/web_task_environment.h" |
| #include "testing/platform_test.h" |
| |
| #if !defined(__has_feature) || !__has_feature(objc_arc) |
| #error "This file requires ARC support." |
| #endif |
| |
| namespace ukm { |
| class UkmService; |
| } |
| |
| class IOSChromeMetricsServiceClientTest : public PlatformTest { |
| public: |
| IOSChromeMetricsServiceClientTest() |
| : scoped_browser_state_manager_( |
| std::make_unique<TestChromeBrowserStateManager>(base::FilePath())), |
| browser_state_(TestChromeBrowserState::Builder().Build()), |
| enabled_state_provider_(/*consent=*/false, /*enabled=*/false) {} |
| |
| void SetUp() override { |
| PlatformTest::SetUp(); |
| metrics::MetricsService::RegisterPrefs(prefs_.registry()); |
| metrics_state_manager_ = metrics::MetricsStateManager::Create( |
| &prefs_, &enabled_state_provider_, std::wstring(), |
| base::BindRepeating( |
| &IOSChromeMetricsServiceClientTest::FakeStoreClientInfoBackup, |
| base::Unretained(this)), |
| base::BindRepeating( |
| &IOSChromeMetricsServiceClientTest::LoadFakeClientInfoBackup, |
| base::Unretained(this))); |
| } |
| |
| protected: |
| void FakeStoreClientInfoBackup(const metrics::ClientInfo& client_info) {} |
| |
| std::unique_ptr<metrics::ClientInfo> LoadFakeClientInfoBackup() { |
| return std::make_unique<metrics::ClientInfo>(); |
| } |
| |
| web::WebTaskEnvironment task_environment_; |
| IOSChromeScopedTestingChromeBrowserStateManager scoped_browser_state_manager_; |
| std::unique_ptr<ChromeBrowserState> browser_state_; |
| metrics::TestEnabledStateProvider enabled_state_provider_; |
| TestingPrefServiceSimple prefs_; |
| std::unique_ptr<metrics::MetricsStateManager> metrics_state_manager_; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(IOSChromeMetricsServiceClientTest); |
| }; |
| |
| namespace { |
| |
| TEST_F(IOSChromeMetricsServiceClientTest, FilterFiles) { |
| base::ProcessId my_pid = base::GetCurrentProcId(); |
| base::FilePath active_dir(FILE_PATH_LITERAL("foo")); |
| base::FilePath upload_dir(FILE_PATH_LITERAL("bar")); |
| base::FilePath upload_path = |
| base::GlobalHistogramAllocator::ConstructFilePathForUploadDir( |
| upload_dir, "TestMetrics"); |
| EXPECT_EQ( |
| metrics::FileMetricsProvider::FILTER_ACTIVE_THIS_PID, |
| IOSChromeMetricsServiceClient::FilterBrowserMetricsFiles(upload_path)); |
| EXPECT_EQ(metrics::FileMetricsProvider::FILTER_PROCESS_FILE, |
| IOSChromeMetricsServiceClient::FilterBrowserMetricsFiles( |
| base::GlobalHistogramAllocator::ConstructFilePathForUploadDir( |
| upload_dir, "Test", base::Time::Now(), (my_pid + 10)))); |
| } |
| |
| } // namespace |
| |
| // This is not in anonymous namespace so this test can be a friend class of |
| // MetricsService for accessing protected ivars. |
| TEST_F(IOSChromeMetricsServiceClientTest, TestRegisterMetricsServiceProviders) { |
| // This is for the two metrics providers added in the MetricsService |
| // constructor: StabilityMetricsProvider and MetricsStateMetricsProvider. |
| size_t expected_providers = 2; |
| |
| // This is the number of metrics providers that are registered inside |
| // IOSChromeMetricsServiceClient::Initialize(). |
| expected_providers += 14; |
| |
| std::unique_ptr<IOSChromeMetricsServiceClient> chrome_metrics_service_client = |
| IOSChromeMetricsServiceClient::Create(metrics_state_manager_.get()); |
| EXPECT_EQ(expected_providers, |
| chrome_metrics_service_client->GetMetricsService() |
| ->delegating_provider_.GetProviders() |
| .size()); |
| } |
| |
| TEST_F(IOSChromeMetricsServiceClientTest, |
| TestRegisterUkmProvidersWhenUKMFeatureEnabled) { |
| base::test::ScopedFeatureList local_feature; |
| local_feature.InitAndEnableFeature(ukm::kUkmFeature); |
| |
| std::unique_ptr<IOSChromeMetricsServiceClient> chrome_metrics_service_client = |
| IOSChromeMetricsServiceClient::Create(metrics_state_manager_.get()); |
| |
| ukm::UkmService* ukmService = |
| chrome_metrics_service_client->GetUkmService(); |
| // Verify that the UKM service is instantiated when enabled. |
| EXPECT_TRUE(ukmService); |
| |
| // Number of providers registered by |
| // IOSChromeMetricsServiceClient::RegisterMetricsServiceProviders(), namely |
| // CPUMetricsProvider, ScreenInfoMetricsProvider, FieldTrialsProvider. |
| const size_t expected_providers = 3; |
| |
| EXPECT_EQ(expected_providers, |
| ukmService->metrics_providers_.GetProviders().size()); |
| } |
| |
| TEST_F(IOSChromeMetricsServiceClientTest, |
| TestRegisterUkmProvidersWhenForceMetricsReporting) { |
| // Disable the feature of reporting UKM metrics. |
| base::test::ScopedFeatureList local_feature; |
| local_feature.InitAndDisableFeature(ukm::kUkmFeature); |
| |
| // Force metrics reporting using the commandline switch. |
| base::CommandLine::ForCurrentProcess()->AppendSwitch( |
| metrics::switches::kForceEnableMetricsReporting); |
| |
| std::unique_ptr<IOSChromeMetricsServiceClient> chrome_metrics_service_client = |
| IOSChromeMetricsServiceClient::Create(metrics_state_manager_.get()); |
| // Verify that the UKM service is instantiated when enabled. |
| EXPECT_TRUE(chrome_metrics_service_client->GetUkmService()); |
| } |
| |
| TEST_F(IOSChromeMetricsServiceClientTest, TestUkmProvidersWhenDisabled) { |
| // Enable demographics reporting feature. |
| base::test::ScopedFeatureList local_feature; |
| local_feature.InitAndDisableFeature(ukm::kUkmFeature); |
| |
| std::unique_ptr<IOSChromeMetricsServiceClient> chrome_metrics_service_client = |
| IOSChromeMetricsServiceClient::Create(metrics_state_manager_.get()); |
| // Verify that the UKM service is not instantiated when disabled. |
| EXPECT_FALSE(chrome_metrics_service_client->GetUkmService()); |
| } |
| |
| TEST_F(IOSChromeMetricsServiceClientTest, GetUploadSigningKey_NotEmpty) { |
| std::unique_ptr<IOSChromeMetricsServiceClient> chrome_metrics_service_client = |
| IOSChromeMetricsServiceClient::Create(metrics_state_manager_.get()); |
| const std::string signing_key = |
| chrome_metrics_service_client->GetUploadSigningKey(); |
| #if BUILDFLAG(GOOGLE_CHROME_BRANDING) |
| // The signing key should never be an empty string for a Chrome-branded build. |
| EXPECT_FALSE(signing_key.empty()); |
| #else |
| // In non-branded builds, we may still have a valid signing key if |
| // USE_OFFICIAL_GOOGLE_API_KEYS is true. However, that macro is not available |
| // in this file. |
| ALLOW_UNUSED_LOCAL(signing_key); |
| #endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) |
| } |
| |
| TEST_F(IOSChromeMetricsServiceClientTest, GetUploadSigningKey_CanSignLogs) { |
| std::unique_ptr<IOSChromeMetricsServiceClient> chrome_metrics_service_client = |
| IOSChromeMetricsServiceClient::Create(metrics_state_manager_.get()); |
| const std::string signing_key = |
| chrome_metrics_service_client->GetUploadSigningKey(); |
| |
| std::string signature; |
| bool sign_success = metrics::UnsentLogStore::ComputeHMACForLog( |
| "Test Log Data", signing_key, &signature); |
| #if BUILDFLAG(GOOGLE_CHROME_BRANDING) |
| // The signing key should be able to sign data for a Chrome-branded build. |
| EXPECT_TRUE(sign_success); |
| EXPECT_FALSE(signature.empty()); |
| #else |
| // In non-branded builds, we may still have a valid signing key if |
| // USE_OFFICIAL_GOOGLE_API_KEYS is true. However, that macro is not available |
| // in this file, so just check that success == a non-empty signature. |
| EXPECT_EQ(sign_success, !signature.empty()); |
| #endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) |
| } |