Add ICU message format support
[chromium-blink-merge.git] / chrome / browser / favicon / content_favicon_driver_browsertest.cc
blobe73a95f74c2d6e10326ad7aaf150af49c6db31c0
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
3 // found in the LICENSE file.
5 #include "components/favicon/content/content_favicon_driver.h"
7 #include "base/location.h"
8 #include "base/memory/weak_ptr.h"
9 #include "base/run_loop.h"
10 #include "base/scoped_observer.h"
11 #include "base/single_thread_task_runner.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "chrome/app/chrome_command_ids.h"
14 #include "chrome/browser/chrome_notification_types.h"
15 #include "chrome/browser/ui/browser.h"
16 #include "chrome/browser/ui/browser_commands.h"
17 #include "chrome/browser/ui/tabs/tab_strip_model.h"
18 #include "chrome/test/base/in_process_browser_test.h"
19 #include "chrome/test/base/ui_test_utils.h"
20 #include "components/favicon/core/favicon_driver_observer.h"
21 #include "components/favicon/core/favicon_handler.h"
22 #include "content/public/browser/notification_observer.h"
23 #include "content/public/browser/notification_registrar.h"
24 #include "content/public/browser/notification_types.h"
25 #include "content/public/browser/resource_dispatcher_host.h"
26 #include "content/public/browser/resource_dispatcher_host_delegate.h"
27 #include "net/base/load_flags.h"
28 #include "net/test/spawned_test_server/spawned_test_server.h"
29 #include "net/url_request/url_request.h"
30 #include "url/url_constants.h"
32 namespace {
34 // Tracks whether the URL passed to the constructor is requested and whether
35 // the request bypasses the cache.
36 class TestResourceDispatcherHostDelegate
37 : public content::ResourceDispatcherHostDelegate {
38 public:
39 explicit TestResourceDispatcherHostDelegate(const GURL& url)
40 : url_(url), was_requested_(false), bypassed_cache_(false) {}
41 ~TestResourceDispatcherHostDelegate() override {}
43 void Reset() {
44 was_requested_ = false;
45 bypassed_cache_ = false;
48 // Resturns whether |url_| was requested.
49 bool was_requested() const { return was_requested_; }
51 // Returns whether any of the requests bypassed the HTTP cache.
52 bool bypassed_cache() const { return bypassed_cache_; }
54 private:
55 // content::ResourceDispatcherHostDelegate:
56 bool ShouldBeginRequest(const std::string& method,
57 const GURL& url,
58 content::ResourceType resource_type,
59 content::ResourceContext* resource_context) override {
60 return true;
63 void RequestBeginning(
64 net::URLRequest* request,
65 content::ResourceContext* resource_context,
66 content::AppCacheService* appcache_service,
67 content::ResourceType resource_type,
68 ScopedVector<content::ResourceThrottle>* throttles) override {
69 if (request->url() == url_) {
70 was_requested_ = true;
71 if (request->load_flags() & net::LOAD_BYPASS_CACHE)
72 bypassed_cache_ = true;
76 void DownloadStarting(
77 net::URLRequest* request,
78 content::ResourceContext* resource_context,
79 int child_id,
80 int route_id,
81 int request_id,
82 bool is_content_initiated,
83 bool must_download,
84 ScopedVector<content::ResourceThrottle>* throttles) override {}
86 private:
87 GURL url_;
88 bool was_requested_;
89 bool bypassed_cache_;
91 DISALLOW_COPY_AND_ASSIGN(TestResourceDispatcherHostDelegate);
94 // Checks whether the FaviconDriver is waiting for a download to complete or
95 // for data from the FaviconService.
96 class FaviconDriverPendingTaskChecker {
97 public:
98 virtual ~FaviconDriverPendingTaskChecker() {}
100 virtual bool HasPendingTasks() = 0;
103 // Waits for the following the finish:
104 // - The pending navigation.
105 // - FaviconHandler's pending favicon database requests.
106 // - FaviconHandler's pending downloads.
107 class PendingTaskWaiter : public content::NotificationObserver,
108 public favicon::FaviconDriverObserver {
109 public:
110 PendingTaskWaiter(content::WebContents* web_contents,
111 FaviconDriverPendingTaskChecker* checker)
112 : checker_(checker),
113 load_stopped_(false),
114 scoped_observer_(this),
115 weak_factory_(this) {
116 registrar_.Add(this, content::NOTIFICATION_LOAD_STOP,
117 content::Source<content::NavigationController>(
118 &web_contents->GetController()));
119 scoped_observer_.Add(
120 favicon::ContentFaviconDriver::FromWebContents(web_contents));
122 ~PendingTaskWaiter() override {}
124 void Wait() {
125 if (load_stopped_ && !checker_->HasPendingTasks())
126 return;
128 base::RunLoop run_loop;
129 quit_closure_ = run_loop.QuitClosure();
130 run_loop.Run();
133 private:
134 // content::NotificationObserver:
135 void Observe(int type,
136 const content::NotificationSource& source,
137 const content::NotificationDetails& details) override {
138 if (type == content::NOTIFICATION_LOAD_STOP)
139 load_stopped_ = true;
141 OnNotification();
144 // favicon::Favicon
145 void OnFaviconAvailable(const gfx::Image& image) override {}
146 void OnFaviconUpdated(favicon::FaviconDriver* favicon_driver,
147 bool icon_url_changed) override {
148 OnNotification();
151 void OnNotification() {
152 if (!quit_closure_.is_null()) {
153 // We stop waiting based on changes in state to FaviconHandler which occur
154 // immediately after OnFaviconUpdated() is called. Post a task to check if
155 // we can stop waiting.
156 base::ThreadTaskRunnerHandle::Get()->PostTask(
157 FROM_HERE, base::Bind(&PendingTaskWaiter::EndLoopIfCanStopWaiting,
158 weak_factory_.GetWeakPtr()));
162 void EndLoopIfCanStopWaiting() {
163 if (!quit_closure_.is_null() &&
164 load_stopped_ &&
165 !checker_->HasPendingTasks()) {
166 quit_closure_.Run();
170 FaviconDriverPendingTaskChecker* checker_; // Not owned.
171 bool load_stopped_;
172 base::Closure quit_closure_;
173 content::NotificationRegistrar registrar_;
174 ScopedObserver<favicon::FaviconDriver, PendingTaskWaiter> scoped_observer_;
175 base::WeakPtrFactory<PendingTaskWaiter> weak_factory_;
177 DISALLOW_COPY_AND_ASSIGN(PendingTaskWaiter);
180 } // namespace
182 class ContentFaviconDriverTest : public InProcessBrowserTest,
183 public FaviconDriverPendingTaskChecker {
184 public:
185 ContentFaviconDriverTest() {}
186 ~ContentFaviconDriverTest() override {}
188 content::WebContents* web_contents() {
189 return browser()->tab_strip_model()->GetActiveWebContents();
192 // FaviconDriverPendingTaskChecker:
193 bool HasPendingTasks() override {
194 return favicon::ContentFaviconDriver::FromWebContents(web_contents())
195 ->HasPendingTasksForTest();
198 private:
199 DISALLOW_COPY_AND_ASSIGN(ContentFaviconDriverTest);
202 // Test that when a user reloads a page ignoring the cache that the favicon is
203 // is redownloaded and (not returned from either the favicon cache or the HTTP
204 // cache).
205 IN_PROC_BROWSER_TEST_F(ContentFaviconDriverTest, ReloadIgnoringCache) {
206 ASSERT_TRUE(test_server()->Start());
207 GURL url = test_server()->GetURL("files/favicon/page_with_favicon.html");
208 GURL icon_url = test_server()->GetURL("files/favicon/icon.ico");
210 scoped_ptr<TestResourceDispatcherHostDelegate> delegate(
211 new TestResourceDispatcherHostDelegate(icon_url));
212 content::ResourceDispatcherHost::Get()->SetDelegate(delegate.get());
214 // Initial visit in order to populate the cache.
216 PendingTaskWaiter waiter(web_contents(), this);
217 ui_test_utils::NavigateToURLWithDisposition(
218 browser(), url, CURRENT_TAB, ui_test_utils::BROWSER_TEST_NONE);
219 waiter.Wait();
221 ASSERT_TRUE(delegate->was_requested());
222 EXPECT_FALSE(delegate->bypassed_cache());
223 delegate->Reset();
225 ui_test_utils::NavigateToURL(browser(), GURL(url::kAboutBlankURL));
227 // A normal visit should fetch the favicon from either the favicon database or
228 // the HTTP cache.
230 PendingTaskWaiter waiter(web_contents(), this);
231 ui_test_utils::NavigateToURLWithDisposition(
232 browser(), url, CURRENT_TAB, ui_test_utils::BROWSER_TEST_NONE);
233 waiter.Wait();
235 EXPECT_FALSE(delegate->bypassed_cache());
236 delegate->Reset();
238 // A reload ignoring the cache should refetch the favicon from the website.
240 PendingTaskWaiter waiter(web_contents(), this);
241 chrome::ExecuteCommand(browser(), IDC_RELOAD_IGNORING_CACHE);
242 waiter.Wait();
244 ASSERT_TRUE(delegate->was_requested());
245 EXPECT_TRUE(delegate->bypassed_cache());