favicon_browsertest.cc 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // Copyright 2021 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 "base/fuchsia/mem_buffer_util.h"
  5. #include "content/public/test/browser_test.h"
  6. #include "fuchsia_web/common/test/frame_test_util.h"
  7. #include "fuchsia_web/common/test/test_navigation_listener.h"
  8. #include "fuchsia_web/webengine/test/frame_for_test.h"
  9. #include "fuchsia_web/webengine/test/test_data.h"
  10. #include "fuchsia_web/webengine/test/web_engine_browser_test.h"
  11. #include "testing/gtest/include/gtest/gtest.h"
  12. namespace {
  13. const char kFaviconPageUrl[] = "/favicon.html";
  14. void QuitLoopIfFaviconUpdated(
  15. base::RepeatingClosure quit_run_loop_closure,
  16. const fuchsia::web::NavigationState& change,
  17. fuchsia::web::NavigationEventListener::OnNavigationStateChangedCallback
  18. ack_callback) {
  19. if (change.has_favicon())
  20. quit_run_loop_closure.Run();
  21. ack_callback();
  22. }
  23. void RunUntilFaviconUpdated(TestNavigationListener* test_navigation_listener) {
  24. base::RunLoop run_loop;
  25. test_navigation_listener->SetBeforeAckHook(
  26. base::BindRepeating(&QuitLoopIfFaviconUpdated, run_loop.QuitClosure()));
  27. run_loop.Run();
  28. }
  29. void ValidateFavicon(const fuchsia::web::Favicon& favicon,
  30. size_t expected_width,
  31. size_t expected_height,
  32. size_t check_point_x,
  33. size_t check_point_y,
  34. uint32_t expected_color) {
  35. ASSERT_TRUE(favicon.has_width());
  36. EXPECT_EQ(favicon.width(), expected_width);
  37. ASSERT_TRUE(favicon.has_height());
  38. EXPECT_EQ(favicon.height(), expected_height);
  39. ASSERT_TRUE(favicon.has_data());
  40. absl::optional<std::string> data = base::StringFromMemBuffer(favicon.data());
  41. ASSERT_TRUE(data.has_value());
  42. size_t expected_size = expected_width * expected_height * sizeof(uint32_t);
  43. ASSERT_EQ(data->size(), expected_size);
  44. size_t offset = check_point_x + check_point_y * expected_width;
  45. uint32_t color = reinterpret_cast<const uint32_t*>(data->data())[offset];
  46. EXPECT_EQ(color, expected_color);
  47. }
  48. } // namespace
  49. class FaviconTest : public WebEngineBrowserTest {
  50. public:
  51. FaviconTest() { set_test_server_root(base::FilePath(kTestServerRoot)); }
  52. ~FaviconTest() override = default;
  53. protected:
  54. void SetUpOnMainThread() override {
  55. WebEngineBrowserTest::SetUpOnMainThread();
  56. ASSERT_TRUE(embedded_test_server()->Start());
  57. frame_ = FrameForTest::Create(context(), {});
  58. }
  59. FrameForTest frame_;
  60. };
  61. // Verify that favicons are not loaded by default.
  62. IN_PROC_BROWSER_TEST_F(FaviconTest, Disabled) {
  63. GURL url = embedded_test_server()->GetURL(kFaviconPageUrl);
  64. EXPECT_TRUE(LoadUrlAndExpectResponse(frame_.GetNavigationController(), {},
  65. url.spec()));
  66. frame_.navigation_listener().RunUntilUrlAndTitleEquals(url, "Favicon");
  67. // Favicon should not be sent.
  68. EXPECT_FALSE(frame_.navigation_listener().current_state()->has_favicon());
  69. // Call GetVisibleEntry() and verify that it doesn't send favicon.
  70. base::RunLoop run_loop;
  71. fuchsia::web::NavigationState visible_entry;
  72. auto nav_controller = frame_.GetNavigationController();
  73. nav_controller->GetVisibleEntry(
  74. [&run_loop, &visible_entry](fuchsia::web::NavigationState result) {
  75. visible_entry = std::move(result);
  76. run_loop.Quit();
  77. });
  78. run_loop.Run();
  79. EXPECT_FALSE(visible_entry.has_favicon());
  80. }
  81. // Check that the favicon for the page is sent after the page is loaded. Also
  82. // verify that the icon is reloaded when the page changes.
  83. IN_PROC_BROWSER_TEST_F(FaviconTest, LoadAndUpdate) {
  84. frame_.CreateAndAttachNavigationListener(
  85. fuchsia::web::NavigationEventListenerFlags::FAVICON);
  86. GURL url = embedded_test_server()->GetURL(kFaviconPageUrl);
  87. EXPECT_TRUE(LoadUrlAndExpectResponse(frame_.GetNavigationController(), {},
  88. url.spec()));
  89. // An empty favicon should be sent first.
  90. RunUntilFaviconUpdated(&frame_.navigation_listener());
  91. EXPECT_TRUE(
  92. frame_.navigation_listener().current_state()->favicon().IsEmpty());
  93. // The image is sent later.
  94. RunUntilFaviconUpdated(&frame_.navigation_listener());
  95. ValidateFavicon(frame_.navigation_listener().current_state()->favicon(), 16,
  96. 16, 7, 4, 0xA6272536);
  97. EXPECT_EQ(frame_.navigation_listener().current_state()->url(), url.spec());
  98. EXPECT_EQ(frame_.navigation_listener().current_state()->title(), "Favicon");
  99. // Update the icon from the page and verify that it's updated as expected.
  100. ExecuteJavaScript(frame_.get(),
  101. "document.getElementById('favicon').href = 'favicon2.png'");
  102. RunUntilFaviconUpdated(&frame_.navigation_listener());
  103. ValidateFavicon(frame_.navigation_listener().current_state()->favicon(), 16,
  104. 16, 12, 7, 0xB5A39C1A);
  105. // URL and Title should not change when the favicon is loaded.
  106. EXPECT_FALSE(frame_.navigation_listener().last_changes()->has_url());
  107. EXPECT_FALSE(frame_.navigation_listener().last_changes()->has_title());
  108. }
  109. // Check that the favicon updates after a navigation.
  110. IN_PROC_BROWSER_TEST_F(FaviconTest, FaviconNavigations) {
  111. frame_.CreateAndAttachNavigationListener(
  112. fuchsia::web::NavigationEventListenerFlags::FAVICON);
  113. GURL url = embedded_test_server()->GetURL(kFaviconPageUrl);
  114. EXPECT_TRUE(LoadUrlAndExpectResponse(frame_.GetNavigationController(), {},
  115. url.spec()));
  116. // An empty favicon should be sent first.
  117. RunUntilFaviconUpdated(&frame_.navigation_listener());
  118. EXPECT_TRUE(
  119. frame_.navigation_listener().current_state()->favicon().IsEmpty());
  120. // The image is sent later.
  121. RunUntilFaviconUpdated(&frame_.navigation_listener());
  122. ValidateFavicon(frame_.navigation_listener().current_state()->favicon(), 16,
  123. 16, 7, 4, 0xA6272536);
  124. // Reload the same page with a different query string.
  125. url = embedded_test_server()->GetURL(std::string(kFaviconPageUrl) +
  126. "?favicon=favicon2.png");
  127. EXPECT_TRUE(LoadUrlAndExpectResponse(frame_.GetNavigationController(), {},
  128. url.spec()));
  129. // An empty icon should be sent when navigating to a new page.
  130. frame_.navigation_listener().RunUntilUrlEquals(url);
  131. EXPECT_TRUE(
  132. frame_.navigation_listener().current_state()->favicon().IsEmpty());
  133. // The favicon is sent later.
  134. RunUntilFaviconUpdated(&frame_.navigation_listener());
  135. ValidateFavicon(frame_.navigation_listener().current_state()->favicon(), 16,
  136. 16, 12, 7, 0xB5A39C1A);
  137. }