Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "components/favicon/content/content_favicon_driver.h" | 5 #include "components/favicon/content/content_favicon_driver.h" |
| 6 | 6 |
| 7 #include "base/location.h" | 7 #include "base/location.h" |
| 8 #include "base/macros.h" | 8 #include "base/macros.h" |
| 9 #include "base/memory/weak_ptr.h" | 9 #include "base/memory/weak_ptr.h" |
| 10 #include "base/run_loop.h" | 10 #include "base/run_loop.h" |
| 11 #include "base/scoped_observer.h" | 11 #include "base/scoped_observer.h" |
| 12 #include "base/single_thread_task_runner.h" | 12 #include "base/single_thread_task_runner.h" |
| 13 #include "base/test/scoped_feature_list.h" | |
| 13 #include "base/threading/thread_task_runner_handle.h" | 14 #include "base/threading/thread_task_runner_handle.h" |
| 14 #include "chrome/app/chrome_command_ids.h" | 15 #include "chrome/app/chrome_command_ids.h" |
| 15 #include "chrome/browser/chrome_notification_types.h" | 16 #include "chrome/browser/chrome_notification_types.h" |
| 17 #include "chrome/browser/favicon/favicon_service_factory.h" | |
| 16 #include "chrome/browser/ui/browser.h" | 18 #include "chrome/browser/ui/browser.h" |
| 17 #include "chrome/browser/ui/browser_commands.h" | 19 #include "chrome/browser/ui/browser_commands.h" |
| 18 #include "chrome/browser/ui/tabs/tab_strip_model.h" | 20 #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| 19 #include "chrome/test/base/in_process_browser_test.h" | 21 #include "chrome/test/base/in_process_browser_test.h" |
| 20 #include "chrome/test/base/ui_test_utils.h" | 22 #include "chrome/test/base/ui_test_utils.h" |
| 21 #include "components/favicon/core/favicon_driver_observer.h" | 23 #include "components/favicon/core/favicon_driver_observer.h" |
| 22 #include "components/favicon/core/favicon_handler.h" | 24 #include "components/favicon/core/favicon_handler.h" |
| 25 #include "components/favicon/core/favicon_service.h" | |
| 23 #include "content/public/browser/notification_observer.h" | 26 #include "content/public/browser/notification_observer.h" |
| 24 #include "content/public/browser/notification_registrar.h" | 27 #include "content/public/browser/notification_registrar.h" |
| 25 #include "content/public/browser/notification_types.h" | 28 #include "content/public/browser/notification_types.h" |
| 26 #include "content/public/browser/resource_dispatcher_host.h" | 29 #include "content/public/browser/resource_dispatcher_host.h" |
| 27 #include "content/public/browser/resource_dispatcher_host_delegate.h" | 30 #include "content/public/browser/resource_dispatcher_host_delegate.h" |
| 28 #include "net/base/load_flags.h" | 31 #include "net/base/load_flags.h" |
| 29 #include "net/test/embedded_test_server/embedded_test_server.h" | 32 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 30 #include "net/url_request/url_request.h" | 33 #include "net/url_request/url_request.h" |
| 31 #include "url/url_constants.h" | 34 #include "url/url_constants.h" |
| 32 | 35 |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 122 } | 125 } |
| 123 | 126 |
| 124 private: | 127 private: |
| 125 // content::NotificationObserver: | 128 // content::NotificationObserver: |
| 126 void Observe(int type, | 129 void Observe(int type, |
| 127 const content::NotificationSource& source, | 130 const content::NotificationSource& source, |
| 128 const content::NotificationDetails& details) override { | 131 const content::NotificationDetails& details) override { |
| 129 if (type == content::NOTIFICATION_LOAD_STOP) | 132 if (type == content::NOTIFICATION_LOAD_STOP) |
| 130 load_stopped_ = true; | 133 load_stopped_ = true; |
| 131 | 134 |
| 132 OnNotification(); | 135 // We need to verify completion periodically because not all paths result |
| 136 // in a notification that can be reacted to immediately. For example, if | |
| 137 // the history database lookup success after candidates have been fed into | |
| 138 // FaviconHandler. | |
|
pkotwicz
2017/05/17 05:20:34
I find this comment confusing
How about: "We need
mastiz
2017/05/17 05:53:02
Done.
| |
| 139 CallOnNotificationPeriodically(); | |
|
pkotwicz
2017/05/17 05:20:34
Maybe rename this function CheckStopWaitingPeriodi
mastiz
2017/05/17 05:53:02
Done.
| |
| 133 } | 140 } |
| 134 | 141 |
| 135 // favicon::Favicon | 142 // favicon::Favicon |
| 136 void OnFaviconUpdated(favicon::FaviconDriver* favicon_driver, | 143 void OnFaviconUpdated(favicon::FaviconDriver* favicon_driver, |
| 137 NotificationIconType notification_icon_type, | 144 NotificationIconType notification_icon_type, |
| 138 const GURL& icon_url, | 145 const GURL& icon_url, |
| 139 bool icon_url_changed, | 146 bool icon_url_changed, |
| 140 const gfx::Image& image) override { | 147 const gfx::Image& image) override { |
|
pkotwicz
2017/05/17 05:20:34
Should we just delete this function now that we po
mastiz
2017/05/17 05:53:03
Done.
| |
| 141 OnNotification(); | 148 OnNotification(); |
| 142 } | 149 } |
| 143 | 150 |
| 144 void OnNotification() { | 151 void OnNotification() { |
| 145 if (!quit_closure_.is_null()) { | 152 if (!quit_closure_.is_null()) { |
| 146 // We stop waiting based on changes in state to FaviconHandler which occur | 153 // We stop waiting based on changes in state to FaviconHandler which occur |
| 147 // immediately after OnFaviconUpdated() is called. Post a task to check if | 154 // immediately after OnFaviconUpdated() is called. Post a task to check if |
| 148 // we can stop waiting. | 155 // we can stop waiting. |
| 149 base::ThreadTaskRunnerHandle::Get()->PostTask( | 156 base::ThreadTaskRunnerHandle::Get()->PostTask( |
| 150 FROM_HERE, base::BindOnce(&PendingTaskWaiter::EndLoopIfCanStopWaiting, | 157 FROM_HERE, base::BindOnce(&PendingTaskWaiter::EndLoopIfCanStopWaiting, |
| 151 weak_factory_.GetWeakPtr())); | 158 weak_factory_.GetWeakPtr())); |
| 152 } | 159 } |
| 153 } | 160 } |
| 154 | 161 |
| 162 void CallOnNotificationPeriodically() { | |
| 163 OnNotification(); | |
|
pkotwicz
2017/05/17 05:20:34
Can we call EndLoopIfCanStopWaiting() directly?
mastiz
2017/05/17 05:53:03
Done.
| |
| 164 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | |
| 165 FROM_HERE, | |
| 166 base::BindOnce(&PendingTaskWaiter::CallOnNotificationPeriodically, | |
| 167 weak_factory_.GetWeakPtr()), | |
| 168 base::TimeDelta::FromSeconds(1)); | |
| 169 } | |
| 170 | |
| 155 void EndLoopIfCanStopWaiting() { | 171 void EndLoopIfCanStopWaiting() { |
| 156 if (!quit_closure_.is_null() && | 172 if (!quit_closure_.is_null() && |
| 157 load_stopped_ && | 173 load_stopped_ && |
| 158 !checker_->HasPendingTasks()) { | 174 !checker_->HasPendingTasks()) { |
| 159 quit_closure_.Run(); | 175 quit_closure_.Run(); |
| 160 } | 176 } |
| 161 } | 177 } |
| 162 | 178 |
| 163 FaviconDriverPendingTaskChecker* checker_; // Not owned. | 179 FaviconDriverPendingTaskChecker* checker_; // Not owned. |
| 164 bool load_stopped_; | 180 bool load_stopped_; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 181 content::WebContents* web_contents() { | 197 content::WebContents* web_contents() { |
| 182 return browser()->tab_strip_model()->GetActiveWebContents(); | 198 return browser()->tab_strip_model()->GetActiveWebContents(); |
| 183 } | 199 } |
| 184 | 200 |
| 185 // FaviconDriverPendingTaskChecker: | 201 // FaviconDriverPendingTaskChecker: |
| 186 bool HasPendingTasks() override { | 202 bool HasPendingTasks() override { |
| 187 return favicon::ContentFaviconDriver::FromWebContents(web_contents()) | 203 return favicon::ContentFaviconDriver::FromWebContents(web_contents()) |
| 188 ->HasPendingTasksForTest(); | 204 ->HasPendingTasksForTest(); |
| 189 } | 205 } |
| 190 | 206 |
| 207 favicon_base::FaviconRawBitmapResult GetFaviconForPageURL(const GURL& url) { | |
| 208 favicon::FaviconService* favicon_service = | |
| 209 FaviconServiceFactory::GetForProfile( | |
| 210 browser()->profile(), ServiceAccessType::EXPLICIT_ACCESS); | |
| 211 | |
| 212 std::vector<favicon_base::FaviconRawBitmapResult> results; | |
| 213 base::CancelableTaskTracker tracker; | |
| 214 base::RunLoop loop; | |
| 215 favicon_service->GetFaviconForPageURL( | |
| 216 url, favicon_base::FAVICON, /*desired_size_in_dip=*/0, | |
| 217 base::Bind( | |
| 218 [](std::vector<favicon_base::FaviconRawBitmapResult>* save_results, | |
| 219 base::RunLoop* loop, | |
| 220 const std::vector<favicon_base::FaviconRawBitmapResult>& | |
| 221 results) { | |
| 222 *save_results = results; | |
| 223 loop->Quit(); | |
| 224 }, | |
| 225 &results, &loop), | |
| 226 &tracker); | |
| 227 loop.Run(); | |
| 228 for (const favicon_base::FaviconRawBitmapResult& result : results) { | |
| 229 if (result.is_valid()) | |
| 230 return result; | |
| 231 } | |
| 232 return favicon_base::FaviconRawBitmapResult(); | |
| 233 } | |
| 234 | |
| 191 private: | 235 private: |
| 192 DISALLOW_COPY_AND_ASSIGN(ContentFaviconDriverTest); | 236 DISALLOW_COPY_AND_ASSIGN(ContentFaviconDriverTest); |
| 193 }; | 237 }; |
| 194 | 238 |
| 195 // Test that when a user reloads a page ignoring the cache that the favicon is | 239 // Test that when a user reloads a page ignoring the cache that the favicon is |
| 196 // is redownloaded and (not returned from either the favicon cache or the HTTP | 240 // is redownloaded and (not returned from either the favicon cache or the HTTP |
| 197 // cache). | 241 // cache). |
| 198 IN_PROC_BROWSER_TEST_F(ContentFaviconDriverTest, ReloadBypassingCache) { | 242 IN_PROC_BROWSER_TEST_F(ContentFaviconDriverTest, ReloadBypassingCache) { |
| 199 ASSERT_TRUE(embedded_test_server()->Start()); | 243 ASSERT_TRUE(embedded_test_server()->Start()); |
| 200 GURL url = embedded_test_server()->GetURL("/favicon/page_with_favicon.html"); | 244 GURL url = embedded_test_server()->GetURL("/favicon/page_with_favicon.html"); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 232 | 276 |
| 233 // A reload ignoring the cache should refetch the favicon from the website. | 277 // A reload ignoring the cache should refetch the favicon from the website. |
| 234 { | 278 { |
| 235 PendingTaskWaiter waiter(web_contents(), this); | 279 PendingTaskWaiter waiter(web_contents(), this); |
| 236 chrome::ExecuteCommand(browser(), IDC_RELOAD_BYPASSING_CACHE); | 280 chrome::ExecuteCommand(browser(), IDC_RELOAD_BYPASSING_CACHE); |
| 237 waiter.Wait(); | 281 waiter.Wait(); |
| 238 } | 282 } |
| 239 ASSERT_TRUE(delegate->was_requested()); | 283 ASSERT_TRUE(delegate->was_requested()); |
| 240 EXPECT_TRUE(delegate->bypassed_cache()); | 284 EXPECT_TRUE(delegate->bypassed_cache()); |
| 241 } | 285 } |
| 286 | |
| 287 // Test that loading a page that contains icons only in the Web Manifest causes | |
| 288 // those icons to be used. | |
| 289 IN_PROC_BROWSER_TEST_F(ContentFaviconDriverTest, LoadIconFromWebManifest) { | |
| 290 base::test::ScopedFeatureList override_features; | |
| 291 override_features.InitAndEnableFeature(favicon::kFaviconsFromWebManifest); | |
| 292 | |
| 293 ASSERT_TRUE(embedded_test_server()->Start()); | |
| 294 GURL url = embedded_test_server()->GetURL("/favicon/page_with_manifest.html"); | |
| 295 GURL icon_url = embedded_test_server()->GetURL("/favicon/icon.png"); | |
| 296 | |
| 297 std::unique_ptr<TestResourceDispatcherHostDelegate> delegate( | |
| 298 new TestResourceDispatcherHostDelegate(icon_url)); | |
| 299 content::ResourceDispatcherHost::Get()->SetDelegate(delegate.get()); | |
| 300 | |
| 301 PendingTaskWaiter waiter(web_contents(), this); | |
| 302 ui_test_utils::NavigateToURLWithDisposition( | |
| 303 browser(), url, WindowOpenDisposition::CURRENT_TAB, | |
| 304 ui_test_utils::BROWSER_TEST_NONE); | |
| 305 waiter.Wait(); | |
| 306 | |
| 307 EXPECT_TRUE(delegate->was_requested()); | |
| 308 } | |
| 309 | |
| 310 // Test that loading a page that contains a Web Manifest without icons and a | |
| 311 // regular favicon in the HTML reports the icon. The regular icon is initially | |
| 312 // cached in the Favicon database. | |
| 313 IN_PROC_BROWSER_TEST_F(ContentFaviconDriverTest, | |
| 314 LoadRegularIconDespiteWebManifestWithoutIcons) { | |
| 315 ASSERT_TRUE(embedded_test_server()->Start()); | |
| 316 GURL url = embedded_test_server()->GetURL( | |
| 317 "/favicon/page_with_manifest_without_icons.html"); | |
| 318 GURL icon_url = embedded_test_server()->GetURL("/favicon/icon.png"); | |
| 319 | |
| 320 // Initial visit with the feature still disabled. | |
|
pkotwicz
2017/05/17 05:20:34
This comment does not really match up
mastiz
2017/05/17 05:53:02
Done.
| |
| 321 std::unique_ptr<TestResourceDispatcherHostDelegate> delegate( | |
| 322 new TestResourceDispatcherHostDelegate(icon_url)); | |
| 323 content::ResourceDispatcherHost::Get()->SetDelegate(delegate.get()); | |
| 324 | |
| 325 // Initial visit with the feature still disabled, to populate the cache. | |
| 326 { | |
| 327 PendingTaskWaiter waiter(web_contents(), this); | |
| 328 ui_test_utils::NavigateToURLWithDisposition( | |
| 329 browser(), url, WindowOpenDisposition::CURRENT_TAB, | |
| 330 ui_test_utils::BROWSER_TEST_NONE); | |
| 331 waiter.Wait(); | |
| 332 } | |
| 333 ASSERT_TRUE(delegate->was_requested()); | |
| 334 delegate->Reset(); | |
|
pkotwicz
2017/05/17 05:20:34
Do you need |delegate| at all for this test?
mastiz
2017/05/17 05:53:02
Done.
| |
| 335 ASSERT_NE(nullptr, GetFaviconForPageURL(url).bitmap_data); | |
| 336 | |
| 337 ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL)); | |
| 338 | |
| 339 // Enable the feature and visit the page again. | |
| 340 base::test::ScopedFeatureList override_features; | |
| 341 override_features.InitAndEnableFeature(favicon::kFaviconsFromWebManifest); | |
| 342 | |
| 343 { | |
| 344 PendingTaskWaiter waiter(web_contents(), this); | |
| 345 ui_test_utils::NavigateToURLWithDisposition( | |
| 346 browser(), url, WindowOpenDisposition::CURRENT_TAB, | |
| 347 ui_test_utils::BROWSER_TEST_NONE); | |
| 348 waiter.Wait(); | |
| 349 } | |
| 350 | |
| 351 EXPECT_NE(nullptr, GetFaviconForPageURL(url).bitmap_data); | |
| 352 } | |
| OLD | NEW |