diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-01-29 16:35:13 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2018-02-01 15:33:35 +0000 |
commit | c8c2d1901aec01e934adf561a9fdf0cc776cdef8 (patch) | |
tree | 9157c3d9815e5870799e070b113813bec53e0535 /chromium/components/ukm | |
parent | abefd5095b41dac94ca451d784ab6e27372e981a (diff) | |
download | qtwebengine-chromium-c8c2d1901aec01e934adf561a9fdf0cc776cdef8.tar.gz |
BASELINE: Update Chromium to 64.0.3282.139
Change-Id: I1cae68fe9c94ff7608b26b8382fc19862cdb293a
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/components/ukm')
19 files changed, 388 insertions, 219 deletions
diff --git a/chromium/components/ukm/BUILD.gn b/chromium/components/ukm/BUILD.gn index eb7723f2462..3705109962a 100644 --- a/chromium/components/ukm/BUILD.gn +++ b/chromium/components/ukm/BUILD.gn @@ -26,9 +26,9 @@ static_library("ukm") { ] public_deps = [ - "//components/metrics/proto", "//services/metrics/public/cpp:metrics_cpp", "//services/metrics/public/interfaces", + "//third_party/metrics_proto", ] deps = [ @@ -41,25 +41,6 @@ static_library("ukm") { ] } -static_library("ukm_interface") { - sources = [ - "ukm_interface.cc", - "ukm_interface.h", - ] - - public_deps = [ - "//base", - "//services/metrics/public/cpp:metrics_cpp", - "//services/metrics/public/interfaces", - ] - - deps = [ - ":ukm", - "//mojo/public/cpp/bindings", - "//services/metrics/public/cpp:metrics_cpp", - ] -} - # Helper library for observing signals that we need to clear any local data. static_library("observers") { sources = [ @@ -85,7 +66,7 @@ static_library("test_support") { public_deps = [ ":ukm", - "//components/metrics/proto", + "//third_party/metrics_proto", ] deps = [ "//base", diff --git a/chromium/components/ukm/DEPS b/chromium/components/ukm/DEPS index 099b24d0d0c..74b50a011d2 100644 --- a/chromium/components/ukm/DEPS +++ b/chromium/components/ukm/DEPS @@ -4,5 +4,6 @@ include_rules = [ "+components/variations", "+mojo/public", "+services/metrics/public", + "+third_party/metrics_proto", "+third_party/zlib/google", ] diff --git a/chromium/components/ukm/OWNERS b/chromium/components/ukm/OWNERS index 189104122ea..684cb163c06 100644 --- a/chromium/components/ukm/OWNERS +++ b/chromium/components/ukm/OWNERS @@ -1,5 +1,3 @@ -asvitkine@chromium.org -holte@chromium.org -rkaplow@chromium.org +file://base/metrics/OWNERS -# COMPONENT: Internals>Metrics +# COMPONENT: Internals>Metrics>UKM diff --git a/chromium/components/ukm/content/source_url_recorder.cc b/chromium/components/ukm/content/source_url_recorder.cc index 573ead41136..43d0f8d1efb 100644 --- a/chromium/components/ukm/content/source_url_recorder.cc +++ b/chromium/components/ukm/content/source_url_recorder.cc @@ -18,10 +18,6 @@ namespace { -bool IsValidUkmUrl(const GURL& url) { - return url.SchemeIsHTTPOrHTTPS(); -} - // SourceUrlRecorderWebContentsObserver is responsible for recording UKM source // URLs, for all main frame navigations in a given WebContents. // SourceUrlRecorderWebContentsObserver records both the final URL for a @@ -105,12 +101,10 @@ void SourceUrlRecorderWebContentsObserver::MaybeRecordUrl( const ukm::SourceId source_id = ukm::ConvertToSourceId( navigation_handle->GetNavigationId(), ukm::SourceIdType::NAVIGATION_ID); - - if (IsValidUkmUrl(initial_url)) - ukm_recorder->UpdateSourceURL(source_id, initial_url); + ukm_recorder->UpdateSourceURL(source_id, initial_url); const GURL& final_url = navigation_handle->GetURL(); - if (final_url != initial_url && IsValidUkmUrl(final_url)) + if (final_url != initial_url) ukm_recorder->UpdateSourceURL(source_id, final_url); } diff --git a/chromium/components/ukm/content/source_url_recorder_browsertest.cc b/chromium/components/ukm/content/source_url_recorder_browsertest.cc index 93575f3e56f..d2501867c12 100644 --- a/chromium/components/ukm/content/source_url_recorder_browsertest.cc +++ b/chromium/components/ukm/content/source_url_recorder_browsertest.cc @@ -2,13 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/command_line.h" #include "base/files/scoped_temp_dir.h" +#include "base/test/scoped_feature_list.h" #include "components/ukm/content/source_url_recorder.h" #include "components/ukm/test_ukm_recorder.h" #include "components/ukm/ukm_source.h" #include "content/public/browser/web_contents.h" -#include "content/public/common/content_switches.h" #include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test_utils.h" #include "content/public/test/navigation_handle_observer.h" @@ -19,26 +18,21 @@ class SourceUrlRecorderWebContentsObserverBrowserTest : public content::ContentBrowserTest { protected: + SourceUrlRecorderWebContentsObserverBrowserTest() { + scoped_feature_list_.InitAndEnableFeature(ukm::kUkmFeature); + } + + ~SourceUrlRecorderWebContentsObserverBrowserTest() override {} + void SetUpOnMainThread() override { content::ContentBrowserTest::SetUpOnMainThread(); ASSERT_TRUE(embedded_test_server()->Start()); - // UKM DCHECKs if the active UkmRecorder is changed from one instance - // to another, rather than being changed from a nullptr; browser_tests - // need to circumvent that to be able to intercept UKM calls with its - // own TestUkmRecorder instance rather than the default UkmRecorder. - ukm::UkmRecorder::Set(nullptr); test_ukm_recorder_ = base::MakeUnique<ukm::TestAutoSetUkmRecorder>(); ukm::InitializeSourceUrlRecorderForWebContents(shell()->web_contents()); } - void SetUpCommandLine(base::CommandLine* command_line) override { - content::ContentBrowserTest::SetUpCommandLine(command_line); - command_line->AppendSwitchASCII(switches::kEnableFeatures, - ukm::kUkmFeature.name); - } - const ukm::UkmSource* GetSourceForNavigationId(int64_t navigation_id) { CHECK_GT(navigation_id, 0); const ukm::SourceId source_id = @@ -46,7 +40,11 @@ class SourceUrlRecorderWebContentsObserverBrowserTest return test_ukm_recorder_->GetSourceForSourceId(source_id); } + private: + base::test::ScopedFeatureList scoped_feature_list_; std::unique_ptr<ukm::TestAutoSetUkmRecorder> test_ukm_recorder_; + + DISALLOW_COPY_AND_ASSIGN(SourceUrlRecorderWebContentsObserverBrowserTest); }; class SourceUrlRecorderWebContentsObserverDownloadBrowserTest @@ -84,15 +82,6 @@ IN_PROC_BROWSER_TEST_F(SourceUrlRecorderWebContentsObserverBrowserTest, Basic) { } IN_PROC_BROWSER_TEST_F(SourceUrlRecorderWebContentsObserverBrowserTest, - IgnoreUnsupportedScheme) { - GURL url("about:blank"); - content::NavigationHandleObserver observer(shell()->web_contents(), url); - content::NavigateToURL(shell(), url); - EXPECT_TRUE(observer.has_committed()); - EXPECT_EQ(nullptr, GetSourceForNavigationId(observer.navigation_id())); -} - -IN_PROC_BROWSER_TEST_F(SourceUrlRecorderWebContentsObserverBrowserTest, IgnoreUrlInSubframe) { GURL main_url = embedded_test_server()->GetURL("/page_with_iframe.html"); GURL subframe_url = embedded_test_server()->GetURL("/title1.html"); diff --git a/chromium/components/ukm/content/source_url_recorder_test.cc b/chromium/components/ukm/content/source_url_recorder_test.cc index 6fd8386226b..6ac04ae7f1b 100644 --- a/chromium/components/ukm/content/source_url_recorder_test.cc +++ b/chromium/components/ukm/content/source_url_recorder_test.cc @@ -29,11 +29,13 @@ class SourceUrlRecorderWebContentsObserverTest TEST_F(SourceUrlRecorderWebContentsObserverTest, Basic) { GURL url("https://www.example.com/"); NavigationSimulator::NavigateAndCommitFromBrowser(web_contents(), url); - EXPECT_EQ(1ul, test_ukm_recorder_.sources_count()); - const ukm::UkmSource* ukm_source = test_ukm_recorder_.GetSourceForUrl(url); - ASSERT_NE(nullptr, ukm_source); - EXPECT_EQ(url, ukm_source->url()); - EXPECT_TRUE(ukm_source->initial_url().is_empty()); + + const auto& sources = test_ukm_recorder_.GetSources(); + EXPECT_EQ(1ul, sources.size()); + for (const auto& kv : sources) { + EXPECT_EQ(url, kv.second->url()); + EXPECT_TRUE(kv.second->initial_url().is_empty()); + } } TEST_F(SourceUrlRecorderWebContentsObserverTest, InitialUrl) { @@ -44,18 +46,12 @@ TEST_F(SourceUrlRecorderWebContentsObserverTest, InitialUrl) { simulator->Start(); simulator->Redirect(final_url); simulator->Commit(); - EXPECT_EQ(1ul, test_ukm_recorder_.sources_count()); - const ukm::UkmSource* ukm_source = - test_ukm_recorder_.GetSourceForUrl(final_url); - ASSERT_NE(nullptr, ukm_source); - EXPECT_EQ(final_url, ukm_source->url()); - EXPECT_EQ(initial_url, ukm_source->initial_url()); -} - -TEST_F(SourceUrlRecorderWebContentsObserverTest, IgnoreUnsupportedScheme) { - NavigationSimulator::NavigateAndCommitFromBrowser(web_contents(), - GURL("about:blank")); - EXPECT_EQ(0ul, test_ukm_recorder_.sources_count()); + const auto& sources = test_ukm_recorder_.GetSources(); + EXPECT_EQ(1ul, sources.size()); + for (const auto& kv : sources) { + EXPECT_EQ(final_url, kv.second->url()); + EXPECT_EQ(initial_url, kv.second->initial_url()); + } } TEST_F(SourceUrlRecorderWebContentsObserverTest, IgnoreUrlInSubframe) { @@ -66,9 +62,13 @@ TEST_F(SourceUrlRecorderWebContentsObserverTest, IgnoreUrlInSubframe) { NavigationSimulator::NavigateAndCommitFromDocument( sub_frame_url, content::RenderFrameHostTester::For(main_rfh())->AppendChild("subframe")); - EXPECT_EQ(1ul, test_ukm_recorder_.sources_count()); - EXPECT_NE(nullptr, test_ukm_recorder_.GetSourceForUrl(main_frame_url)); - EXPECT_EQ(nullptr, test_ukm_recorder_.GetSourceForUrl(sub_frame_url)); + + const auto& sources = test_ukm_recorder_.GetSources(); + EXPECT_EQ(1ul, sources.size()); + for (const auto& kv : sources) { + EXPECT_EQ(main_frame_url, kv.second->url()); + EXPECT_TRUE(kv.second->initial_url().is_empty()); + } } TEST_F(SourceUrlRecorderWebContentsObserverTest, IgnoreSameDocumentNavigation) { @@ -77,11 +77,13 @@ TEST_F(SourceUrlRecorderWebContentsObserverTest, IgnoreSameDocumentNavigation) { NavigationSimulator::NavigateAndCommitFromBrowser(web_contents(), url); NavigationSimulator::CreateRendererInitiated(same_document_url, main_rfh()) ->CommitSameDocument(); + EXPECT_EQ(same_document_url, web_contents()->GetLastCommittedURL()); - EXPECT_EQ(1ul, test_ukm_recorder_.sources_count()); - EXPECT_EQ(nullptr, test_ukm_recorder_.GetSourceForUrl(same_document_url)); - const ukm::UkmSource* ukm_source = test_ukm_recorder_.GetSourceForUrl(url); - ASSERT_NE(nullptr, ukm_source); - EXPECT_EQ(url, ukm_source->url()); - EXPECT_TRUE(ukm_source->initial_url().is_empty()); + + const auto& sources = test_ukm_recorder_.GetSources(); + EXPECT_EQ(1ul, sources.size()); + for (const auto& kv : sources) { + EXPECT_EQ(url, kv.second->url()); + EXPECT_TRUE(kv.second->initial_url().is_empty()); + } } diff --git a/chromium/components/ukm/debug_page/debug_page.cc b/chromium/components/ukm/debug_page/debug_page.cc index fb6e60dffcf..1bc33a5f3c3 100644 --- a/chromium/components/ukm/debug_page/debug_page.cc +++ b/chromium/components/ukm/debug_page/debug_page.cc @@ -10,7 +10,7 @@ #include "base/strings/stringprintf.h" #include "components/ukm/ukm_service.h" #include "components/ukm/ukm_source.h" -#include "services/metrics/public/cpp/ukm_builders.h" +#include "services/metrics/public/cpp/ukm_decode.h" #include "url/gurl.h" namespace ukm { diff --git a/chromium/components/ukm/test_ukm_recorder.cc b/chromium/components/ukm/test_ukm_recorder.cc index 5f9e9e60bb6..c3c876cb05a 100644 --- a/chromium/components/ukm/test_ukm_recorder.cc +++ b/chromium/components/ukm/test_ukm_recorder.cc @@ -9,13 +9,30 @@ #include "base/logging.h" #include "base/metrics/metrics_hashes.h" +#include "base/task_scheduler/post_task.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "components/ukm/ukm_source.h" +#include "services/metrics/public/cpp/delegating_ukm_recorder.h" #include "testing/gtest/include/gtest/gtest.h" namespace ukm { namespace { +// Merge the data from |in| to |out|. +void MergeEntry(const mojom::UkmEntry* in, mojom::UkmEntry* out) { + if (out->event_hash) { + EXPECT_EQ(out->source_id, in->source_id); + EXPECT_EQ(out->event_hash, in->event_hash); + } else { + out->event_hash = in->event_hash; + out->source_id = in->source_id; + } + for (const auto& metric : in->metrics) { + out->metrics.emplace_back(metric->Clone()); + } +} + // Provides a single merged ukm::mojom::UkmEntry proto that contains all metrics // from the given |entries|. |entries| must be non-empty, and all |entries| must // have the same |source_id| and |event_hash|. @@ -24,16 +41,7 @@ mojom::UkmEntryPtr GetMergedEntry( EXPECT_FALSE(entries.empty()); mojom::UkmEntryPtr merged_entry = mojom::UkmEntry::New(); for (const auto* entry : entries) { - if (merged_entry->event_hash) { - EXPECT_EQ(merged_entry->source_id, entry->source_id); - EXPECT_EQ(merged_entry->event_hash, entry->event_hash); - } else { - merged_entry->event_hash = entry->event_hash; - merged_entry->source_id = entry->source_id; - } - for (const auto& metric : entry->metrics) { - merged_entry->metrics.emplace_back(metric->Clone()); - } + MergeEntry(entry, merged_entry.get()); } return merged_entry; } @@ -122,12 +130,74 @@ const mojom::UkmEntry* TestUkmRecorder::GetEntryForEntryName( return nullptr; } +std::vector<const mojom::UkmEntry*> TestUkmRecorder::GetEntriesByName( + base::StringPiece entry_name) const { + uint64_t hash = base::HashMetricName(entry_name); + std::vector<const mojom::UkmEntry*> result; + for (const auto& it : entries()) { + if (it->event_hash == hash) + result.push_back(it.get()); + } + return result; +} + +std::map<ukm::SourceId, mojom::UkmEntryPtr> +TestUkmRecorder::GetMergedEntriesByName(base::StringPiece entry_name) const { + uint64_t hash = base::HashMetricName(entry_name); + std::map<ukm::SourceId, mojom::UkmEntryPtr> result; + for (const auto& it : entries()) { + if (it->event_hash != hash) + continue; + mojom::UkmEntryPtr& entry_ptr = result[it->source_id]; + if (!entry_ptr) + entry_ptr = mojom::UkmEntry::New(); + MergeEntry(it.get(), entry_ptr.get()); + } + return result; +} + +// static +bool TestUkmRecorder::EntryHasMetric(const mojom::UkmEntry* entry, + base::StringPiece metric_name) { + return FindMetric(entry, metric_name) != nullptr; +} + +void TestUkmRecorder::ExpectEntrySourceHasUrl(const mojom::UkmEntry* entry, + const GURL& url) const { + const UkmSource* src = GetSourceForSourceId(entry->source_id); + if (src == nullptr) { + FAIL() << "Entry source id has no associated Source."; + return; + } + EXPECT_EQ(src->url(), url); +} + +// static +const int64_t* TestUkmRecorder::GetEntryMetric(const mojom::UkmEntry* entry, + base::StringPiece metric_name) { + const mojom::UkmMetric* metric = FindMetric(entry, metric_name); + return metric ? &metric->value : nullptr; +} + +// static +void TestUkmRecorder::ExpectEntryMetric(const mojom::UkmEntry* entry, + base::StringPiece metric_name, + int64_t expected_value) { + const mojom::UkmMetric* metric = FindMetric(entry, metric_name); + if (metric == nullptr) { + FAIL() << "Failed to find metric for event: " << metric_name; + return; + } + EXPECT_EQ(metric->value, expected_value) << " for metric:" << metric_name; +} + // static const mojom::UkmMetric* TestUkmRecorder::FindMetric( const mojom::UkmEntry* entry, - const char* metric_name) { + base::StringPiece metric_name) { + uint64_t hash = base::HashMetricName(metric_name); for (const auto& metric : entry->metrics) { - if (metric->metric_hash == base::HashMetricName(metric_name)) + if (metric->metric_hash == hash) return metric.get(); } return nullptr; @@ -270,12 +340,12 @@ std::vector<int64_t> TestUkmRecorder::GetMetrics( return GetMetricValues(source.id(), event_name, metric_name); } -TestAutoSetUkmRecorder::TestAutoSetUkmRecorder() { - UkmRecorder::Set(this); +TestAutoSetUkmRecorder::TestAutoSetUkmRecorder() : self_ptr_factory_(this) { + DelegatingUkmRecorder::Get()->AddDelegate(self_ptr_factory_.GetWeakPtr()); } TestAutoSetUkmRecorder::~TestAutoSetUkmRecorder() { - UkmRecorder::Set(nullptr); + DelegatingUkmRecorder::Get()->RemoveDelegate(this); }; } // namespace ukm diff --git a/chromium/components/ukm/test_ukm_recorder.h b/chromium/components/ukm/test_ukm_recorder.h index 5bce2e87c39..0ad19b71244 100644 --- a/chromium/components/ukm/test_ukm_recorder.h +++ b/chromium/components/ukm/test_ukm_recorder.h @@ -14,6 +14,7 @@ #include "base/compiler_specific.h" #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "components/ukm/ukm_recorder_impl.h" #include "services/metrics/public/cpp/ukm_recorder.h" #include "services/metrics/public/interfaces/ukm_interface.mojom.h" @@ -31,22 +32,57 @@ class TestUkmRecorder : public UkmRecorderImpl { size_t sources_count() const { return sources().size(); } - // Get all SourceIds with any data associated with them. - std::set<ukm::SourceId> GetSourceIds() const; + size_t entries_count() const { return entries().size(); } + using UkmRecorderImpl::UpdateSourceURL; + + // Get all recorded UkmSource data. const std::map<ukm::SourceId, std::unique_ptr<UkmSource>>& GetSources() const { return sources(); } + // Get UkmSource data for a single SourceId. + const UkmSource* GetSourceForSourceId(ukm::SourceId source_id) const; + + // Get all of the entries recorded for entry name. + std::vector<const mojom::UkmEntry*> GetEntriesByName( + base::StringPiece entry_name) const; + + // Get the data for all entries with given entry name, merged to one entry + // for each source id. Intended for singular="true" metrics. + std::map<ukm::SourceId, mojom::UkmEntryPtr> GetMergedEntriesByName( + base::StringPiece entry_name) const; + + // Check if an entry is associated with a url. + void ExpectEntrySourceHasUrl(const mojom::UkmEntry* entry, + const GURL& url) const; + + // Expect the value of a metric from an entry. + static void ExpectEntryMetric(const mojom::UkmEntry* entry, + base::StringPiece metric_name, + int64_t expected_value); + + // Check if an entry contains a specific metric. + static bool EntryHasMetric(const mojom::UkmEntry* entry, + base::StringPiece metric_name); + + // Expect the value of a metric from an entry. + static const int64_t* GetEntryMetric(const mojom::UkmEntry* entry, + base::StringPiece metric_name); + + // All of the methods below are deprecated. + // Use GetEntriesByName based testing instead. + // TODO(crbug/761524): Migrate tests and remove these. + + // Get all SourceIds with any data associated with them. + std::set<ukm::SourceId> GetSourceIds() const; + const UkmSource* GetSourceForUrl(const char* url) const; const UkmSource* GetSourceForUrl(const GURL& url) const { return GetSourceForUrl(url.spec().c_str()); } std::vector<const ukm::UkmSource*> GetSourcesForUrl(const char* url) const; - const UkmSource* GetSourceForSourceId(ukm::SourceId source_id) const; - - size_t entries_count() const { return entries().size(); } // Returns whether the given UKM |source| has an entry with the given // |event_name|. @@ -124,7 +160,7 @@ class TestUkmRecorder : public UkmRecorderImpl { // Deprecated. static const mojom::UkmMetric* FindMetric(const mojom::UkmEntry* entry, - const char* metric_name); + base::StringPiece metric_name); private: ukm::mojom::UkmEntryPtr GetMergedEntryForSourceID( @@ -144,6 +180,9 @@ class TestAutoSetUkmRecorder : public TestUkmRecorder { public: TestAutoSetUkmRecorder(); ~TestAutoSetUkmRecorder() override; + + private: + base::WeakPtrFactory<TestAutoSetUkmRecorder> self_ptr_factory_; }; } // namespace ukm diff --git a/chromium/components/ukm/ukm_interface.cc b/chromium/components/ukm/ukm_interface.cc deleted file mode 100644 index 3cc99a25d7a..00000000000 --- a/chromium/components/ukm/ukm_interface.cc +++ /dev/null @@ -1,42 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "components/ukm/ukm_interface.h" - -#include "base/atomic_sequence_num.h" -#include "base/memory/ptr_util.h" -#include "mojo/public/cpp/bindings/strong_binding.h" -#include "services/metrics/public/cpp/ukm_recorder.h" -#include "services/metrics/public/cpp/ukm_source_id.h" -#include "url/gurl.h" - -namespace ukm { - -UkmInterface::UkmInterface(UkmRecorder* ukm_recorder, int64_t instance_id) - : ukm_recorder_(ukm_recorder), instance_id_(instance_id) {} - -UkmInterface::~UkmInterface() = default; - -// static -void UkmInterface::Create(UkmRecorder* ukm_recorder, - mojom::UkmRecorderInterfaceRequest request) { - static base::AtomicSequenceNumber seq; - mojo::MakeStrongBinding( - base::MakeUnique<UkmInterface>(ukm_recorder, - static_cast<int64_t>(seq.GetNext()) + 1), - std::move(request)); -} - -void UkmInterface::AddEntry(mojom::UkmEntryPtr ukm_entry) { - ukm_entry->source_id = - ConvertSourceIdFromInstance(instance_id_, ukm_entry->source_id); - ukm_recorder_->AddEntry(std::move(ukm_entry)); -} - -void UkmInterface::UpdateSourceURL(int64_t source_id, const std::string& url) { - ukm_recorder_->UpdateSourceURL( - ConvertSourceIdFromInstance(instance_id_, source_id), GURL(url)); -} - -} // namespace ukm diff --git a/chromium/components/ukm/ukm_interface.h b/chromium/components/ukm/ukm_interface.h deleted file mode 100644 index 9432de1fa7d..00000000000 --- a/chromium/components/ukm/ukm_interface.h +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2017 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef COMPONENTS_UKM_UKM_INTERFACE_H_ -#define COMPONENTS_UKM_UKM_INTERFACE_H_ - -#include "services/metrics/public/interfaces/ukm_interface.mojom.h" - -namespace ukm { - -class UkmRecorder; - -class UkmInterface : public mojom::UkmRecorderInterface { - public: - UkmInterface(UkmRecorder* ukm_recorder, int64_t instance_id); - ~UkmInterface() override; - - static void Create(UkmRecorder* ukm_recorder, - mojom::UkmRecorderInterfaceRequest request); - - private: - // ukm::mojom::UkmRecorderInterface: - void AddEntry(mojom::UkmEntryPtr entry) override; - void UpdateSourceURL(int64_t source_id, const std::string& url) override; - - UkmRecorder* ukm_recorder_; - int64_t instance_id_; - - DISALLOW_COPY_AND_ASSIGN(UkmInterface); -}; - -} // namespace ukm - -#endif // COMPONENTS_UKM_UKM_INTERFACE_H_ diff --git a/chromium/components/ukm/ukm_recorder_impl.cc b/chromium/components/ukm/ukm_recorder_impl.cc index 43adec45b40..28a5bbdf095 100644 --- a/chromium/components/ukm/ukm_recorder_impl.cc +++ b/chromium/components/ukm/ukm_recorder_impl.cc @@ -4,16 +4,21 @@ #include "components/ukm/ukm_recorder_impl.h" +#include <memory> +#include <string> +#include <utility> + #include "base/metrics/field_trial.h" #include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_macros.h" #include "base/metrics/metrics_hashes.h" #include "base/strings/string_split.h" -#include "components/metrics/proto/ukm/entry.pb.h" -#include "components/metrics/proto/ukm/report.pb.h" -#include "components/metrics/proto/ukm/source.pb.h" #include "components/ukm/ukm_source.h" #include "services/metrics/public/cpp/ukm_source_id.h" +#include "third_party/metrics_proto/ukm/entry.pb.h" +#include "third_party/metrics_proto/ukm/report.pb.h" +#include "third_party/metrics_proto/ukm/source.pb.h" +#include "url/gurl.h" namespace ukm { @@ -55,6 +60,18 @@ size_t GetMaxEntries() { kUkmFeature, "MaxEntries", kDefaultMaxEntries)); } +// Returns whether |url| has one of the schemes supported for logging to UKM. +// URLs with other schemes will not be logged. +// Note: This currently excludes chrome-extension:// URLs as in order to log +// them, UKM needs to take into account extension-sync consent, which is not +// yet done. +bool HasSupportedScheme(const GURL& url) { + // Note: kChromeUIScheme is defined in content, which this code can't + // depend on - since it's used by iOS too. So "chrome" is hardcoded here. + return url.SchemeIsHTTPOrHTTPS() || url.SchemeIs(url::kFtpScheme) || + url.SchemeIs(url::kAboutScheme) || url.SchemeIs("chrome"); +} + // True if we should record the initial_url field of the UKM Source proto. bool ShouldRecordInitialUrl() { return base::GetFieldTrialParamByFeatureAsBool(kUkmFeature, @@ -66,6 +83,7 @@ enum class DroppedDataReason { RECORDING_DISABLED = 1, MAX_HIT = 2, NOT_WHITELISTED = 3, + UNSUPPORTED_URL_SCHEME = 4, NUM_DROPPED_DATA_REASONS }; @@ -94,6 +112,18 @@ void StoreEntryProto(const mojom::UkmEntry& in, Entry* out) { } } +GURL SanitizeURL(const GURL& url) { + GURL::Replacements remove_params; + remove_params.ClearUsername(); + remove_params.ClearPassword(); + // chrome:// and about: URLs params are never used for navigation, only to + // prepopulate data on the page, so don't include their params. + if (url.SchemeIs(url::kAboutScheme) || url.SchemeIs("chrome")) { + remove_params.ClearQuery(); + } + return url.ReplaceComponents(remove_params); +} + } // namespace UkmRecorderImpl::UkmRecorderImpl() : recording_enabled_(false) {} @@ -110,11 +140,14 @@ void UkmRecorderImpl::DisableRecording() { } void UkmRecorderImpl::Purge() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); sources_.clear(); entries_.clear(); } void UkmRecorderImpl::StoreRecordingsInReport(Report* report) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + std::set<SourceId> ids_seen; for (const auto& entry : entries_) { Entry* proto_entry = report->add_entries(); @@ -172,9 +205,9 @@ bool UkmRecorderImpl::ShouldRestrictToWhitelistedSourceIds() const { kUkmFeature, "RestrictToWhitelistedSourceIds", true); } -void UkmRecorderImpl::UpdateSourceURL(ukm::SourceId source_id, - const GURL& url) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); +void UkmRecorderImpl::UpdateSourceURL(SourceId source_id, + const GURL& unsanitized_url) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!recording_enabled_) { RecordDroppedSource(DroppedDataReason::RECORDING_DISABLED); @@ -187,6 +220,13 @@ void UkmRecorderImpl::UpdateSourceURL(ukm::SourceId source_id, return; } + GURL url = SanitizeURL(unsanitized_url); + + if (!HasSupportedScheme(url)) { + RecordDroppedSource(DroppedDataReason::UNSUPPORTED_URL_SCHEME); + return; + } + // Update the pre-existing source if there is any. This happens when the // initial URL is different from the committed URL for the same source, e.g., // when there is redirection. @@ -206,7 +246,7 @@ void UkmRecorderImpl::UpdateSourceURL(ukm::SourceId source_id, } void UkmRecorderImpl::AddEntry(mojom::UkmEntryPtr entry) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (!recording_enabled_) { RecordDroppedEntry(DroppedDataReason::RECORDING_DISABLED); @@ -227,6 +267,7 @@ void UkmRecorderImpl::AddEntry(mojom::UkmEntryPtr entry) { } void UkmRecorderImpl::StoreWhitelistedEntries() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); const auto entries = base::SplitString(GetWhitelistEntries(), ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY); diff --git a/chromium/components/ukm/ukm_recorder_impl.h b/chromium/components/ukm/ukm_recorder_impl.h index c3cdc8d254b..a24820aabde 100644 --- a/chromium/components/ukm/ukm_recorder_impl.h +++ b/chromium/components/ukm/ukm_recorder_impl.h @@ -9,12 +9,13 @@ #include <set> #include <vector> -#include "base/threading/thread_checker.h" +#include "base/sequence_checker.h" #include "services/metrics/public/cpp/ukm_recorder.h" #include "services/metrics/public/interfaces/ukm_interface.mojom.h" namespace metrics { class UkmBrowserTest; +class UkmEGTestHelper; } namespace ukm { @@ -51,14 +52,16 @@ class UkmRecorderImpl : public UkmRecorder { const std::vector<mojom::UkmEntryPtr>& entries() const { return entries_; } + // UkmRecorder: + void UpdateSourceURL(SourceId source_id, const GURL& url) override; + virtual bool ShouldRestrictToWhitelistedSourceIds() const; private: friend ::metrics::UkmBrowserTest; + friend ::metrics::UkmEGTestHelper; friend ::ukm::debug::DebugPage; - // UkmRecorder: - void UpdateSourceURL(SourceId source_id, const GURL& url) override; void AddEntry(mojom::UkmEntryPtr entry) override; // Whether recording new data is currently allowed. @@ -72,7 +75,7 @@ class UkmRecorderImpl : public UkmRecorder { // Whitelisted Entry hashes, only the ones in this set will be recorded. std::set<uint64_t> whitelisted_entry_hashes_; - THREAD_CHECKER(thread_checker_); + SEQUENCE_CHECKER(sequence_checker_); }; } // namespace ukm diff --git a/chromium/components/ukm/ukm_reporting_service.cc b/chromium/components/ukm/ukm_reporting_service.cc index aba99ad1cea..9a7502ff9b5 100644 --- a/chromium/components/ukm/ukm_reporting_service.cc +++ b/chromium/components/ukm/ukm_reporting_service.cc @@ -75,6 +75,10 @@ std::string UkmReportingService::GetUploadUrl() const { return GetServerUrl(); } +std::string UkmReportingService::GetInsecureUploadUrl() const { + return ""; +} + base::StringPiece UkmReportingService::upload_mime_type() const { return kMimeType; } @@ -90,7 +94,9 @@ void UkmReportingService::LogCellularConstraint(bool upload_canceled) { } void UkmReportingService::LogResponseOrErrorCode(int response_code, - int error_code) { + int error_code, + bool was_https) { + // |was_https| is ignored since all UKM logs are received over HTTPS. UMA_HISTOGRAM_SPARSE_SLOWLY("UKM.LogUpload.ResponseOrErrorCode", response_code >= 0 ? response_code : error_code); } diff --git a/chromium/components/ukm/ukm_reporting_service.h b/chromium/components/ukm/ukm_reporting_service.h index c62a5e3fdcd..a805395148e 100644 --- a/chromium/components/ukm/ukm_reporting_service.h +++ b/chromium/components/ukm/ukm_reporting_service.h @@ -48,10 +48,14 @@ class UkmReportingService : public metrics::ReportingService { // metrics:ReportingService: metrics::LogStore* log_store() override; std::string GetUploadUrl() const override; + // Returns an empty string since retrying over HTTP is not enabled for UKM + std::string GetInsecureUploadUrl() const override; base::StringPiece upload_mime_type() const override; metrics::MetricsLogUploader::MetricServiceType service_type() const override; void LogCellularConstraint(bool upload_canceled) override; - void LogResponseOrErrorCode(int response_code, int error_code) override; + void LogResponseOrErrorCode(int response_code, + int error_code, + bool was_https) override; void LogSuccess(size_t log_size) override; void LogLargeRejection(size_t log_size) override; diff --git a/chromium/components/ukm/ukm_service.cc b/chromium/components/ukm/ukm_service.cc index 8a2a2e48987..aa21e48d02f 100644 --- a/chromium/components/ukm/ukm_service.cc +++ b/chromium/components/ukm/ukm_service.cc @@ -15,16 +15,17 @@ #include "base/metrics/field_trial_params.h" #include "base/metrics/histogram_macros.h" #include "base/rand_util.h" -#include "base/threading/thread_task_runner_handle.h" +#include "base/threading/sequenced_task_runner_handle.h" #include "base/time/time.h" #include "components/metrics/metrics_log.h" #include "components/metrics/metrics_service_client.h" -#include "components/metrics/proto/ukm/report.pb.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "components/ukm/persisted_logs_metrics_impl.h" #include "components/ukm/ukm_pref_names.h" #include "components/ukm/ukm_rotation_scheduler.h" +#include "services/metrics/public/cpp/delegating_ukm_recorder.h" +#include "third_party/metrics_proto/ukm/report.pb.h" namespace ukm { @@ -93,28 +94,28 @@ UkmService::UkmService(PrefService* pref_service, StoreWhitelistedEntries(); - UkmRecorder::Set(this); + DelegatingUkmRecorder::Get()->AddDelegate(self_ptr_factory_.GetWeakPtr()); } UkmService::~UkmService() { DisableReporting(); - UkmRecorder::Set(nullptr); + DelegatingUkmRecorder::Get()->RemoveDelegate(this); } void UkmService::Initialize() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK(!initialize_started_); DVLOG(1) << "UkmService::Initialize"; initialize_started_ = true; - base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( + base::SequencedTaskRunnerHandle::Get()->PostDelayedTask( FROM_HERE, base::Bind(&UkmService::StartInitTask, self_ptr_factory_.GetWeakPtr()), base::TimeDelta::FromSeconds(kInitializationDelaySeconds)); } void UkmService::EnableReporting() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DVLOG(1) << "UkmService::EnableReporting"; if (reporting_service_.reporting_active()) return; @@ -128,7 +129,7 @@ void UkmService::EnableReporting() { } void UkmService::DisableReporting() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DVLOG(1) << "UkmService::DisableReporting"; reporting_service_.DisableReporting(); @@ -141,7 +142,7 @@ void UkmService::DisableReporting() { #if defined(OS_ANDROID) || defined(OS_IOS) void UkmService::OnAppEnterForeground() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DVLOG(1) << "UkmService::OnAppEnterForeground"; // If initialize_started_ is false, UKM has not yet been started, so bail. The @@ -153,7 +154,7 @@ void UkmService::OnAppEnterForeground() { } void UkmService::OnAppEnterBackground() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DVLOG(1) << "UkmService::OnAppEnterBackground"; if (!initialize_started_) @@ -169,14 +170,14 @@ void UkmService::OnAppEnterBackground() { #endif void UkmService::Flush() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (initialize_complete_) BuildAndStoreLog(); reporting_service_.ukm_log_store()->PersistUnsentLogs(); } void UkmService::Purge() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DVLOG(1) << "UkmService::Purge"; reporting_service_.ukm_log_store()->Purge(); UkmRecorderImpl::Purge(); @@ -185,6 +186,7 @@ void UkmService::Purge() { // TODO(bmcquade): rename this to something more generic, like // ResetClientState. Consider resetting all prefs here. void UkmService::ResetClientId() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); client_id_ = GenerateClientId(pref_service_); session_id_ = LoadSessionId(pref_service_); report_count_ = 0; @@ -203,7 +205,7 @@ void UkmService::RegisterPrefs(PrefRegistrySimple* registry) { } void UkmService::StartInitTask() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DVLOG(1) << "UkmService::StartInitTask"; client_id_ = LoadOrGenerateClientId(pref_service_); session_id_ = LoadSessionId(pref_service_); @@ -214,14 +216,14 @@ void UkmService::StartInitTask() { } void UkmService::FinishedInitTask() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DVLOG(1) << "UkmService::FinishedInitTask"; initialize_complete_ = true; scheduler_->InitTaskComplete(); } void UkmService::RotateLog() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DVLOG(1) << "UkmService::RotateLog"; if (!reporting_service_.ukm_log_store()->has_unsent_logs()) BuildAndStoreLog(); @@ -229,7 +231,7 @@ void UkmService::RotateLog() { } void UkmService::BuildAndStoreLog() { - DCHECK(thread_checker_.CalledOnValidThread()); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DVLOG(1) << "UkmService::BuildAndStoreLog"; // Suppress generating a log if we have no new data to include. diff --git a/chromium/components/ukm/ukm_service.h b/chromium/components/ukm/ukm_service.h index 22b7ef5ee27..5c70a84256b 100644 --- a/chromium/components/ukm/ukm_service.h +++ b/chromium/components/ukm/ukm_service.h @@ -11,7 +11,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" -#include "base/threading/thread_checker.h" +#include "base/sequence_checker.h" #include "build/build_config.h" #include "components/metrics/delegating_provider.h" #include "components/metrics/metrics_provider.h" @@ -25,6 +25,7 @@ class PrefService; namespace metrics { class MetricsServiceClient; class UkmBrowserTest; +class UkmEGTestHelper; } namespace ukm { @@ -76,8 +77,9 @@ class UkmService : public UkmRecorderImpl { static void RegisterPrefs(PrefRegistrySimple* registry); private: - friend ::ukm::debug::DebugPage; friend ::metrics::UkmBrowserTest; + friend ::metrics::UkmEGTestHelper; + friend ::ukm::debug::DebugPage; FRIEND_TEST_ALL_PREFIXES(UkmServiceTest, AddEntryWithEmptyMetrics); FRIEND_TEST_ALL_PREFIXES(UkmServiceTest, EntryBuilderAndSerialization); @@ -132,7 +134,7 @@ class UkmService : public UkmRecorderImpl { // The scheduler for determining when uploads should happen. std::unique_ptr<metrics::MetricsRotationScheduler> scheduler_; - base::ThreadChecker thread_checker_; + SEQUENCE_CHECKER(sequence_checker_); bool initialize_started_; bool initialize_complete_; diff --git a/chromium/components/ukm/ukm_service_unittest.cc b/chromium/components/ukm/ukm_service_unittest.cc index 4c5b80e401c..d5437dbc719 100644 --- a/chromium/components/ukm/ukm_service_unittest.cc +++ b/chromium/components/ukm/ukm_service_unittest.cc @@ -17,8 +17,6 @@ #include "base/threading/platform_thread.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/time.h" -#include "components/metrics/proto/ukm/report.pb.h" -#include "components/metrics/proto/ukm/source.pb.h" #include "components/metrics/test_metrics_provider.h" #include "components/metrics/test_metrics_service_client.h" #include "components/prefs/testing_pref_service.h" @@ -29,6 +27,8 @@ #include "services/metrics/public/cpp/ukm_builders.h" #include "services/metrics/public/cpp/ukm_entry_builder.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/metrics_proto/ukm/report.pb.h" +#include "third_party/metrics_proto/ukm/source.pb.h" #include "third_party/zlib/google/compression_utils.h" namespace ukm { @@ -36,11 +36,11 @@ namespace ukm { // A small shim exposing UkmRecorder methods to tests. class TestRecordingHelper { public: - TestRecordingHelper(UkmRecorder* recorder) : recorder_(recorder) {} + explicit TestRecordingHelper(UkmRecorder* recorder) : recorder_(recorder) {} void UpdateSourceURL(SourceId source_id, const GURL& url) { recorder_->UpdateSourceURL(source_id, url); - }; + } std::unique_ptr<UkmEntryBuilder> GetEntryBuilder(SourceId source_id, const char* event_name) { @@ -49,6 +49,8 @@ class TestRecordingHelper { private: UkmRecorder* recorder_; + + DISALLOW_COPY_AND_ASSIGN(TestRecordingHelper); }; namespace { @@ -668,8 +670,8 @@ TEST_F(UkmServiceTest, UnreferencedNonWhitelistedSources) { } ids.push_back(GetNonWhitelistedSourceId(i)); - recorder.UpdateSourceURL( - ids.back(), GURL("https://google.com/foobar" + base::IntToString(i))); + recorder.UpdateSourceURL(ids.back(), GURL("https://google.com/foobar" + + base::NumberToString(i))); last_time = base::TimeTicks::Now(); } @@ -720,4 +722,116 @@ TEST_F(UkmServiceTest, UnreferencedNonWhitelistedSources) { } } +TEST_F(UkmServiceTest, UnsupportedSchemes) { + struct { + const char* url; + bool expected_kept; + } test_cases[] = { + {"http://google.ca/", true}, + {"https://google.ca/", true}, + {"ftp://google.ca/", true}, + {"about:blank", true}, + {"chrome://version/", true}, + {"file:///tmp/", false}, + {"chrome-extension://bhcnanendmgjjeghamaccjnochlnhcgj", false}, + {"abc://google.ca/", false}, + {"www.google.ca/", false}, + }; + + base::FieldTrialList field_trial_list(nullptr /* entropy_provider */); + ScopedUkmFeatureParams params(base::FeatureList::OVERRIDE_ENABLE_FEATURE, {}); + UkmService service(&prefs_, &client_); + TestRecordingHelper recorder(&service); + + EXPECT_EQ(GetPersistedLogCount(), 0); + service.Initialize(); + task_runner_->RunUntilIdle(); + service.EnableRecording(); + service.EnableReporting(); + + int64_t id_counter = 1; + int expected_kept_count = 0; + for (const auto& test : test_cases) { + auto source_id = GetWhitelistedSourceId(id_counter++); + recorder.UpdateSourceURL(source_id, GURL(test.url)); + recorder.GetEntryBuilder(source_id, "FakeEntry"); + if (test.expected_kept) + ++expected_kept_count; + } + + service.Flush(); + EXPECT_EQ(GetPersistedLogCount(), 1); + Report proto_report = GetPersistedReport(); + + EXPECT_EQ(expected_kept_count, proto_report.sources_size()); + for (const auto& test : test_cases) { + bool found = false; + for (int i = 0; i < proto_report.sources_size(); ++i) { + if (proto_report.sources(i).url() == test.url) { + found = true; + break; + } + } + EXPECT_EQ(test.expected_kept, found) << test.url; + } +} + +TEST_F(UkmServiceTest, SanitizeUrlAuthParams) { + UkmService service(&prefs_, &client_); + TestRecordingHelper recorder(&service); + EXPECT_EQ(0, GetPersistedLogCount()); + service.Initialize(); + task_runner_->RunUntilIdle(); + service.EnableRecording(); + service.EnableReporting(); + + auto id = GetWhitelistedSourceId(0); + recorder.UpdateSourceURL(id, GURL("https://username:password@example.com/")); + + service.Flush(); + EXPECT_EQ(1, GetPersistedLogCount()); + + auto proto_report = GetPersistedReport(); + ASSERT_EQ(1, proto_report.sources_size()); + const Source& proto_source = proto_report.sources(0); + EXPECT_EQ("https://example.com/", proto_source.url()); +} + +TEST_F(UkmServiceTest, SanitizeChromeUrlParams) { + struct { + const char* url; + const char* expected_url; + } test_cases[] = { + {"chrome://version/?foo=bar", "chrome://version/"}, + {"about:blank?foo=bar", "about:blank"}, + {"chrome://histograms/Variations", "chrome://histograms/Variations"}, + {"http://google.ca/?foo=bar", "http://google.ca/?foo=bar"}, + {"https://google.ca/?foo=bar", "https://google.ca/?foo=bar"}, + {"ftp://google.ca/?foo=bar", "ftp://google.ca/?foo=bar"}, + }; + + for (const auto& test : test_cases) { + ClearPrefs(); + + UkmService service(&prefs_, &client_); + TestRecordingHelper recorder(&service); + EXPECT_EQ(0, GetPersistedLogCount()); + service.Initialize(); + task_runner_->RunUntilIdle(); + service.EnableRecording(); + service.EnableReporting(); + + auto id = GetWhitelistedSourceId(0); + recorder.UpdateSourceURL(id, GURL(test.url)); + + service.Flush(); + EXPECT_EQ(1, GetPersistedLogCount()); + + auto proto_report = GetPersistedReport(); + ASSERT_EQ(1, proto_report.sources_size()); + const Source& proto_source = proto_report.sources(0); + EXPECT_EQ(test.expected_url, proto_source.url()); + } +} + } // namespace ukm diff --git a/chromium/components/ukm/ukm_source.cc b/chromium/components/ukm/ukm_source.cc index 4a701495ecb..e74e05356a2 100644 --- a/chromium/components/ukm/ukm_source.cc +++ b/chromium/components/ukm/ukm_source.cc @@ -6,7 +6,7 @@ #include "base/atomicops.h" #include "base/hash.h" -#include "components/metrics/proto/ukm/source.pb.h" +#include "third_party/metrics_proto/ukm/source.pb.h" namespace ukm { |