| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <stddef.h> | 5 #include <stddef.h> |
| 6 #include <stdint.h> | 6 #include <stdint.h> |
| 7 | 7 |
| 8 #include <cstdio> | 8 #include <cstdio> |
| 9 #include <memory> | 9 #include <memory> |
| 10 #include <string> | 10 #include <string> |
| 11 #include <vector> | 11 #include <vector> |
| 12 | 12 |
| 13 #include "base/callback_helpers.h" |
| 13 #include "base/files/file_util.h" | 14 #include "base/files/file_util.h" |
| 14 #include "base/location.h" | 15 #include "base/location.h" |
| 15 #include "base/macros.h" | 16 #include "base/macros.h" |
| 16 #include "base/memory/shared_memory.h" | 17 #include "base/memory/ptr_util.h" |
| 17 #include "base/process/process_handle.h" | 18 #include "base/process/process_handle.h" |
| 18 #include "base/run_loop.h" | 19 #include "base/run_loop.h" |
| 19 #include "base/single_thread_task_runner.h" | 20 #include "base/single_thread_task_runner.h" |
| 20 #include "base/strings/string_util.h" | 21 #include "base/strings/string_util.h" |
| 21 #include "base/threading/thread_task_runner_handle.h" | 22 #include "base/threading/thread_task_runner_handle.h" |
| 22 #include "base/time/time.h" | 23 #include "base/time/time.h" |
| 24 #include "base/timer/mock_timer.h" |
| 23 #include "components/visitedlink/browser/visitedlink_delegate.h" | 25 #include "components/visitedlink/browser/visitedlink_delegate.h" |
| 24 #include "components/visitedlink/browser/visitedlink_event_listener.h" | 26 #include "components/visitedlink/browser/visitedlink_event_listener.h" |
| 25 #include "components/visitedlink/browser/visitedlink_master.h" | 27 #include "components/visitedlink/browser/visitedlink_master.h" |
| 26 #include "components/visitedlink/common/visitedlink_messages.h" | 28 #include "components/visitedlink/common/visitedlink.mojom.h" |
| 27 #include "components/visitedlink/renderer/visitedlink_slave.h" | 29 #include "components/visitedlink/renderer/visitedlink_slave.h" |
| 28 #include "content/public/browser/browser_thread.h" | 30 #include "content/public/browser/browser_thread.h" |
| 29 #include "content/public/browser/notification_service.h" | 31 #include "content/public/browser/notification_service.h" |
| 30 #include "content/public/browser/notification_types.h" | 32 #include "content/public/browser/notification_types.h" |
| 31 #include "content/public/test/mock_render_process_host.h" | 33 #include "content/public/test/mock_render_process_host.h" |
| 32 #include "content/public/test/test_browser_context.h" | 34 #include "content/public/test/test_browser_context.h" |
| 33 #include "content/public/test/test_browser_thread_bundle.h" | 35 #include "content/public/test/test_browser_thread_bundle.h" |
| 34 #include "content/public/test/test_renderer_host.h" | 36 #include "content/public/test/test_renderer_host.h" |
| 35 #include "content/public/test/test_utils.h" | 37 #include "content/public/test/test_utils.h" |
| 38 #include "services/shell/public/cpp/interface_provider.h" |
| 36 #include "testing/gtest/include/gtest/gtest.h" | 39 #include "testing/gtest/include/gtest/gtest.h" |
| 37 #include "url/gurl.h" | 40 #include "url/gurl.h" |
| 38 | 41 |
| 39 using content::BrowserThread; | 42 using content::BrowserThread; |
| 40 using content::MockRenderProcessHost; | 43 using content::MockRenderProcessHost; |
| 41 using content::RenderViewHostTester; | 44 using content::RenderViewHostTester; |
| 42 | 45 |
| 43 namespace visitedlink { | 46 namespace visitedlink { |
| 44 | 47 |
| 45 namespace { | 48 namespace { |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 108 | 111 |
| 109 } // namespace | 112 } // namespace |
| 110 | 113 |
| 111 class TrackingVisitedLinkEventListener : public VisitedLinkMaster::Listener { | 114 class TrackingVisitedLinkEventListener : public VisitedLinkMaster::Listener { |
| 112 public: | 115 public: |
| 113 TrackingVisitedLinkEventListener() | 116 TrackingVisitedLinkEventListener() |
| 114 : reset_count_(0), | 117 : reset_count_(0), |
| 115 completely_reset_count_(0), | 118 completely_reset_count_(0), |
| 116 add_count_(0) {} | 119 add_count_(0) {} |
| 117 | 120 |
| 118 void NewTable(base::SharedMemory* table) override { | 121 void NewTable(mojo::SharedBufferHandle table) override { |
| 119 if (table) { | 122 if (table.is_valid()) { |
| 120 for (std::vector<VisitedLinkSlave>::size_type i = 0; | 123 for (std::vector<VisitedLinkSlave>::size_type i = 0; |
| 121 i < g_slaves.size(); i++) { | 124 i < g_slaves.size(); i++) { |
| 122 base::SharedMemoryHandle new_handle = base::SharedMemory::NULLHandle(); | 125 g_slaves[i]->UpdateVisitedLinks(table.Clone()); |
| 123 table->ShareToProcess(base::GetCurrentProcessHandle(), &new_handle); | |
| 124 g_slaves[i]->OnUpdateVisitedLinks(new_handle); | |
| 125 } | 126 } |
| 126 } | 127 } |
| 127 } | 128 } |
| 128 void Add(VisitedLinkCommon::Fingerprint) override { add_count_++; } | 129 void Add(VisitedLinkCommon::Fingerprint) override { add_count_++; } |
| 129 void Reset(bool invalidate_hashes) override { | 130 void Reset(bool invalidate_hashes) override { |
| 130 if (invalidate_hashes) | 131 if (invalidate_hashes) |
| 131 completely_reset_count_++; | 132 completely_reset_count_++; |
| 132 else | 133 else |
| 133 reset_count_++; | 134 reset_count_++; |
| 134 } | 135 } |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 194 ASSERT_TRUE(InitVisited(0, true, true)); | 195 ASSERT_TRUE(InitVisited(0, true, true)); |
| 195 | 196 |
| 196 master_->DebugValidate(); | 197 master_->DebugValidate(); |
| 197 | 198 |
| 198 // check that the table has the proper number of entries | 199 // check that the table has the proper number of entries |
| 199 int used_count = master_->GetUsedCount(); | 200 int used_count = master_->GetUsedCount(); |
| 200 ASSERT_EQ(used_count, g_test_count); | 201 ASSERT_EQ(used_count, g_test_count); |
| 201 | 202 |
| 202 // Create a slave database. | 203 // Create a slave database. |
| 203 VisitedLinkSlave slave; | 204 VisitedLinkSlave slave; |
| 204 base::SharedMemoryHandle new_handle = base::SharedMemory::NULLHandle(); | 205 slave.UpdateVisitedLinks(master_->shared_memory().Clone()); |
| 205 master_->shared_memory()->ShareToProcess( | |
| 206 base::GetCurrentProcessHandle(), &new_handle); | |
| 207 slave.OnUpdateVisitedLinks(new_handle); | |
| 208 g_slaves.push_back(&slave); | 206 g_slaves.push_back(&slave); |
| 209 | 207 |
| 210 bool found; | 208 bool found; |
| 211 for (int i = 0; i < g_test_count; i++) { | 209 for (int i = 0; i < g_test_count; i++) { |
| 212 GURL cur = TestURL(i); | 210 GURL cur = TestURL(i); |
| 213 found = master_->IsVisited(cur); | 211 found = master_->IsVisited(cur); |
| 214 EXPECT_TRUE(found) << "URL " << i << "not found in master."; | 212 EXPECT_TRUE(found) << "URL " << i << "not found in master."; |
| 215 | 213 |
| 216 found = slave.IsVisited(cur); | 214 found = slave.IsVisited(cur); |
| 217 EXPECT_TRUE(found) << "URL " << i << "not found in slave."; | 215 EXPECT_TRUE(found) << "URL " << i << "not found in slave."; |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 325 master_->DebugValidate(); | 323 master_->DebugValidate(); |
| 326 | 324 |
| 327 Reload(); | 325 Reload(); |
| 328 } | 326 } |
| 329 | 327 |
| 330 TEST_F(VisitedLinkTest, DeleteAll) { | 328 TEST_F(VisitedLinkTest, DeleteAll) { |
| 331 ASSERT_TRUE(InitVisited(0, true, true)); | 329 ASSERT_TRUE(InitVisited(0, true, true)); |
| 332 | 330 |
| 333 { | 331 { |
| 334 VisitedLinkSlave slave; | 332 VisitedLinkSlave slave; |
| 335 base::SharedMemoryHandle new_handle = base::SharedMemory::NULLHandle(); | 333 slave.UpdateVisitedLinks(master_->shared_memory().Clone()); |
| 336 master_->shared_memory()->ShareToProcess( | |
| 337 base::GetCurrentProcessHandle(), &new_handle); | |
| 338 slave.OnUpdateVisitedLinks(new_handle); | |
| 339 g_slaves.push_back(&slave); | 334 g_slaves.push_back(&slave); |
| 340 | 335 |
| 341 // Add the test URLs. | 336 // Add the test URLs. |
| 342 for (int i = 0; i < g_test_count; i++) { | 337 for (int i = 0; i < g_test_count; i++) { |
| 343 master_->AddURL(TestURL(i)); | 338 master_->AddURL(TestURL(i)); |
| 344 ASSERT_EQ(i + 1, master_->GetUsedCount()); | 339 ASSERT_EQ(i + 1, master_->GetUsedCount()); |
| 345 } | 340 } |
| 346 master_->DebugValidate(); | 341 master_->DebugValidate(); |
| 347 | 342 |
| 348 // Make sure the slave picked up the adds. | 343 // Make sure the slave picked up the adds. |
| (...skipping 23 matching lines...) Expand all Loading... |
| 372 | 367 |
| 373 // This tests that the master correctly resizes its tables when it gets too | 368 // This tests that the master correctly resizes its tables when it gets too |
| 374 // full, notifies its slaves of the change, and updates the disk. | 369 // full, notifies its slaves of the change, and updates the disk. |
| 375 TEST_F(VisitedLinkTest, Resizing) { | 370 TEST_F(VisitedLinkTest, Resizing) { |
| 376 // Create a very small database. | 371 // Create a very small database. |
| 377 const int32_t initial_size = 17; | 372 const int32_t initial_size = 17; |
| 378 ASSERT_TRUE(InitVisited(initial_size, true, true)); | 373 ASSERT_TRUE(InitVisited(initial_size, true, true)); |
| 379 | 374 |
| 380 // ...and a slave | 375 // ...and a slave |
| 381 VisitedLinkSlave slave; | 376 VisitedLinkSlave slave; |
| 382 base::SharedMemoryHandle new_handle = base::SharedMemory::NULLHandle(); | 377 slave.UpdateVisitedLinks(master_->shared_memory().Clone()); |
| 383 master_->shared_memory()->ShareToProcess( | |
| 384 base::GetCurrentProcessHandle(), &new_handle); | |
| 385 slave.OnUpdateVisitedLinks(new_handle); | |
| 386 g_slaves.push_back(&slave); | 378 g_slaves.push_back(&slave); |
| 387 | 379 |
| 388 int32_t used_count = master_->GetUsedCount(); | 380 int32_t used_count = master_->GetUsedCount(); |
| 389 ASSERT_EQ(used_count, 0); | 381 ASSERT_EQ(used_count, 0); |
| 390 | 382 |
| 391 for (int i = 0; i < g_test_count; i++) { | 383 for (int i = 0; i < g_test_count; i++) { |
| 392 master_->AddURL(TestURL(i)); | 384 master_->AddURL(TestURL(i)); |
| 393 used_count = master_->GetUsedCount(); | 385 used_count = master_->GetUsedCount(); |
| 394 ASSERT_EQ(i + 1, used_count); | 386 ASSERT_EQ(i + 1, used_count); |
| 395 } | 387 } |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 520 | 512 |
| 521 ASSERT_TRUE(InitVisited(0, true, true)); | 513 ASSERT_TRUE(InitVisited(0, true, true)); |
| 522 | 514 |
| 523 listener = | 515 listener = |
| 524 static_cast<TrackingVisitedLinkEventListener*>(master_->GetListener()); | 516 static_cast<TrackingVisitedLinkEventListener*>(master_->GetListener()); |
| 525 // Verify that VisitedLinkMaster::Listener::Reset(true) was called when the | 517 // Verify that VisitedLinkMaster::Listener::Reset(true) was called when the |
| 526 // table was loaded. | 518 // table was loaded. |
| 527 EXPECT_EQ(1, listener->completely_reset_count()); | 519 EXPECT_EQ(1, listener->completely_reset_count()); |
| 528 } | 520 } |
| 529 | 521 |
| 530 class VisitCountingContext : public content::TestBrowserContext { | 522 class VisitCountingContext : public mojom::VisitedLinkNotificationSink { |
| 531 public: | 523 public: |
| 532 VisitCountingContext() | 524 VisitCountingContext() |
| 533 : add_count_(0), | 525 : add_count_(0), |
| 534 add_event_count_(0), | 526 add_event_count_(0), |
| 535 reset_event_count_(0), | 527 reset_event_count_(0), |
| 536 completely_reset_event_count_(0), | 528 completely_reset_event_count_(0), |
| 537 new_table_count_(0) {} | 529 new_table_count_(0), |
| 530 binding_(this) {} |
| 538 | 531 |
| 539 void CountAddEvent(int by) { | 532 void Bind(mojo::ScopedMessagePipeHandle handle) { |
| 540 add_count_ += by; | 533 binding_.Bind(mojo::MakeRequest<mojom::VisitedLinkNotificationSink>( |
| 541 add_event_count_++; | 534 std::move(handle))); |
| 542 } | 535 } |
| 543 | 536 |
| 544 void CountResetEvent() { | 537 void WaitForUpdate() { |
| 545 reset_event_count_++; | 538 base::RunLoop run_loop; |
| 539 quit_closure_ = run_loop.QuitClosure(); |
| 540 run_loop.Run(); |
| 546 } | 541 } |
| 547 | 542 |
| 548 void CountCompletelyResetEvent() { | 543 void WaitForNoUpdate() { binding_.FlushForTesting(); } |
| 549 completely_reset_event_count_++; | 544 |
| 545 mojo::Binding<mojom::VisitedLinkNotificationSink>& binding() { |
| 546 return binding_; |
| 550 } | 547 } |
| 551 | 548 |
| 552 void CountNewTable() { | 549 void NotifyUpdate() { |
| 550 if (!quit_closure_.is_null()) |
| 551 base::ResetAndReturn(&quit_closure_).Run(); |
| 552 } |
| 553 |
| 554 void UpdateVisitedLinks( |
| 555 mojo::ScopedSharedBufferHandle table_handle) override { |
| 553 new_table_count_++; | 556 new_table_count_++; |
| 557 NotifyUpdate(); |
| 558 } |
| 559 |
| 560 void AddVisitedLinks(const std::vector<uint64_t>& link_hashes) override { |
| 561 add_count_ += link_hashes.size(); |
| 562 add_event_count_++; |
| 563 NotifyUpdate(); |
| 564 } |
| 565 |
| 566 void ResetVisitedLinks(bool invalidate_cached_hashes) override { |
| 567 if (invalidate_cached_hashes) |
| 568 completely_reset_event_count_++; |
| 569 else |
| 570 reset_event_count_++; |
| 571 NotifyUpdate(); |
| 554 } | 572 } |
| 555 | 573 |
| 556 int add_count() const { return add_count_; } | 574 int add_count() const { return add_count_; } |
| 557 int add_event_count() const { return add_event_count_; } | 575 int add_event_count() const { return add_event_count_; } |
| 558 int reset_event_count() const { return reset_event_count_; } | 576 int reset_event_count() const { return reset_event_count_; } |
| 559 int completely_reset_event_count() const { | 577 int completely_reset_event_count() const { |
| 560 return completely_reset_event_count_; | 578 return completely_reset_event_count_; |
| 561 } | 579 } |
| 562 int new_table_count() const { return new_table_count_; } | 580 int new_table_count() const { return new_table_count_; } |
| 563 | 581 |
| 564 private: | 582 private: |
| 565 int add_count_; | 583 int add_count_; |
| 566 int add_event_count_; | 584 int add_event_count_; |
| 567 int reset_event_count_; | 585 int reset_event_count_; |
| 568 int completely_reset_event_count_; | 586 int completely_reset_event_count_; |
| 569 int new_table_count_; | 587 int new_table_count_; |
| 588 |
| 589 base::Closure quit_closure_; |
| 590 mojo::Binding<mojom::VisitedLinkNotificationSink> binding_; |
| 570 }; | 591 }; |
| 571 | 592 |
| 572 // Stub out as little as possible, borrowing from RenderProcessHost. | 593 // Stub out as little as possible, borrowing from RenderProcessHost. |
| 573 class VisitRelayingRenderProcessHost : public MockRenderProcessHost { | 594 class VisitRelayingRenderProcessHost : public MockRenderProcessHost { |
| 574 public: | 595 public: |
| 575 explicit VisitRelayingRenderProcessHost( | 596 explicit VisitRelayingRenderProcessHost( |
| 576 content::BrowserContext* browser_context) | 597 content::BrowserContext* browser_context, |
| 577 : MockRenderProcessHost(browser_context), widgets_(0) { | 598 VisitCountingContext* context) |
| 599 : MockRenderProcessHost(browser_context), widgets_(0) { |
| 600 SetRemoteInterfaces(base::MakeUnique<shell::InterfaceProvider>()); |
| 601 shell::InterfaceProvider::TestApi test_api(GetRemoteInterfaces()); |
| 602 test_api.SetBinderForName( |
| 603 mojom::VisitedLinkNotificationSink::Name_, |
| 604 base::Bind(&VisitCountingContext::Bind, base::Unretained(context))); |
| 578 content::NotificationService::current()->Notify( | 605 content::NotificationService::current()->Notify( |
| 579 content::NOTIFICATION_RENDERER_PROCESS_CREATED, | 606 content::NOTIFICATION_RENDERER_PROCESS_CREATED, |
| 580 content::Source<RenderProcessHost>(this), | 607 content::Source<RenderProcessHost>(this), |
| 581 content::NotificationService::NoDetails()); | 608 content::NotificationService::NoDetails()); |
| 582 } | 609 } |
| 583 ~VisitRelayingRenderProcessHost() override { | 610 ~VisitRelayingRenderProcessHost() override { |
| 584 content::NotificationService::current()->Notify( | 611 content::NotificationService::current()->Notify( |
| 585 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, | 612 content::NOTIFICATION_RENDERER_PROCESS_TERMINATED, |
| 586 content::Source<content::RenderProcessHost>(this), | 613 content::Source<content::RenderProcessHost>(this), |
| 587 content::NotificationService::NoDetails()); | 614 content::NotificationService::NoDetails()); |
| 588 } | 615 } |
| 589 | 616 |
| 590 void WidgetRestored() override { widgets_++; } | 617 void WidgetRestored() override { widgets_++; } |
| 591 void WidgetHidden() override { widgets_--; } | 618 void WidgetHidden() override { widgets_--; } |
| 592 int VisibleWidgetCount() const override { return widgets_; } | 619 int VisibleWidgetCount() const override { return widgets_; } |
| 593 | 620 |
| 594 bool Send(IPC::Message* msg) override { | |
| 595 VisitCountingContext* counting_context = | |
| 596 static_cast<VisitCountingContext*>( | |
| 597 GetBrowserContext()); | |
| 598 | |
| 599 if (msg->type() == ChromeViewMsg_VisitedLink_Add::ID) { | |
| 600 base::PickleIterator iter(*msg); | |
| 601 std::vector<uint64_t> fingerprints; | |
| 602 CHECK(IPC::ReadParam(msg, &iter, &fingerprints)); | |
| 603 counting_context->CountAddEvent(fingerprints.size()); | |
| 604 } else if (msg->type() == ChromeViewMsg_VisitedLink_Reset::ID) { | |
| 605 base::PickleIterator iter(*msg); | |
| 606 bool invalidate_hashes; | |
| 607 CHECK(IPC::ReadParam(msg, &iter, &invalidate_hashes)); | |
| 608 if (invalidate_hashes) | |
| 609 counting_context->CountCompletelyResetEvent(); | |
| 610 else | |
| 611 counting_context->CountResetEvent(); | |
| 612 } else if (msg->type() == ChromeViewMsg_VisitedLink_NewTable::ID) { | |
| 613 counting_context->CountNewTable(); | |
| 614 } | |
| 615 | |
| 616 delete msg; | |
| 617 return true; | |
| 618 } | |
| 619 | |
| 620 private: | 621 private: |
| 621 int widgets_; | 622 int widgets_; |
| 622 | 623 |
| 623 DISALLOW_COPY_AND_ASSIGN(VisitRelayingRenderProcessHost); | 624 DISALLOW_COPY_AND_ASSIGN(VisitRelayingRenderProcessHost); |
| 624 }; | 625 }; |
| 625 | 626 |
| 626 class VisitedLinkRenderProcessHostFactory | 627 class VisitedLinkRenderProcessHostFactory |
| 627 : public content::RenderProcessHostFactory { | 628 : public content::RenderProcessHostFactory { |
| 628 public: | 629 public: |
| 629 VisitedLinkRenderProcessHostFactory() | 630 VisitedLinkRenderProcessHostFactory() : context_(new VisitCountingContext) {} |
| 630 : content::RenderProcessHostFactory() {} | |
| 631 content::RenderProcessHost* CreateRenderProcessHost( | 631 content::RenderProcessHost* CreateRenderProcessHost( |
| 632 content::BrowserContext* browser_context, | 632 content::BrowserContext* browser_context, |
| 633 content::SiteInstance* site_instance) const override { | 633 content::SiteInstance* site_instance) const override { |
| 634 return new VisitRelayingRenderProcessHost(browser_context); | 634 return new VisitRelayingRenderProcessHost(browser_context, context_.get()); |
| 635 } | 635 } |
| 636 | 636 |
| 637 VisitCountingContext* context() { return context_.get(); } |
| 638 |
| 637 private: | 639 private: |
| 640 std::unique_ptr<VisitCountingContext> context_; |
| 638 DISALLOW_COPY_AND_ASSIGN(VisitedLinkRenderProcessHostFactory); | 641 DISALLOW_COPY_AND_ASSIGN(VisitedLinkRenderProcessHostFactory); |
| 639 }; | 642 }; |
| 640 | 643 |
| 641 class VisitedLinkEventsTest : public content::RenderViewHostTestHarness { | 644 class VisitedLinkEventsTest : public content::RenderViewHostTestHarness { |
| 642 public: | 645 public: |
| 643 void SetUp() override { | 646 void SetUp() override { |
| 644 SetRenderProcessHostFactory(&vc_rph_factory_); | 647 SetRenderProcessHostFactory(&vc_rph_factory_); |
| 645 content::RenderViewHostTestHarness::SetUp(); | 648 content::RenderViewHostTestHarness::SetUp(); |
| 646 } | 649 } |
| 647 | 650 |
| 648 void TearDown() override { | 651 void TearDown() override { |
| 649 // Explicitly destroy the master before proceeding with the rest | 652 // Explicitly destroy the master before proceeding with the rest |
| 650 // of teardown because it posts a task to close a file handle, and | 653 // of teardown because it posts a task to close a file handle, and |
| 651 // we need to make sure we've finished all file related work | 654 // we need to make sure we've finished all file related work |
| 652 // before our superclass sets about destroying the scoped temp | 655 // before our superclass sets about destroying the scoped temp |
| 653 // directory. | 656 // directory. |
| 654 master_.reset(); | 657 master_.reset(); |
| 655 RenderViewHostTestHarness::TearDown(); | 658 RenderViewHostTestHarness::TearDown(); |
| 656 } | 659 } |
| 657 | 660 |
| 658 content::BrowserContext* CreateBrowserContext() override { | 661 content::BrowserContext* CreateBrowserContext() override { |
| 659 VisitCountingContext* context = new VisitCountingContext(); | 662 content::BrowserContext* context = new content::TestBrowserContext(); |
| 660 CreateVisitedLinkMaster(context); | 663 CreateVisitedLinkMaster(context); |
| 661 return context; | 664 return context; |
| 662 } | 665 } |
| 663 | 666 |
| 664 VisitCountingContext* context() { | 667 VisitCountingContext* context() { return vc_rph_factory_.context(); } |
| 665 return static_cast<VisitCountingContext*>(browser_context()); | |
| 666 } | |
| 667 | 668 |
| 668 VisitedLinkMaster* master() const { | 669 VisitedLinkMaster* master() const { |
| 669 return master_.get(); | 670 return master_.get(); |
| 670 } | 671 } |
| 671 | 672 |
| 672 void WaitForCoalescence() { | |
| 673 // Let the timer fire. | |
| 674 // | |
| 675 // TODO(ajwong): This is horrid! What is the right synchronization method? | |
| 676 base::RunLoop run_loop; | |
| 677 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 678 FROM_HERE, run_loop.QuitClosure(), | |
| 679 base::TimeDelta::FromMilliseconds(110)); | |
| 680 run_loop.Run(); | |
| 681 } | |
| 682 | |
| 683 protected: | 673 protected: |
| 684 void CreateVisitedLinkMaster(content::BrowserContext* browser_context) { | 674 void CreateVisitedLinkMaster(content::BrowserContext* browser_context) { |
| 675 timer_.reset(new base::MockTimer(false, false)); |
| 685 master_.reset(new VisitedLinkMaster(browser_context, &delegate_, true)); | 676 master_.reset(new VisitedLinkMaster(browser_context, &delegate_, true)); |
| 677 static_cast<VisitedLinkEventListener*>(master_->GetListener()) |
| 678 ->SetCoalesceTimerForTest(timer_.get()); |
| 686 master_->Init(); | 679 master_->Init(); |
| 687 } | 680 } |
| 688 | 681 |
| 689 VisitedLinkRenderProcessHostFactory vc_rph_factory_; | 682 VisitedLinkRenderProcessHostFactory vc_rph_factory_; |
| 690 | 683 |
| 691 TestVisitedLinkDelegate delegate_; | 684 TestVisitedLinkDelegate delegate_; |
| 685 std::unique_ptr<base::MockTimer> timer_; |
| 692 std::unique_ptr<VisitedLinkMaster> master_; | 686 std::unique_ptr<VisitedLinkMaster> master_; |
| 693 }; | 687 }; |
| 694 | 688 |
| 695 TEST_F(VisitedLinkEventsTest, Coalescence) { | 689 TEST_F(VisitedLinkEventsTest, Coalescence) { |
| 696 // Waiting complete rebuild the table. | 690 // Waiting complete rebuild the table. |
| 697 content::RunAllBlockingPoolTasksUntilIdle(); | 691 content::RunAllBlockingPoolTasksUntilIdle(); |
| 698 | 692 |
| 699 WaitForCoalescence(); | |
| 700 | |
| 701 // After rebuild table expect reset event. | 693 // After rebuild table expect reset event. |
| 702 EXPECT_EQ(1, context()->reset_event_count()); | 694 EXPECT_EQ(1, context()->reset_event_count()); |
| 703 | 695 |
| 704 // add some URLs to master. | 696 // add some URLs to master. |
| 705 // Add a few URLs. | 697 // Add a few URLs. |
| 706 master()->AddURL(GURL("http://acidtests.org/")); | 698 master()->AddURL(GURL("http://acidtests.org/")); |
| 707 master()->AddURL(GURL("http://google.com/")); | 699 master()->AddURL(GURL("http://google.com/")); |
| 708 master()->AddURL(GURL("http://chromium.org/")); | 700 master()->AddURL(GURL("http://chromium.org/")); |
| 709 // Just for kicks, add a duplicate URL. This shouldn't increase the resulting | 701 // Just for kicks, add a duplicate URL. This shouldn't increase the resulting |
| 710 master()->AddURL(GURL("http://acidtests.org/")); | 702 master()->AddURL(GURL("http://acidtests.org/")); |
| 703 ASSERT_TRUE(timer_->IsRunning()); |
| 704 timer_->Fire(); |
| 711 | 705 |
| 712 // Make sure that coalescing actually occurs. There should be no links or | 706 context()->WaitForUpdate(); |
| 713 // events received by the renderer. | |
| 714 EXPECT_EQ(0, context()->add_count()); | |
| 715 EXPECT_EQ(0, context()->add_event_count()); | |
| 716 | |
| 717 WaitForCoalescence(); | |
| 718 | 707 |
| 719 // We now should have 3 entries added in 1 event. | 708 // We now should have 3 entries added in 1 event. |
| 720 EXPECT_EQ(3, context()->add_count()); | 709 EXPECT_EQ(3, context()->add_count()); |
| 721 EXPECT_EQ(1, context()->add_event_count()); | 710 EXPECT_EQ(1, context()->add_event_count()); |
| 722 | 711 |
| 723 // Test whether the coalescing continues by adding a few more URLs. | 712 // Test whether the coalescing continues by adding a few more URLs. |
| 724 master()->AddURL(GURL("http://google.com/chrome/")); | 713 master()->AddURL(GURL("http://google.com/chrome/")); |
| 725 master()->AddURL(GURL("http://webkit.org/")); | 714 master()->AddURL(GURL("http://webkit.org/")); |
| 726 master()->AddURL(GURL("http://acid3.acidtests.org/")); | 715 master()->AddURL(GURL("http://acid3.acidtests.org/")); |
| 727 | 716 |
| 728 WaitForCoalescence(); | 717 ASSERT_TRUE(timer_->IsRunning()); |
| 718 timer_->Fire(); |
| 719 context()->WaitForUpdate(); |
| 729 | 720 |
| 730 // We should have 6 entries added in 2 events. | 721 // We should have 6 entries added in 2 events. |
| 731 EXPECT_EQ(6, context()->add_count()); | 722 EXPECT_EQ(6, context()->add_count()); |
| 732 EXPECT_EQ(2, context()->add_event_count()); | 723 EXPECT_EQ(2, context()->add_event_count()); |
| 733 | 724 |
| 734 // Test whether duplicate entries produce add events. | 725 // Test whether duplicate entries produce add events. |
| 735 master()->AddURL(GURL("http://acidtests.org/")); | 726 master()->AddURL(GURL("http://acidtests.org/")); |
| 736 | 727 EXPECT_FALSE(timer_->IsRunning()); |
| 737 WaitForCoalescence(); | 728 context()->WaitForNoUpdate(); |
| 738 | 729 |
| 739 // We should have no change in results. | 730 // We should have no change in results. |
| 740 EXPECT_EQ(6, context()->add_count()); | 731 EXPECT_EQ(6, context()->add_count()); |
| 741 EXPECT_EQ(2, context()->add_event_count()); | 732 EXPECT_EQ(2, context()->add_event_count()); |
| 742 | 733 |
| 743 // Ensure that the coalescing does not resume after resetting. | 734 // Ensure that the coalescing does not resume after resetting. |
| 744 master()->AddURL(GURL("http://build.chromium.org/")); | 735 master()->AddURL(GURL("http://build.chromium.org/")); |
| 736 EXPECT_TRUE(timer_->IsRunning()); |
| 745 master()->DeleteAllURLs(); | 737 master()->DeleteAllURLs(); |
| 746 | 738 EXPECT_FALSE(timer_->IsRunning()); |
| 747 WaitForCoalescence(); | 739 context()->WaitForNoUpdate(); |
| 748 | 740 |
| 749 // We should have no change in results except for one new reset event. | 741 // We should have no change in results except for one new reset event. |
| 750 EXPECT_EQ(6, context()->add_count()); | 742 EXPECT_EQ(6, context()->add_count()); |
| 751 EXPECT_EQ(2, context()->add_event_count()); | 743 EXPECT_EQ(2, context()->add_event_count()); |
| 752 EXPECT_EQ(2, context()->reset_event_count()); | 744 EXPECT_EQ(2, context()->reset_event_count()); |
| 753 } | 745 } |
| 754 | 746 |
| 755 TEST_F(VisitedLinkEventsTest, Basics) { | 747 TEST_F(VisitedLinkEventsTest, Basics) { |
| 756 RenderViewHostTester::For(rvh())->CreateTestRenderView( | 748 RenderViewHostTester::For(rvh())->CreateTestRenderView( |
| 757 base::string16(), MSG_ROUTING_NONE, MSG_ROUTING_NONE, -1, false); | 749 base::string16(), MSG_ROUTING_NONE, MSG_ROUTING_NONE, -1, false); |
| 758 | 750 |
| 759 // Waiting complete rebuild the table. | 751 // Waiting complete rebuild the table. |
| 760 content::RunAllBlockingPoolTasksUntilIdle(); | 752 content::RunAllBlockingPoolTasksUntilIdle(); |
| 761 | 753 |
| 762 WaitForCoalescence(); | |
| 763 | |
| 764 // After rebuild table expect reset event. | 754 // After rebuild table expect reset event. |
| 765 EXPECT_EQ(1, context()->reset_event_count()); | 755 EXPECT_EQ(1, context()->reset_event_count()); |
| 766 | 756 |
| 767 // Add a few URLs. | 757 // Add a few URLs. |
| 768 master()->AddURL(GURL("http://acidtests.org/")); | 758 master()->AddURL(GURL("http://acidtests.org/")); |
| 769 master()->AddURL(GURL("http://google.com/")); | 759 master()->AddURL(GURL("http://google.com/")); |
| 770 master()->AddURL(GURL("http://chromium.org/")); | 760 master()->AddURL(GURL("http://chromium.org/")); |
| 771 | 761 ASSERT_TRUE(timer_->IsRunning()); |
| 772 WaitForCoalescence(); | 762 timer_->Fire(); |
| 763 context()->WaitForUpdate(); |
| 773 | 764 |
| 774 // We now should have 1 add event. | 765 // We now should have 1 add event. |
| 775 EXPECT_EQ(1, context()->add_event_count()); | 766 EXPECT_EQ(1, context()->add_event_count()); |
| 776 EXPECT_EQ(1, context()->reset_event_count()); | 767 EXPECT_EQ(1, context()->reset_event_count()); |
| 777 | 768 |
| 778 master()->DeleteAllURLs(); | 769 master()->DeleteAllURLs(); |
| 779 | 770 |
| 780 WaitForCoalescence(); | 771 EXPECT_FALSE(timer_->IsRunning()); |
| 772 context()->WaitForNoUpdate(); |
| 781 | 773 |
| 782 // We should have no change in add results, plus one new reset event. | 774 // We should have no change in add results, plus one new reset event. |
| 783 EXPECT_EQ(1, context()->add_event_count()); | 775 EXPECT_EQ(1, context()->add_event_count()); |
| 784 EXPECT_EQ(2, context()->reset_event_count()); | 776 EXPECT_EQ(2, context()->reset_event_count()); |
| 785 } | 777 } |
| 786 | 778 |
| 787 TEST_F(VisitedLinkEventsTest, TabVisibility) { | 779 TEST_F(VisitedLinkEventsTest, TabVisibility) { |
| 788 RenderViewHostTester::For(rvh())->CreateTestRenderView( | 780 RenderViewHostTester::For(rvh())->CreateTestRenderView( |
| 789 base::string16(), MSG_ROUTING_NONE, MSG_ROUTING_NONE, -1, false); | 781 base::string16(), MSG_ROUTING_NONE, MSG_ROUTING_NONE, -1, false); |
| 790 | 782 |
| 791 // Waiting complete rebuild the table. | 783 // Waiting complete rebuild the table. |
| 792 content::RunAllBlockingPoolTasksUntilIdle(); | 784 content::RunAllBlockingPoolTasksUntilIdle(); |
| 793 | 785 |
| 794 WaitForCoalescence(); | |
| 795 | |
| 796 // After rebuild table expect reset event. | 786 // After rebuild table expect reset event. |
| 797 EXPECT_EQ(1, context()->reset_event_count()); | 787 EXPECT_EQ(1, context()->reset_event_count()); |
| 798 | 788 |
| 799 // Simulate tab becoming inactive. | 789 // Simulate tab becoming inactive. |
| 800 RenderViewHostTester::For(rvh())->SimulateWasHidden(); | 790 RenderViewHostTester::For(rvh())->SimulateWasHidden(); |
| 801 | 791 |
| 802 // Add a few URLs. | 792 // Add a few URLs. |
| 803 master()->AddURL(GURL("http://acidtests.org/")); | 793 master()->AddURL(GURL("http://acidtests.org/")); |
| 804 master()->AddURL(GURL("http://google.com/")); | 794 master()->AddURL(GURL("http://google.com/")); |
| 805 master()->AddURL(GURL("http://chromium.org/")); | 795 master()->AddURL(GURL("http://chromium.org/")); |
| 806 | 796 ASSERT_TRUE(timer_->IsRunning()); |
| 807 WaitForCoalescence(); | 797 timer_->Fire(); |
| 798 context()->WaitForNoUpdate(); |
| 808 | 799 |
| 809 // We shouldn't have any events. | 800 // We shouldn't have any events. |
| 810 EXPECT_EQ(0, context()->add_event_count()); | 801 EXPECT_EQ(0, context()->add_event_count()); |
| 811 EXPECT_EQ(1, context()->reset_event_count()); | 802 EXPECT_EQ(1, context()->reset_event_count()); |
| 812 | 803 |
| 813 // Simulate the tab becoming active. | 804 // Simulate the tab becoming active. |
| 814 RenderViewHostTester::For(rvh())->SimulateWasShown(); | 805 RenderViewHostTester::For(rvh())->SimulateWasShown(); |
| 806 context()->WaitForUpdate(); |
| 815 | 807 |
| 816 // We should now have 3 add events, still no reset events. | 808 // We should now have 3 add events, still no reset events. |
| 817 EXPECT_EQ(1, context()->add_event_count()); | 809 EXPECT_EQ(1, context()->add_event_count()); |
| 818 EXPECT_EQ(1, context()->reset_event_count()); | 810 EXPECT_EQ(1, context()->reset_event_count()); |
| 819 | 811 |
| 820 // Deactivate the tab again. | 812 // Deactivate the tab again. |
| 821 RenderViewHostTester::For(rvh())->SimulateWasHidden(); | 813 RenderViewHostTester::For(rvh())->SimulateWasHidden(); |
| 822 | 814 |
| 823 // Add a bunch of URLs (over 50) to exhaust the link event buffer. | 815 // Add a bunch of URLs (over 50) to exhaust the link event buffer. |
| 824 for (int i = 0; i < 100; i++) | 816 for (int i = 0; i < 100; i++) |
| 825 master()->AddURL(TestURL(i)); | 817 master()->AddURL(TestURL(i)); |
| 826 | 818 |
| 827 WaitForCoalescence(); | 819 ASSERT_TRUE(timer_->IsRunning()); |
| 820 timer_->Fire(); |
| 821 context()->WaitForNoUpdate(); |
| 828 | 822 |
| 829 // Again, no change in events until tab is active. | 823 // Again, no change in events until tab is active. |
| 830 EXPECT_EQ(1, context()->add_event_count()); | 824 EXPECT_EQ(1, context()->add_event_count()); |
| 831 EXPECT_EQ(1, context()->reset_event_count()); | 825 EXPECT_EQ(1, context()->reset_event_count()); |
| 832 | 826 |
| 833 // Activate the tab. | 827 // Activate the tab. |
| 834 RenderViewHostTester::For(rvh())->SimulateWasShown(); | 828 RenderViewHostTester::For(rvh())->SimulateWasShown(); |
| 829 EXPECT_FALSE(timer_->IsRunning()); |
| 830 context()->WaitForUpdate(); |
| 835 | 831 |
| 836 // We should have only one more reset event. | 832 // We should have only one more reset event. |
| 837 EXPECT_EQ(1, context()->add_event_count()); | 833 EXPECT_EQ(1, context()->add_event_count()); |
| 838 EXPECT_EQ(2, context()->reset_event_count()); | 834 EXPECT_EQ(2, context()->reset_event_count()); |
| 839 } | 835 } |
| 840 | 836 |
| 841 // Tests that VisitedLink ignores renderer process creation notification for a | 837 // Tests that VisitedLink ignores renderer process creation notification for a |
| 842 // different context. | 838 // different context. |
| 843 TEST_F(VisitedLinkEventsTest, IgnoreRendererCreationFromDifferentContext) { | 839 TEST_F(VisitedLinkEventsTest, IgnoreRendererCreationFromDifferentContext) { |
| 844 VisitCountingContext different_context; | 840 content::TestBrowserContext different_context; |
| 845 VisitRelayingRenderProcessHost different_process_host(&different_context); | 841 VisitCountingContext counting_context; |
| 842 VisitRelayingRenderProcessHost different_process_host(&different_context, |
| 843 &counting_context); |
| 846 | 844 |
| 847 content::NotificationService::current()->Notify( | 845 content::NotificationService::current()->Notify( |
| 848 content::NOTIFICATION_RENDERER_PROCESS_CREATED, | 846 content::NOTIFICATION_RENDERER_PROCESS_CREATED, |
| 849 content::Source<content::RenderProcessHost>(&different_process_host), | 847 content::Source<content::RenderProcessHost>(&different_process_host), |
| 850 content::NotificationService::NoDetails()); | 848 content::NotificationService::NoDetails()); |
| 851 WaitForCoalescence(); | 849 EXPECT_FALSE(counting_context.binding().is_bound()); |
| 852 | |
| 853 EXPECT_EQ(0, different_context.new_table_count()); | |
| 854 } | 850 } |
| 855 | 851 |
| 856 class VisitedLinkCompletelyResetEventTest : public VisitedLinkEventsTest { | 852 class VisitedLinkCompletelyResetEventTest : public VisitedLinkEventsTest { |
| 857 public: | 853 public: |
| 858 content::BrowserContext* CreateBrowserContext() override { | 854 content::BrowserContext* CreateBrowserContext() override { |
| 859 VisitCountingContext* context = new VisitCountingContext(); | 855 content::BrowserContext* context = new content::TestBrowserContext(); |
| 860 CreateVisitedLinkFile(context); | 856 CreateVisitedLinkFile(context); |
| 861 CreateVisitedLinkMaster(context); | 857 CreateVisitedLinkMaster(context); |
| 862 return context; | 858 return context; |
| 863 } | 859 } |
| 864 | 860 |
| 865 void CreateVisitedLinkFile(content::BrowserContext* browser_context) { | 861 void CreateVisitedLinkFile(content::BrowserContext* browser_context) { |
| 866 base::FilePath visited_file = | 862 base::FilePath visited_file = |
| 867 browser_context->GetPath().Append(FILE_PATH_LITERAL("Visited Links")); | 863 browser_context->GetPath().Append(FILE_PATH_LITERAL("Visited Links")); |
| 868 std::unique_ptr<VisitedLinkMaster> master( | 864 std::unique_ptr<VisitedLinkMaster> master( |
| 869 new VisitedLinkMaster(new TrackingVisitedLinkEventListener(), | 865 new VisitedLinkMaster(new TrackingVisitedLinkEventListener(), |
| 870 &delegate_, true, true, visited_file, 0)); | 866 &delegate_, true, true, visited_file, 0)); |
| 871 master->Init(); | 867 master->Init(); |
| 872 // Waiting complete create the table. | 868 // Waiting complete create the table. |
| 873 content::RunAllBlockingPoolTasksUntilIdle(); | 869 content::RunAllBlockingPoolTasksUntilIdle(); |
| 874 | 870 |
| 875 master.reset(); | 871 master.reset(); |
| 876 // Wait for all pending file I/O to be completed. | 872 // Wait for all pending file I/O to be completed. |
| 877 content::RunAllBlockingPoolTasksUntilIdle(); | 873 content::RunAllBlockingPoolTasksUntilIdle(); |
| 878 } | 874 } |
| 879 }; | 875 }; |
| 880 | 876 |
| 881 TEST_F(VisitedLinkCompletelyResetEventTest, LoadTable) { | 877 TEST_F(VisitedLinkCompletelyResetEventTest, LoadTable) { |
| 882 // Waiting complete loading the table. | 878 // Waiting complete loading the table. |
| 883 content::RunAllBlockingPoolTasksUntilIdle(); | 879 content::RunAllBlockingPoolTasksUntilIdle(); |
| 884 | 880 |
| 885 WaitForCoalescence(); | 881 context()->binding().FlushForTesting(); |
| 886 | 882 |
| 887 // After load table expect completely reset event. | 883 // After load table expect completely reset event. |
| 888 EXPECT_EQ(1, context()->completely_reset_event_count()); | 884 EXPECT_EQ(1, context()->completely_reset_event_count()); |
| 889 } | 885 } |
| 890 | 886 |
| 891 } // namespace visitedlink | 887 } // namespace visitedlink |
| OLD | NEW |