browsing_topics_page_load_data_tracker_unittest.cc 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. // Copyright 2022 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "components/browsing_topics/browsing_topics_page_load_data_tracker.h"
  5. #include "base/files/scoped_temp_dir.h"
  6. #include "base/memory/raw_ptr.h"
  7. #include "base/test/bind.h"
  8. #include "base/test/scoped_feature_list.h"
  9. #include "components/browsing_topics/test_util.h"
  10. #include "components/history/content/browser/history_context_helper.h"
  11. #include "components/history/core/browser/history_database_params.h"
  12. #include "components/history/core/browser/history_service.h"
  13. #include "components/history/core/test/test_history_database.h"
  14. #include "components/ukm/test_ukm_recorder.h"
  15. #include "content/public/browser/navigation_entry.h"
  16. #include "content/public/test/back_forward_cache_util.h"
  17. #include "content/public/test/browsing_topics_test_util.h"
  18. #include "content/public/test/navigation_simulator.h"
  19. #include "content/public/test/test_utils.h"
  20. #include "content/public/test/web_contents_tester.h"
  21. #include "content/test/test_render_view_host.h"
  22. #include "services/metrics/public/cpp/metrics_utils.h"
  23. #include "services/metrics/public/cpp/ukm_builders.h"
  24. namespace browsing_topics {
  25. class BrowsingTopicsPageLoadDataTrackerTest
  26. : public content::RenderViewHostTestHarness {
  27. public:
  28. BrowsingTopicsPageLoadDataTrackerTest() {
  29. scoped_feature_list_.InitWithFeatures(
  30. /*enabled_features=*/{blink::features::kBrowsingTopics},
  31. /*disabled_features=*/{});
  32. EXPECT_TRUE(temp_dir_.CreateUniqueTempDir());
  33. history_service_ = std::make_unique<history::HistoryService>();
  34. history_service_->Init(
  35. history::TestHistoryDatabaseParamsForPath(temp_dir_.GetPath()));
  36. }
  37. ~BrowsingTopicsPageLoadDataTrackerTest() override = default;
  38. void SetUp() override {
  39. content::RenderViewHostTestHarness::SetUp();
  40. // The test assumes pages gets deleted after navigation, triggering metrics
  41. // recording. Disable back/forward cache to ensure that pages don't get
  42. // preserved in the cache.
  43. content::DisableBackForwardCacheForTesting(
  44. web_contents(), content::BackForwardCache::TEST_REQUIRES_NO_CACHING);
  45. }
  46. void TearDown() override {
  47. DCHECK(history_service_);
  48. base::RunLoop run_loop;
  49. history_service_->SetOnBackendDestroyTask(run_loop.QuitClosure());
  50. history_service_.reset();
  51. run_loop.Run();
  52. content::RenderViewHostTestHarness::TearDown();
  53. }
  54. void NavigateToPage(const GURL& url,
  55. bool publicly_routable,
  56. bool browsing_topics_permissions_policy_allowed,
  57. bool interest_cohort_permissions_policy_allowed) {
  58. auto simulator = content::NavigationSimulator::CreateBrowserInitiated(
  59. url, web_contents());
  60. simulator->SetTransition(ui::PageTransition::PAGE_TRANSITION_TYPED);
  61. if (!publicly_routable) {
  62. net::IPAddress address;
  63. EXPECT_TRUE(address.AssignFromIPLiteral("0.0.0.0"));
  64. simulator->SetSocketAddress(net::IPEndPoint(address, /*port=*/0));
  65. }
  66. blink::ParsedPermissionsPolicy policy;
  67. if (!browsing_topics_permissions_policy_allowed) {
  68. policy.emplace_back(
  69. blink::mojom::PermissionsPolicyFeature::kBrowsingTopics,
  70. /*values=*/std::vector<url::Origin>(), /*matches_all_origins=*/false,
  71. /*matches_opaque_src=*/false);
  72. }
  73. if (!interest_cohort_permissions_policy_allowed) {
  74. policy.emplace_back(blink::mojom::PermissionsPolicyFeature::
  75. kBrowsingTopicsBackwardCompatible,
  76. /*values=*/std::vector<url::Origin>(),
  77. /*matches_all_origins=*/false,
  78. /*matches_opaque_src=*/false);
  79. }
  80. simulator->SetPermissionsPolicyHeader(std::move(policy));
  81. simulator->Commit();
  82. history_service_->AddPage(
  83. url, base::Time::Now(),
  84. history::ContextIDForWebContents(web_contents()),
  85. web_contents()->GetController().GetLastCommittedEntry()->GetUniqueID(),
  86. /*referrer=*/GURL(),
  87. /*redirects=*/{}, ui::PageTransition::PAGE_TRANSITION_TYPED,
  88. history::VisitSource::SOURCE_BROWSED,
  89. /*did_replace_entry=*/false);
  90. }
  91. BrowsingTopicsPageLoadDataTracker* GetBrowsingTopicsPageLoadDataTracker() {
  92. return BrowsingTopicsPageLoadDataTracker::GetOrCreateForPage(
  93. web_contents()->GetPrimaryMainFrame()->GetPage());
  94. }
  95. content::BrowsingTopicsSiteDataManager* topics_site_data_manager() {
  96. return web_contents()
  97. ->GetPrimaryMainFrame()
  98. ->GetProcess()
  99. ->GetStoragePartition()
  100. ->GetBrowsingTopicsSiteDataManager();
  101. }
  102. protected:
  103. base::test::ScopedFeatureList scoped_feature_list_;
  104. std::unique_ptr<history::HistoryService> history_service_;
  105. base::ScopedTempDir temp_dir_;
  106. };
  107. TEST_F(BrowsingTopicsPageLoadDataTrackerTest, OneUsage) {
  108. GURL url("https://foo.com");
  109. NavigateToPage(url, /*publicly_routable=*/true,
  110. /*browsing_topics_permissions_policy_allowed=*/true,
  111. /*interest_cohort_permissions_policy_allowed=*/true);
  112. EXPECT_FALSE(BrowsingTopicsEligibleForURLVisit(history_service_.get(), url));
  113. EXPECT_TRUE(
  114. content::GetBrowsingTopicsApiUsage(topics_site_data_manager()).empty());
  115. GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
  116. HashedDomain(123), history_service_.get());
  117. EXPECT_TRUE(BrowsingTopicsEligibleForURLVisit(history_service_.get(), url));
  118. std::vector<ApiUsageContext> api_usage_contexts =
  119. content::GetBrowsingTopicsApiUsage(topics_site_data_manager());
  120. EXPECT_EQ(api_usage_contexts.size(), 1u);
  121. EXPECT_EQ(api_usage_contexts[0].hashed_main_frame_host,
  122. HashMainFrameHostForStorage("foo.com"));
  123. EXPECT_EQ(api_usage_contexts[0].hashed_context_domain, HashedDomain(123));
  124. }
  125. TEST_F(BrowsingTopicsPageLoadDataTrackerTest, TwoUsages) {
  126. GURL url("https://foo.com");
  127. NavigateToPage(url, /*publicly_routable=*/true,
  128. /*browsing_topics_permissions_policy_allowed=*/true,
  129. /*interest_cohort_permissions_policy_allowed=*/true);
  130. GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
  131. HashedDomain(123), history_service_.get());
  132. GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
  133. HashedDomain(456), history_service_.get());
  134. EXPECT_TRUE(BrowsingTopicsEligibleForURLVisit(history_service_.get(), url));
  135. std::vector<ApiUsageContext> api_usage_contexts =
  136. content::GetBrowsingTopicsApiUsage(topics_site_data_manager());
  137. EXPECT_EQ(api_usage_contexts.size(), 2u);
  138. EXPECT_EQ(api_usage_contexts[0].hashed_main_frame_host,
  139. HashMainFrameHostForStorage("foo.com"));
  140. EXPECT_EQ(api_usage_contexts[0].hashed_context_domain, HashedDomain(123));
  141. EXPECT_EQ(api_usage_contexts[1].hashed_main_frame_host,
  142. HashMainFrameHostForStorage("foo.com"));
  143. EXPECT_EQ(api_usage_contexts[1].hashed_context_domain, HashedDomain(456));
  144. }
  145. TEST_F(BrowsingTopicsPageLoadDataTrackerTest, OneUsage_PageLoadUkm) {
  146. ukm::TestAutoSetUkmRecorder ukm_recorder;
  147. NavigateToPage(GURL("https://foo.com"), /*publicly_routable=*/true,
  148. /*browsing_topics_permissions_policy_allowed=*/true,
  149. /*interest_cohort_permissions_policy_allowed=*/true);
  150. GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
  151. HashedDomain(123), history_service_.get());
  152. NavigateToPage(GURL(url::kAboutBlankURL), /*publicly_routable=*/true,
  153. /*browsing_topics_permissions_policy_allowed=*/true,
  154. /*interest_cohort_permissions_policy_allowed=*/true);
  155. auto entries = ukm_recorder.GetEntriesByName(
  156. ukm::builders::BrowsingTopics_PageLoad::kEntryName);
  157. EXPECT_EQ(1u, entries.size());
  158. ASSERT_EQ(1, ukm::GetExponentialBucketMinForCounts1000(1));
  159. ukm_recorder.ExpectEntryMetric(entries.back(),
  160. ukm::builders::BrowsingTopics_PageLoad::
  161. kTopicsRequestingContextDomainsCountName,
  162. 1);
  163. }
  164. TEST_F(BrowsingTopicsPageLoadDataTrackerTest, OneThousandUsages_PageLoadUkm) {
  165. ukm::TestAutoSetUkmRecorder ukm_recorder;
  166. NavigateToPage(GURL("https://foo.com"), /*publicly_routable=*/true,
  167. /*browsing_topics_permissions_policy_allowed=*/true,
  168. /*interest_cohort_permissions_policy_allowed=*/true);
  169. for (int i = 0; i < 1000; ++i) {
  170. GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
  171. HashedDomain(i), history_service_.get());
  172. }
  173. NavigateToPage(GURL(url::kAboutBlankURL), /*publicly_routable=*/true,
  174. /*browsing_topics_permissions_policy_allowed=*/true,
  175. /*interest_cohort_permissions_policy_allowed=*/true);
  176. auto entries = ukm_recorder.GetEntriesByName(
  177. ukm::builders::BrowsingTopics_PageLoad::kEntryName);
  178. EXPECT_EQ(1u, entries.size());
  179. ASSERT_EQ(943, ukm::GetExponentialBucketMinForCounts1000(1000));
  180. ukm_recorder.ExpectEntryMetric(entries.back(),
  181. ukm::builders::BrowsingTopics_PageLoad::
  182. kTopicsRequestingContextDomainsCountName,
  183. 943);
  184. }
  185. TEST_F(BrowsingTopicsPageLoadDataTrackerTest, TwoThousandUsages_PageLoadUkm) {
  186. ukm::TestAutoSetUkmRecorder ukm_recorder;
  187. NavigateToPage(GURL("https://foo.com"), /*publicly_routable=*/true,
  188. /*browsing_topics_permissions_policy_allowed=*/true,
  189. /*interest_cohort_permissions_policy_allowed=*/true);
  190. for (int i = 0; i < 2000; ++i) {
  191. GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
  192. HashedDomain(i), history_service_.get());
  193. }
  194. NavigateToPage(GURL(url::kAboutBlankURL), /*publicly_routable=*/true,
  195. /*browsing_topics_permissions_policy_allowed=*/true,
  196. /*interest_cohort_permissions_policy_allowed=*/true);
  197. auto entries = ukm_recorder.GetEntriesByName(
  198. ukm::builders::BrowsingTopics_PageLoad::kEntryName);
  199. EXPECT_EQ(1u, entries.size());
  200. ASSERT_EQ(943, ukm::GetExponentialBucketMinForCounts1000(1000));
  201. ASSERT_EQ(1896, ukm::GetExponentialBucketMinForCounts1000(2000));
  202. ukm_recorder.ExpectEntryMetric(entries.back(),
  203. ukm::builders::BrowsingTopics_PageLoad::
  204. kTopicsRequestingContextDomainsCountName,
  205. 943);
  206. }
  207. TEST_F(BrowsingTopicsPageLoadDataTrackerTest, DuplicateDomains) {
  208. GURL url("https://foo.com");
  209. NavigateToPage(url, /*publicly_routable=*/true,
  210. /*browsing_topics_permissions_policy_allowed=*/true,
  211. /*interest_cohort_permissions_policy_allowed=*/true);
  212. GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
  213. HashedDomain(123), history_service_.get());
  214. GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
  215. HashedDomain(456), history_service_.get());
  216. GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
  217. HashedDomain(123), history_service_.get());
  218. EXPECT_TRUE(BrowsingTopicsEligibleForURLVisit(history_service_.get(), url));
  219. std::vector<ApiUsageContext> api_usage_contexts =
  220. content::GetBrowsingTopicsApiUsage(topics_site_data_manager());
  221. EXPECT_EQ(api_usage_contexts.size(), 2u);
  222. EXPECT_EQ(api_usage_contexts[0].hashed_main_frame_host,
  223. HashMainFrameHostForStorage("foo.com"));
  224. EXPECT_EQ(api_usage_contexts[0].hashed_context_domain, HashedDomain(123));
  225. EXPECT_EQ(api_usage_contexts[1].hashed_main_frame_host,
  226. HashMainFrameHostForStorage("foo.com"));
  227. EXPECT_EQ(api_usage_contexts[1].hashed_context_domain, HashedDomain(456));
  228. // The second HashedDomain(123) shouldn't update the database. Verify this by
  229. // verifying that the timestamp for HashedDomain(123) is no greater than the
  230. // timestamp for HashedDomain(456).
  231. EXPECT_LE(api_usage_contexts[0].time, api_usage_contexts[1].time);
  232. }
  233. TEST_F(BrowsingTopicsPageLoadDataTrackerTest, NumberOfDomainsExceedsLimit) {
  234. GURL url("https://foo.com");
  235. NavigateToPage(url, /*publicly_routable=*/true,
  236. /*browsing_topics_permissions_policy_allowed=*/true,
  237. /*interest_cohort_permissions_policy_allowed=*/true);
  238. for (int i = 0; i < 31; ++i) {
  239. GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
  240. HashedDomain(i), history_service_.get());
  241. }
  242. EXPECT_TRUE(BrowsingTopicsEligibleForURLVisit(history_service_.get(), url));
  243. std::vector<ApiUsageContext> api_usage_contexts =
  244. content::GetBrowsingTopicsApiUsage(topics_site_data_manager());
  245. EXPECT_EQ(api_usage_contexts.size(), 30u);
  246. for (int i = 0; i < 30; ++i) {
  247. EXPECT_EQ(api_usage_contexts[i].hashed_main_frame_host,
  248. HashMainFrameHostForStorage("foo.com"));
  249. EXPECT_EQ(api_usage_contexts[i].hashed_context_domain, HashedDomain(i));
  250. }
  251. }
  252. TEST_F(BrowsingTopicsPageLoadDataTrackerTest, NotPubliclyRoutable) {
  253. GURL url("https://foo.com");
  254. NavigateToPage(url, /*publicly_routable=*/false,
  255. /*browsing_topics_permissions_policy_allowed=*/true,
  256. /*interest_cohort_permissions_policy_allowed=*/true);
  257. GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
  258. HashedDomain(123), history_service_.get());
  259. EXPECT_FALSE(BrowsingTopicsEligibleForURLVisit(history_service_.get(), url));
  260. EXPECT_TRUE(
  261. content::GetBrowsingTopicsApiUsage(topics_site_data_manager()).empty());
  262. }
  263. TEST_F(BrowsingTopicsPageLoadDataTrackerTest,
  264. BrowsingTopicsPermissionsPolicyNotAllowed) {
  265. GURL url("https://foo.com");
  266. NavigateToPage(url, /*publicly_routable=*/true,
  267. /*browsing_topics_permissions_policy_allowed=*/false,
  268. /*interest_cohort_permissions_policy_allowed=*/true);
  269. GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
  270. HashedDomain(123), history_service_.get());
  271. EXPECT_FALSE(BrowsingTopicsEligibleForURLVisit(history_service_.get(), url));
  272. EXPECT_TRUE(
  273. content::GetBrowsingTopicsApiUsage(topics_site_data_manager()).empty());
  274. }
  275. TEST_F(BrowsingTopicsPageLoadDataTrackerTest,
  276. InterestCohortPermissionsPolicyNotAllowed) {
  277. GURL url("https://foo.com");
  278. NavigateToPage(url, /*publicly_routable=*/true,
  279. /*browsing_topics_permissions_policy_allowed=*/true,
  280. /*interest_cohort_permissions_policy_allowed=*/false);
  281. GetBrowsingTopicsPageLoadDataTracker()->OnBrowsingTopicsApiUsed(
  282. HashedDomain(123), history_service_.get());
  283. EXPECT_FALSE(BrowsingTopicsEligibleForURLVisit(history_service_.get(), url));
  284. EXPECT_TRUE(
  285. content::GetBrowsingTopicsApiUsage(topics_site_data_manager()).empty());
  286. }
  287. } // namespace browsing_topics