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 |