favicon_fetcher_browsertest.cc 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "weblayer/browser/favicon/favicon_fetcher_impl.h"
  5. #include "base/run_loop.h"
  6. #include "build/build_config.h"
  7. #include "components/favicon/content/content_favicon_driver.h"
  8. #include "ui/gfx/image/image.h"
  9. #include "weblayer/browser/browser_context_impl.h"
  10. #include "weblayer/browser/favicon/favicon_fetcher_impl.h"
  11. #include "weblayer/browser/favicon/favicon_service_impl.h"
  12. #include "weblayer/browser/favicon/favicon_service_impl_factory.h"
  13. #include "weblayer/browser/favicon/favicon_service_impl_observer.h"
  14. #include "weblayer/browser/favicon/test_favicon_fetcher_delegate.h"
  15. #include "weblayer/browser/profile_impl.h"
  16. #include "weblayer/browser/tab_impl.h"
  17. #include "weblayer/public/browser.h"
  18. #include "weblayer/public/favicon_fetcher_delegate.h"
  19. #include "weblayer/public/navigation_controller.h"
  20. #include "weblayer/shell/browser/shell.h"
  21. #include "weblayer/test/test_navigation_observer.h"
  22. #include "weblayer/test/weblayer_browser_test.h"
  23. #include "weblayer/test/weblayer_browser_test_utils.h"
  24. namespace weblayer {
  25. namespace {
  26. // FaviconServiceImplObserver used to wait for download to fail.
  27. class TestFaviconServiceImplObserver : public FaviconServiceImplObserver {
  28. public:
  29. void Wait() {
  30. ASSERT_EQ(nullptr, run_loop_.get());
  31. run_loop_ = std::make_unique<base::RunLoop>();
  32. run_loop_->Run();
  33. run_loop_.reset();
  34. }
  35. // FaviconServiceImplObserver:
  36. void OnUnableToDownloadFavicon() override {
  37. if (run_loop_)
  38. run_loop_->Quit();
  39. }
  40. private:
  41. std::unique_ptr<base::RunLoop> run_loop_;
  42. };
  43. } // namespace
  44. using FaviconFetcherBrowserTest = WebLayerBrowserTest;
  45. IN_PROC_BROWSER_TEST_F(FaviconFetcherBrowserTest, Basic) {
  46. ASSERT_TRUE(embedded_test_server()->Start());
  47. TestFaviconFetcherDelegate fetcher_delegate;
  48. auto fetcher = shell()->tab()->CreateFaviconFetcher(&fetcher_delegate);
  49. NavigateAndWaitForCompletion(
  50. embedded_test_server()->GetURL(
  51. "/simple_page_with_favicon_and_before_unload.html"),
  52. shell());
  53. fetcher_delegate.WaitForFavicon();
  54. EXPECT_FALSE(fetcher_delegate.last_image().IsEmpty());
  55. EXPECT_EQ(fetcher_delegate.last_image(), fetcher->GetFavicon());
  56. EXPECT_EQ(1, fetcher_delegate.on_favicon_changed_call_count());
  57. fetcher_delegate.ClearLastImage();
  58. const GURL url2 =
  59. embedded_test_server()->GetURL("/simple_page_with_favicon.html");
  60. shell()->tab()->GetNavigationController()->Navigate(url2);
  61. // Favicon doesn't change immediately on navigation.
  62. EXPECT_FALSE(fetcher->GetFavicon().IsEmpty());
  63. // Favicon does change once start is received.
  64. TestNavigationObserver test_observer(
  65. url2, TestNavigationObserver::NavigationEvent::kStart, shell());
  66. test_observer.Wait();
  67. EXPECT_TRUE(fetcher_delegate.last_image().IsEmpty());
  68. fetcher_delegate.WaitForNonemptyFavicon();
  69. EXPECT_FALSE(fetcher_delegate.last_image().IsEmpty());
  70. EXPECT_EQ(fetcher_delegate.last_image(), fetcher->GetFavicon());
  71. // OnFaviconChanged() is called twice, once with an empty image (because of
  72. // the navigation), the second with the real image.
  73. EXPECT_EQ(2, fetcher_delegate.on_favicon_changed_call_count());
  74. }
  75. IN_PROC_BROWSER_TEST_F(FaviconFetcherBrowserTest, NavigateToPageWithNoFavicon) {
  76. ASSERT_TRUE(embedded_test_server()->Start());
  77. TestFaviconFetcherDelegate fetcher_delegate;
  78. auto fetcher = shell()->tab()->CreateFaviconFetcher(&fetcher_delegate);
  79. NavigateAndWaitForCompletion(
  80. embedded_test_server()->GetURL("/simple_page_with_favicon.html"),
  81. shell());
  82. fetcher_delegate.WaitForFavicon();
  83. fetcher_delegate.ClearLastImage();
  84. TestFaviconServiceImplObserver test_observer;
  85. FaviconServiceImplFactory::GetForBrowserContext(
  86. static_cast<TabImpl*>(shell()->tab())->profile()->GetBrowserContext())
  87. ->set_observer(&test_observer);
  88. const GURL url2 = embedded_test_server()->GetURL("/simple_page.html");
  89. shell()->tab()->GetNavigationController()->Navigate(url2);
  90. EXPECT_TRUE(fetcher_delegate.last_image().IsEmpty());
  91. // The delegate should be notified of the empty image once.
  92. test_observer.Wait();
  93. EXPECT_TRUE(fetcher_delegate.last_image().IsEmpty());
  94. EXPECT_EQ(1, fetcher_delegate.on_favicon_changed_call_count());
  95. }
  96. IN_PROC_BROWSER_TEST_F(FaviconFetcherBrowserTest,
  97. ContentFaviconDriverLifetime) {
  98. ASSERT_TRUE(embedded_test_server()->Start());
  99. content::WebContents* web_contents =
  100. static_cast<TabImpl*>(shell()->tab())->web_contents();
  101. // Initially there should be no driver (because favicons haven't been
  102. // requested).
  103. EXPECT_EQ(nullptr,
  104. favicon::ContentFaviconDriver::FromWebContents(web_contents));
  105. // Request a fetcher, which should trigger creating ContentFaviconDriver.
  106. TestFaviconFetcherDelegate fetcher_delegate;
  107. auto fetcher = shell()->tab()->CreateFaviconFetcher(&fetcher_delegate);
  108. EXPECT_NE(nullptr,
  109. favicon::ContentFaviconDriver::FromWebContents(web_contents));
  110. // Destroy the fetcher, which should destroy ContentFaviconDriver.
  111. fetcher.reset();
  112. EXPECT_EQ(nullptr,
  113. favicon::ContentFaviconDriver::FromWebContents(web_contents));
  114. // One more time, and this time navigate.
  115. fetcher = shell()->tab()->CreateFaviconFetcher(&fetcher_delegate);
  116. NavigateAndWaitForCompletion(
  117. embedded_test_server()->GetURL("/simple_page_with_favicon.html"),
  118. shell());
  119. fetcher_delegate.WaitForFavicon();
  120. EXPECT_FALSE(fetcher_delegate.last_image().IsEmpty());
  121. }
  122. // This test creates a Browser and Tab, which doesn't work well with Java when
  123. // driven from native code.
  124. #if !BUILDFLAG(IS_ANDROID)
  125. IN_PROC_BROWSER_TEST_F(FaviconFetcherBrowserTest, OffTheRecord) {
  126. auto otr_profile = Profile::Create(std::string(), true);
  127. ProfileImpl* otr_profile_impl = static_cast<ProfileImpl*>(otr_profile.get());
  128. EXPECT_TRUE(otr_profile_impl->GetBrowserContext()->IsOffTheRecord());
  129. auto otr_browser = Browser::Create(otr_profile.get(), nullptr);
  130. Tab* tab = otr_browser->CreateTab();
  131. // There is no FaviconService for off the record profiles. FaviconService
  132. // writes to disk, which is not appropriate for off the record mode.
  133. EXPECT_EQ(nullptr, FaviconServiceImplFactory::GetForBrowserContext(
  134. otr_profile_impl->GetBrowserContext()));
  135. ASSERT_TRUE(embedded_test_server()->Start());
  136. TestFaviconFetcherDelegate fetcher_delegate;
  137. auto fetcher = tab->CreateFaviconFetcher(&fetcher_delegate);
  138. NavigateAndWaitForCompletion(
  139. embedded_test_server()->GetURL("/simple_page_with_favicon.html"), tab);
  140. fetcher_delegate.WaitForFavicon();
  141. EXPECT_FALSE(fetcher_delegate.last_image().IsEmpty());
  142. EXPECT_EQ(fetcher_delegate.last_image(), fetcher->GetFavicon());
  143. EXPECT_EQ(1, fetcher_delegate.on_favicon_changed_call_count());
  144. }
  145. #endif
  146. } // namespace weblayer