blob: e00784c780e7c003f83ecbb11802d3ce710156f3 [file] [log] [blame]
Avi Drissman8ba1bad2022-09-13 19:22:361// Copyright 2012 The Chromium Authors
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commit09911bf2008-07-26 23:55:294
avi5dd91f82015-12-25 22:30:465#include <stddef.h>
6#include <stdint.h>
7
initial.commit09911bf2008-07-26 23:55:298#include <cstdio>
dcheng3f767dc32016-04-25 22:54:229#include <memory>
[email protected]c38831a12011-10-28 12:44:4910#include <string>
11#include <vector>
initial.commit09911bf2008-07-26 23:55:2912
thestig819adcc82014-09-10 22:24:5313#include "base/files/file_util.h"
Greg Thompson5310924e22019-11-04 20:22:0214#include "base/files/scoped_temp_dir.h"
Avi Drissman12be0312023-01-11 09:16:0915#include "base/functional/bind.h"
skyostilb0daa012015-06-02 19:03:4816#include "base/location.h"
Keishi Hattorie175ac52022-06-07 06:24:5717#include "base/memory/raw_ptr.h"
[email protected]27730162013-07-23 14:51:5518#include "base/process/process_handle.h"
[email protected]ec04d3f2013-06-06 21:31:3919#include "base/run_loop.h"
[email protected]c72674b2013-06-11 04:16:4320#include "base/strings/string_util.h"
Lei Zhange02299a2021-04-26 23:12:2421#include "base/strings/stringprintf.h"
Patrick Monette643cdf62021-10-15 19:13:4222#include "base/task/single_thread_task_runner.h"
[email protected]bbd8da92013-06-28 02:12:2023#include "base/time/time.h"
sammcaa222762016-09-21 07:30:4224#include "base/timer/mock_timer.h"
[email protected]1f371fa2013-01-23 00:35:1425#include "components/visitedlink/browser/visitedlink_delegate.h"
26#include "components/visitedlink/browser/visitedlink_event_listener.h"
Robert Sesekffeae8e2019-11-26 17:10:1527#include "components/visitedlink/browser/visitedlink_writer.h"
sammcaa222762016-09-21 07:30:4228#include "components/visitedlink/common/visitedlink.mojom.h"
Artin Lindqvistd0647cca2023-02-27 19:23:0229#include "components/visitedlink/common/visitedlink_common.h"
Robert Sesekffeae8e2019-11-26 17:10:1530#include "components/visitedlink/renderer/visitedlink_reader.h"
[email protected]ec04d3f2013-06-06 21:31:3931#include "content/public/browser/browser_thread.h"
Gabriel Charettec7108742019-08-23 03:31:4032#include "content/public/test/browser_task_environment.h"
[email protected]08a932d52012-06-03 21:42:1233#include "content/public/test/mock_render_process_host.h"
[email protected]4c3d9d62013-01-09 22:37:2034#include "content/public/test/test_browser_context.h"
[email protected]b1e3f202012-06-04 14:45:5035#include "content/public/test/test_renderer_host.h"
mtomaszf7d99a5c2014-09-15 16:23:4636#include "content/public/test/test_utils.h"
Julie Jeongeun Kim8ab180f72019-09-25 09:25:4637#include "mojo/public/cpp/bindings/pending_receiver.h"
38#include "mojo/public/cpp/bindings/receiver_set.h"
initial.commit09911bf2008-07-26 23:55:2939#include "testing/gtest/include/gtest/gtest.h"
Anton Bikineev1156b5f2021-05-15 22:35:3640#include "third_party/abseil-cpp/absl/types/optional.h"
[email protected]e3b599e2013-07-05 07:15:1741#include "url/gurl.h"
initial.commit09911bf2008-07-26 23:55:2942
[email protected]631bb742011-11-02 11:29:3943using content::BrowserThread;
[email protected]eddd886702012-03-16 14:53:2344using content::MockRenderProcessHost;
[email protected]c0257382012-03-12 20:15:3445using content::RenderViewHostTester;
[email protected]631bb742011-11-02 11:29:3946
Matt Falkenhagen24abf7822017-12-15 23:55:1147namespace content {
48class SiteInstance;
49}
50
[email protected]ab3eaeed2013-05-17 00:18:4451namespace visitedlink {
[email protected]1f371fa2013-01-23 00:35:1452
initial.commit09911bf2008-07-26 23:55:2953namespace {
54
[email protected]4c3d9d62013-01-09 22:37:2055typedef std::vector<GURL> URLs;
56
initial.commit09911bf2008-07-26 23:55:2957// a nice long URL that we can append numbers to to get new URLs
Eric Seckler4364b052019-11-21 21:37:5558const char kTestPrefix[] =
59 "http://www.google.com/products/foo/index.html?id=45028640526508376&seq=";
60constexpr int kTestCount = 1000;
initial.commit09911bf2008-07-26 23:55:2961
62// Returns a test URL for index |i|
63GURL TestURL(int i) {
Eric Seckler4364b052019-11-21 21:37:5564 return GURL(base::StringPrintf("%s%d", kTestPrefix, i));
initial.commit09911bf2008-07-26 23:55:2965}
66
Robert Sesekffeae8e2019-11-26 17:10:1567std::vector<VisitedLinkReader*> g_readers;
[email protected]4c3d9d62013-01-09 22:37:2068
69class TestVisitedLinkDelegate : public VisitedLinkDelegate {
70 public:
dcheng00ea022b2014-10-21 11:24:5671 void RebuildTable(const scoped_refptr<URLEnumerator>& enumerator) override;
[email protected]4c3d9d62013-01-09 22:37:2072
73 void AddURLForRebuild(const GURL& url);
74
75 private:
[email protected]4c3d9d62013-01-09 22:37:2076 URLs rebuild_urls_;
77};
78
[email protected]4c3d9d62013-01-09 22:37:2079void TestVisitedLinkDelegate::RebuildTable(
80 const scoped_refptr<URLEnumerator>& enumerator) {
81 for (URLs::const_iterator itr = rebuild_urls_.begin();
Ken Rockot4a16adb2019-12-17 07:31:4282 itr != rebuild_urls_.end(); ++itr)
[email protected]4c3d9d62013-01-09 22:37:2083 enumerator->OnURL(*itr);
84 enumerator->OnComplete(true);
85}
86
87void TestVisitedLinkDelegate::AddURLForRebuild(const GURL& url) {
88 rebuild_urls_.push_back(url);
89}
90
Robert Sesekffeae8e2019-11-26 17:10:1591class TestURLIterator : public VisitedLinkWriter::URLIterator {
[email protected]4c3d9d62013-01-09 22:37:2092 public:
93 explicit TestURLIterator(const URLs& urls);
94
dcheng00ea022b2014-10-21 11:24:5695 const GURL& NextURL() override;
96 bool HasNextURL() const override;
[email protected]4c3d9d62013-01-09 22:37:2097
98 private:
99 URLs::const_iterator iterator_;
100 URLs::const_iterator end_;
101};
102
103TestURLIterator::TestURLIterator(const URLs& urls)
Ken Rockot4a16adb2019-12-17 07:31:42104 : iterator_(urls.begin()), end_(urls.end()) {}
[email protected]4c3d9d62013-01-09 22:37:20105
106const GURL& TestURLIterator::NextURL() {
107 return *(iterator_++);
108}
109
110bool TestURLIterator::HasNextURL() const {
111 return iterator_ != end_;
112}
[email protected]dba45e32013-01-04 20:27:15113
[email protected]3e90d4a2009-07-03 17:38:39114} // namespace
115
Robert Sesekffeae8e2019-11-26 17:10:15116class TrackingVisitedLinkEventListener : public VisitedLinkWriter::Listener {
[email protected]3e90d4a2009-07-03 17:38:39117 public:
118 TrackingVisitedLinkEventListener()
Ken Rockot4a16adb2019-12-17 07:31:42119 : reset_count_(0), completely_reset_count_(0), add_count_(0) {}
[email protected]3e90d4a2009-07-03 17:38:39120
Ken Rockotaeb7eca2018-03-30 16:40:09121 void NewTable(base::ReadOnlySharedMemoryRegion* table_region) override {
122 if (table_region->IsValid()) {
Robert Sesekffeae8e2019-11-26 17:10:15123 for (std::vector<VisitedLinkReader>::size_type i = 0;
124 i < g_readers.size(); i++) {
125 g_readers[i]->UpdateVisitedLinks(table_region->Duplicate());
[email protected]3e90d4a2009-07-03 17:38:39126 }
initial.commit09911bf2008-07-26 23:55:29127 }
128 }
dcheng00ea022b2014-10-21 11:24:56129 void Add(VisitedLinkCommon::Fingerprint) override { add_count_++; }
sathaf37203d2015-12-15 15:10:42130 void Reset(bool invalidate_hashes) override {
131 if (invalidate_hashes)
132 completely_reset_count_++;
133 else
134 reset_count_++;
135 }
initial.commit09911bf2008-07-26 23:55:29136
[email protected]3e90d4a2009-07-03 17:38:39137 void SetUp() {
138 reset_count_ = 0;
139 add_count_ = 0;
140 }
141
142 int reset_count() const { return reset_count_; }
sathaf37203d2015-12-15 15:10:42143 int completely_reset_count() { return completely_reset_count_; }
[email protected]3e90d4a2009-07-03 17:38:39144 int add_count() const { return add_count_; }
145
146 private:
147 int reset_count_;
sathaf37203d2015-12-15 15:10:42148 int completely_reset_count_;
[email protected]3e90d4a2009-07-03 17:38:39149 int add_count_;
150};
[email protected]c2c998c2009-01-27 19:08:39151
[email protected]583844c2011-08-27 00:38:35152class VisitedLinkTest : public testing::Test {
initial.commit09911bf2008-07-26 23:55:29153 protected:
initial.commit09911bf2008-07-26 23:55:29154 // Initializes the visited link objects. Pass in the size that you want a
155 // freshly created table to be. 0 means use the default.
156 //
157 // |suppress_rebuild| is set when we're not testing rebuilding, see
Robert Sesekffeae8e2019-11-26 17:10:15158 // the VisitedLinkWriter constructor.
sathaf37203d2015-12-15 15:10:42159 //
160 // |wait_for_io_complete| wait for result of async loading.
161 bool InitVisited(int initial_size,
162 bool suppress_rebuild,
163 bool wait_for_io_complete) {
initial.commit09911bf2008-07-26 23:55:29164 // Initialize the visited link system.
Peter Boström665b49d2021-04-05 19:29:58165 writer_ = std::make_unique<VisitedLinkWriter>(
166 new TrackingVisitedLinkEventListener(), &delegate_, true,
167 suppress_rebuild, visited_file_, initial_size);
Robert Sesekffeae8e2019-11-26 17:10:15168 bool result = writer_->Init();
sathaf37203d2015-12-15 15:10:42169 if (result && wait_for_io_complete) {
170 // Wait for all pending file I/O to be completed.
Gabriel Charette01507a22017-09-27 21:30:08171 content::RunAllTasksUntilIdle();
sathaf37203d2015-12-15 15:10:42172 }
173 return result;
initial.commit09911bf2008-07-26 23:55:29174 }
175
176 // May be called multiple times (some tests will do this to clear things,
177 // and TearDown will do this to make sure eveything is shiny before quitting.
178 void ClearDB() {
Robert Sesekffeae8e2019-11-26 17:10:15179 writer_.reset(nullptr);
initial.commit09911bf2008-07-26 23:55:29180
[email protected]3189013e2012-01-19 04:11:57181 // Wait for all pending file I/O to be completed.
Gabriel Charette01507a22017-09-27 21:30:08182 content::RunAllTasksUntilIdle();
initial.commit09911bf2008-07-26 23:55:29183 }
184
185 // Loads the database from disk and makes sure that the same URLs are present
186 // as were generated by TestIO_Create(). This also checks the URLs with a
Robert Sesekffeae8e2019-11-26 17:10:15187 // reader to make sure it reads the data properly.
initial.commit09911bf2008-07-26 23:55:29188 void Reload() {
189 // Clean up after our caller, who may have left the database open.
190 ClearDB();
191
sathaf37203d2015-12-15 15:10:42192 ASSERT_TRUE(InitVisited(0, true, true));
193
Robert Sesekffeae8e2019-11-26 17:10:15194 writer_->DebugValidate();
initial.commit09911bf2008-07-26 23:55:29195
196 // check that the table has the proper number of entries
Robert Sesekffeae8e2019-11-26 17:10:15197 int used_count = writer_->GetUsedCount();
Eric Seckler4364b052019-11-21 21:37:55198 ASSERT_EQ(used_count, kTestCount);
initial.commit09911bf2008-07-26 23:55:29199
Robert Sesekffeae8e2019-11-26 17:10:15200 // Create a reader database.
201 VisitedLinkReader reader;
202 reader.UpdateVisitedLinks(
203 writer_->mapped_table_memory().region.Duplicate());
204 g_readers.push_back(&reader);
initial.commit09911bf2008-07-26 23:55:29205
206 bool found;
Eric Seckler4364b052019-11-21 21:37:55207 for (int i = 0; i < kTestCount; i++) {
initial.commit09911bf2008-07-26 23:55:29208 GURL cur = TestURL(i);
Robert Sesekffeae8e2019-11-26 17:10:15209 found = writer_->IsVisited(cur);
210 EXPECT_TRUE(found) << "URL " << i << "not found in writer.";
initial.commit09911bf2008-07-26 23:55:29211
Robert Sesekffeae8e2019-11-26 17:10:15212 found = reader.IsVisited(cur);
213 EXPECT_TRUE(found) << "URL " << i << "not found in reader.";
initial.commit09911bf2008-07-26 23:55:29214 }
215
216 // test some random URL so we know that it returns false sometimes too
Robert Sesekffeae8e2019-11-26 17:10:15217 found = writer_->IsVisited(GURL("http://unfound.site/"));
initial.commit09911bf2008-07-26 23:55:29218 ASSERT_FALSE(found);
Robert Sesekffeae8e2019-11-26 17:10:15219 found = reader.IsVisited(GURL("http://unfound.site/"));
initial.commit09911bf2008-07-26 23:55:29220 ASSERT_FALSE(found);
221
Robert Sesekffeae8e2019-11-26 17:10:15222 writer_->DebugValidate();
initial.commit09911bf2008-07-26 23:55:29223
Robert Sesekffeae8e2019-11-26 17:10:15224 g_readers.clear();
initial.commit09911bf2008-07-26 23:55:29225 }
226
227 // testing::Test
dcheng30a1b1542014-10-29 21:27:50228 void SetUp() override {
[email protected]f708ed12010-09-23 12:18:34229 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
230
vabr8c498ea42016-09-15 12:41:58231 history_dir_ = temp_dir_.GetPath().AppendASCII("VisitedLinkTest");
[email protected]426d1c92013-12-03 20:08:54232 ASSERT_TRUE(base::CreateDirectory(history_dir_));
initial.commit09911bf2008-07-26 23:55:29233
[email protected]c2c998c2009-01-27 19:08:39234 visited_file_ = history_dir_.Append(FILE_PATH_LITERAL("VisitedLinks"));
initial.commit09911bf2008-07-26 23:55:29235 }
236
Greg Thompson5310924e22019-11-04 20:22:02237 void TearDown() override {
238 ClearDB();
239 ASSERT_TRUE(temp_dir_.Delete());
240 }
[email protected]f0a51fb52009-03-05 12:46:38241
[email protected]ea1a3f62012-11-16 20:34:23242 base::ScopedTempDir temp_dir_;
[email protected]f708ed12010-09-23 12:18:34243
initial.commit09911bf2008-07-26 23:55:29244 // Filenames for the services;
[email protected]9e275712013-02-10 19:20:14245 base::FilePath history_dir_;
246 base::FilePath visited_file_;
initial.commit09911bf2008-07-26 23:55:29247
Robert Sesekffeae8e2019-11-26 17:10:15248 std::unique_ptr<VisitedLinkWriter> writer_;
[email protected]4c3d9d62013-01-09 22:37:20249 TestVisitedLinkDelegate delegate_;
Gabriel Charette798fde72019-08-20 22:24:04250 content::BrowserTaskEnvironment task_environment_;
initial.commit09911bf2008-07-26 23:55:29251};
252
initial.commit09911bf2008-07-26 23:55:29253// This test creates and reads some databases to make sure the data is
254// preserved throughout those operations.
255TEST_F(VisitedLinkTest, DatabaseIO) {
sathaf37203d2015-12-15 15:10:42256 ASSERT_TRUE(InitVisited(0, true, true));
initial.commit09911bf2008-07-26 23:55:29257
Eric Seckler4364b052019-11-21 21:37:55258 for (int i = 0; i < kTestCount; i++)
Robert Sesekffeae8e2019-11-26 17:10:15259 writer_->AddURL(TestURL(i));
initial.commit09911bf2008-07-26 23:55:29260
261 // Test that the database was written properly
262 Reload();
263}
264
Eric Seckler4364b052019-11-21 21:37:55265// This test fills a database using AddURLs() and verifies that it can be read
266// back correctly.
267TEST_F(VisitedLinkTest, DatabaseIOAddURLs) {
268 ASSERT_TRUE(InitVisited(0, true, true));
269
270 constexpr int kHalfCount = kTestCount / 2;
271
272 // Add urls in pairs of two. Simulates calls to AddURLs() after navigations
273 // with redirects.
274 for (int i = 0; i < (kHalfCount - 1); i += 2)
Robert Sesekffeae8e2019-11-26 17:10:15275 writer_->AddURLs({TestURL(i), TestURL(i + 1)});
Eric Seckler4364b052019-11-21 21:37:55276
277 // Add a big vector of URLs, exceeding kBulkOperationThreshold.
278 std::vector<GURL> urls;
Robert Sesekffeae8e2019-11-26 17:10:15279 static_assert(kHalfCount > VisitedLinkWriter::kBulkOperationThreshold,
Eric Seckler4364b052019-11-21 21:37:55280 "kBulkOperationThreshold not exceeded");
281 for (int i = kHalfCount; i < kTestCount; i++)
282 urls.push_back(TestURL(i));
Robert Sesekffeae8e2019-11-26 17:10:15283 writer_->AddURLs(urls);
Eric Seckler4364b052019-11-21 21:37:55284
285 // Test that the database was written properly.
286 Reload();
287}
288
initial.commit09911bf2008-07-26 23:55:29289// Checks that we can delete things properly when there are collisions.
290TEST_F(VisitedLinkTest, Delete) {
avi5dd91f82015-12-25 22:30:46291 static const int32_t kInitialSize = 17;
sathaf37203d2015-12-15 15:10:42292 ASSERT_TRUE(InitVisited(kInitialSize, true, true));
initial.commit09911bf2008-07-26 23:55:29293
294 // Add a cluster from 14-17 wrapping around to 0. These will all hash to the
295 // same value.
[email protected]c2c998c2009-01-27 19:08:39296 const VisitedLinkCommon::Fingerprint kFingerprint0 = kInitialSize * 0 + 14;
297 const VisitedLinkCommon::Fingerprint kFingerprint1 = kInitialSize * 1 + 14;
298 const VisitedLinkCommon::Fingerprint kFingerprint2 = kInitialSize * 2 + 14;
299 const VisitedLinkCommon::Fingerprint kFingerprint3 = kInitialSize * 3 + 14;
300 const VisitedLinkCommon::Fingerprint kFingerprint4 = kInitialSize * 4 + 14;
Robert Sesekffeae8e2019-11-26 17:10:15301 writer_->AddFingerprint(kFingerprint0, false); // @14
302 writer_->AddFingerprint(kFingerprint1, false); // @15
303 writer_->AddFingerprint(kFingerprint2, false); // @16
304 writer_->AddFingerprint(kFingerprint3, false); // @0
305 writer_->AddFingerprint(kFingerprint4, false); // @1
initial.commit09911bf2008-07-26 23:55:29306
307 // Deleting 14 should move the next value up one slot (we do not specify an
308 // order).
Robert Sesekffeae8e2019-11-26 17:10:15309 EXPECT_EQ(kFingerprint3, writer_->hash_table_[0]);
310 writer_->DeleteFingerprint(kFingerprint3, false);
[email protected]c2c998c2009-01-27 19:08:39311 VisitedLinkCommon::Fingerprint zero_fingerprint = 0;
Robert Sesekffeae8e2019-11-26 17:10:15312 EXPECT_EQ(zero_fingerprint, writer_->hash_table_[1]);
313 EXPECT_NE(zero_fingerprint, writer_->hash_table_[0]);
initial.commit09911bf2008-07-26 23:55:29314
315 // Deleting the other four should leave the table empty.
Robert Sesekffeae8e2019-11-26 17:10:15316 writer_->DeleteFingerprint(kFingerprint0, false);
317 writer_->DeleteFingerprint(kFingerprint1, false);
318 writer_->DeleteFingerprint(kFingerprint2, false);
319 writer_->DeleteFingerprint(kFingerprint4, false);
initial.commit09911bf2008-07-26 23:55:29320
Robert Sesekffeae8e2019-11-26 17:10:15321 EXPECT_EQ(0, writer_->used_items_);
initial.commit09911bf2008-07-26 23:55:29322 for (int i = 0; i < kInitialSize; i++)
Robert Sesekffeae8e2019-11-26 17:10:15323 EXPECT_EQ(zero_fingerprint, writer_->hash_table_[i])
324 << "Hash table has values in it.";
initial.commit09911bf2008-07-26 23:55:29325}
326
Eric Seckler4364b052019-11-21 21:37:55327// When we delete more than kBulkOperationThreshold we trigger different
328// behavior where the entire file is rewritten.
initial.commit09911bf2008-07-26 23:55:29329TEST_F(VisitedLinkTest, BigDelete) {
sathaf37203d2015-12-15 15:10:42330 ASSERT_TRUE(InitVisited(16381, true, true));
initial.commit09911bf2008-07-26 23:55:29331
332 // Add the base set of URLs that won't be deleted.
333 // Reload() will test for these.
Eric Seckler4364b052019-11-21 21:37:55334 for (int32_t i = 0; i < kTestCount; i++)
Robert Sesekffeae8e2019-11-26 17:10:15335 writer_->AddURL(TestURL(i));
initial.commit09911bf2008-07-26 23:55:29336
337 // Add more URLs than necessary to trigger this case.
Robert Sesekffeae8e2019-11-26 17:10:15338 const int kTestDeleteCount = VisitedLinkWriter::kBulkOperationThreshold + 2;
[email protected]4c3d9d62013-01-09 22:37:20339 URLs urls_to_delete;
Eric Seckler4364b052019-11-21 21:37:55340 for (int32_t i = kTestCount; i < kTestCount + kTestDeleteCount; i++) {
initial.commit09911bf2008-07-26 23:55:29341 GURL url(TestURL(i));
Robert Sesekffeae8e2019-11-26 17:10:15342 writer_->AddURL(url);
[email protected]4c3d9d62013-01-09 22:37:20343 urls_to_delete.push_back(url);
initial.commit09911bf2008-07-26 23:55:29344 }
345
[email protected]4c3d9d62013-01-09 22:37:20346 TestURLIterator iterator(urls_to_delete);
Robert Sesekffeae8e2019-11-26 17:10:15347 writer_->DeleteURLs(&iterator);
348 writer_->DebugValidate();
initial.commit09911bf2008-07-26 23:55:29349
350 Reload();
351}
352
353TEST_F(VisitedLinkTest, DeleteAll) {
sathaf37203d2015-12-15 15:10:42354 ASSERT_TRUE(InitVisited(0, true, true));
initial.commit09911bf2008-07-26 23:55:29355
356 {
Robert Sesekffeae8e2019-11-26 17:10:15357 VisitedLinkReader reader;
358 reader.UpdateVisitedLinks(
359 writer_->mapped_table_memory().region.Duplicate());
360 g_readers.push_back(&reader);
initial.commit09911bf2008-07-26 23:55:29361
362 // Add the test URLs.
Eric Seckler4364b052019-11-21 21:37:55363 for (int i = 0; i < kTestCount; i++) {
Robert Sesekffeae8e2019-11-26 17:10:15364 writer_->AddURL(TestURL(i));
365 ASSERT_EQ(i + 1, writer_->GetUsedCount());
initial.commit09911bf2008-07-26 23:55:29366 }
Robert Sesekffeae8e2019-11-26 17:10:15367 writer_->DebugValidate();
initial.commit09911bf2008-07-26 23:55:29368
Robert Sesekffeae8e2019-11-26 17:10:15369 // Make sure the reader picked up the adds.
Eric Seckler4364b052019-11-21 21:37:55370 for (int i = 0; i < kTestCount; i++)
Robert Sesekffeae8e2019-11-26 17:10:15371 EXPECT_TRUE(reader.IsVisited(TestURL(i)));
initial.commit09911bf2008-07-26 23:55:29372
Robert Sesekffeae8e2019-11-26 17:10:15373 // Clear the table and make sure the reader picked it up.
374 writer_->DeleteAllURLs();
375 EXPECT_EQ(0, writer_->GetUsedCount());
Eric Seckler4364b052019-11-21 21:37:55376 for (int i = 0; i < kTestCount; i++) {
Robert Sesekffeae8e2019-11-26 17:10:15377 EXPECT_FALSE(writer_->IsVisited(TestURL(i)));
378 EXPECT_FALSE(reader.IsVisited(TestURL(i)));
initial.commit09911bf2008-07-26 23:55:29379 }
380
381 // Close the database.
Robert Sesekffeae8e2019-11-26 17:10:15382 g_readers.clear();
initial.commit09911bf2008-07-26 23:55:29383 ClearDB();
384 }
385
386 // Reopen and validate.
sathaf37203d2015-12-15 15:10:42387 ASSERT_TRUE(InitVisited(0, true, true));
Robert Sesekffeae8e2019-11-26 17:10:15388 writer_->DebugValidate();
389 EXPECT_EQ(0, writer_->GetUsedCount());
Eric Seckler4364b052019-11-21 21:37:55390 for (int i = 0; i < kTestCount; i++)
Robert Sesekffeae8e2019-11-26 17:10:15391 EXPECT_FALSE(writer_->IsVisited(TestURL(i)));
initial.commit09911bf2008-07-26 23:55:29392}
393
Robert Sesekffeae8e2019-11-26 17:10:15394// This tests that the writer correctly resizes its tables when it gets too
395// full, notifies its readers of the change, and updates the disk.
initial.commit09911bf2008-07-26 23:55:29396TEST_F(VisitedLinkTest, Resizing) {
397 // Create a very small database.
avi5dd91f82015-12-25 22:30:46398 const int32_t initial_size = 17;
sathaf37203d2015-12-15 15:10:42399 ASSERT_TRUE(InitVisited(initial_size, true, true));
initial.commit09911bf2008-07-26 23:55:29400
Robert Sesekffeae8e2019-11-26 17:10:15401 // ...and a reader
402 VisitedLinkReader reader;
403 reader.UpdateVisitedLinks(writer_->mapped_table_memory().region.Duplicate());
404 g_readers.push_back(&reader);
initial.commit09911bf2008-07-26 23:55:29405
Robert Sesekffeae8e2019-11-26 17:10:15406 int32_t used_count = writer_->GetUsedCount();
initial.commit09911bf2008-07-26 23:55:29407 ASSERT_EQ(used_count, 0);
408
Eric Seckler4364b052019-11-21 21:37:55409 for (int i = 0; i < kTestCount; i++) {
Robert Sesekffeae8e2019-11-26 17:10:15410 writer_->AddURL(TestURL(i));
411 used_count = writer_->GetUsedCount();
initial.commit09911bf2008-07-26 23:55:29412 ASSERT_EQ(i + 1, used_count);
413 }
414
415 // Verify that the table got resized sufficiently.
avi5dd91f82015-12-25 22:30:46416 int32_t table_size;
initial.commit09911bf2008-07-26 23:55:29417 VisitedLinkCommon::Fingerprint* table;
Robert Sesekffeae8e2019-11-26 17:10:15418 writer_->GetUsageStatistics(&table_size, &table);
419 used_count = writer_->GetUsedCount();
initial.commit09911bf2008-07-26 23:55:29420 ASSERT_GT(table_size, used_count);
Eric Seckler4364b052019-11-21 21:37:55421 ASSERT_EQ(used_count, kTestCount)
422 << "table count doesn't match the # of things we added";
initial.commit09911bf2008-07-26 23:55:29423
Robert Sesekffeae8e2019-11-26 17:10:15424 // Verify that the reader got the resize message and has the same
initial.commit09911bf2008-07-26 23:55:29425 // table information.
avi5dd91f82015-12-25 22:30:46426 int32_t child_table_size;
initial.commit09911bf2008-07-26 23:55:29427 VisitedLinkCommon::Fingerprint* child_table;
Robert Sesekffeae8e2019-11-26 17:10:15428 reader.GetUsageStatistics(&child_table_size, &child_table);
initial.commit09911bf2008-07-26 23:55:29429 ASSERT_EQ(table_size, child_table_size);
avi5dd91f82015-12-25 22:30:46430 for (int32_t i = 0; i < table_size; i++) {
initial.commit09911bf2008-07-26 23:55:29431 ASSERT_EQ(table[i], child_table[i]);
432 }
433
Robert Sesekffeae8e2019-11-26 17:10:15434 writer_->DebugValidate();
435 g_readers.clear();
initial.commit09911bf2008-07-26 23:55:29436
437 // This tests that the file is written correctly by reading it in using
438 // a new database.
439 Reload();
440}
441
442// Tests that if the database doesn't exist, it will be rebuilt from history.
443TEST_F(VisitedLinkTest, Rebuild) {
initial.commit09911bf2008-07-26 23:55:29444 // Add half of our URLs to history. This needs to be done before we
445 // initialize the visited link DB.
Eric Seckler4364b052019-11-21 21:37:55446 int history_count = kTestCount / 2;
initial.commit09911bf2008-07-26 23:55:29447 for (int i = 0; i < history_count; i++)
[email protected]4c3d9d62013-01-09 22:37:20448 delegate_.AddURLForRebuild(TestURL(i));
initial.commit09911bf2008-07-26 23:55:29449
450 // Initialize the visited link DB. Since the visited links file doesn't exist
451 // and we don't suppress history rebuilding, this will load from history.
sathaf37203d2015-12-15 15:10:42452 ASSERT_TRUE(InitVisited(0, false, false));
initial.commit09911bf2008-07-26 23:55:29453
454 // While the table is rebuilding, add the rest of the URLs to the visited
455 // link system. This isn't guaranteed to happen during the rebuild, so we
456 // can't be 100% sure we're testing the right thing, but in practice is.
457 // All the adds above will generally take some time queuing up on the
458 // history thread, and it will take a while to catch up to actually
459 // processing the rebuild that has queued behind it. We will generally
460 // finish adding all of the URLs before it has even found the first URL.
Eric Seckler4364b052019-11-21 21:37:55461 for (int i = history_count; i < kTestCount; i++)
Robert Sesekffeae8e2019-11-26 17:10:15462 writer_->AddURL(TestURL(i));
initial.commit09911bf2008-07-26 23:55:29463
464 // Add one more and then delete it.
Robert Sesekffeae8e2019-11-26 17:10:15465 writer_->AddURL(TestURL(kTestCount));
[email protected]4c3d9d62013-01-09 22:37:20466 URLs urls_to_delete;
Eric Seckler4364b052019-11-21 21:37:55467 urls_to_delete.push_back(TestURL(kTestCount));
[email protected]4c3d9d62013-01-09 22:37:20468 TestURLIterator iterator(urls_to_delete);
Robert Sesekffeae8e2019-11-26 17:10:15469 writer_->DeleteURLs(&iterator);
initial.commit09911bf2008-07-26 23:55:29470
471 // Wait for the rebuild to complete. The task will terminate the message
472 // loop when the rebuild is done. There's no chance that the rebuild will
473 // complete before we set the task because the rebuild completion message
474 // is posted to the message loop; until we Run() it, rebuild can not
475 // complete.
[email protected]ec04d3f2013-06-06 21:31:39476 base::RunLoop run_loop;
Robert Sesekffeae8e2019-11-26 17:10:15477 writer_->set_rebuild_complete_task(run_loop.QuitClosure());
[email protected]ec04d3f2013-06-06 21:31:39478 run_loop.Run();
initial.commit09911bf2008-07-26 23:55:29479
480 // Test that all URLs were written to the database properly.
481 Reload();
482
483 // Make sure the extra one was *not* written (Reload won't test this).
Robert Sesekffeae8e2019-11-26 17:10:15484 EXPECT_FALSE(writer_->IsVisited(TestURL(kTestCount)));
initial.commit09911bf2008-07-26 23:55:29485}
[email protected]3e90d4a2009-07-03 17:38:39486
[email protected]aed132ed2009-08-19 22:44:12487// Test that importing a large number of URLs will work
488TEST_F(VisitedLinkTest, BigImport) {
sathaf37203d2015-12-15 15:10:42489 ASSERT_TRUE(InitVisited(0, false, false));
[email protected]aed132ed2009-08-19 22:44:12490
491 // Before the table rebuilds, add a large number of URLs
Robert Sesekffeae8e2019-11-26 17:10:15492 int total_count = VisitedLinkWriter::kDefaultTableSize + 10;
[email protected]aed132ed2009-08-19 22:44:12493 for (int i = 0; i < total_count; i++)
Robert Sesekffeae8e2019-11-26 17:10:15494 writer_->AddURL(TestURL(i));
[email protected]aed132ed2009-08-19 22:44:12495
496 // Wait for the rebuild to complete.
[email protected]ec04d3f2013-06-06 21:31:39497 base::RunLoop run_loop;
Robert Sesekffeae8e2019-11-26 17:10:15498 writer_->set_rebuild_complete_task(run_loop.QuitClosure());
[email protected]ec04d3f2013-06-06 21:31:39499 run_loop.Run();
[email protected]aed132ed2009-08-19 22:44:12500
501 // Ensure that the right number of URLs are present
Robert Sesekffeae8e2019-11-26 17:10:15502 int used_count = writer_->GetUsedCount();
[email protected]aed132ed2009-08-19 22:44:12503 ASSERT_EQ(used_count, total_count);
504}
505
[email protected]3e90d4a2009-07-03 17:38:39506TEST_F(VisitedLinkTest, Listener) {
sathaf37203d2015-12-15 15:10:42507 ASSERT_TRUE(InitVisited(0, true, true));
508
509 TrackingVisitedLinkEventListener* listener =
Robert Sesekffeae8e2019-11-26 17:10:15510 static_cast<TrackingVisitedLinkEventListener*>(writer_->GetListener());
sathaf37203d2015-12-15 15:10:42511
Robert Sesekffeae8e2019-11-26 17:10:15512 // Verify that VisitedLinkWriter::Listener::Reset(true) was never called when
sathaf37203d2015-12-15 15:10:42513 // the table was created.
514 EXPECT_EQ(0, listener->completely_reset_count());
[email protected]3e90d4a2009-07-03 17:38:39515
516 // Add test URLs.
Eric Seckler4364b052019-11-21 21:37:55517 for (int i = 0; i < kTestCount; i++) {
Robert Sesekffeae8e2019-11-26 17:10:15518 writer_->AddURL(TestURL(i));
519 ASSERT_EQ(i + 1, writer_->GetUsedCount());
[email protected]3e90d4a2009-07-03 17:38:39520 }
521
[email protected]3e90d4a2009-07-03 17:38:39522 // Delete an URL.
[email protected]4c3d9d62013-01-09 22:37:20523 URLs urls_to_delete;
524 urls_to_delete.push_back(TestURL(0));
525 TestURLIterator iterator(urls_to_delete);
Robert Sesekffeae8e2019-11-26 17:10:15526 writer_->DeleteURLs(&iterator);
[email protected]4c3d9d62013-01-09 22:37:20527
[email protected]3e90d4a2009-07-03 17:38:39528 // ... and all of the remaining ones.
Robert Sesekffeae8e2019-11-26 17:10:15529 writer_->DeleteAllURLs();
[email protected]3e90d4a2009-07-03 17:38:39530
Robert Sesekffeae8e2019-11-26 17:10:15531 // Verify that VisitedLinkWriter::Listener::Add was called for each added URL.
Eric Seckler4364b052019-11-21 21:37:55532 EXPECT_EQ(kTestCount, listener->add_count());
Robert Sesekffeae8e2019-11-26 17:10:15533 // Verify that VisitedLinkWriter::Listener::Reset was called both when one and
[email protected]3e90d4a2009-07-03 17:38:39534 // all URLs are deleted.
[email protected]b42e6d82012-11-02 02:44:56535 EXPECT_EQ(2, listener->reset_count());
sathaf37203d2015-12-15 15:10:42536
537 ClearDB();
538
539 ASSERT_TRUE(InitVisited(0, true, true));
540
541 listener =
Robert Sesekffeae8e2019-11-26 17:10:15542 static_cast<TrackingVisitedLinkEventListener*>(writer_->GetListener());
543 // Verify that VisitedLinkWriter::Listener::Reset(true) was called when the
sathaf37203d2015-12-15 15:10:42544 // table was loaded.
545 EXPECT_EQ(1, listener->completely_reset_count());
[email protected]3e90d4a2009-07-03 17:38:39546}
547
Artin Lindqvistd0647cca2023-02-27 19:23:02548TEST_F(VisitedLinkTest, HashRangeWraparound) {
549 ASSERT_TRUE(InitVisited(0, true, true));
550
551 // Create two fingerprints that, when added, will create a wraparound hash
552 // range.
553 const VisitedLinkCommon::Fingerprint kFingerprint0 =
554 writer_->DefaultTableSize() - 1;
555 const VisitedLinkCommon::Fingerprint kFingerprint1 = kFingerprint0 + 1;
556
557 // Add the two fingerprints.
558 const VisitedLinkCommon::Hash hash0 =
559 writer_->AddFingerprint(kFingerprint0, false);
560 const VisitedLinkCommon::Hash hash1 =
561 writer_->AddFingerprint(kFingerprint1, false);
562
563 // Verify the hashes form a range that wraps around.
564 EXPECT_EQ(hash0, VisitedLinkCommon::Hash(writer_->DefaultTableSize() - 1));
565 EXPECT_EQ(hash1, 0);
566
567 // Write the database to file.
568 writer_->WriteUsedItemCountToFile();
569 writer_->WriteHashRangeToFile(hash0, hash1);
570
571 // Close and reopen the database.
572 ClearDB();
573 ASSERT_TRUE(InitVisited(0, true, true));
574
575 // Verify database contents.
576 ASSERT_EQ(writer_->GetUsedCount(), 2);
577 ASSERT_TRUE(writer_->IsVisited(kFingerprint0));
578 ASSERT_TRUE(writer_->IsVisited(kFingerprint1));
579}
580
Artin Lindqvist05c32ee2023-04-04 17:01:24581TEST_F(VisitedLinkTest, ResizeErrorHandling) {
582 // Create a small database.
583 const int32_t initial_size = 17;
584 ASSERT_TRUE(InitVisited(initial_size, true, true));
585
586 // Add test URL.
587 GURL url = TestURL(0);
588 writer_->AddURL(url);
589
590 // Simulate shared memory allocation failure, causing CreateURLTable() to
591 // fail.
592 VisitedLinkWriter::fail_table_creation_for_testing_ = true;
593
594 // Expect resize to fail silently.
595 const int32_t new_size = 23;
596 writer_->ResizeTable(new_size);
597
598 // Restore global state for subsequent tests.
599 VisitedLinkWriter::fail_table_creation_for_testing_ = false;
600
601 // Verify contents.
602 ASSERT_EQ(writer_->GetUsedCount(), 1);
603 ASSERT_TRUE(writer_->IsVisited(url));
604}
605
sammcaa222762016-09-21 07:30:42606class VisitCountingContext : public mojom::VisitedLinkNotificationSink {
[email protected]3e90d4a2009-07-03 17:38:39607 public:
[email protected]28a66e252013-01-25 07:54:02608 VisitCountingContext()
[email protected]3e90d4a2009-07-03 17:38:39609 : add_count_(0),
610 add_event_count_(0),
[email protected]c2134fb2013-01-23 04:28:52611 reset_event_count_(0),
sathaf37203d2015-12-15 15:10:42612 completely_reset_event_count_(0),
Lukasz Anforowicz2b2699732018-04-12 18:49:10613 new_table_count_(0) {}
[email protected]3e90d4a2009-07-03 17:38:39614
Peter Boström9f667c382021-10-01 20:09:31615 VisitCountingContext(const VisitCountingContext&) = delete;
616 VisitCountingContext& operator=(const VisitCountingContext&) = delete;
617
sammcaa222762016-09-21 07:30:42618 void Bind(mojo::ScopedMessagePipeHandle handle) {
Julie Jeongeun Kim8ab180f72019-09-25 09:25:46619 receiver_.Add(this,
620 mojo::PendingReceiver<mojom::VisitedLinkNotificationSink>(
621 std::move(handle)));
[email protected]3e90d4a2009-07-03 17:38:39622 }
623
sammcaa222762016-09-21 07:30:42624 void WaitForUpdate() {
625 base::RunLoop run_loop;
626 quit_closure_ = run_loop.QuitClosure();
627 run_loop.Run();
[email protected]3e90d4a2009-07-03 17:38:39628 }
629
Julie Jeongeun Kim8ab180f72019-09-25 09:25:46630 void WaitForNoUpdate() { receiver_.FlushForTesting(); }
sammcaa222762016-09-21 07:30:42631
Julie Jeongeun Kim8ab180f72019-09-25 09:25:46632 mojo::ReceiverSet<mojom::VisitedLinkNotificationSink>& binding() {
633 return receiver_;
sathaf37203d2015-12-15 15:10:42634 }
635
sammcaa222762016-09-21 07:30:42636 void NotifyUpdate() {
637 if (!quit_closure_.is_null())
Daniel Cheng83563bc2019-04-30 23:50:24638 std::move(quit_closure_).Run();
sammcaa222762016-09-21 07:30:42639 }
640
641 void UpdateVisitedLinks(
Ken Rockotaeb7eca2018-03-30 16:40:09642 base::ReadOnlySharedMemoryRegion table_region) override {
[email protected]c2134fb2013-01-23 04:28:52643 new_table_count_++;
sammcaa222762016-09-21 07:30:42644 NotifyUpdate();
645 }
646
647 void AddVisitedLinks(const std::vector<uint64_t>& link_hashes) override {
648 add_count_ += link_hashes.size();
649 add_event_count_++;
650 NotifyUpdate();
651 }
652
653 void ResetVisitedLinks(bool invalidate_cached_hashes) override {
654 if (invalidate_cached_hashes)
655 completely_reset_event_count_++;
656 else
657 reset_event_count_++;
658 NotifyUpdate();
[email protected]c2134fb2013-01-23 04:28:52659 }
660
[email protected]3e90d4a2009-07-03 17:38:39661 int add_count() const { return add_count_; }
662 int add_event_count() const { return add_event_count_; }
663 int reset_event_count() const { return reset_event_count_; }
sathaf37203d2015-12-15 15:10:42664 int completely_reset_event_count() const {
665 return completely_reset_event_count_;
666 }
[email protected]c2134fb2013-01-23 04:28:52667 int new_table_count() const { return new_table_count_; }
[email protected]3e90d4a2009-07-03 17:38:39668
669 private:
670 int add_count_;
671 int add_event_count_;
672 int reset_event_count_;
sathaf37203d2015-12-15 15:10:42673 int completely_reset_event_count_;
[email protected]c2134fb2013-01-23 04:28:52674 int new_table_count_;
sammcaa222762016-09-21 07:30:42675
Ken Rockot4a16adb2019-12-17 07:31:42676 base::OnceClosure quit_closure_;
Julie Jeongeun Kim8ab180f72019-09-25 09:25:46677 mojo::ReceiverSet<mojom::VisitedLinkNotificationSink> receiver_;
[email protected]3e90d4a2009-07-03 17:38:39678};
679
[email protected]f3b1a082011-11-18 00:34:30680// Stub out as little as possible, borrowing from RenderProcessHost.
[email protected]b6a2f8de2012-01-31 17:28:49681class VisitRelayingRenderProcessHost : public MockRenderProcessHost {
[email protected]3e90d4a2009-07-03 17:38:39682 public:
[email protected]3d7474ff2011-07-27 17:47:37683 explicit VisitRelayingRenderProcessHost(
sammcaa222762016-09-21 07:30:42684 content::BrowserContext* browser_context,
685 VisitCountingContext* context)
Bo Liueb218ee2018-03-21 20:24:35686 : MockRenderProcessHost(browser_context) {
Ken Rockot4a16adb2019-12-17 07:31:42687 OverrideBinderForTesting(mojom::VisitedLinkNotificationSink::Name_,
688 base::BindRepeating(&VisitCountingContext::Bind,
689 base::Unretained(context)));
[email protected]3e90d4a2009-07-03 17:38:39690 }
Peter Boström09c01822021-09-20 22:43:27691
692 VisitRelayingRenderProcessHost(const VisitRelayingRenderProcessHost&) =
693 delete;
694 VisitRelayingRenderProcessHost& operator=(
695 const VisitRelayingRenderProcessHost&) = delete;
[email protected]3e90d4a2009-07-03 17:38:39696};
697
698class VisitedLinkRenderProcessHostFactory
[email protected]f3b1a082011-11-18 00:34:30699 : public content::RenderProcessHostFactory {
[email protected]3e90d4a2009-07-03 17:38:39700 public:
sammcaa222762016-09-21 07:30:42701 VisitedLinkRenderProcessHostFactory() : context_(new VisitCountingContext) {}
Peter Boström9f667c382021-10-01 20:09:31702
703 VisitedLinkRenderProcessHostFactory(
704 const VisitedLinkRenderProcessHostFactory&) = delete;
705 VisitedLinkRenderProcessHostFactory& operator=(
706 const VisitedLinkRenderProcessHostFactory&) = delete;
707
dcheng00ea022b2014-10-21 11:24:56708 content::RenderProcessHost* CreateRenderProcessHost(
Matt Falkenhagen24abf7822017-12-15 23:55:11709 content::BrowserContext* browser_context,
Lucas Furukawa Gadani0a70be92019-06-28 17:31:26710 content::SiteInstance* site_instance) override {
Dave Tapuska65a04872020-11-12 18:12:34711 auto rph = std::make_unique<VisitRelayingRenderProcessHost>(browser_context,
712 context_.get());
713 content::RenderProcessHost* result = rph.get();
714 processes_.push_back(std::move(rph));
715 return result;
[email protected]3e90d4a2009-07-03 17:38:39716 }
717
Jonathan Ross08ad2892023-03-14 20:51:33718 // RenderProcessHostImpl::OnProcessLaunched only notifies once the child
719 // process has launched. This is after RenderWidgetHost has been created. We
720 // will notify at the end of SetUp.
721 void NotifyProcessLaunced() {
722 for (auto& rph : processes_) {
723 creation_observer_->OnRenderProcessHostCreated(rph.get());
724 }
725 }
726
dan sinclair9b5e0272022-03-01 14:49:12727 void SetRenderProcessHostCreationObserver(
728 content::RenderProcessHostCreationObserver* observer) {
729 creation_observer_ = observer;
730 }
731
sammcaa222762016-09-21 07:30:42732 VisitCountingContext* context() { return context_.get(); }
733
Dave Tapuska65a04872020-11-12 18:12:34734 void DeleteRenderProcessHosts() { processes_.clear(); }
735
[email protected]3e90d4a2009-07-03 17:38:39736 private:
Arthur Sonzognie98d2142023-06-01 15:02:25737 raw_ptr<content::RenderProcessHostCreationObserver, DanglingUntriaged>
738 creation_observer_ = nullptr;
dan sinclair9b5e0272022-03-01 14:49:12739
Dave Tapuska65a04872020-11-12 18:12:34740 std::list<std::unique_ptr<VisitRelayingRenderProcessHost>> processes_;
sammcaa222762016-09-21 07:30:42741 std::unique_ptr<VisitCountingContext> context_;
[email protected]3e90d4a2009-07-03 17:38:39742};
743
[email protected]28a66e252013-01-25 07:54:02744class VisitedLinkEventsTest : public content::RenderViewHostTestHarness {
[email protected]3e90d4a2009-07-03 17:38:39745 public:
dcheng30a1b1542014-10-29 21:27:50746 void SetUp() override {
[email protected]9a46725f2012-10-24 18:25:48747 SetRenderProcessHostFactory(&vc_rph_factory_);
[email protected]4c3d9d62013-01-09 22:37:20748 content::RenderViewHostTestHarness::SetUp();
Jonathan Ross08ad2892023-03-14 20:51:33749 vc_rph_factory_.NotifyProcessLaunced();
[email protected]3e90d4a2009-07-03 17:38:39750 }
751
wkorman1c17345b2015-11-12 03:02:42752 void TearDown() override {
Robert Sesekffeae8e2019-11-26 17:10:15753 // Explicitly destroy the writer before proceeding with the rest
wkorman1c17345b2015-11-12 03:02:42754 // of teardown because it posts a task to close a file handle, and
755 // we need to make sure we've finished all file related work
756 // before our superclass sets about destroying the scoped temp
757 // directory.
Robert Sesekffeae8e2019-11-26 17:10:15758 writer_.reset();
Dave Tapuska65a04872020-11-12 18:12:34759 DeleteContents();
760 vc_rph_factory_.DeleteRenderProcessHosts();
wkorman1c17345b2015-11-12 03:02:42761 RenderViewHostTestHarness::TearDown();
762 }
763
Sylvain Defresne330d05c2019-08-07 12:36:37764 std::unique_ptr<content::BrowserContext> CreateBrowserContext() override {
765 auto context = std::make_unique<content::TestBrowserContext>();
Robert Sesekffeae8e2019-11-26 17:10:15766 CreateVisitedLinkWriter(context.get());
dan sinclair9b5e0272022-03-01 14:49:12767 vc_rph_factory_.SetRenderProcessHostCreationObserver(
768 static_cast<VisitedLinkEventListener*>(writer_->GetListener()));
[email protected]cc99c9f2013-07-15 12:26:09769 return context;
770 }
771
sammcaa222762016-09-21 07:30:42772 VisitCountingContext* context() { return vc_rph_factory_.context(); }
[email protected]3e90d4a2009-07-03 17:38:39773
Robert Sesekffeae8e2019-11-26 17:10:15774 VisitedLinkWriter* writer() const { return writer_.get(); }
[email protected]5016ee12012-10-26 23:56:31775
[email protected]3e90d4a2009-07-03 17:38:39776 protected:
Robert Sesekffeae8e2019-11-26 17:10:15777 void CreateVisitedLinkWriter(content::BrowserContext* browser_context) {
Peter Boström665b49d2021-04-05 19:29:58778 timer_ = std::make_unique<base::MockOneShotTimer>();
779 writer_ =
780 std::make_unique<VisitedLinkWriter>(browser_context, &delegate_, true);
Robert Sesekffeae8e2019-11-26 17:10:15781 static_cast<VisitedLinkEventListener*>(writer_->GetListener())
sammcaa222762016-09-21 07:30:42782 ->SetCoalesceTimerForTest(timer_.get());
Robert Sesekffeae8e2019-11-26 17:10:15783 writer_->Init();
sathaf37203d2015-12-15 15:10:42784 }
785
[email protected]3e90d4a2009-07-03 17:38:39786 VisitedLinkRenderProcessHostFactory vc_rph_factory_;
787
[email protected]4c3d9d62013-01-09 22:37:20788 TestVisitedLinkDelegate delegate_;
tzik57c66e32018-07-02 08:02:57789 std::unique_ptr<base::MockOneShotTimer> timer_;
Robert Sesekffeae8e2019-11-26 17:10:15790 std::unique_ptr<VisitedLinkWriter> writer_;
[email protected]3e90d4a2009-07-03 17:38:39791};
792
wkorman1c17345b2015-11-12 03:02:42793TEST_F(VisitedLinkEventsTest, Coalescence) {
sathaf37203d2015-12-15 15:10:42794 // Waiting complete rebuild the table.
Gabriel Charette01507a22017-09-27 21:30:08795 content::RunAllTasksUntilIdle();
sathaf37203d2015-12-15 15:10:42796
sathaf37203d2015-12-15 15:10:42797 // After rebuild table expect reset event.
798 EXPECT_EQ(1, context()->reset_event_count());
799
Robert Sesekffeae8e2019-11-26 17:10:15800 // add some URLs to writer.
[email protected]3e90d4a2009-07-03 17:38:39801 // Add a few URLs.
Robert Sesekffeae8e2019-11-26 17:10:15802 writer()->AddURL(GURL("http://acidtests.org/"));
803 writer()->AddURL(GURL("http://google.com/"));
804 writer()->AddURL(GURL("http://chromium.org/"));
[email protected]3e90d4a2009-07-03 17:38:39805 // Just for kicks, add a duplicate URL. This shouldn't increase the resulting
Robert Sesekffeae8e2019-11-26 17:10:15806 writer()->AddURL(GURL("http://acidtests.org/"));
sammcaa222762016-09-21 07:30:42807 ASSERT_TRUE(timer_->IsRunning());
808 timer_->Fire();
[email protected]3e90d4a2009-07-03 17:38:39809
sammcaa222762016-09-21 07:30:42810 context()->WaitForUpdate();
[email protected]3e90d4a2009-07-03 17:38:39811
812 // We now should have 3 entries added in 1 event.
[email protected]28a66e252013-01-25 07:54:02813 EXPECT_EQ(3, context()->add_count());
814 EXPECT_EQ(1, context()->add_event_count());
[email protected]3e90d4a2009-07-03 17:38:39815
816 // Test whether the coalescing continues by adding a few more URLs.
Robert Sesekffeae8e2019-11-26 17:10:15817 writer()->AddURL(GURL("http://google.com/chrome/"));
818 writer()->AddURL(GURL("http://webkit.org/"));
819 writer()->AddURL(GURL("http://acid3.acidtests.org/"));
[email protected]3e90d4a2009-07-03 17:38:39820
sammcaa222762016-09-21 07:30:42821 ASSERT_TRUE(timer_->IsRunning());
822 timer_->Fire();
823 context()->WaitForUpdate();
[email protected]3e90d4a2009-07-03 17:38:39824
825 // We should have 6 entries added in 2 events.
[email protected]28a66e252013-01-25 07:54:02826 EXPECT_EQ(6, context()->add_count());
827 EXPECT_EQ(2, context()->add_event_count());
[email protected]3e90d4a2009-07-03 17:38:39828
829 // Test whether duplicate entries produce add events.
Robert Sesekffeae8e2019-11-26 17:10:15830 writer()->AddURL(GURL("http://acidtests.org/"));
sammcaa222762016-09-21 07:30:42831 EXPECT_FALSE(timer_->IsRunning());
832 context()->WaitForNoUpdate();
[email protected]3e90d4a2009-07-03 17:38:39833
834 // We should have no change in results.
[email protected]28a66e252013-01-25 07:54:02835 EXPECT_EQ(6, context()->add_count());
836 EXPECT_EQ(2, context()->add_event_count());
[email protected]3e90d4a2009-07-03 17:38:39837
838 // Ensure that the coalescing does not resume after resetting.
Robert Sesekffeae8e2019-11-26 17:10:15839 writer()->AddURL(GURL("http://build.chromium.org/"));
sammcaa222762016-09-21 07:30:42840 EXPECT_TRUE(timer_->IsRunning());
Robert Sesekffeae8e2019-11-26 17:10:15841 writer()->DeleteAllURLs();
sammcaa222762016-09-21 07:30:42842 EXPECT_FALSE(timer_->IsRunning());
843 context()->WaitForNoUpdate();
[email protected]3e90d4a2009-07-03 17:38:39844
845 // We should have no change in results except for one new reset event.
[email protected]28a66e252013-01-25 07:54:02846 EXPECT_EQ(6, context()->add_count());
847 EXPECT_EQ(2, context()->add_event_count());
sathaf37203d2015-12-15 15:10:42848 EXPECT_EQ(2, context()->reset_event_count());
[email protected]3e90d4a2009-07-03 17:38:39849}
850
[email protected]7fa7dd52011-04-24 01:09:42851TEST_F(VisitedLinkEventsTest, Basics) {
Aaron Colwell40563522021-02-18 17:14:35852 RenderViewHostTester::For(rvh())->CreateTestRenderView();
[email protected]6e8d64642009-08-10 15:27:19853
sathaf37203d2015-12-15 15:10:42854 // Waiting complete rebuild the table.
Gabriel Charette01507a22017-09-27 21:30:08855 content::RunAllTasksUntilIdle();
sathaf37203d2015-12-15 15:10:42856
sathaf37203d2015-12-15 15:10:42857 // After rebuild table expect reset event.
858 EXPECT_EQ(1, context()->reset_event_count());
859
[email protected]3e90d4a2009-07-03 17:38:39860 // Add a few URLs.
Robert Sesekffeae8e2019-11-26 17:10:15861 writer()->AddURL(GURL("http://acidtests.org/"));
862 writer()->AddURL(GURL("http://google.com/"));
863 writer()->AddURL(GURL("http://chromium.org/"));
sammcaa222762016-09-21 07:30:42864 ASSERT_TRUE(timer_->IsRunning());
865 timer_->Fire();
866 context()->WaitForUpdate();
[email protected]3e90d4a2009-07-03 17:38:39867
868 // We now should have 1 add event.
[email protected]28a66e252013-01-25 07:54:02869 EXPECT_EQ(1, context()->add_event_count());
sathaf37203d2015-12-15 15:10:42870 EXPECT_EQ(1, context()->reset_event_count());
[email protected]3e90d4a2009-07-03 17:38:39871
Robert Sesekffeae8e2019-11-26 17:10:15872 writer()->DeleteAllURLs();
[email protected]3e90d4a2009-07-03 17:38:39873
sammcaa222762016-09-21 07:30:42874 EXPECT_FALSE(timer_->IsRunning());
875 context()->WaitForNoUpdate();
[email protected]3e90d4a2009-07-03 17:38:39876
877 // We should have no change in add results, plus one new reset event.
[email protected]28a66e252013-01-25 07:54:02878 EXPECT_EQ(1, context()->add_event_count());
sathaf37203d2015-12-15 15:10:42879 EXPECT_EQ(2, context()->reset_event_count());
[email protected]3e90d4a2009-07-03 17:38:39880}
881
[email protected]7fa7dd52011-04-24 01:09:42882TEST_F(VisitedLinkEventsTest, TabVisibility) {
Aaron Colwell40563522021-02-18 17:14:35883 RenderViewHostTester::For(rvh())->CreateTestRenderView();
[email protected]3e90d4a2009-07-03 17:38:39884
sathaf37203d2015-12-15 15:10:42885 // Waiting complete rebuild the table.
Gabriel Charette01507a22017-09-27 21:30:08886 content::RunAllTasksUntilIdle();
sathaf37203d2015-12-15 15:10:42887
sathaf37203d2015-12-15 15:10:42888 // After rebuild table expect reset event.
889 EXPECT_EQ(1, context()->reset_event_count());
890
[email protected]3e90d4a2009-07-03 17:38:39891 // Simulate tab becoming inactive.
bsepf3b00fa52017-02-11 00:06:38892 RenderViewHostTester::For(rvh())->SimulateWasHidden();
[email protected]3e90d4a2009-07-03 17:38:39893
894 // Add a few URLs.
Robert Sesekffeae8e2019-11-26 17:10:15895 writer()->AddURL(GURL("http://acidtests.org/"));
896 writer()->AddURL(GURL("http://google.com/"));
897 writer()->AddURL(GURL("http://chromium.org/"));
sammcaa222762016-09-21 07:30:42898 ASSERT_TRUE(timer_->IsRunning());
899 timer_->Fire();
900 context()->WaitForNoUpdate();
[email protected]3e90d4a2009-07-03 17:38:39901
902 // We shouldn't have any events.
[email protected]28a66e252013-01-25 07:54:02903 EXPECT_EQ(0, context()->add_event_count());
sathaf37203d2015-12-15 15:10:42904 EXPECT_EQ(1, context()->reset_event_count());
[email protected]3e90d4a2009-07-03 17:38:39905
906 // Simulate the tab becoming active.
bsepf3b00fa52017-02-11 00:06:38907 RenderViewHostTester::For(rvh())->SimulateWasShown();
sammcaa222762016-09-21 07:30:42908 context()->WaitForUpdate();
[email protected]3e90d4a2009-07-03 17:38:39909
910 // We should now have 3 add events, still no reset events.
[email protected]28a66e252013-01-25 07:54:02911 EXPECT_EQ(1, context()->add_event_count());
sathaf37203d2015-12-15 15:10:42912 EXPECT_EQ(1, context()->reset_event_count());
[email protected]3e90d4a2009-07-03 17:38:39913
914 // Deactivate the tab again.
bsepf3b00fa52017-02-11 00:06:38915 RenderViewHostTester::For(rvh())->SimulateWasHidden();
[email protected]3e90d4a2009-07-03 17:38:39916
917 // Add a bunch of URLs (over 50) to exhaust the link event buffer.
918 for (int i = 0; i < 100; i++)
Robert Sesekffeae8e2019-11-26 17:10:15919 writer()->AddURL(TestURL(i));
[email protected]3e90d4a2009-07-03 17:38:39920
sammcaa222762016-09-21 07:30:42921 ASSERT_TRUE(timer_->IsRunning());
922 timer_->Fire();
923 context()->WaitForNoUpdate();
[email protected]3e90d4a2009-07-03 17:38:39924
925 // Again, no change in events until tab is active.
[email protected]28a66e252013-01-25 07:54:02926 EXPECT_EQ(1, context()->add_event_count());
sathaf37203d2015-12-15 15:10:42927 EXPECT_EQ(1, context()->reset_event_count());
[email protected]3e90d4a2009-07-03 17:38:39928
929 // Activate the tab.
bsepf3b00fa52017-02-11 00:06:38930 RenderViewHostTester::For(rvh())->SimulateWasShown();
sammcaa222762016-09-21 07:30:42931 EXPECT_FALSE(timer_->IsRunning());
932 context()->WaitForUpdate();
[email protected]3e90d4a2009-07-03 17:38:39933
934 // We should have only one more reset event.
[email protected]28a66e252013-01-25 07:54:02935 EXPECT_EQ(1, context()->add_event_count());
sathaf37203d2015-12-15 15:10:42936 EXPECT_EQ(2, context()->reset_event_count());
[email protected]3e90d4a2009-07-03 17:38:39937}
[email protected]1f371fa2013-01-23 00:35:14938
[email protected]c2134fb2013-01-23 04:28:52939// Tests that VisitedLink ignores renderer process creation notification for a
[email protected]28a66e252013-01-25 07:54:02940// different context.
[email protected]c2134fb2013-01-23 04:28:52941TEST_F(VisitedLinkEventsTest, IgnoreRendererCreationFromDifferentContext) {
sammcaa222762016-09-21 07:30:42942 content::TestBrowserContext different_context;
943 VisitCountingContext counting_context;
dan sinclair9b5e0272022-03-01 14:49:12944 // There are two render process hosts in play with this test. The primary
945 // one is where the observer callback (done below) will be received
946 // and don't need an observer for the other process host as it isn't
947 // needed in the test.
sammcaa222762016-09-21 07:30:42948 VisitRelayingRenderProcessHost different_process_host(&different_context,
949 &counting_context);
[email protected]c2134fb2013-01-23 04:28:52950
Lukasz Anforowicz2b2699732018-04-12 18:49:10951 size_t old_size = counting_context.binding().size();
dan sinclair9b5e0272022-03-01 14:49:12952
953 static_cast<VisitedLinkEventListener*>(writer()->GetListener())
954 ->OnRenderProcessHostCreated(&different_process_host);
Lukasz Anforowicz2b2699732018-04-12 18:49:10955 size_t new_size = counting_context.binding().size();
956 EXPECT_EQ(old_size, new_size);
[email protected]c2134fb2013-01-23 04:28:52957}
958
sathaf37203d2015-12-15 15:10:42959class VisitedLinkCompletelyResetEventTest : public VisitedLinkEventsTest {
960 public:
Sylvain Defresne330d05c2019-08-07 12:36:37961 std::unique_ptr<content::BrowserContext> CreateBrowserContext() override {
962 auto context = std::make_unique<content::TestBrowserContext>();
963 CreateVisitedLinkFile(context.get());
Robert Sesekffeae8e2019-11-26 17:10:15964 CreateVisitedLinkWriter(context.get());
dan sinclair9b5e0272022-03-01 14:49:12965 vc_rph_factory_.SetRenderProcessHostCreationObserver(
966 static_cast<VisitedLinkEventListener*>(writer_->GetListener()));
sathaf37203d2015-12-15 15:10:42967 return context;
968 }
969
970 void CreateVisitedLinkFile(content::BrowserContext* browser_context) {
971 base::FilePath visited_file =
972 browser_context->GetPath().Append(FILE_PATH_LITERAL("Visited Links"));
Robert Sesekffeae8e2019-11-26 17:10:15973 std::unique_ptr<VisitedLinkWriter> writer(
974 new VisitedLinkWriter(new TrackingVisitedLinkEventListener(),
sathaf37203d2015-12-15 15:10:42975 &delegate_, true, true, visited_file, 0));
Robert Sesekffeae8e2019-11-26 17:10:15976 writer->Init();
sathaf37203d2015-12-15 15:10:42977 // Waiting complete create the table.
Gabriel Charette01507a22017-09-27 21:30:08978 content::RunAllTasksUntilIdle();
sathaf37203d2015-12-15 15:10:42979
Robert Sesekffeae8e2019-11-26 17:10:15980 writer.reset();
sathaf37203d2015-12-15 15:10:42981 // Wait for all pending file I/O to be completed.
Gabriel Charette01507a22017-09-27 21:30:08982 content::RunAllTasksUntilIdle();
sathaf37203d2015-12-15 15:10:42983 }
984};
985
986TEST_F(VisitedLinkCompletelyResetEventTest, LoadTable) {
987 // Waiting complete loading the table.
Gabriel Charette01507a22017-09-27 21:30:08988 content::RunAllTasksUntilIdle();
sathaf37203d2015-12-15 15:10:42989
sammcaa222762016-09-21 07:30:42990 context()->binding().FlushForTesting();
sathaf37203d2015-12-15 15:10:42991
992 // After load table expect completely reset event.
993 EXPECT_EQ(1, context()->completely_reset_event_count());
994}
995
[email protected]ab3eaeed2013-05-17 00:18:44996} // namespace visitedlink