diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/components/ukm | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-85-based.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/components/ukm')
-rw-r--r-- | chromium/components/ukm/BUILD.gn | 3 | ||||
-rw-r--r-- | chromium/components/ukm/field_trials_provider_helper.cc | 23 | ||||
-rw-r--r-- | chromium/components/ukm/field_trials_provider_helper.h | 20 | ||||
-rw-r--r-- | chromium/components/ukm/observers/ukm_consent_state_observer.cc | 2 | ||||
-rw-r--r-- | chromium/components/ukm/ukm_recorder_impl.cc | 30 | ||||
-rw-r--r-- | chromium/components/ukm/ukm_reporting_service.cc | 13 | ||||
-rw-r--r-- | chromium/components/ukm/ukm_service.cc | 41 | ||||
-rw-r--r-- | chromium/components/ukm/ukm_service.h | 13 | ||||
-rw-r--r-- | chromium/components/ukm/ukm_service_unittest.cc | 144 | ||||
-rw-r--r-- | chromium/components/ukm/ukm_test_helper.cc | 9 |
10 files changed, 175 insertions, 123 deletions
diff --git a/chromium/components/ukm/BUILD.gn b/chromium/components/ukm/BUILD.gn index 1a7343b89f6..278cd3f0648 100644 --- a/chromium/components/ukm/BUILD.gn +++ b/chromium/components/ukm/BUILD.gn @@ -11,6 +11,8 @@ static_library("ukm") { sources = [ "app_source_url_recorder.cc", "app_source_url_recorder.h", + "field_trials_provider_helper.cc", + "field_trials_provider_helper.h", "scheme_constants.cc", "scheme_constants.h", "ukm_entry_filter.h", @@ -134,6 +136,5 @@ static_library("ukm_test_helper") { "//components/metrics", "//services/metrics/public/cpp:metrics_cpp", "//third_party/metrics_proto", - "//third_party/zlib/google:compression_utils", ] } diff --git a/chromium/components/ukm/field_trials_provider_helper.cc b/chromium/components/ukm/field_trials_provider_helper.cc new file mode 100644 index 00000000000..ec817c2efe9 --- /dev/null +++ b/chromium/components/ukm/field_trials_provider_helper.cc @@ -0,0 +1,23 @@ +// Copyright 2020 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/field_trials_provider_helper.h" + +namespace ukm { + +namespace { + +// UKM suffix for field trial recording. +const char kUKMFieldTrialSuffix[] = "UKM"; + +} // namespace + +std::unique_ptr<variations::FieldTrialsProvider> +CreateFieldTrialsProviderForUkm() { + // TODO(crbug.com/754877): Support synthetic trials for UKM. + return std::make_unique<variations::FieldTrialsProvider>( + nullptr, kUKMFieldTrialSuffix); +} + +} // namespace ukm diff --git a/chromium/components/ukm/field_trials_provider_helper.h b/chromium/components/ukm/field_trials_provider_helper.h new file mode 100644 index 00000000000..829d3b921e9 --- /dev/null +++ b/chromium/components/ukm/field_trials_provider_helper.h @@ -0,0 +1,20 @@ +// Copyright 2020 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. + +#ifndef COMPONENTS_UKM_FIELD_TRIALS_PROVIDER_HELPER_H_ +#define COMPONENTS_UKM_FIELD_TRIALS_PROVIDER_HELPER_H_ + +#include <memory> + +#include "components/metrics/field_trials_provider.h" + +namespace ukm { + +// Creates a FieldTrialsProvider for use with UKMs. +std::unique_ptr<variations::FieldTrialsProvider> +CreateFieldTrialsProviderForUkm(); + +} // namespace ukm + +#endif // COMPONENTS_UKM_FIELD_TRIALS_PROVIDER_HELPER_H_ diff --git a/chromium/components/ukm/observers/ukm_consent_state_observer.cc b/chromium/components/ukm/observers/ukm_consent_state_observer.cc index 96bfed06bfc..e67a74bf46f 100644 --- a/chromium/components/ukm/observers/ukm_consent_state_observer.cc +++ b/chromium/components/ukm/observers/ukm_consent_state_observer.cc @@ -48,7 +48,7 @@ void UkmConsentStateObserver::StartObserving(syncer::SyncService* sync_service, PrefService* prefs) { std::unique_ptr<UrlKeyedDataCollectionConsentHelper> consent_helper = UrlKeyedDataCollectionConsentHelper:: - NewAnonymizedDataCollectionConsentHelper(prefs, sync_service); + NewAnonymizedDataCollectionConsentHelper(prefs); ProfileState state = GetProfileState(sync_service, consent_helper.get()); previous_states_[sync_service] = state; diff --git a/chromium/components/ukm/ukm_recorder_impl.cc b/chromium/components/ukm/ukm_recorder_impl.cc index 4764371538d..dd401aceb82 100644 --- a/chromium/components/ukm/ukm_recorder_impl.cc +++ b/chromium/components/ukm/ukm_recorder_impl.cc @@ -13,6 +13,7 @@ #include "base/metrics/crc32.h" #include "base/metrics/field_trial.h" #include "base/metrics/field_trial_params.h" +#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/metrics_hashes.h" #include "base/rand_util.h" @@ -106,7 +107,13 @@ void RecordDroppedSource(DroppedDataReason reason) { static_cast<int>(DroppedDataReason::NUM_DROPPED_DATA_REASONS)); } -void RecordDroppedEntry(DroppedDataReason reason) { +void RecordDroppedEntry(uint64_t event_hash, DroppedDataReason reason) { + // The enum for this histogram gets populated by the PopulateEnumWithUkmEvents + // function in populate_enums.py when producing the merged XML. + base::UmaHistogramSparse("UKM.Entries.Dropped.ByEntryHash", + // Truncate the unsigned 64-bit hash to 31 bits, to + // make it a suitable histogram sample. + event_hash & 0x7fffffff); UMA_HISTOGRAM_ENUMERATION( "UKM.Entries.Dropped", static_cast<int>(reason), static_cast<int>(DroppedDataReason::NUM_DROPPED_DATA_REASONS)); @@ -363,8 +370,8 @@ void UkmRecorderImpl::StoreRecordingsInReport(Report* report) { if (!base::Contains(source_ids_seen, kv.first)) { continue; } else { - // Source of base::UkmSourceId::Type::UKM type will not be kept after - // entries are logged. + // Source of base::UkmSourceId::Type::DEFAULT type will not be kept + // after entries are logged. MarkSourceForDeletion(kv.first); } } @@ -433,8 +440,9 @@ void UkmRecorderImpl::StoreRecordingsInReport(Report* report) { UMA_HISTOGRAM_COUNTS_1000("UKM.Sources.UnmatchedSourcesCount", num_sources_unmatched); - UMA_HISTOGRAM_COUNTS_1000("UKM.Sources.SerializedCount2.Ukm", - serialized_source_type_counts[SourceIdType::UKM]); + UMA_HISTOGRAM_COUNTS_1000( + "UKM.Sources.SerializedCount2.Default", + serialized_source_type_counts[SourceIdType::DEFAULT]); UMA_HISTOGRAM_COUNTS_1000( "UKM.Sources.SerializedCount2.Navigation", serialized_source_type_counts[SourceIdType::NAVIGATION_ID]); @@ -681,12 +689,14 @@ void UkmRecorderImpl::AddEntry(mojom::UkmEntryPtr entry) { DCHECK(!HasUnknownMetrics(decode_map_, *entry)); if (!recording_enabled_) { - RecordDroppedEntry(DroppedDataReason::RECORDING_DISABLED); + RecordDroppedEntry(entry->event_hash, + DroppedDataReason::RECORDING_DISABLED); return; } if (!ApplyEntryFilter(entry.get())) { - RecordDroppedEntry(DroppedDataReason::REJECTED_BY_FILTER); + RecordDroppedEntry(entry->event_hash, + DroppedDataReason::REJECTED_BY_FILTER); return; } @@ -703,7 +713,7 @@ void UkmRecorderImpl::AddEntry(mojom::UkmEntryPtr entry) { if (ShouldRestrictToWhitelistedEntries() && !base::Contains(whitelisted_entry_hashes_, entry->event_hash)) { - RecordDroppedEntry(DroppedDataReason::NOT_WHITELISTED); + RecordDroppedEntry(entry->event_hash, DroppedDataReason::NOT_WHITELISTED); event_aggregate.dropped_due_to_whitelist++; for (auto& metric : entry->metrics) event_aggregate.metrics[metric.first].dropped_due_to_whitelist++; @@ -718,7 +728,7 @@ void UkmRecorderImpl::AddEntry(mojom::UkmEntryPtr entry) { bool sampled_in = IsSampledIn(entry->source_id, entry->event_hash); if (!sampled_in) { - RecordDroppedEntry(DroppedDataReason::SAMPLED_OUT); + RecordDroppedEntry(entry->event_hash, DroppedDataReason::SAMPLED_OUT); event_aggregate.dropped_due_to_sampling++; for (auto& metric : entry->metrics) event_aggregate.metrics[metric.first].dropped_due_to_sampling++; @@ -727,7 +737,7 @@ void UkmRecorderImpl::AddEntry(mojom::UkmEntryPtr entry) { } if (recordings_.entries.size() >= GetMaxEntries()) { - RecordDroppedEntry(DroppedDataReason::MAX_HIT); + RecordDroppedEntry(entry->event_hash, DroppedDataReason::MAX_HIT); event_aggregate.dropped_due_to_limits++; for (auto& metric : entry->metrics) event_aggregate.metrics[metric.first].dropped_due_to_limits++; diff --git a/chromium/components/ukm/ukm_reporting_service.cc b/chromium/components/ukm/ukm_reporting_service.cc index 0b23f3a1421..8beedce934d 100644 --- a/chromium/components/ukm/ukm_reporting_service.cc +++ b/chromium/components/ukm/ukm_reporting_service.cc @@ -62,12 +62,13 @@ UkmReportingService::UkmReportingService(metrics::MetricsServiceClient* client, PrefService* local_state) : ReportingService(client, local_state, kMaxLogRetransmitSize), unsent_log_store_(std::make_unique<ukm::UnsentLogStoreMetricsImpl>(), - local_state, - prefs::kUkmUnsentLogStore, - kMinUnsentLogCount, - kMinUnsentLogBytes, - kMaxLogRetransmitSize, - client->GetUploadSigningKey()) {} + local_state, + prefs::kUkmUnsentLogStore, + nullptr, + kMinUnsentLogCount, + kMinUnsentLogBytes, + kMaxLogRetransmitSize, + client->GetUploadSigningKey()) {} UkmReportingService::~UkmReportingService() {} diff --git a/chromium/components/ukm/ukm_service.cc b/chromium/components/ukm/ukm_service.cc index 337cf3faa09..b285a1e319c 100644 --- a/chromium/components/ukm/ukm_service.cc +++ b/chromium/components/ukm/ukm_service.cc @@ -111,6 +111,7 @@ void PurgeExtensionDataFromUnsentLogStore( const std::string& compressed_log_data = ukm_log_store->GetLogAtIndex(index); std::string uncompressed_log_data; + // TODO(crbug/1086910): Use the utilities in log_decoder.h instead. const bool uncompress_successful = compression::GzipUncompress( compressed_log_data, &uncompressed_log_data); DCHECK(uncompress_successful); @@ -153,10 +154,14 @@ void PurgeExtensionDataFromUnsentLogStore( std::string reserialized_log_data; report.SerializeToString(&reserialized_log_data); + // This allows catching errors with bad UKM serialization we've seen before + // that would otherwise only be noticed on the server. + DCHECK(UkmService::LogCanBeParsed(reserialized_log_data)); // Replace the compressed log in the store by its filtered version. const std::string old_compressed_log_data = - ukm_log_store->ReplaceLogAtIndex(index, reserialized_log_data); + ukm_log_store->ReplaceLogAtIndex(index, reserialized_log_data, + base::nullopt); // Reached here only if extensions were found in the log, so data should now // be different after filtering. @@ -170,21 +175,32 @@ void PurgeExtensionDataFromUnsentLogStore( const base::Feature UkmService::kReportUserNoisedUserBirthYearAndGender = { "UkmReportNoisedUserBirthYearAndGender", base::FEATURE_ENABLED_BY_DEFAULT}; +bool UkmService::LogCanBeParsed(const std::string& serialized_data) { + Report report; + bool report_parse_successful = report.ParseFromString(serialized_data); + if (!report_parse_successful) + return false; + // Make sure the reserialzed log from this |report| matches the input + // |serialized_data|. + std::string reserialized_from_report; + report.SerializeToString(&reserialized_from_report); + return reserialized_from_report == serialized_data; +} + UkmService::UkmService(PrefService* pref_service, metrics::MetricsServiceClient* client, - bool restrict_to_whitelist_entries, std::unique_ptr<metrics::UkmDemographicMetricsProvider> demographics_provider) : pref_service_(pref_service), - restrict_to_whitelist_entries_(restrict_to_whitelist_entries), + // We only need to restrict to whitelisted Entries if metrics reporting is + // not forced. + restrict_to_whitelist_entries_(!client->IsMetricsReportingForceEnabled()), client_(client), demographics_provider_(std::move(demographics_provider)), reporting_service_(client, pref_service) { DCHECK(pref_service_); DCHECK(client_); - DCHECK(demographics_provider_); DVLOG(1) << "UkmService::Constructor"; - reporting_service_.Initialize(); base::RepeatingClosure rotate_callback = base::BindRepeating( @@ -361,8 +377,10 @@ void UkmService::RotateLog() { } void UkmService::AddSyncedUserNoiseBirthYearAndGenderToReport(Report* report) { - if (!base::FeatureList::IsEnabled(kReportUserNoisedUserBirthYearAndGender)) + if (!base::FeatureList::IsEnabled(kReportUserNoisedUserBirthYearAndGender) || + !demographics_provider_) { return; + } demographics_provider_->ProvideSyncedUserNoisedBirthYearAndGenderToReport( report); @@ -383,6 +401,12 @@ void UkmService::BuildAndStoreLog() { report.set_session_id(session_id_); report.set_report_id(++report_count_); + const auto product = static_cast<metrics::ChromeUserMetricsExtension_Product>( + client_->GetProduct()); + // Only set the product if it differs from the default value. + if (product != report.product()) + report.set_product(product); + StoreRecordingsInReport(&report); metrics::MetricsLog::RecordCoreSystemProfile(client_, @@ -395,7 +419,10 @@ void UkmService::BuildAndStoreLog() { std::string serialized_log; report.SerializeToString(&serialized_log); - reporting_service_.ukm_log_store()->StoreLog(serialized_log); + // This allows catching errors with bad UKM serialization we've seen before + // that would otherwise only be noticed on the server. + DCHECK(LogCanBeParsed(serialized_log)); + reporting_service_.ukm_log_store()->StoreLog(serialized_log, base::nullopt); } bool UkmService::ShouldRestrictToWhitelistedEntries() const { diff --git a/chromium/components/ukm/ukm_service.h b/chromium/components/ukm/ukm_service.h index 2ebeb130734..37d6ab19591 100644 --- a/chromium/components/ukm/ukm_service.h +++ b/chromium/components/ukm/ukm_service.h @@ -18,6 +18,7 @@ #include "components/metrics/delegating_provider.h" #include "components/metrics/metrics_provider.h" #include "components/metrics/metrics_rotation_scheduler.h" +#include "components/metrics/ukm_demographic_metrics_provider.h" #include "components/ukm/ukm_entry_filter.h" #include "components/ukm/ukm_recorder_impl.h" #include "components/ukm/ukm_reporting_service.h" @@ -31,7 +32,6 @@ FORWARD_DECLARE_TEST(IOSChromeMetricsServiceClientTest, namespace metrics { class MetricsServiceClient; class UkmBrowserTestBase; -class UkmDemographicMetricsProvider; } namespace ukm { @@ -59,10 +59,10 @@ class UkmService : public UkmRecorderImpl { // Constructs a UkmService. // Calling code is responsible for ensuring that the lifetime of // |pref_service| is longer than the lifetime of UkmService. The parameters - // |pref_service|, |client|, and |demographics_provider| must not be null. + // |pref_service|, |client| must not be null. |demographics_provider| may be + // null. UkmService(PrefService* pref_service, metrics::MetricsServiceClient* client, - bool restrict_to_whitelist_entries, std::unique_ptr<metrics::UkmDemographicMetricsProvider> demographics_provider); ~UkmService() override; @@ -108,11 +108,18 @@ class UkmService : public UkmRecorderImpl { int32_t report_count() const { return report_count_; } + void set_restrict_to_whitelist_entries_for_testing(bool value) { + restrict_to_whitelist_entries_ = value; + } + // Enables adding the synced user's noised birth year and gender to the UKM // report. For more details, see doc of metrics::DemographicMetricsProvider in // components/metrics/demographic_metrics_provider.h. static const base::Feature kReportUserNoisedUserBirthYearAndGender; + // Makes sure that the serialized ukm report can be parsed. + static bool LogCanBeParsed(const std::string& serialized_data); + private: friend ::metrics::UkmBrowserTestBase; friend ::ukm::UkmTestHelper; diff --git a/chromium/components/ukm/ukm_service_unittest.cc b/chromium/components/ukm/ukm_service_unittest.cc index a0d6a91cef4..7d90ad8074a 100644 --- a/chromium/components/ukm/ukm_service_unittest.cc +++ b/chromium/components/ukm/ukm_service_unittest.cc @@ -24,6 +24,7 @@ #include "base/threading/platform_thread.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" +#include "components/metrics/log_decoder.h" #include "components/metrics/metrics_log_uploader.h" #include "components/metrics/test/test_metrics_provider.h" #include "components/metrics/test/test_metrics_service_client.h" @@ -47,14 +48,14 @@ namespace ukm { // Some arbitrary events used in tests. -using TestEvent1 = ukm::builders::PageLoad; +using TestEvent1 = builders::PageLoad; const char* kTestEvent1Metric1 = TestEvent1::kPaintTiming_NavigationToFirstContentfulPaintName; -const char* kTestEvent1Metric2 = TestEvent1::kNet_CacheBytesName; -using TestEvent2 = ukm::builders::Memory_Experimental; +const char* kTestEvent1Metric2 = TestEvent1::kNet_CacheBytes2Name; +using TestEvent2 = builders::Memory_Experimental; const char* kTestEvent2Metric1 = TestEvent2::kArrayBufferName; const char* kTestEvent2Metric2 = TestEvent2::kBlinkGCName; -using TestEvent3 = ukm::builders::Previews; +using TestEvent3 = builders::Previews; std::string Entry1And2Whitelist() { return std::string(TestEvent1::kEntryName) + ',' + TestEvent2::kEntryName; @@ -118,7 +119,7 @@ class MockDemographicMetricsProvider // DemographicMetricsProvider: MOCK_METHOD1(ProvideSyncedUserNoisedBirthYearAndGenderToReport, - void(ukm::Report* report)); + void(Report* report)); }; class UkmServiceTest : public testing::Test { @@ -145,21 +146,18 @@ class UkmServiceTest : public testing::Test { Report GetPersistedReport() { EXPECT_GE(GetPersistedLogCount(), 1); metrics::UnsentLogStore result_unsent_log_store( - std::make_unique<ukm::UnsentLogStoreMetricsImpl>(), &prefs_, - prefs::kUkmUnsentLogStore, - 3, // log count limit - 1000, // byte limit - 0, std::string()); + std::make_unique<UnsentLogStoreMetricsImpl>(), &prefs_, + prefs::kUkmUnsentLogStore, /* meta_data_pref_name= */ nullptr, + /* min_log_count= */ 3, /* min_log_bytes= */ 1000, + /* max_log_size= */ 0, + /* signing_key= */ std::string()); result_unsent_log_store.LoadPersistedUnsentLogs(); result_unsent_log_store.StageNextLog(); - std::string uncompressed_log_data; - EXPECT_TRUE(compression::GzipUncompress( - result_unsent_log_store.staged_log(), &uncompressed_log_data)); - Report report; - EXPECT_TRUE(report.ParseFromString(uncompressed_log_data)); + EXPECT_TRUE(metrics::DecodeLogDataToProto( + result_unsent_log_store.staged_log(), &report)); return report; } @@ -168,7 +166,7 @@ class UkmServiceTest : public testing::Test { } static SourceId GetNonWhitelistedSourceId(int64_t id) { - return ConvertToSourceId(id, SourceIdType::UKM); + return ConvertToSourceId(id, SourceIdType::DEFAULT); } protected: @@ -187,7 +185,6 @@ class UkmServiceTest : public testing::Test { TEST_F(UkmServiceTest, ClientIdMigration) { prefs_.SetInt64(prefs::kUkmClientId, -1); UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); service.Initialize(); uint64_t migrated_id = prefs_.GetUint64(prefs::kUkmClientId); @@ -198,7 +195,6 @@ TEST_F(UkmServiceTest, ClientIdMigration) { TEST_F(UkmServiceTest, ClientIdClonedInstall) { prefs_.SetInt64(prefs::kUkmClientId, 123); UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); EXPECT_FALSE(client_.ShouldResetClientIdsOnClonedInstall()); @@ -213,7 +209,6 @@ TEST_F(UkmServiceTest, ClientIdClonedInstall) { TEST_F(UkmServiceTest, EnableDisableSchedule) { UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); EXPECT_FALSE(task_runner_->HasPendingTask()); service.Initialize(); @@ -230,7 +225,6 @@ TEST_F(UkmServiceTest, PersistAndPurge) { ScopedUkmFeatureParams params({{"WhitelistEntries", Entry1And2Whitelist()}}); UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); EXPECT_EQ(GetPersistedLogCount(), 0); @@ -254,7 +248,6 @@ TEST_F(UkmServiceTest, PersistAndPurge) { TEST_F(UkmServiceTest, Purge) { UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); EXPECT_EQ(GetPersistedLogCount(), 0); @@ -276,12 +269,11 @@ TEST_F(UkmServiceTest, Purge) { TEST_F(UkmServiceTest, PurgeExtensionDataFromUnsentLogStore) { UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); auto* unsent_log_store = service.reporting_service_.ukm_log_store(); // Initialize a Report to be saved to the log store. - ukm::Report report; + Report report; report.set_client_id(1); report.set_session_id(1); report.set_report_id(1); @@ -291,29 +283,29 @@ TEST_F(UkmServiceTest, PurgeExtensionDataFromUnsentLogStore) { "chrome-extension://bmnlcjabgnpnenekpadlanbbkooimhnj/manifest.json"; // Add both extension- and non-extension-related sources to the Report. - ukm::Source* proto_source_1 = report.add_sources(); - ukm::SourceId source_id_1 = - ukm::ConvertToSourceId(1, ukm::SourceIdType::NAVIGATION_ID); + Source* proto_source_1 = report.add_sources(); + SourceId source_id_1 = ConvertToSourceId(1, SourceIdType::NAVIGATION_ID); proto_source_1->set_id(source_id_1); proto_source_1->add_urls()->set_url(non_extension_url); - ukm::Source* proto_source_2 = report.add_sources(); - ukm::SourceId source_id_2 = - ukm::ConvertToSourceId(2, ukm::SourceIdType::NAVIGATION_ID); + Source* proto_source_2 = report.add_sources(); + SourceId source_id_2 = ConvertToSourceId(2, SourceIdType::NAVIGATION_ID); proto_source_2->set_id(source_id_2); proto_source_2->add_urls()->set_url(extension_url); // Add some entries for both sources. - ukm::Entry* entry_1 = report.add_entries(); + Entry* entry_1 = report.add_entries(); entry_1->set_source_id(source_id_2); - ukm::Entry* entry_2 = report.add_entries(); + Entry* entry_2 = report.add_entries(); entry_2->set_source_id(source_id_1); - ukm::Entry* entry_3 = report.add_entries(); + Entry* entry_3 = report.add_entries(); entry_3->set_source_id(source_id_2); // Save the Report to the store. std::string serialized_log; report.SerializeToString(&serialized_log); - unsent_log_store->StoreLog(serialized_log); + // Makes sure that the serialized ukm report can be parsed. + ASSERT_TRUE(UkmService::LogCanBeParsed(serialized_log)); + unsent_log_store->StoreLog(serialized_log, base::nullopt); // Do extension purging. service.PurgeExtensions(); @@ -324,8 +316,9 @@ TEST_F(UkmServiceTest, PurgeExtensionDataFromUnsentLogStore) { const std::string& compressed_log_data = unsent_log_store->staged_log(); std::string uncompressed_log_data; + // TODO(crbug/1086910): Use the utilities in log_decoder.h instead. compression::GzipUncompress(compressed_log_data, &uncompressed_log_data); - ukm::Report filtered_report; + Report filtered_report; filtered_report.ParseFromString(uncompressed_log_data); // Only proto_source_1 with non-extension URL is kept. @@ -340,7 +333,6 @@ TEST_F(UkmServiceTest, PurgeExtensionDataFromUnsentLogStore) { TEST_F(UkmServiceTest, SourceSerialization) { UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); EXPECT_EQ(GetPersistedLogCount(), 0); @@ -353,7 +345,7 @@ TEST_F(UkmServiceTest, SourceSerialization) { navigation_data.urls = {GURL("https://google.com/initial"), GURL("https://google.com/final")}; - ukm::SourceId id = GetWhitelistedSourceId(0); + SourceId id = GetWhitelistedSourceId(0); recorder.RecordNavigation(id, navigation_data); service.Flush(); @@ -373,7 +365,6 @@ TEST_F(UkmServiceTest, AddEntryWithEmptyMetrics) { ScopedUkmFeatureParams params({{"WhitelistEntries", Entry1And2Whitelist()}}); UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); ASSERT_EQ(0, GetPersistedLogCount()); @@ -382,7 +373,7 @@ TEST_F(UkmServiceTest, AddEntryWithEmptyMetrics) { service.EnableRecording(/*extensions=*/false); service.EnableReporting(); - ukm::SourceId id = GetWhitelistedSourceId(0); + SourceId id = GetWhitelistedSourceId(0); recorder.UpdateSourceURL(id, GURL("https://google.com/foobar")); TestEvent1(id).Record(&service); @@ -396,7 +387,6 @@ TEST_F(UkmServiceTest, MetricsProviderTest) { ScopedUkmFeatureParams params({{"WhitelistEntries", Entry1And2Whitelist()}}); UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); @@ -413,7 +403,7 @@ TEST_F(UkmServiceTest, MetricsProviderTest) { service.EnableRecording(/*extensions=*/false); service.EnableReporting(); - ukm::SourceId id = GetWhitelistedSourceId(0); + SourceId id = GetWhitelistedSourceId(0); recorder.UpdateSourceURL(id, GURL("https://google.com/foobar")); TestEvent1(id).Record(&service); service.Flush(); @@ -431,7 +421,6 @@ TEST_F(UkmServiceTest, MetricsProviderTest) { // system profile fields. TEST_F(UkmServiceTest, SystemProfileTest) { UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); @@ -441,7 +430,7 @@ TEST_F(UkmServiceTest, SystemProfileTest) { service.EnableRecording(/*extensions=*/false); service.EnableReporting(); - ukm::SourceId id = GetWhitelistedSourceId(0); + SourceId id = GetWhitelistedSourceId(0); recorder.UpdateSourceURL(id, GURL("https://google.com/foobar")); TestEvent1(id).Record(&service); service.Flush(); @@ -468,14 +457,13 @@ TEST_F(UkmServiceTest, AddUserDemograhicsWhenAvailableAndFeatureEnabled) { ProvideSyncedUserNoisedBirthYearAndGenderToReport(testing::_)) .Times(2) .WillRepeatedly([&number_of_invocations, test_gender, - test_birth_year](ukm::Report* report) { + test_birth_year](Report* report) { report->mutable_user_demographics()->set_birth_year(test_birth_year); report->mutable_user_demographics()->set_gender(test_gender); ++number_of_invocations; }); UkmService service(&prefs_, &client_, - /*restrict_to_whitelisted_entries=*/true, std::move(provider)); TestRecordingHelper recorder(&service); @@ -489,7 +477,7 @@ TEST_F(UkmServiceTest, AddUserDemograhicsWhenAvailableAndFeatureEnabled) { service.EnableRecording(/*extensions=*/false); service.EnableReporting(); - ukm::SourceId id = GetWhitelistedSourceId(0); + SourceId id = GetWhitelistedSourceId(0); recorder.UpdateSourceURL(id, GURL("https://google.com/foobar")); TestEvent1(id).Record(&service); service.Flush(); @@ -514,10 +502,9 @@ TEST_F(UkmServiceTest, EXPECT_CALL(*provider, ProvideSyncedUserNoisedBirthYearAndGenderToReport(testing::_)) .Times(2) - .WillRepeatedly([](ukm::Report* report) {}); + .WillRepeatedly([](Report* report) {}); UkmService service(&prefs_, &client_, - /*restrict_to_whitelisted_entries=*/true, std::move(provider)); TestRecordingHelper recorder(&service); service.Initialize(); @@ -526,7 +513,7 @@ TEST_F(UkmServiceTest, service.EnableRecording(/*extensions=*/false); service.EnableReporting(); - ukm::SourceId id = GetWhitelistedSourceId(0); + SourceId id = GetWhitelistedSourceId(0); recorder.UpdateSourceURL(id, GURL("https://google.com/foobar")); TestEvent1(id).Record(&service); service.Flush(); @@ -551,7 +538,6 @@ TEST_F(UkmServiceTest, DontAddUserDemograhicsWhenFeatureDisabled) { .Times(0); UkmService service(&prefs_, &client_, - /*restrict_to_whitelisted_entries=*/true, std::move(provider)); TestRecordingHelper recorder(&service); @@ -561,7 +547,7 @@ TEST_F(UkmServiceTest, DontAddUserDemograhicsWhenFeatureDisabled) { service.EnableRecording(/*extensions=*/false); service.EnableReporting(); - ukm::SourceId id = GetWhitelistedSourceId(0); + SourceId id = GetWhitelistedSourceId(0); recorder.UpdateSourceURL(id, GURL("https://google.com/foobar")); TestEvent1(id).Record(&service); service.Flush(); @@ -575,7 +561,6 @@ TEST_F(UkmServiceTest, DontAddUserDemograhicsWhenFeatureDisabled) { TEST_F(UkmServiceTest, LogsRotation) { UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); EXPECT_EQ(GetPersistedLogCount(), 0); @@ -587,7 +572,7 @@ TEST_F(UkmServiceTest, LogsRotation) { EXPECT_EQ(0, service.report_count()); // Log rotation should generate a log. - const ukm::SourceId id = GetWhitelistedSourceId(0); + const SourceId id = GetWhitelistedSourceId(0); recorder.UpdateSourceURL(id, GURL("https://google.com/foobar")); task_runner_->RunPendingTasks(); EXPECT_EQ(1, service.report_count()); @@ -620,7 +605,6 @@ TEST_F(UkmServiceTest, LogsUploadedOnlyWhenHavingSourcesOrEntries) { ScopedUkmFeatureParams params({{"WhitelistEntries", Entry1And2Whitelist()}}); UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); EXPECT_EQ(GetPersistedLogCount(), 0); @@ -635,7 +619,7 @@ TEST_F(UkmServiceTest, LogsUploadedOnlyWhenHavingSourcesOrEntries) { service.Flush(); EXPECT_EQ(GetPersistedLogCount(), 0); - ukm::SourceId id = GetWhitelistedSourceId(0); + SourceId id = GetWhitelistedSourceId(0); recorder.UpdateSourceURL(id, GURL("https://google.com/foobar")); // Includes a Source, so will persist. service.Flush(); @@ -660,9 +644,9 @@ TEST_F(UkmServiceTest, LogsUploadedOnlyWhenHavingSourcesOrEntries) { } TEST_F(UkmServiceTest, GetNewSourceID) { - ukm::SourceId id1 = UkmRecorder::GetNewSourceID(); - ukm::SourceId id2 = UkmRecorder::GetNewSourceID(); - ukm::SourceId id3 = UkmRecorder::GetNewSourceID(); + SourceId id1 = UkmRecorder::GetNewSourceID(); + SourceId id2 = UkmRecorder::GetNewSourceID(); + SourceId id3 = UkmRecorder::GetNewSourceID(); EXPECT_NE(id1, id2); EXPECT_NE(id1, id3); EXPECT_NE(id2, id3); @@ -671,7 +655,6 @@ TEST_F(UkmServiceTest, GetNewSourceID) { TEST_F(UkmServiceTest, RecordRedirectedUrl) { ClearPrefs(); UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); EXPECT_EQ(GetPersistedLogCount(), 0); @@ -680,7 +663,7 @@ TEST_F(UkmServiceTest, RecordRedirectedUrl) { service.EnableRecording(/*extensions=*/false); service.EnableReporting(); - ukm::SourceId id = GetWhitelistedSourceId(0); + SourceId id = GetWhitelistedSourceId(0); UkmSource::NavigationData navigation_data; navigation_data.urls = {GURL("https://google.com/initial"), GURL("https://google.com/final")}; @@ -710,7 +693,6 @@ TEST_F(UkmServiceTest, RestrictToWhitelistedSourceIds) { ClearPrefs(); UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); EXPECT_EQ(GetPersistedLogCount(), 0); @@ -719,12 +701,12 @@ TEST_F(UkmServiceTest, RestrictToWhitelistedSourceIds) { service.EnableRecording(/*extensions=*/false); service.EnableReporting(); - ukm::SourceId id1 = GetWhitelistedSourceId(0); + SourceId id1 = GetWhitelistedSourceId(0); recorder.UpdateSourceURL(id1, kURL); TestEvent1(id1).Record(&service); // Create a non-navigation-based sourceid, which should not be whitelisted. - ukm::SourceId id2 = GetNonWhitelistedSourceId(1); + SourceId id2 = GetNonWhitelistedSourceId(1); recorder.UpdateSourceURL(id2, kURL); TestEvent1(id2).Record(&service); @@ -754,7 +736,6 @@ TEST_F(UkmServiceTest, RestrictToWhitelistedSourceIds) { TEST_F(UkmServiceTest, RecordSessionId) { ClearPrefs(); UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); EXPECT_EQ(0, GetPersistedLogCount()); @@ -780,7 +761,6 @@ TEST_F(UkmServiceTest, SourceSize) { ClearPrefs(); UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); EXPECT_EQ(0, GetPersistedLogCount()); @@ -807,7 +787,6 @@ TEST_F(UkmServiceTest, SourceSize) { TEST_F(UkmServiceTest, PurgeMidUpload) { UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); EXPECT_EQ(GetPersistedLogCount(), 0); @@ -835,7 +814,6 @@ TEST_F(UkmServiceTest, WhitelistEntryTest) { ClearPrefs(); UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); EXPECT_EQ(0, GetPersistedLogCount()); @@ -873,7 +851,6 @@ TEST_F(UkmServiceTest, WhitelistEntryTest) { TEST_F(UkmServiceTest, SourceURLLength) { UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); EXPECT_EQ(0, GetPersistedLogCount()); @@ -910,7 +887,6 @@ TEST_F(UkmServiceTest, UnreferencedNonWhitelistedSources) { ClearPrefs(); UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); EXPECT_EQ(0, GetPersistedLogCount()); @@ -921,7 +897,7 @@ TEST_F(UkmServiceTest, UnreferencedNonWhitelistedSources) { // Record with whitelisted ID to whitelist the URL. // Use a larger ID to make it last in the proto. - ukm::SourceId whitelisted_id = GetWhitelistedSourceId(100); + SourceId whitelisted_id = GetWhitelistedSourceId(100); recorder.UpdateSourceURL(whitelisted_id, kURL); std::vector<SourceId> ids; @@ -1047,7 +1023,6 @@ TEST_F(UkmServiceTest, NonWhitelistedUrls) { for (const auto& test : test_cases) { ClearPrefs(); UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); @@ -1058,11 +1033,11 @@ TEST_F(UkmServiceTest, NonWhitelistedUrls) { service.EnableReporting(); // Record with whitelisted ID to whitelist the URL. - ukm::SourceId whitelist_id = GetWhitelistedSourceId(1); + SourceId whitelist_id = GetWhitelistedSourceId(1); recorder.UpdateSourceURL(whitelist_id, kURL); // Record non whitelisted ID with an entry. - ukm::SourceId nonwhitelist_id = GetNonWhitelistedSourceId(100); + SourceId nonwhitelist_id = GetNonWhitelistedSourceId(100); recorder.UpdateSourceURL(nonwhitelist_id, test.url); TestEvent1(nonwhitelist_id).Record(&service); @@ -1095,7 +1070,7 @@ TEST_F(UkmServiceTest, NonWhitelistedUrls) { // be unchanged, thus the the report should still contain the same numbers // of sources as before, that is, non-whitelisted URLs should not have // whitelisted themselves during the previous log rotation. - ukm::SourceId nonwhitelist_id2 = GetNonWhitelistedSourceId(101); + SourceId nonwhitelist_id2 = GetNonWhitelistedSourceId(101); recorder.UpdateSourceURL(nonwhitelist_id2, test.url); TestEvent1(nonwhitelist_id2).Record(&service); service.Flush(); @@ -1122,7 +1097,7 @@ TEST_F(UkmServiceTest, WhitelistIdType) { ScopedUkmFeatureParams params({{"WhitelistEntries", Entry1And2Whitelist()}}); std::map<SourceIdType, bool> source_id_type_whitelisted = { - {SourceIdType::UKM, false}, {SourceIdType::NAVIGATION_ID, true}, + {SourceIdType::DEFAULT, false}, {SourceIdType::NAVIGATION_ID, true}, {SourceIdType::APP_ID, true}, {SourceIdType::HISTORY_ID, true}, {SourceIdType::WEBAPK_ID, true}, }; @@ -1130,7 +1105,6 @@ TEST_F(UkmServiceTest, WhitelistIdType) { for (std::pair<SourceIdType, bool> type : source_id_type_whitelisted) { ClearPrefs(); UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); EXPECT_EQ(0, GetPersistedLogCount()); @@ -1191,7 +1165,6 @@ TEST_F(UkmServiceTest, SupportedSchemes) { ScopedUkmFeatureParams params({}); UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); service.SetIsWebstoreExtensionCallback( @@ -1250,7 +1223,6 @@ TEST_F(UkmServiceTest, SupportedSchemesNoExtensions) { ScopedUkmFeatureParams params({}); UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); @@ -1289,7 +1261,6 @@ TEST_F(UkmServiceTest, SupportedSchemesNoExtensions) { TEST_F(UkmServiceTest, SanitizeUrlAuthParams) { UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); EXPECT_EQ(0, GetPersistedLogCount()); @@ -1329,7 +1300,6 @@ TEST_F(UkmServiceTest, SanitizeChromeUrlParams) { ClearPrefs(); UkmService service(&prefs_, &client_, - true /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); service.SetIsWebstoreExtensionCallback( @@ -1356,7 +1326,6 @@ TEST_F(UkmServiceTest, SanitizeChromeUrlParams) { TEST_F(UkmServiceTest, MarkSourceForDeletion) { UkmService service(&prefs_, &client_, - true /* restrict_to_whitelist_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); EXPECT_EQ(0, GetPersistedLogCount()); @@ -1405,7 +1374,6 @@ TEST_F(UkmServiceTest, MarkSourceForDeletion) { TEST_F(UkmServiceTest, PurgeNonNavigationSources) { UkmService service(&prefs_, &client_, - true /* restrict_to_whitelist_entries */, std::make_unique<MockDemographicMetricsProvider>()); TestRecordingHelper recorder(&service); EXPECT_EQ(0, GetPersistedLogCount()); @@ -1415,7 +1383,7 @@ TEST_F(UkmServiceTest, PurgeNonNavigationSources) { service.EnableReporting(); // Seed some fake sources. - SourceId ukm_id = ConvertToSourceId(0, SourceIdType::UKM); + SourceId ukm_id = ConvertToSourceId(0, SourceIdType::DEFAULT); recorder.UpdateSourceURL(ukm_id, GURL("https://www.example0.com/")); SourceId navigation_id = ConvertSourceIdToWhitelistedType(1, SourceIdType::NAVIGATION_ID); @@ -1457,8 +1425,8 @@ TEST_F(UkmServiceTest, PurgeNonNavigationSources) { TEST_F(UkmServiceTest, IdentifiabilityMetricsDontExplode) { UkmService service(&prefs_, &client_, - false /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); + service.set_restrict_to_whitelist_entries_for_testing(false); TestRecordingHelper recorder(&service); ASSERT_EQ(0, GetPersistedLogCount()); service.Initialize(); @@ -1466,7 +1434,7 @@ TEST_F(UkmServiceTest, IdentifiabilityMetricsDontExplode) { service.EnableRecording(/*extensions=*/false); service.EnableReporting(); - ukm::SourceId id = GetWhitelistedSourceId(0); + SourceId id = GetWhitelistedSourceId(0); recorder.UpdateSourceURL(id, GURL("https://google.com/foobar")); builders::Identifiability(id).SetStudyGeneration_626(0).Record(&service); @@ -1493,8 +1461,8 @@ TEST_F(UkmServiceTest, FilterCanRemoveMetrics) { }; UkmService service(&prefs_, &client_, - false /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); + service.set_restrict_to_whitelist_entries_for_testing(false); service.RegisterEventFilter(std::make_unique<TestEntryFilter>()); TestRecordingHelper recorder(&service); ASSERT_EQ(0, GetPersistedLogCount()); @@ -1503,7 +1471,7 @@ TEST_F(UkmServiceTest, FilterCanRemoveMetrics) { service.EnableRecording(/*extensions=*/false); service.EnableReporting(); - ukm::SourceId id = GetWhitelistedSourceId(0); + SourceId id = GetWhitelistedSourceId(0); recorder.UpdateSourceURL(id, GURL("https://google.com/foobar")); // This event sticks around albeit with a single metric instead of two. @@ -1551,8 +1519,8 @@ TEST_F(UkmServiceTest, FilterRejectsEvent) { }; UkmService service(&prefs_, &client_, - false /* restrict_to_whitelisted_entries */, std::make_unique<MockDemographicMetricsProvider>()); + service.set_restrict_to_whitelist_entries_for_testing(false); service.RegisterEventFilter(std::make_unique<TestEntryFilter>()); TestRecordingHelper recorder(&service); ASSERT_EQ(0, GetPersistedLogCount()); @@ -1561,7 +1529,7 @@ TEST_F(UkmServiceTest, FilterRejectsEvent) { service.EnableRecording(/*extensions=*/false); service.EnableReporting(); - ukm::SourceId id = GetWhitelistedSourceId(0); + SourceId id = GetWhitelistedSourceId(0); recorder.UpdateSourceURL(id, GURL("https://google.com/foobar")); TestEvent1(id).SetCpuTime(0).Record(&service); diff --git a/chromium/components/ukm/ukm_test_helper.cc b/chromium/components/ukm/ukm_test_helper.cc index 6ea053f8dd1..c41df9fec09 100644 --- a/chromium/components/ukm/ukm_test_helper.cc +++ b/chromium/components/ukm/ukm_test_helper.cc @@ -10,8 +10,8 @@ #include "base/feature_list.h" #include "base/run_loop.h" #include "base/stl_util.h" +#include "components/metrics/log_decoder.h" #include "components/metrics/unsent_log_store.h" -#include "third_party/zlib/google/compression_utils.h" namespace ukm { @@ -51,13 +51,8 @@ std::unique_ptr<Report> UkmTestHelper::GetUkmReport() { if (!log_store->has_staged_log()) return nullptr; - std::string uncompressed_log_data; - if (!compression::GzipUncompress(log_store->staged_log(), - &uncompressed_log_data)) - return nullptr; - std::unique_ptr<ukm::Report> report = std::make_unique<ukm::Report>(); - if (!report->ParseFromString(uncompressed_log_data)) + if (!metrics::DecodeLogDataToProto(log_store->staged_log(), report.get())) return nullptr; return report; |