blob: e12a533f11de63621404408b41c7c7b22b3ef82d [file] [log] [blame]
[email protected]02798a982012-01-27 00:45:331// Copyright (c) 2012 The Chromium Authors. All rights reserved.
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
initial.commit09911bf2008-07-26 23:55:295#include <cstdio>
[email protected]c38831a12011-10-28 12:44:496#include <string>
7#include <vector>
initial.commit09911bf2008-07-26 23:55:298
initial.commit09911bf2008-07-26 23:55:299#include "base/file_util.h"
[email protected]c38831a12011-10-28 12:44:4910#include "base/message_loop.h"
initial.commit09911bf2008-07-26 23:55:2911#include "base/path_service.h"
[email protected]c2c998c2009-01-27 19:08:3912#include "base/process_util.h"
initial.commit09911bf2008-07-26 23:55:2913#include "base/shared_memory.h"
14#include "base/string_util.h"
[email protected]8ecad5e2010-12-02 21:18:3315#include "chrome/browser/visitedlink/visitedlink_event_listener.h"
[email protected]c38831a12011-10-28 12:44:4916#include "chrome/browser/visitedlink/visitedlink_master.h"
[email protected]3e90d4a2009-07-03 17:38:3917#include "chrome/common/render_messages.h"
initial.commit09911bf2008-07-26 23:55:2918#include "chrome/renderer/visitedlink_slave.h"
[email protected]93ab5932011-09-14 07:38:1719#include "chrome/test/base/chrome_render_view_host_test_harness.h"
[email protected]a4ff9eae2011-08-01 19:58:1620#include "chrome/test/base/testing_profile.h"
[email protected]b6a2f8de2012-01-31 17:28:4921#include "content/browser/renderer_host/mock_render_process_host.h"
[email protected]ad50def52011-10-19 23:17:0722#include "content/public/browser/notification_service.h"
[email protected]0d6e9bd2011-10-18 04:29:1623#include "content/public/browser/notification_types.h"
[email protected]c38831a12011-10-28 12:44:4924#include "content/test/test_browser_thread.h"
[email protected]c0257382012-03-12 20:15:3425#include "content/test/test_renderer_host.h"
initial.commit09911bf2008-07-26 23:55:2926#include "googleurl/src/gurl.h"
27#include "testing/gtest/include/gtest/gtest.h"
28
[email protected]631bb742011-11-02 11:29:3929using content::BrowserThread;
[email protected]c0257382012-03-12 20:15:3430using content::RenderViewHostTester;
[email protected]631bb742011-11-02 11:29:3931
initial.commit09911bf2008-07-26 23:55:2932namespace {
33
34// a nice long URL that we can append numbers to to get new URLs
35const char g_test_prefix[] =
36 "http://www.google.com/products/foo/index.html?id=45028640526508376&seq=";
37const int g_test_count = 1000;
38
39// Returns a test URL for index |i|
40GURL TestURL(int i) {
41 return GURL(StringPrintf("%s%d", g_test_prefix, i));
42}
43
initial.commit09911bf2008-07-26 23:55:2944std::vector<VisitedLinkSlave*> g_slaves;
45
[email protected]3e90d4a2009-07-03 17:38:3946} // namespace
47
48class TrackingVisitedLinkEventListener : public VisitedLinkMaster::Listener {
49 public:
50 TrackingVisitedLinkEventListener()
51 : reset_count_(0),
52 add_count_(0) {}
53
54 virtual void NewTable(base::SharedMemory* table) {
55 if (table) {
56 for (std::vector<VisitedLinkSlave>::size_type i = 0;
57 i < g_slaves.size(); i++) {
58 base::SharedMemoryHandle new_handle = base::SharedMemory::NULLHandle();
59 table->ShareToProcess(base::GetCurrentProcessHandle(), &new_handle);
[email protected]8d97ade2011-04-14 18:17:0860 g_slaves[i]->OnUpdateVisitedLinks(new_handle);
[email protected]3e90d4a2009-07-03 17:38:3961 }
initial.commit09911bf2008-07-26 23:55:2962 }
63 }
[email protected]3e90d4a2009-07-03 17:38:3964 virtual void Add(VisitedLinkCommon::Fingerprint) { add_count_++; }
65 virtual void Reset() { reset_count_++; }
initial.commit09911bf2008-07-26 23:55:2966
[email protected]3e90d4a2009-07-03 17:38:3967 void SetUp() {
68 reset_count_ = 0;
69 add_count_ = 0;
70 }
71
72 int reset_count() const { return reset_count_; }
73 int add_count() const { return add_count_; }
74
75 private:
76 int reset_count_;
77 int add_count_;
78};
[email protected]c2c998c2009-01-27 19:08:3979
[email protected]583844c2011-08-27 00:38:3580class VisitedLinkTest : public testing::Test {
initial.commit09911bf2008-07-26 23:55:2981 protected:
[email protected]6fad2632009-11-02 05:59:3782 VisitedLinkTest()
[email protected]0c7d74f2010-10-11 11:55:2683 : ui_thread_(BrowserThread::UI, &message_loop_),
84 file_thread_(BrowserThread::FILE, &message_loop_) {}
initial.commit09911bf2008-07-26 23:55:2985 // Initialize the history system. This should be called before InitVisited().
86 bool InitHistory() {
87 history_service_ = new HistoryService;
[email protected]f7011fcb2009-01-28 21:54:3288 return history_service_->Init(history_dir_, NULL);
initial.commit09911bf2008-07-26 23:55:2989 }
90
91 // Initializes the visited link objects. Pass in the size that you want a
92 // freshly created table to be. 0 means use the default.
93 //
94 // |suppress_rebuild| is set when we're not testing rebuilding, see
95 // the VisitedLinkMaster constructor.
96 bool InitVisited(int initial_size, bool suppress_rebuild) {
97 // Initialize the visited link system.
[email protected]6fad2632009-11-02 05:59:3798 master_.reset(new VisitedLinkMaster(&listener_, history_service_,
[email protected]3e90d4a2009-07-03 17:38:3999 suppress_rebuild, visited_file_,
100 initial_size));
initial.commit09911bf2008-07-26 23:55:29101 return master_->Init();
102 }
103
104 // May be called multiple times (some tests will do this to clear things,
105 // and TearDown will do this to make sure eveything is shiny before quitting.
106 void ClearDB() {
107 if (master_.get())
108 master_.reset(NULL);
109
110 if (history_service_.get()) {
[email protected]1cb1a242011-12-10 18:36:51111 history_service_->SetOnBackendDestroyTask(MessageLoop::QuitClosure());
initial.commit09911bf2008-07-26 23:55:29112 history_service_->Cleanup();
113 history_service_ = NULL;
114
115 // Wait for the backend class to terminate before deleting the files and
116 // moving to the next test. Note: if this never terminates, somebody is
117 // probably leaking a reference to the history backend, so it never calls
118 // our destroy task.
119 MessageLoop::current()->Run();
120 }
[email protected]3189013e2012-01-19 04:11:57121
122 // Wait for all pending file I/O to be completed.
123 BrowserThread::GetBlockingPool()->FlushForTesting();
initial.commit09911bf2008-07-26 23:55:29124 }
125
126 // Loads the database from disk and makes sure that the same URLs are present
127 // as were generated by TestIO_Create(). This also checks the URLs with a
128 // slave to make sure it reads the data properly.
129 void Reload() {
130 // Clean up after our caller, who may have left the database open.
131 ClearDB();
132
133 ASSERT_TRUE(InitHistory());
134 ASSERT_TRUE(InitVisited(0, true));
135 master_->DebugValidate();
136
137 // check that the table has the proper number of entries
138 int used_count = master_->GetUsedCount();
139 ASSERT_EQ(used_count, g_test_count);
140
141 // Create a slave database.
142 VisitedLinkSlave slave;
[email protected]76aac1e2009-03-16 16:45:36143 base::SharedMemoryHandle new_handle = base::SharedMemory::NULLHandle();
[email protected]9610ef242009-11-18 02:41:26144 master_->shared_memory()->ShareToProcess(
145 base::GetCurrentProcessHandle(), &new_handle);
[email protected]8d97ade2011-04-14 18:17:08146 slave.OnUpdateVisitedLinks(new_handle);
initial.commit09911bf2008-07-26 23:55:29147 g_slaves.push_back(&slave);
148
149 bool found;
150 for (int i = 0; i < g_test_count; i++) {
151 GURL cur = TestURL(i);
152 found = master_->IsVisited(cur);
153 EXPECT_TRUE(found) << "URL " << i << "not found in master.";
154
155 found = slave.IsVisited(cur);
156 EXPECT_TRUE(found) << "URL " << i << "not found in slave.";
157 }
158
159 // test some random URL so we know that it returns false sometimes too
160 found = master_->IsVisited(GURL("http://unfound.site/"));
161 ASSERT_FALSE(found);
162 found = slave.IsVisited(GURL("http://unfound.site/"));
163 ASSERT_FALSE(found);
164
165 master_->DebugValidate();
166
167 g_slaves.clear();
168 }
169
170 // testing::Test
171 virtual void SetUp() {
[email protected]f708ed12010-09-23 12:18:34172 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
173
174 history_dir_ = temp_dir_.path().AppendASCII("VisitedLinkTest");
175 ASSERT_TRUE(file_util::CreateDirectory(history_dir_));
initial.commit09911bf2008-07-26 23:55:29176
[email protected]c2c998c2009-01-27 19:08:39177 visited_file_ = history_dir_.Append(FILE_PATH_LITERAL("VisitedLinks"));
[email protected]3e90d4a2009-07-03 17:38:39178 listener_.SetUp();
initial.commit09911bf2008-07-26 23:55:29179 }
180
181 virtual void TearDown() {
182 ClearDB();
initial.commit09911bf2008-07-26 23:55:29183 }
[email protected]f0a51fb52009-03-05 12:46:38184
[email protected]f708ed12010-09-23 12:18:34185 ScopedTempDir temp_dir_;
186
[email protected]ab820df2008-08-26 05:55:10187 MessageLoop message_loop_;
[email protected]c38831a12011-10-28 12:44:49188 content::TestBrowserThread ui_thread_;
189 content::TestBrowserThread file_thread_;
initial.commit09911bf2008-07-26 23:55:29190
191 // Filenames for the services;
[email protected]c2c998c2009-01-27 19:08:39192 FilePath history_dir_;
193 FilePath visited_file_;
initial.commit09911bf2008-07-26 23:55:29194
195 scoped_ptr<VisitedLinkMaster> master_;
196 scoped_refptr<HistoryService> history_service_;
[email protected]3e90d4a2009-07-03 17:38:39197 TrackingVisitedLinkEventListener listener_;
initial.commit09911bf2008-07-26 23:55:29198};
199
initial.commit09911bf2008-07-26 23:55:29200// This test creates and reads some databases to make sure the data is
201// preserved throughout those operations.
202TEST_F(VisitedLinkTest, DatabaseIO) {
203 ASSERT_TRUE(InitHistory());
204 ASSERT_TRUE(InitVisited(0, true));
205
206 for (int i = 0; i < g_test_count; i++)
207 master_->AddURL(TestURL(i));
208
209 // Test that the database was written properly
210 Reload();
211}
212
213// Checks that we can delete things properly when there are collisions.
214TEST_F(VisitedLinkTest, Delete) {
215 static const int32 kInitialSize = 17;
216 ASSERT_TRUE(InitHistory());
217 ASSERT_TRUE(InitVisited(kInitialSize, true));
218
219 // Add a cluster from 14-17 wrapping around to 0. These will all hash to the
220 // same value.
[email protected]c2c998c2009-01-27 19:08:39221 const VisitedLinkCommon::Fingerprint kFingerprint0 = kInitialSize * 0 + 14;
222 const VisitedLinkCommon::Fingerprint kFingerprint1 = kInitialSize * 1 + 14;
223 const VisitedLinkCommon::Fingerprint kFingerprint2 = kInitialSize * 2 + 14;
224 const VisitedLinkCommon::Fingerprint kFingerprint3 = kInitialSize * 3 + 14;
225 const VisitedLinkCommon::Fingerprint kFingerprint4 = kInitialSize * 4 + 14;
[email protected]f8c42c92009-07-04 17:22:08226 master_->AddFingerprint(kFingerprint0, false); // @14
227 master_->AddFingerprint(kFingerprint1, false); // @15
228 master_->AddFingerprint(kFingerprint2, false); // @16
229 master_->AddFingerprint(kFingerprint3, false); // @0
230 master_->AddFingerprint(kFingerprint4, false); // @1
initial.commit09911bf2008-07-26 23:55:29231
232 // Deleting 14 should move the next value up one slot (we do not specify an
233 // order).
234 EXPECT_EQ(kFingerprint3, master_->hash_table_[0]);
235 master_->DeleteFingerprint(kFingerprint3, false);
[email protected]c2c998c2009-01-27 19:08:39236 VisitedLinkCommon::Fingerprint zero_fingerprint = 0;
237 EXPECT_EQ(zero_fingerprint, master_->hash_table_[1]);
238 EXPECT_NE(zero_fingerprint, master_->hash_table_[0]);
initial.commit09911bf2008-07-26 23:55:29239
240 // Deleting the other four should leave the table empty.
241 master_->DeleteFingerprint(kFingerprint0, false);
242 master_->DeleteFingerprint(kFingerprint1, false);
243 master_->DeleteFingerprint(kFingerprint2, false);
244 master_->DeleteFingerprint(kFingerprint4, false);
245
246 EXPECT_EQ(0, master_->used_items_);
247 for (int i = 0; i < kInitialSize; i++)
[email protected]c2c998c2009-01-27 19:08:39248 EXPECT_EQ(zero_fingerprint, master_->hash_table_[i]) <<
249 "Hash table has values in it.";
initial.commit09911bf2008-07-26 23:55:29250}
251
252// When we delete more than kBigDeleteThreshold we trigger different behavior
253// where the entire file is rewritten.
254TEST_F(VisitedLinkTest, BigDelete) {
255 ASSERT_TRUE(InitHistory());
256 ASSERT_TRUE(InitVisited(16381, true));
257
258 // Add the base set of URLs that won't be deleted.
259 // Reload() will test for these.
260 for (int32 i = 0; i < g_test_count; i++)
261 master_->AddURL(TestURL(i));
262
263 // Add more URLs than necessary to trigger this case.
264 const int kTestDeleteCount = VisitedLinkMaster::kBigDeleteThreshold + 2;
265 std::set<GURL> urls_to_delete;
266 for (int32 i = g_test_count; i < g_test_count + kTestDeleteCount; i++) {
267 GURL url(TestURL(i));
268 master_->AddURL(url);
269 urls_to_delete.insert(url);
270 }
271
272 master_->DeleteURLs(urls_to_delete);
273 master_->DebugValidate();
274
275 Reload();
276}
277
278TEST_F(VisitedLinkTest, DeleteAll) {
279 ASSERT_TRUE(InitHistory());
280 ASSERT_TRUE(InitVisited(0, true));
281
282 {
283 VisitedLinkSlave slave;
[email protected]76aac1e2009-03-16 16:45:36284 base::SharedMemoryHandle new_handle = base::SharedMemory::NULLHandle();
[email protected]9610ef242009-11-18 02:41:26285 master_->shared_memory()->ShareToProcess(
286 base::GetCurrentProcessHandle(), &new_handle);
[email protected]8d97ade2011-04-14 18:17:08287 slave.OnUpdateVisitedLinks(new_handle);
initial.commit09911bf2008-07-26 23:55:29288 g_slaves.push_back(&slave);
289
290 // Add the test URLs.
291 for (int i = 0; i < g_test_count; i++) {
292 master_->AddURL(TestURL(i));
293 ASSERT_EQ(i + 1, master_->GetUsedCount());
294 }
295 master_->DebugValidate();
296
297 // Make sure the slave picked up the adds.
298 for (int i = 0; i < g_test_count; i++)
299 EXPECT_TRUE(slave.IsVisited(TestURL(i)));
300
301 // Clear the table and make sure the slave picked it up.
302 master_->DeleteAllURLs();
303 EXPECT_EQ(0, master_->GetUsedCount());
304 for (int i = 0; i < g_test_count; i++) {
305 EXPECT_FALSE(master_->IsVisited(TestURL(i)));
306 EXPECT_FALSE(slave.IsVisited(TestURL(i)));
307 }
308
309 // Close the database.
310 g_slaves.clear();
311 ClearDB();
312 }
313
314 // Reopen and validate.
315 ASSERT_TRUE(InitHistory());
316 ASSERT_TRUE(InitVisited(0, true));
317 master_->DebugValidate();
318 EXPECT_EQ(0, master_->GetUsedCount());
319 for (int i = 0; i < g_test_count; i++)
320 EXPECT_FALSE(master_->IsVisited(TestURL(i)));
321}
322
323// This tests that the master correctly resizes its tables when it gets too
324// full, notifies its slaves of the change, and updates the disk.
325TEST_F(VisitedLinkTest, Resizing) {
326 // Create a very small database.
327 const int32 initial_size = 17;
328 ASSERT_TRUE(InitHistory());
329 ASSERT_TRUE(InitVisited(initial_size, true));
330
331 // ...and a slave
332 VisitedLinkSlave slave;
[email protected]76aac1e2009-03-16 16:45:36333 base::SharedMemoryHandle new_handle = base::SharedMemory::NULLHandle();
[email protected]9610ef242009-11-18 02:41:26334 master_->shared_memory()->ShareToProcess(
335 base::GetCurrentProcessHandle(), &new_handle);
[email protected]8d97ade2011-04-14 18:17:08336 slave.OnUpdateVisitedLinks(new_handle);
initial.commit09911bf2008-07-26 23:55:29337 g_slaves.push_back(&slave);
338
339 int32 used_count = master_->GetUsedCount();
340 ASSERT_EQ(used_count, 0);
341
342 for (int i = 0; i < g_test_count; i++) {
343 master_->AddURL(TestURL(i));
344 used_count = master_->GetUsedCount();
345 ASSERT_EQ(i + 1, used_count);
346 }
347
348 // Verify that the table got resized sufficiently.
349 int32 table_size;
350 VisitedLinkCommon::Fingerprint* table;
351 master_->GetUsageStatistics(&table_size, &table);
352 used_count = master_->GetUsedCount();
353 ASSERT_GT(table_size, used_count);
354 ASSERT_EQ(used_count, g_test_count) <<
355 "table count doesn't match the # of things we added";
356
357 // Verify that the slave got the resize message and has the same
358 // table information.
359 int32 child_table_size;
360 VisitedLinkCommon::Fingerprint* child_table;
361 slave.GetUsageStatistics(&child_table_size, &child_table);
362 ASSERT_EQ(table_size, child_table_size);
363 for (int32 i = 0; i < table_size; i++) {
364 ASSERT_EQ(table[i], child_table[i]);
365 }
366
367 master_->DebugValidate();
368 g_slaves.clear();
369
370 // This tests that the file is written correctly by reading it in using
371 // a new database.
372 Reload();
373}
374
375// Tests that if the database doesn't exist, it will be rebuilt from history.
376TEST_F(VisitedLinkTest, Rebuild) {
377 ASSERT_TRUE(InitHistory());
378
379 // Add half of our URLs to history. This needs to be done before we
380 // initialize the visited link DB.
381 int history_count = g_test_count / 2;
382 for (int i = 0; i < history_count; i++)
[email protected]5989f1a2010-08-21 02:21:11383 history_service_->AddPage(TestURL(i), history::SOURCE_BROWSED);
initial.commit09911bf2008-07-26 23:55:29384
385 // Initialize the visited link DB. Since the visited links file doesn't exist
386 // and we don't suppress history rebuilding, this will load from history.
387 ASSERT_TRUE(InitVisited(0, false));
388
389 // While the table is rebuilding, add the rest of the URLs to the visited
390 // link system. This isn't guaranteed to happen during the rebuild, so we
391 // can't be 100% sure we're testing the right thing, but in practice is.
392 // All the adds above will generally take some time queuing up on the
393 // history thread, and it will take a while to catch up to actually
394 // processing the rebuild that has queued behind it. We will generally
395 // finish adding all of the URLs before it has even found the first URL.
396 for (int i = history_count; i < g_test_count; i++)
397 master_->AddURL(TestURL(i));
398
399 // Add one more and then delete it.
400 master_->AddURL(TestURL(g_test_count));
401 std::set<GURL> deleted_urls;
402 deleted_urls.insert(TestURL(g_test_count));
403 master_->DeleteURLs(deleted_urls);
404
405 // Wait for the rebuild to complete. The task will terminate the message
406 // loop when the rebuild is done. There's no chance that the rebuild will
407 // complete before we set the task because the rebuild completion message
408 // is posted to the message loop; until we Run() it, rebuild can not
409 // complete.
[email protected]1cb1a242011-12-10 18:36:51410 master_->set_rebuild_complete_task(MessageLoop::QuitClosure());
initial.commit09911bf2008-07-26 23:55:29411 MessageLoop::current()->Run();
412
413 // Test that all URLs were written to the database properly.
414 Reload();
415
416 // Make sure the extra one was *not* written (Reload won't test this).
417 EXPECT_FALSE(master_->IsVisited(TestURL(g_test_count)));
418}
[email protected]3e90d4a2009-07-03 17:38:39419
[email protected]aed132ed2009-08-19 22:44:12420// Test that importing a large number of URLs will work
421TEST_F(VisitedLinkTest, BigImport) {
422 ASSERT_TRUE(InitHistory());
423 ASSERT_TRUE(InitVisited(0, false));
424
425 // Before the table rebuilds, add a large number of URLs
426 int total_count = VisitedLinkMaster::kDefaultTableSize + 10;
427 for (int i = 0; i < total_count; i++)
428 master_->AddURL(TestURL(i));
429
430 // Wait for the rebuild to complete.
[email protected]1cb1a242011-12-10 18:36:51431 master_->set_rebuild_complete_task(MessageLoop::QuitClosure());
[email protected]aed132ed2009-08-19 22:44:12432 MessageLoop::current()->Run();
433
434 // Ensure that the right number of URLs are present
435 int used_count = master_->GetUsedCount();
436 ASSERT_EQ(used_count, total_count);
437}
438
[email protected]3e90d4a2009-07-03 17:38:39439TEST_F(VisitedLinkTest, Listener) {
440 ASSERT_TRUE(InitHistory());
441 ASSERT_TRUE(InitVisited(0, true));
442
443 // Add test URLs.
444 for (int i = 0; i < g_test_count; i++) {
445 master_->AddURL(TestURL(i));
446 ASSERT_EQ(i + 1, master_->GetUsedCount());
447 }
448
449 std::set<GURL> deleted_urls;
450 deleted_urls.insert(TestURL(0));
451 // Delete an URL.
452 master_->DeleteURLs(deleted_urls);
453 // ... and all of the remaining ones.
454 master_->DeleteAllURLs();
455
456 // Verify that VisitedLinkMaster::Listener::Add was called for each added URL.
457 EXPECT_EQ(g_test_count, listener_.add_count());
458 // Verify that VisitedLinkMaster::Listener::Reset was called both when one and
459 // all URLs are deleted.
460 EXPECT_EQ(2, listener_.reset_count());
461}
462
463class VisitCountingProfile : public TestingProfile {
464 public:
[email protected]2d66488c2011-10-14 21:10:00465 VisitCountingProfile()
[email protected]3e90d4a2009-07-03 17:38:39466 : add_count_(0),
467 add_event_count_(0),
468 reset_event_count_(0),
[email protected]2d66488c2011-10-14 21:10:00469 event_listener_(ALLOW_THIS_IN_INITIALIZER_LIST(
470 new VisitedLinkEventListener(this))) {}
[email protected]3e90d4a2009-07-03 17:38:39471
472 virtual VisitedLinkMaster* GetVisitedLinkMaster() {
473 if (!visited_link_master_.get()) {
[email protected]2d66488c2011-10-14 21:10:00474 visited_link_master_.reset(
475 new VisitedLinkMaster(event_listener_.get(), this));
[email protected]3e90d4a2009-07-03 17:38:39476 visited_link_master_->Init();
477 }
478 return visited_link_master_.get();
479 }
480
481 void CountAddEvent(int by) {
482 add_count_ += by;
483 add_event_count_++;
484 }
485
486 void CountResetEvent() {
487 reset_event_count_++;
488 }
489
490 VisitedLinkMaster* master() const { return visited_link_master_.get(); }
491 int add_count() const { return add_count_; }
492 int add_event_count() const { return add_event_count_; }
493 int reset_event_count() const { return reset_event_count_; }
494
495 private:
496 int add_count_;
497 int add_event_count_;
498 int reset_event_count_;
[email protected]2d66488c2011-10-14 21:10:00499 scoped_ptr<VisitedLinkEventListener> event_listener_;
[email protected]3e90d4a2009-07-03 17:38:39500 scoped_ptr<VisitedLinkMaster> visited_link_master_;
501};
502
[email protected]f3b1a082011-11-18 00:34:30503// Stub out as little as possible, borrowing from RenderProcessHost.
[email protected]b6a2f8de2012-01-31 17:28:49504class VisitRelayingRenderProcessHost : public MockRenderProcessHost {
[email protected]3e90d4a2009-07-03 17:38:39505 public:
[email protected]3d7474ff2011-07-27 17:47:37506 explicit VisitRelayingRenderProcessHost(
507 content::BrowserContext* browser_context)
[email protected]b6a2f8de2012-01-31 17:28:49508 : MockRenderProcessHost(browser_context), widgets_(0) {
[email protected]ad50def52011-10-19 23:17:07509 content::NotificationService::current()->Notify(
[email protected]432115822011-07-10 15:52:27510 content::NOTIFICATION_RENDERER_PROCESS_CREATED,
[email protected]6c2381d2011-10-19 02:52:53511 content::Source<RenderProcessHost>(this),
[email protected]ad50def52011-10-19 23:17:07512 content::NotificationService::NoDetails());
[email protected]3e90d4a2009-07-03 17:38:39513 }
514 virtual ~VisitRelayingRenderProcessHost() {
[email protected]ad50def52011-10-19 23:17:07515 content::NotificationService::current()->Notify(
[email protected]432115822011-07-10 15:52:27516 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED,
[email protected]f3b1a082011-11-18 00:34:30517 content::Source<content::RenderProcessHost>(this),
[email protected]ad50def52011-10-19 23:17:07518 content::NotificationService::NoDetails());
[email protected]3e90d4a2009-07-03 17:38:39519 }
520
[email protected]b6a2f8de2012-01-31 17:28:49521 virtual void WidgetRestored() OVERRIDE { widgets_++; }
522 virtual void WidgetHidden() OVERRIDE { widgets_--; }
523 virtual int VisibleWidgetCount() const OVERRIDE { return widgets_; }
[email protected]3e90d4a2009-07-03 17:38:39524
[email protected]b6a2f8de2012-01-31 17:28:49525 virtual bool Send(IPC::Message* msg) OVERRIDE {
[email protected]3e90d4a2009-07-03 17:38:39526 VisitCountingProfile* counting_profile =
[email protected]9b62ecf2011-07-27 20:23:08527 static_cast<VisitCountingProfile*>(
[email protected]f3b1a082011-11-18 00:34:30528 Profile::FromBrowserContext(GetBrowserContext()));
[email protected]3e90d4a2009-07-03 17:38:39529
[email protected]2ccf45c2011-08-19 23:35:50530 if (msg->type() == ChromeViewMsg_VisitedLink_Add::ID) {
[email protected]ce208f872012-03-07 20:42:56531 PickleIterator iter(*msg);
[email protected]7fa7dd52011-04-24 01:09:42532 std::vector<uint64> fingerprints;
533 CHECK(IPC::ReadParam(msg, &iter, &fingerprints));
534 counting_profile->CountAddEvent(fingerprints.size());
[email protected]2ccf45c2011-08-19 23:35:50535 } else if (msg->type() == ChromeViewMsg_VisitedLink_Reset::ID) {
[email protected]3e90d4a2009-07-03 17:38:39536 counting_profile->CountResetEvent();
[email protected]7fa7dd52011-04-24 01:09:42537 }
[email protected]3e90d4a2009-07-03 17:38:39538
539 delete msg;
540 return true;
541 }
542
[email protected]3e90d4a2009-07-03 17:38:39543 private:
[email protected]b6a2f8de2012-01-31 17:28:49544 int widgets_;
545
[email protected]3e90d4a2009-07-03 17:38:39546 DISALLOW_COPY_AND_ASSIGN(VisitRelayingRenderProcessHost);
547};
548
549class VisitedLinkRenderProcessHostFactory
[email protected]f3b1a082011-11-18 00:34:30550 : public content::RenderProcessHostFactory {
[email protected]3e90d4a2009-07-03 17:38:39551 public:
552 VisitedLinkRenderProcessHostFactory()
[email protected]f3b1a082011-11-18 00:34:30553 : content::RenderProcessHostFactory() {}
554 virtual content::RenderProcessHost* CreateRenderProcessHost(
[email protected]3d7474ff2011-07-27 17:47:37555 content::BrowserContext* browser_context) const OVERRIDE {
556 return new VisitRelayingRenderProcessHost(browser_context);
[email protected]3e90d4a2009-07-03 17:38:39557 }
558
[email protected]3e90d4a2009-07-03 17:38:39559 private:
[email protected]3e90d4a2009-07-03 17:38:39560
561 DISALLOW_COPY_AND_ASSIGN(VisitedLinkRenderProcessHostFactory);
562};
563
[email protected]93ab5932011-09-14 07:38:17564class VisitedLinkEventsTest : public ChromeRenderViewHostTestHarness {
[email protected]3e90d4a2009-07-03 17:38:39565 public:
[email protected]6fad2632009-11-02 05:59:37566 VisitedLinkEventsTest()
[email protected]93ab5932011-09-14 07:38:17567 : ui_thread_(BrowserThread::UI, &message_loop_),
[email protected]0c7d74f2010-10-11 11:55:26568 file_thread_(BrowserThread::FILE, &message_loop_) {}
[email protected]93ab5932011-09-14 07:38:17569 virtual ~VisitedLinkEventsTest() {}
[email protected]3e90d4a2009-07-03 17:38:39570 virtual void SetUp() {
[email protected]c0257382012-03-12 20:15:34571 SetRenderProcessHostFactory(&vc_rph_factory_);
[email protected]2d66488c2011-10-14 21:10:00572 browser_context_.reset(new VisitCountingProfile());
[email protected]93ab5932011-09-14 07:38:17573 ChromeRenderViewHostTestHarness::SetUp();
[email protected]3e90d4a2009-07-03 17:38:39574 }
575
576 VisitCountingProfile* profile() const {
[email protected]93ab5932011-09-14 07:38:17577 return static_cast<VisitCountingProfile*>(browser_context_.get());
[email protected]3e90d4a2009-07-03 17:38:39578 }
579
580 void WaitForCoalescense() {
581 // Let the timer fire.
[email protected]02798a982012-01-27 00:45:33582 MessageLoop::current()->PostDelayedTask(
583 FROM_HERE,
584 MessageLoop::QuitClosure(),
585 base::TimeDelta::FromMilliseconds(110));
[email protected]3e90d4a2009-07-03 17:38:39586 MessageLoop::current()->Run();
587 }
588
589 protected:
590 VisitedLinkRenderProcessHostFactory vc_rph_factory_;
591
592 private:
[email protected]c38831a12011-10-28 12:44:49593 content::TestBrowserThread ui_thread_;
594 content::TestBrowserThread file_thread_;
[email protected]3e90d4a2009-07-03 17:38:39595
596 DISALLOW_COPY_AND_ASSIGN(VisitedLinkEventsTest);
597};
598
[email protected]3e90d4a2009-07-03 17:38:39599TEST_F(VisitedLinkEventsTest, Coalescense) {
600 // add some URLs to master.
[email protected]93ab5932011-09-14 07:38:17601 VisitedLinkMaster* master = profile()->GetVisitedLinkMaster();
[email protected]3e90d4a2009-07-03 17:38:39602 // Add a few URLs.
603 master->AddURL(GURL("http://acidtests.org/"));
604 master->AddURL(GURL("http://google.com/"));
605 master->AddURL(GURL("http://chromium.org/"));
606 // Just for kicks, add a duplicate URL. This shouldn't increase the resulting
607 master->AddURL(GURL("http://acidtests.org/"));
608
609 // Make sure that coalescing actually occurs. There should be no links or
610 // events received by the renderer.
611 EXPECT_EQ(0, profile()->add_count());
612 EXPECT_EQ(0, profile()->add_event_count());
613
614 WaitForCoalescense();
615
616 // We now should have 3 entries added in 1 event.
617 EXPECT_EQ(3, profile()->add_count());
618 EXPECT_EQ(1, profile()->add_event_count());
619
620 // Test whether the coalescing continues by adding a few more URLs.
621 master->AddURL(GURL("http://google.com/chrome/"));
622 master->AddURL(GURL("http://webkit.org/"));
623 master->AddURL(GURL("http://acid3.acidtests.org/"));
624
625 WaitForCoalescense();
626
627 // We should have 6 entries added in 2 events.
628 EXPECT_EQ(6, profile()->add_count());
629 EXPECT_EQ(2, profile()->add_event_count());
630
631 // Test whether duplicate entries produce add events.
632 master->AddURL(GURL("http://acidtests.org/"));
633
634 WaitForCoalescense();
635
636 // We should have no change in results.
637 EXPECT_EQ(6, profile()->add_count());
638 EXPECT_EQ(2, profile()->add_event_count());
639
640 // Ensure that the coalescing does not resume after resetting.
641 master->AddURL(GURL("http://build.chromium.org/"));
642 master->DeleteAllURLs();
643
644 WaitForCoalescense();
645
646 // We should have no change in results except for one new reset event.
647 EXPECT_EQ(6, profile()->add_count());
648 EXPECT_EQ(2, profile()->add_event_count());
649 EXPECT_EQ(1, profile()->reset_event_count());
650}
651
[email protected]7fa7dd52011-04-24 01:09:42652TEST_F(VisitedLinkEventsTest, Basics) {
[email protected]93ab5932011-09-14 07:38:17653 VisitedLinkMaster* master = profile()->GetVisitedLinkMaster();
[email protected]c0257382012-03-12 20:15:34654 rvh_tester()->CreateRenderView(string16(), -1);
[email protected]6e8d64642009-08-10 15:27:19655
[email protected]3e90d4a2009-07-03 17:38:39656 // Add a few URLs.
657 master->AddURL(GURL("http://acidtests.org/"));
658 master->AddURL(GURL("http://google.com/"));
659 master->AddURL(GURL("http://chromium.org/"));
660
661 WaitForCoalescense();
662
663 // We now should have 1 add event.
664 EXPECT_EQ(1, profile()->add_event_count());
665 EXPECT_EQ(0, profile()->reset_event_count());
666
667 master->DeleteAllURLs();
668
669 WaitForCoalescense();
670
671 // We should have no change in add results, plus one new reset event.
672 EXPECT_EQ(1, profile()->add_event_count());
673 EXPECT_EQ(1, profile()->reset_event_count());
674}
675
[email protected]7fa7dd52011-04-24 01:09:42676TEST_F(VisitedLinkEventsTest, TabVisibility) {
[email protected]93ab5932011-09-14 07:38:17677 VisitedLinkMaster* master = profile()->GetVisitedLinkMaster();
[email protected]c0257382012-03-12 20:15:34678 rvh_tester()->CreateRenderView(string16(), -1);
[email protected]3e90d4a2009-07-03 17:38:39679
680 // Simulate tab becoming inactive.
[email protected]c0257382012-03-12 20:15:34681 rvh_tester()->SimulateWasHidden();
[email protected]3e90d4a2009-07-03 17:38:39682
683 // Add a few URLs.
684 master->AddURL(GURL("http://acidtests.org/"));
685 master->AddURL(GURL("http://google.com/"));
686 master->AddURL(GURL("http://chromium.org/"));
687
688 WaitForCoalescense();
689
690 // We shouldn't have any events.
691 EXPECT_EQ(0, profile()->add_event_count());
692 EXPECT_EQ(0, profile()->reset_event_count());
693
694 // Simulate the tab becoming active.
[email protected]c0257382012-03-12 20:15:34695 rvh_tester()->SimulateWasRestored();
[email protected]3e90d4a2009-07-03 17:38:39696
697 // We should now have 3 add events, still no reset events.
698 EXPECT_EQ(1, profile()->add_event_count());
699 EXPECT_EQ(0, profile()->reset_event_count());
700
701 // Deactivate the tab again.
[email protected]c0257382012-03-12 20:15:34702 rvh_tester()->SimulateWasHidden();
[email protected]3e90d4a2009-07-03 17:38:39703
704 // Add a bunch of URLs (over 50) to exhaust the link event buffer.
705 for (int i = 0; i < 100; i++)
706 master->AddURL(TestURL(i));
707
708 WaitForCoalescense();
709
710 // Again, no change in events until tab is active.
711 EXPECT_EQ(1, profile()->add_event_count());
712 EXPECT_EQ(0, profile()->reset_event_count());
713
714 // Activate the tab.
[email protected]c0257382012-03-12 20:15:34715 rvh_tester()->SimulateWasRestored();
[email protected]3e90d4a2009-07-03 17:38:39716
717 // We should have only one more reset event.
718 EXPECT_EQ(1, profile()->add_event_count());
719 EXPECT_EQ(1, profile()->reset_event_count());
720}