1 // Copyright (c) 2012 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 
5 #include "components/favicon/core/favicon_handler.h"
6 
7 #include <stddef.h>
8 
9 #include <map>
10 #include <memory>
11 #include <utility>
12 #include <vector>
13 
14 #include "base/bind.h"
15 #include "base/bind_helpers.h"
16 #include "base/macros.h"
17 #include "base/run_loop.h"
18 #include "base/strings/stringprintf.h"
19 #include "base/test/metrics/histogram_tester.h"
20 #include "base/test/scoped_feature_list.h"
21 #include "base/test/task_environment.h"
22 #include "base/test/test_simple_task_runner.h"
23 #include "components/favicon/core/favicon_driver.h"
24 #include "components/favicon/core/features.h"
25 #include "components/favicon/core/test/mock_favicon_service.h"
26 #include "skia/ext/image_operations.h"
27 #include "testing/gmock/include/gmock/gmock.h"
28 #include "testing/gtest/include/gtest/gtest.h"
29 #include "third_party/skia/include/core/SkBitmap.h"
30 #include "third_party/skia/include/core/SkColor.h"
31 #include "ui/base/layout.h"
32 #include "ui/gfx/codec/png_codec.h"
33 #include "ui/gfx/favicon_size.h"
34 #include "ui/gfx/image/image.h"
35 
36 namespace favicon {
37 namespace {
38 
39 using favicon_base::FaviconRawBitmapResult;
40 using testing::_;
41 using testing::AnyNumber;
42 using testing::Assign;
43 using testing::Contains;
44 using testing::ElementsAre;
45 using testing::InSequence;
46 using testing::Invoke;
47 using testing::IsEmpty;
48 using testing::Not;
49 using testing::Return;
50 using testing::SizeIs;
51 
52 using IntVector = std::vector<int>;
53 using URLVector = std::vector<GURL>;
54 using BitmapVector = std::vector<SkBitmap>;
55 using SizeVector = std::vector<gfx::Size>;
56 
57 constexpr favicon_base::IconType kFavicon = favicon_base::IconType::kFavicon;
58 constexpr favicon_base::IconType kTouchIcon =
59     favicon_base::IconType::kTouchIcon;
60 constexpr favicon_base::IconType kTouchPrecomposedIcon =
61     favicon_base::IconType::kTouchPrecomposedIcon;
62 constexpr favicon_base::IconType kWebManifestIcon =
63     favicon_base::IconType::kWebManifestIcon;
64 
65 MATCHER_P2(ImageSizeIs, width, height, "") {
66   *result_listener << "where size is " << arg.Width() << "x" << arg.Height();
67   return arg.Size() == gfx::Size(width, height);
68 }
69 
70 // |arg| is a gfx::Image.
71 MATCHER_P(ImageColorIs, expected_color, "") {
72   SkBitmap bitmap = arg.AsBitmap();
73   if (bitmap.empty()) {
74     *result_listener << "expected color but no bitmap data available";
75     return false;
76   }
77 
78   SkColor actual_color = bitmap.getColor(1, 1);
79   if (actual_color != expected_color) {
80     *result_listener << "expected color "
81                      << base::StringPrintf("%08X", expected_color)
82                      << " but actual color is "
83                      << base::StringPrintf("%08X", actual_color);
84     return false;
85   }
86   return true;
87 }
88 
CreateBitmapWithEdgeSize(int size,SkColor color)89 SkBitmap CreateBitmapWithEdgeSize(int size, SkColor color) {
90   SkBitmap bmp;
91   bmp.allocN32Pixels(size, size);
92   bmp.eraseColor(color);
93   return bmp;
94 }
95 
96 // Fill the given data buffer with valid png data.
FillBitmapWithEdgeSize(int size,SkColor color)97 std::vector<unsigned char> FillBitmapWithEdgeSize(int size, SkColor color) {
98   SkBitmap bitmap = CreateBitmapWithEdgeSize(size, color);
99   std::vector<unsigned char> output;
100   gfx::PNGCodec::EncodeBGRASkBitmap(bitmap, false, &output);
101   return output;
102 }
103 
CreateRawBitmapResult(const GURL & icon_url,favicon_base::IconType icon_type=kFavicon,bool expired=false,int edge_size=gfx::kFaviconSize,SkColor color=SK_ColorRED)104 std::vector<FaviconRawBitmapResult> CreateRawBitmapResult(
105     const GURL& icon_url,
106     favicon_base::IconType icon_type = kFavicon,
107     bool expired = false,
108     int edge_size = gfx::kFaviconSize,
109     SkColor color = SK_ColorRED) {
110   scoped_refptr<base::RefCountedBytes> data(new base::RefCountedBytes());
111   data->data() = FillBitmapWithEdgeSize(edge_size, color);
112   FaviconRawBitmapResult bitmap_result;
113   bitmap_result.expired = expired;
114   bitmap_result.bitmap_data = data;
115   // Use a pixel size other than (0,0) as (0,0) has a special meaning.
116   bitmap_result.pixel_size = gfx::Size(edge_size, edge_size);
117   bitmap_result.icon_type = icon_type;
118   bitmap_result.icon_url = icon_url;
119   return {bitmap_result};
120 }
121 
122 // Fake that implements the calls to FaviconHandler::Delegate's DownloadImage(),
123 // delegated to this class through MockDelegate.
124 class FakeImageDownloader {
125  public:
126   struct Response {
127     int http_status_code = 404;
128     BitmapVector bitmaps;
129     SizeVector original_bitmap_sizes;
130   };
131 
132   // |downloads| must not be nullptr and must outlive this object.
FakeImageDownloader(URLVector * downloads)133   explicit FakeImageDownloader(URLVector* downloads)
134       : downloads_(downloads), next_download_id_(1) {}
135 
136   // Implementation of FaviconHalder::Delegate's DownloadImage(). If a given
137   // URL is not known (i.e. not previously added via Add()), it produces 404s.
DownloadImage(const GURL & url,int max_image_size,FaviconHandler::Delegate::ImageDownloadCallback callback)138   int DownloadImage(const GURL& url,
139                     int max_image_size,
140                     FaviconHandler::Delegate::ImageDownloadCallback callback) {
141     downloads_->push_back(url);
142 
143     Response response = responses_[url];
144     DCHECK_EQ(response.bitmaps.size(), response.original_bitmap_sizes.size());
145     // Apply maximum image size.
146     for (size_t i = 0; i < response.bitmaps.size(); ++i) {
147       if (response.bitmaps[i].width() > max_image_size ||
148           response.bitmaps[i].height() > max_image_size) {
149         response.bitmaps[i] = skia::ImageOperations::Resize(
150             response.bitmaps[i], skia::ImageOperations::RESIZE_LANCZOS3,
151             max_image_size, max_image_size);
152       }
153     }
154 
155     int download_id = next_download_id_++;
156     base::OnceClosure bound_callback = base::BindOnce(
157         std::move(callback), download_id, response.http_status_code, url,
158         response.bitmaps, response.original_bitmap_sizes);
159     if (url == manual_callback_url_)
160       manual_callbacks_.push_back(std::move(bound_callback));
161     else
162       base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
163                                                     std::move(bound_callback));
164     return download_id;
165   }
166 
Add(const GURL & icon_url,const IntVector & original_sizes,SkColor color=SK_ColorRED)167   void Add(const GURL& icon_url,
168            const IntVector& original_sizes,
169            SkColor color = SK_ColorRED) {
170     Response response;
171     response.http_status_code = 200;
172     for (int size : original_sizes) {
173       response.original_bitmap_sizes.push_back(gfx::Size(size, size));
174       response.bitmaps.push_back(CreateBitmapWithEdgeSize(size, color));
175     }
176     responses_[icon_url] = response;
177   }
178 
AddError(const GURL & icon_url,int http_status_code)179   void AddError(const GURL& icon_url, int http_status_code) {
180     Response response;
181     response.http_status_code = http_status_code;
182     responses_[icon_url] = response;
183   }
184 
185   // Disables automatic callback for |url|. This is useful for emulating a
186   // download taking a long time. The callback for DownloadImage() will be
187   // stored in |manual_callbacks_|.
SetRunCallbackManuallyForUrl(const GURL & url)188   void SetRunCallbackManuallyForUrl(const GURL& url) {
189     manual_callback_url_ = url;
190   }
191 
192   // Returns whether an ongoing download exists for a url previously selected
193   // via SetRunCallbackManuallyForUrl().
HasPendingManualCallback()194   bool HasPendingManualCallback() { return !manual_callbacks_.empty(); }
195 
196   // Triggers responses for downloads previously selected for manual triggering
197   // via SetRunCallbackManuallyForUrl().
RunCallbackManually()198   bool RunCallbackManually() {
199     if (!HasPendingManualCallback())
200       return false;
201     for (auto& callback : std::move(manual_callbacks_))
202       std::move(callback).Run();
203     return true;
204   }
205 
206  private:
207   URLVector* downloads_;
208   int next_download_id_;
209 
210   // URL to disable automatic callbacks for.
211   GURL manual_callback_url_;
212 
213   // Callback for DownloadImage() request for |manual_callback_url_|.
214   std::vector<base::OnceClosure> manual_callbacks_;
215 
216   // Registered responses.
217   std::map<GURL, Response> responses_;
218 
219   DISALLOW_COPY_AND_ASSIGN(FakeImageDownloader);
220 };
221 
222 // Fake that implements the calls to FaviconHandler::Delegate's
223 // DownloadManifest(), delegated to this class through MockDelegate.
224 class FakeManifestDownloader {
225  public:
226   struct Response {
227     std::vector<favicon::FaviconURL> favicon_urls;
228   };
229 
230   // |downloads| must not be nullptr and must outlive this object.
FakeManifestDownloader(URLVector * downloads)231   explicit FakeManifestDownloader(URLVector* downloads)
232       : downloads_(downloads) {}
233 
234   // Implementation of FaviconHalder::Delegate's DownloadManifest(). If a given
235   // URL is not known (i.e. not previously added via Add()), it produces 404s.
DownloadManifest(const GURL & url,FaviconHandler::Delegate::ManifestDownloadCallback callback)236   void DownloadManifest(
237       const GURL& url,
238       FaviconHandler::Delegate::ManifestDownloadCallback callback) {
239     downloads_->push_back(url);
240 
241     const Response& response = responses_[url];
242     base::OnceClosure bound_callback =
243         base::BindOnce(std::move(callback), response.favicon_urls);
244     if (url == manual_callback_url_)
245       manual_callbacks_.push_back(std::move(bound_callback));
246     else
247       base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
248                                                     std::move(bound_callback));
249   }
250 
Add(const GURL & manifest_url,const std::vector<favicon::FaviconURL> & favicon_urls)251   void Add(const GURL& manifest_url,
252            const std::vector<favicon::FaviconURL>& favicon_urls) {
253     Response response;
254     response.favicon_urls = favicon_urls;
255     responses_[manifest_url] = response;
256   }
257 
AddError(const GURL & manifest_url)258   void AddError(const GURL& manifest_url) {
259     responses_[manifest_url] = Response();
260   }
261 
262   // Disables automatic callback for |url|. This is useful for emulating a
263   // download taking a long time. The callback for DownloadManifest() will be
264   // stored in |manual_callback_|.
SetRunCallbackManuallyForUrl(const GURL & url)265   void SetRunCallbackManuallyForUrl(const GURL& url) {
266     manual_callback_url_ = url;
267   }
268 
269   // Returns whether an ongoing download exists for a url previously selected
270   // via SetRunCallbackManuallyForUrl().
HasPendingManualCallback()271   bool HasPendingManualCallback() { return !manual_callbacks_.empty(); }
272 
273   // Triggers responses for downloads previously selected for manual triggering
274   // via SetRunCallbackManuallyForUrl().
RunCallbackManually()275   bool RunCallbackManually() {
276     if (!HasPendingManualCallback())
277       return false;
278     for (auto& callback : std::move(manual_callbacks_))
279       std::move(callback).Run();
280     return true;
281   }
282 
283  private:
284   URLVector* downloads_;
285 
286   // URL to disable automatic callbacks for.
287   GURL manual_callback_url_;
288 
289   // Callback for DownloadManifest() request for |manual_callback_url_|.
290   std::vector<base::OnceClosure> manual_callbacks_;
291 
292   // Registered responses.
293   std::map<GURL, Response> responses_;
294 
295   DISALLOW_COPY_AND_ASSIGN(FakeManifestDownloader);
296 };
297 
298 class MockDelegate : public FaviconHandler::Delegate {
299  public:
MockDelegate()300   MockDelegate()
301       : fake_image_downloader_(&downloads_),
302         fake_manifest_downloader_(&downloads_) {
303   }
304 
DownloadImage(const GURL & url,int max_image_size,ImageDownloadCallback callback)305   int DownloadImage(const GURL& url,
306                     int max_image_size,
307                     ImageDownloadCallback callback) override {
308     return fake_image_downloader_.DownloadImage(url, max_image_size,
309                                                 std::move(callback));
310   }
311 
DownloadManifest(const GURL & url,ManifestDownloadCallback callback)312   void DownloadManifest(const GURL& url,
313                         ManifestDownloadCallback callback) override {
314     fake_manifest_downloader_.DownloadManifest(url, std::move(callback));
315   }
316 
317   MOCK_METHOD0(IsOffTheRecord, bool());
318   MOCK_METHOD1(IsBookmarked, bool(const GURL& url));
319   MOCK_METHOD5(OnFaviconUpdated,
320                void(const GURL& page_url,
321                     FaviconDriverObserver::NotificationIconType type,
322                     const GURL& icon_url,
323                     bool icon_url_changed,
324                     const gfx::Image& image));
325   MOCK_METHOD2(OnFaviconDeleted,
326                void(const GURL& page_url,
327                     FaviconDriverObserver::NotificationIconType type));
328 
fake_image_downloader()329   FakeImageDownloader& fake_image_downloader() {
330     return fake_image_downloader_;
331   }
332 
fake_manifest_downloader()333   FakeManifestDownloader& fake_manifest_downloader() {
334     return fake_manifest_downloader_;
335   }
336 
337   // Returns pending and completed download URLs.
downloads() const338   const URLVector& downloads() const { return downloads_; }
339 
ClearDownloads()340   void ClearDownloads() { downloads_.clear(); }
341 
342  private:
343   // Pending and completed download URLs.
344   URLVector downloads_;
345   FakeImageDownloader fake_image_downloader_;
346   FakeManifestDownloader fake_manifest_downloader_;
347 };
348 
349 // FakeFaviconService mimics a FaviconService backend that allows setting up
350 // test data stored via Store(). If Store() has not been called for a
351 // particular URL, the callback is called with empty database results.
352 class FakeFaviconService {
353  public:
FakeFaviconService()354   FakeFaviconService()
355       : manual_callback_task_runner_(new base::TestSimpleTaskRunner()) {}
356 
357   // Stores favicon with bitmap data in |results| at |page_url| and |icon_url|.
Store(const GURL & page_url,const GURL & icon_url,const std::vector<favicon_base::FaviconRawBitmapResult> & result)358   void Store(const GURL& page_url,
359              const GURL& icon_url,
360              const std::vector<favicon_base::FaviconRawBitmapResult>& result) {
361     results_[icon_url] = result;
362     results_[page_url] = result;
363   }
364 
365   // Returns pending and completed database request URLs.
db_requests() const366   const URLVector& db_requests() const { return db_requests_; }
367 
ClearDbRequests()368   void ClearDbRequests() { db_requests_.clear(); }
369 
GetFavicon(const GURL & icon_url,favicon_base::IconType icon_type,int desired_size_in_dip,favicon_base::FaviconResultsCallback callback,base::CancelableTaskTracker * tracker)370   base::CancelableTaskTracker::TaskId GetFavicon(
371       const GURL& icon_url,
372       favicon_base::IconType icon_type,
373       int desired_size_in_dip,
374       favicon_base::FaviconResultsCallback callback,
375       base::CancelableTaskTracker* tracker) {
376     return GetFaviconForPageOrIconURL(icon_url, std::move(callback), tracker);
377   }
378 
GetFaviconForPageURL(const GURL & page_url,const favicon_base::IconTypeSet & icon_types,int desired_size_in_dip,favicon_base::FaviconResultsCallback callback,base::CancelableTaskTracker * tracker)379   base::CancelableTaskTracker::TaskId GetFaviconForPageURL(
380       const GURL& page_url,
381       const favicon_base::IconTypeSet& icon_types,
382       int desired_size_in_dip,
383       favicon_base::FaviconResultsCallback callback,
384       base::CancelableTaskTracker* tracker) {
385     return GetFaviconForPageOrIconURL(page_url, std::move(callback), tracker);
386   }
387 
UpdateFaviconMappingsAndFetch(const base::flat_set<GURL> & page_urls,const GURL & icon_url,favicon_base::IconType icon_type,int desired_size_in_dip,favicon_base::FaviconResultsCallback callback,base::CancelableTaskTracker * tracker)388   base::CancelableTaskTracker::TaskId UpdateFaviconMappingsAndFetch(
389       const base::flat_set<GURL>& page_urls,
390       const GURL& icon_url,
391       favicon_base::IconType icon_type,
392       int desired_size_in_dip,
393       favicon_base::FaviconResultsCallback callback,
394       base::CancelableTaskTracker* tracker) {
395     return GetFaviconForPageOrIconURL(icon_url, std::move(callback), tracker);
396   }
397 
398   // Disables automatic callback for |url|. This is useful for emulating a
399   // DB lookup taking a long time. The callback for
400   // GetFaviconForPageOrIconURL() will be stored in |manual_callback_|.
SetRunCallbackManuallyForUrl(const GURL & url)401   void SetRunCallbackManuallyForUrl(const GURL& url) {
402     manual_callback_url_ = url;
403   }
404 
405   // Returns whether an ongoing lookup exists for a url previously selected
406   // via SetRunCallbackManuallyForUrl().
HasPendingManualCallback()407   bool HasPendingManualCallback() {
408     return manual_callback_task_runner_->HasPendingTask();
409   }
410 
411   // Triggers the response for a lookup previously selected for manual
412   // triggering via SetRunCallbackManuallyForUrl().
RunCallbackManually()413   bool RunCallbackManually() {
414     if (!HasPendingManualCallback())
415       return false;
416     manual_callback_task_runner_->RunPendingTasks();
417     return true;
418   }
419 
420  private:
GetFaviconForPageOrIconURL(const GURL & page_or_icon_url,favicon_base::FaviconResultsCallback callback,base::CancelableTaskTracker * tracker)421   base::CancelableTaskTracker::TaskId GetFaviconForPageOrIconURL(
422       const GURL& page_or_icon_url,
423       favicon_base::FaviconResultsCallback callback,
424       base::CancelableTaskTracker* tracker) {
425     db_requests_.push_back(page_or_icon_url);
426 
427     base::OnceClosure bound_callback =
428         base::BindOnce(std::move(callback), results_[page_or_icon_url]);
429 
430     // In addition to checking the URL against |manual_callback_url_|, we also
431     // defer responses if there are already pending responses (i.e. a previous
432     // lookup matched |manual_callback_url_|), because requests to the history
433     // should be executed sequentially.
434     if (page_or_icon_url != manual_callback_url_ &&
435         !HasPendingManualCallback()) {
436       return tracker->PostTask(base::ThreadTaskRunnerHandle::Get().get(),
437                                FROM_HERE, std::move(bound_callback));
438     }
439 
440     // We use PostTaskAndReply() to cause |callback| being run in the current
441     // TaskRunner.
442     return tracker->PostTaskAndReply(manual_callback_task_runner_.get(),
443                                      FROM_HERE, base::DoNothing(),
444                                      std::move(bound_callback));
445   }
446 
447   std::map<GURL, std::vector<favicon_base::FaviconRawBitmapResult>> results_;
448   URLVector db_requests_;
449 
450   // URL to disable automatic callbacks for.
451   GURL manual_callback_url_;
452 
453   // Callback for GetFaviconForPageOrIconURL() request for
454   // |manual_callback_url_|.
455   scoped_refptr<base::TestSimpleTaskRunner> manual_callback_task_runner_;
456 
457   DISALLOW_COPY_AND_ASSIGN(FakeFaviconService);
458 };
459 
460 // MockFaviconService subclass that delegates DB reads to FakeFaviconService.
461 class MockFaviconServiceWithFake : public MockFaviconService {
462  public:
MockFaviconServiceWithFake()463   MockFaviconServiceWithFake() {
464     // Delegate the various methods that read from the DB.
465     ON_CALL(*this, GetFavicon(_, _, _, _, _))
466         .WillByDefault(Invoke(&fake_, &FakeFaviconService::GetFavicon));
467     ON_CALL(*this, GetFaviconForPageURL(_, _, _, _, _))
468         .WillByDefault(
469             Invoke(&fake_, &FakeFaviconService::GetFaviconForPageURL));
470     ON_CALL(*this, UpdateFaviconMappingsAndFetch(_, _, _, _, _, _))
471         .WillByDefault(
472             Invoke(&fake_, &FakeFaviconService::UpdateFaviconMappingsAndFetch));
473   }
474 
fake()475   FakeFaviconService* fake() { return &fake_; }
476 
477  private:
478   FakeFaviconService fake_;
479 
480   DISALLOW_COPY_AND_ASSIGN(MockFaviconServiceWithFake);
481 };
482 
483 class FaviconHandlerTest : public testing::Test {
484  protected:
485   const std::vector<gfx::Size> kEmptySizes;
486 
487   // Some known icons for which download will succeed.
488   const GURL kPageURL = GURL("http://www.google.com");
489   const GURL kIconURL10x10 = GURL("http://www.google.com/favicon10x10");
490   const GURL kIconURL12x12 = GURL("http://www.google.com/favicon12x12");
491   const GURL kIconURL16x16 = GURL("http://www.google.com/favicon16x16");
492   const GURL kIconURL64x64 = GURL("http://www.google.com/favicon64x64");
493 
FaviconHandlerTest()494   FaviconHandlerTest()
495       : task_environment_(
496             base::test::SingleThreadTaskEnvironment::MainThreadType::UI) {
497     // Register various known icon URLs.
498     delegate_.fake_image_downloader().Add(kIconURL10x10, IntVector{10});
499     delegate_.fake_image_downloader().Add(kIconURL12x12, IntVector{12});
500     delegate_.fake_image_downloader().Add(kIconURL16x16, IntVector{16});
501     delegate_.fake_image_downloader().Add(kIconURL64x64, IntVector{64});
502 
503     // The score computed by SelectFaviconFrames() is dependent on the supported
504     // scale factors of the platform. It is used for determining the goodness of
505     // a downloaded bitmap in FaviconHandler::OnDidDownloadFavicon().
506     // Force the values of the scale factors so that the tests produce the same
507     // results on all platforms.
508     scoped_set_supported_scale_factors_.reset(
509         new ui::test::ScopedSetSupportedScaleFactors({ui::SCALE_FACTOR_100P}));
510   }
511 
VerifyAndClearExpectations()512   bool VerifyAndClearExpectations() {
513     base::RunLoop().RunUntilIdle();
514     favicon_service_.fake()->ClearDbRequests();
515     delegate_.ClearDownloads();
516     return testing::Mock::VerifyAndClearExpectations(&favicon_service_) &&
517            testing::Mock::VerifyAndClearExpectations(&delegate_);
518   }
519 
520   // Creates a new handler and feeds in the page URL and the candidates.
521   // Returns the handler in case tests want to exercise further steps.
RunHandlerWithCandidates(FaviconDriverObserver::NotificationIconType handler_type,const std::vector<FaviconURL> & candidates,const GURL & manifest_url=GURL ())522   std::unique_ptr<FaviconHandler> RunHandlerWithCandidates(
523       FaviconDriverObserver::NotificationIconType handler_type,
524       const std::vector<FaviconURL>& candidates,
525       const GURL& manifest_url = GURL()) {
526     auto handler = std::make_unique<FaviconHandler>(&favicon_service_,
527                                                     &delegate_, handler_type);
528     handler->FetchFavicon(kPageURL, /*is_same_document=*/false);
529     // The first RunUntilIdle() causes the FaviconService lookups be faster than
530     // OnUpdateCandidates(), which is the most likely scenario.
531     base::RunLoop().RunUntilIdle();
532     handler->OnUpdateCandidates(kPageURL, candidates, manifest_url);
533     base::RunLoop().RunUntilIdle();
534     return handler;
535   }
536 
537   // Same as above, but for the simplest case where all types are kFavicon and
538   // no sizes are provided, using a FaviconHandler of type NON_TOUCH_16_DIP.
RunHandlerWithSimpleFaviconCandidates(const std::vector<GURL> & urls,const GURL & manifest_url=GURL ())539   std::unique_ptr<FaviconHandler> RunHandlerWithSimpleFaviconCandidates(
540       const std::vector<GURL>& urls,
541       const GURL& manifest_url = GURL()) {
542     std::vector<favicon::FaviconURL> candidates;
543     for (const GURL& url : urls) {
544       candidates.emplace_back(url, kFavicon, kEmptySizes);
545     }
546     return RunHandlerWithCandidates(FaviconDriverObserver::NON_TOUCH_16_DIP,
547                                     candidates, manifest_url);
548   }
549 
550   base::test::SingleThreadTaskEnvironment task_environment_;
551   std::unique_ptr<ui::test::ScopedSetSupportedScaleFactors>
552       scoped_set_supported_scale_factors_;
553   testing::NiceMock<MockFaviconServiceWithFake> favicon_service_;
554   testing::NiceMock<MockDelegate> delegate_;
555 };
556 
TEST_F(FaviconHandlerTest,GetFaviconFromHistory)557 TEST_F(FaviconHandlerTest, GetFaviconFromHistory) {
558   base::HistogramTester histogram_tester;
559   const GURL kIconURL("http://www.google.com/favicon");
560 
561   favicon_service_.fake()->Store(kPageURL, kIconURL,
562                                  CreateRawBitmapResult(kIconURL));
563 
564   EXPECT_CALL(delegate_, OnFaviconUpdated(
565                              kPageURL, FaviconDriverObserver::NON_TOUCH_16_DIP,
566                              kIconURL, /*icon_url_changed=*/true, _));
567 
568   RunHandlerWithSimpleFaviconCandidates({kIconURL});
569   EXPECT_THAT(delegate_.downloads(), IsEmpty());
570 }
571 
572 // Test that UpdateFaviconsAndFetch() is called with the appropriate parameters
573 // when there is no data in the database for the page URL.
TEST_F(FaviconHandlerTest,UpdateFaviconMappingsAndFetch)574 TEST_F(FaviconHandlerTest, UpdateFaviconMappingsAndFetch) {
575   EXPECT_CALL(favicon_service_,
576               UpdateFaviconMappingsAndFetch(base::flat_set<GURL>{kPageURL},
577                                             kIconURL16x16, kFavicon,
578                                             /*desired_size_in_dip=*/16, _, _));
579 
580   RunHandlerWithSimpleFaviconCandidates({kIconURL16x16});
581 }
582 
583 // Test that we don't try to delete favicon mappings when a page URL is not in
584 // history even if the page lists no favicons.
TEST_F(FaviconHandlerTest,DoNotDeleteFaviconMappingsIfNotInHistory)585 TEST_F(FaviconHandlerTest, DoNotDeleteFaviconMappingsIfNotInHistory) {
586   const GURL kIconURL("http://www.google.com/favicon");
587 
588   EXPECT_CALL(favicon_service_, DeleteFaviconMappings(_, _)).Times(0);
589   EXPECT_CALL(delegate_, OnFaviconDeleted(_, _)).Times(0);
590 
591   RunHandlerWithSimpleFaviconCandidates(URLVector());
592 }
593 
594 // Test that favicon mappings are deleted when:
595 // - There is data in the favicon database for the page URL.
596 // - The page lists no candidates.
597 // AND
598 // - FaviconService::OnFaviconDataForManifestFromFaviconService() runs before
599 //   FaviconHandler::OnUpdateCandidates() is called.
TEST_F(FaviconHandlerTest,DeleteFaviconMappingsIfCandidatesSlower)600 TEST_F(FaviconHandlerTest, DeleteFaviconMappingsIfCandidatesSlower) {
601   const GURL kIconURL("http://www.google.com/favicon");
602 
603   favicon_service_.fake()->Store(kPageURL, kIconURL,
604                                  CreateRawBitmapResult(kIconURL));
605 
606   // Defer the database lookup completion to control the exact timing.
607   favicon_service_.fake()->SetRunCallbackManuallyForUrl(kPageURL);
608 
609   EXPECT_CALL(delegate_, OnFaviconDeleted(_, _)).Times(0);
610   EXPECT_CALL(favicon_service_, DeleteFaviconMappings(_, _)).Times(0);
611 
612   FaviconHandler handler(&favicon_service_, &delegate_,
613                          FaviconDriverObserver::NON_TOUCH_16_DIP);
614   handler.FetchFavicon(kPageURL, /*is_same_document=*/false);
615   base::RunLoop().RunUntilIdle();
616   // Database lookup for |kPageURL| is ongoing.
617   ASSERT_TRUE(favicon_service_.fake()->HasPendingManualCallback());
618   // Causes FaviconService lookups be faster than OnUpdateCandidates().
619   ASSERT_TRUE(favicon_service_.fake()->RunCallbackManually());
620   ASSERT_TRUE(VerifyAndClearExpectations());
621 
622   EXPECT_CALL(
623       delegate_,
624       OnFaviconDeleted(kPageURL, FaviconDriverObserver::NON_TOUCH_16_DIP));
625   EXPECT_CALL(favicon_service_,
626               DeleteFaviconMappings(base::flat_set<GURL>{kPageURL}, kFavicon));
627 
628   // Feed in (zero) candidates now that the database lookup is completed.
629   handler.OnUpdateCandidates(kPageURL, std::vector<FaviconURL>(),
630                              /*manifest_url=*/GURL());
631   base::RunLoop().RunUntilIdle();
632 }
633 
634 // Test that favicon mappings are deleted when:
635 // - There is data in the favicon database for the page URL.
636 // - The page lists no candidates.
637 // AND
638 // - FaviconHandler::OnUpdateCandidates() is called before
639 //   FaviconService::OnFaviconDataForManifestFromFaviconService() runs.
TEST_F(FaviconHandlerTest,DeleteFaviconMappingsIfCandidatesFaster)640 TEST_F(FaviconHandlerTest, DeleteFaviconMappingsIfCandidatesFaster) {
641   const GURL kIconURL("http://www.google.com/favicon");
642 
643   favicon_service_.fake()->Store(kPageURL, kIconURL,
644                                  CreateRawBitmapResult(kIconURL));
645 
646   // Defer the database lookup completion to control the exact timing.
647   favicon_service_.fake()->SetRunCallbackManuallyForUrl(kPageURL);
648 
649   EXPECT_CALL(delegate_, OnFaviconDeleted(_, _)).Times(0);
650   EXPECT_CALL(favicon_service_, DeleteFaviconMappings(_, _)).Times(0);
651 
652   FaviconHandler handler(&favicon_service_, &delegate_,
653                          FaviconDriverObserver::NON_TOUCH_16_DIP);
654   handler.FetchFavicon(kPageURL, /*is_same_document=*/false);
655   base::RunLoop().RunUntilIdle();
656   // Feed in (zero) candidates before completing the database lookup.
657   handler.OnUpdateCandidates(kPageURL, std::vector<FaviconURL>(),
658                              /*manifest_url=*/GURL());
659   ASSERT_TRUE(VerifyAndClearExpectations());
660   // Database lookup for |kPageURL| is ongoing.
661   ASSERT_TRUE(favicon_service_.fake()->HasPendingManualCallback());
662 
663   EXPECT_CALL(
664       delegate_,
665       OnFaviconDeleted(kPageURL, FaviconDriverObserver::NON_TOUCH_16_DIP));
666   EXPECT_CALL(favicon_service_,
667               DeleteFaviconMappings(base::flat_set<GURL>{kPageURL}, kFavicon));
668 
669   // Complete the lookup for |kPageURL|.
670   ASSERT_TRUE(favicon_service_.fake()->RunCallbackManually());
671   base::RunLoop().RunUntilIdle();
672 }
673 
674 // Test that favicon mappings are deleted when a page in history lists a
675 // candidate that is expired and is known to return a 404.
TEST_F(FaviconHandlerTest,DeleteFaviconMappingsDespitePrior404)676 TEST_F(FaviconHandlerTest, DeleteFaviconMappingsDespitePrior404) {
677   const GURL kIconURL("http://www.google.com/favicon");
678 
679   favicon_service_.fake()->Store(
680       kPageURL, kIconURL,
681       CreateRawBitmapResult(kIconURL, kFavicon, /*expired=*/true));
682 
683   ON_CALL(favicon_service_, WasUnableToDownloadFavicon(kIconURL))
684       .WillByDefault(Return(true));
685 
686   EXPECT_CALL(
687       delegate_,
688       OnFaviconDeleted(kPageURL, FaviconDriverObserver::NON_TOUCH_16_DIP));
689   EXPECT_CALL(favicon_service_,
690               DeleteFaviconMappings(base::flat_set<GURL>{kPageURL}, kFavicon));
691 
692   RunHandlerWithSimpleFaviconCandidates({kIconURL});
693 }
694 
695 // Test that favicon mappings are deleted for a page in history, when all icons
696 // listed in the page return a 404.
TEST_F(FaviconHandlerTest,DeleteFaviconMappingsDueTo404)697 TEST_F(FaviconHandlerTest, DeleteFaviconMappingsDueTo404) {
698   const GURL kIconURLInHistory("http://www.google.com/favicon-in-history");
699   const GURL k404IconURL("http://www.google.com/404.png");
700 
701   favicon_service_.fake()->Store(kPageURL, kIconURLInHistory,
702                                  CreateRawBitmapResult(kIconURLInHistory));
703 
704   EXPECT_CALL(favicon_service_,
705               DeleteFaviconMappings(base::flat_set<GURL>{kPageURL}, kFavicon));
706 
707   RunHandlerWithSimpleFaviconCandidates({k404IconURL});
708 }
709 
710 // Test that we don't try to delete favicon mappings when a page URL is not in
711 // history even if all icons listed in the page return a 404.
TEST_F(FaviconHandlerTest,DoNotDeleteFaviconMappingsIfNotInHistoryDespite404)712 TEST_F(FaviconHandlerTest, DoNotDeleteFaviconMappingsIfNotInHistoryDespite404) {
713   const GURL k404IconURL("http://www.google.com/404.png");
714 
715   EXPECT_CALL(favicon_service_, DeleteFaviconMappings(_, _)).Times(0);
716 
717   RunHandlerWithSimpleFaviconCandidates({k404IconURL});
718 }
719 
720 // Test that favicon mappings are not deleted for a page in history when all
721 // icons listed in the page return a 503.
TEST_F(FaviconHandlerTest,DoNotDeleteFaviconMappingsDueTo503)722 TEST_F(FaviconHandlerTest, DoNotDeleteFaviconMappingsDueTo503) {
723   const GURL kIconURLInHistory("http://www.google.com/favicon-in-history");
724   const GURL k503IconURL("http://www.google.com/503.png");
725 
726   delegate_.fake_image_downloader().AddError(k503IconURL, 503);
727 
728   favicon_service_.fake()->Store(kPageURL, kIconURLInHistory,
729                                  CreateRawBitmapResult(kIconURLInHistory));
730 
731   EXPECT_CALL(favicon_service_, DeleteFaviconMappings(_, _)).Times(0);
732 
733   RunHandlerWithSimpleFaviconCandidates({k503IconURL});
734 }
735 
736 // Test that UpdateFaviconsAndFetch() is called with the appropriate parameters
737 // when there is no data in the database for the page URL, for the case where
738 // multiple page URLs exist due to a quick in-same-document navigation (e.g.
739 // fragment navigation).
TEST_F(FaviconHandlerTest,UpdateFaviconMappingsAndFetchWithMultipleURLs)740 TEST_F(FaviconHandlerTest, UpdateFaviconMappingsAndFetchWithMultipleURLs) {
741   const GURL kDifferentPageURL = GURL("http://www.google.com/other");
742 
743   EXPECT_CALL(favicon_service_,
744               UpdateFaviconMappingsAndFetch(
745                   base::flat_set<GURL>{kPageURL, kDifferentPageURL},
746                   kIconURL16x16, _, _, _, _));
747 
748   std::unique_ptr<FaviconHandler> handler = std::make_unique<FaviconHandler>(
749       &favicon_service_, &delegate_, FaviconDriverObserver::NON_TOUCH_16_DIP);
750   handler->FetchFavicon(kPageURL, /*is_same_document=*/false);
751   base::RunLoop().RunUntilIdle();
752   // Load a new URL (same document) without feeding any candidates for the first
753   // URL.
754   handler->FetchFavicon(kDifferentPageURL, /*is_same_document=*/true);
755   base::RunLoop().RunUntilIdle();
756   // Feed in candidates for the second URL.
757   handler->OnUpdateCandidates(
758       kDifferentPageURL, {FaviconURL(kIconURL16x16, kFavicon, kEmptySizes)},
759       /*manifest_url=*/GURL());
760   base::RunLoop().RunUntilIdle();
761 }
762 
763 // Test that CloneFaviconMappingsForPages() is called for the simplest case,
764 // i.e. a single page without redirect URLs to update mappings for (no known
765 // in-same-document navigation). This is important in case there are server-side
766 // redirects to update (that are only known within HistoryService).
TEST_F(FaviconHandlerTest,CloneFaviconMappingsForPageInHistory)767 TEST_F(FaviconHandlerTest, CloneFaviconMappingsForPageInHistory) {
768   favicon_service_.fake()->Store(kPageURL, kIconURL16x16,
769                                  CreateRawBitmapResult(kIconURL16x16));
770 
771   EXPECT_CALL(favicon_service_,
772               CloneFaviconMappingsForPages(
773                   kPageURL, favicon_base::IconTypeSet({kFavicon}),
774                   base::flat_set<GURL>({kPageURL})));
775 
776   std::unique_ptr<FaviconHandler> handler = std::make_unique<FaviconHandler>(
777       &favicon_service_, &delegate_, FaviconDriverObserver::NON_TOUCH_16_DIP);
778   handler->FetchFavicon(kPageURL, /*is_same_document=*/false);
779   base::RunLoop().RunUntilIdle();
780 }
781 
782 // Test that CloneFaviconMappingsForPages() is called when there is data in the
783 // database for the page URL, for the case where multiple page URLs exist due to
784 // a quick in-same-document navigation (e.g. fragment navigation).
785 // FaviconService should be told to propagate the mappings from the last page
786 // URL (lookup hit) to the rest of the URLs.
TEST_F(FaviconHandlerTest,CloneFaviconMappingsWithMultipleURLs)787 TEST_F(FaviconHandlerTest, CloneFaviconMappingsWithMultipleURLs) {
788   const GURL kPageURLInHistory = GURL("http://www.google.com/other");
789 
790   favicon_service_.fake()->Store(kPageURLInHistory, kIconURL16x16,
791                                  CreateRawBitmapResult(kIconURL16x16));
792 
793   std::unique_ptr<FaviconHandler> handler = std::make_unique<FaviconHandler>(
794       &favicon_service_, &delegate_, FaviconDriverObserver::NON_TOUCH_16_DIP);
795   handler->FetchFavicon(kPageURL, /*is_same_document=*/false);
796   base::RunLoop().RunUntilIdle();
797 
798   EXPECT_CALL(favicon_service_,
799               CloneFaviconMappingsForPages(
800                   kPageURLInHistory, favicon_base::IconTypeSet({kFavicon}),
801                   base::flat_set<GURL>({kPageURL, kPageURLInHistory})));
802 
803   handler->FetchFavicon(kPageURLInHistory, /*is_same_document=*/true);
804   base::RunLoop().RunUntilIdle();
805 }
806 
807 // Test that CloneFaviconMappingsForPages() is not called for incognito tabs.
TEST_F(FaviconHandlerTest,NotCloneFaviconMappingsInIncognito)808 TEST_F(FaviconHandlerTest, NotCloneFaviconMappingsInIncognito) {
809   ON_CALL(delegate_, IsOffTheRecord()).WillByDefault(Return(true));
810 
811   favicon_service_.fake()->Store(kPageURL, kIconURL16x16,
812                                  CreateRawBitmapResult(kIconURL16x16));
813 
814   EXPECT_CALL(favicon_service_, CloneFaviconMappingsForPages(_, _, _)).Times(0);
815 
816   std::unique_ptr<FaviconHandler> handler = std::make_unique<FaviconHandler>(
817       &favicon_service_, &delegate_, FaviconDriverObserver::NON_TOUCH_16_DIP);
818   handler->FetchFavicon(kPageURL, /*is_same_document=*/false);
819   base::RunLoop().RunUntilIdle();
820 }
821 
822 // Test that the FaviconHandler process finishes when:
823 // - There is data in the database for neither the page URL nor the icon URL.
824 // AND
825 // - FaviconService::GetFaviconForPageURL() callback returns before
826 //   FaviconHandler::OnUpdateCandidates() is called.
TEST_F(FaviconHandlerTest,DownloadUnknownFaviconIfCandidatesSlower)827 TEST_F(FaviconHandlerTest, DownloadUnknownFaviconIfCandidatesSlower) {
828   // Defer the database lookup completion to control the exact timing.
829   favicon_service_.fake()->SetRunCallbackManuallyForUrl(kPageURL);
830 
831   EXPECT_CALL(favicon_service_, SetFavicons(_, _, _, _)).Times(0);
832   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, _, _, _)).Times(0);
833 
834   FaviconHandler handler(&favicon_service_, &delegate_,
835                          FaviconDriverObserver::NON_TOUCH_16_DIP);
836   handler.FetchFavicon(kPageURL, /*is_same_document=*/false);
837   base::RunLoop().RunUntilIdle();
838   // Database lookup for |kPageURL| is ongoing.
839   ASSERT_TRUE(favicon_service_.fake()->HasPendingManualCallback());
840   // Causes FaviconService lookups be faster than OnUpdateCandidates().
841   ASSERT_TRUE(favicon_service_.fake()->RunCallbackManually());
842   ASSERT_TRUE(VerifyAndClearExpectations());
843 
844   EXPECT_CALL(favicon_service_,
845               SetFavicons(base::flat_set<GURL>{kPageURL}, kIconURL16x16,
846                           kFavicon, ImageSizeIs(16, 16)));
847   EXPECT_CALL(delegate_, OnFaviconUpdated(
848                              kPageURL, FaviconDriverObserver::NON_TOUCH_16_DIP,
849                              kIconURL16x16, /*icon_url_changed=*/true, _));
850   // Feed in favicons now that the database lookup is completed.
851   handler.OnUpdateCandidates(
852       kPageURL, {FaviconURL(kIconURL16x16, kFavicon, kEmptySizes)}, GURL());
853   base::RunLoop().RunUntilIdle();
854 
855   EXPECT_THAT(favicon_service_.fake()->db_requests(),
856               ElementsAre(kIconURL16x16));
857   EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL16x16));
858 }
859 
860 // Test that the FaviconHandler process finishes when:
861 // - There is data in the database for neither the page URL nor the icon URL.
862 // AND
863 // - FaviconService::GetFaviconForPageURL() callback returns after
864 //   FaviconHandler::OnUpdateCandidates() is called.
TEST_F(FaviconHandlerTest,DownloadUnknownFaviconIfCandidatesFaster)865 TEST_F(FaviconHandlerTest, DownloadUnknownFaviconIfCandidatesFaster) {
866   // Defer the database lookup completion to control the exact timing.
867   favicon_service_.fake()->SetRunCallbackManuallyForUrl(kPageURL);
868 
869   EXPECT_CALL(favicon_service_, SetFavicons(_, _, _, _)).Times(0);
870   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, _, _, _)).Times(0);
871 
872   FaviconHandler handler(&favicon_service_, &delegate_,
873                          FaviconDriverObserver::NON_TOUCH_16_DIP);
874   handler.FetchFavicon(kPageURL, /*is_same_document=*/false);
875   base::RunLoop().RunUntilIdle();
876   // Feed in favicons before completing the database lookup.
877   handler.OnUpdateCandidates(
878       kPageURL, {FaviconURL(kIconURL16x16, kFavicon, kEmptySizes)}, GURL());
879 
880   ASSERT_TRUE(VerifyAndClearExpectations());
881   // Database lookup for |kPageURL| is ongoing.
882   ASSERT_TRUE(favicon_service_.fake()->HasPendingManualCallback());
883 
884   EXPECT_CALL(favicon_service_,
885               SetFavicons(base::flat_set<GURL>{kPageURL}, kIconURL16x16,
886                           kFavicon, ImageSizeIs(16, 16)));
887   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kIconURL16x16, _, _));
888 
889   // Complete the lookup for |kPageURL|.
890   ASSERT_TRUE(favicon_service_.fake()->RunCallbackManually());
891   base::RunLoop().RunUntilIdle();
892 
893   EXPECT_THAT(favicon_service_.fake()->db_requests(),
894               ElementsAre(kIconURL16x16));
895   EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL16x16));
896 }
897 
898 // Test that the FaviconHandler process does not save anything to the database
899 // for incognito tabs.
TEST_F(FaviconHandlerTest,DownloadUnknownFaviconInIncognito)900 TEST_F(FaviconHandlerTest, DownloadUnknownFaviconInIncognito) {
901   ON_CALL(delegate_, IsOffTheRecord()).WillByDefault(Return(true));
902 
903   // No writes expected.
904   EXPECT_CALL(favicon_service_, UpdateFaviconMappingsAndFetch(_, _, _, _, _, _))
905       .Times(0);
906   EXPECT_CALL(favicon_service_, SetFavicons(_, _, _, _)).Times(0);
907 
908   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kIconURL16x16, _, _));
909 
910   RunHandlerWithSimpleFaviconCandidates({kIconURL16x16});
911   EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL16x16));
912   EXPECT_THAT(favicon_service_.fake()->db_requests(),
913               ElementsAre(kPageURL, kIconURL16x16));
914 }
915 
916 // Test that favicon mappings are not deleted in incognito even if the page
917 // lists no candidates.
TEST_F(FaviconHandlerTest,DoNotDeleteFaviconMappingsInIncognito)918 TEST_F(FaviconHandlerTest, DoNotDeleteFaviconMappingsInIncognito) {
919   const GURL kIconURL("http://www.google.com/favicon");
920 
921   ON_CALL(delegate_, IsOffTheRecord()).WillByDefault(Return(true));
922   favicon_service_.fake()->Store(kPageURL, kIconURL,
923                                  CreateRawBitmapResult(kIconURL));
924 
925   EXPECT_CALL(favicon_service_, DeleteFaviconMappings(_, _)).Times(0);
926 
927   EXPECT_CALL(
928       delegate_,
929       OnFaviconDeleted(kPageURL, FaviconDriverObserver::NON_TOUCH_16_DIP));
930 
931   RunHandlerWithSimpleFaviconCandidates(URLVector());
932 }
933 
934 // Test that the icon is redownloaded if the icon cached for the page URL
935 // expired.
TEST_F(FaviconHandlerTest,RedownloadExpiredPageUrlFavicon)936 TEST_F(FaviconHandlerTest, RedownloadExpiredPageUrlFavicon) {
937   const GURL kIconURL("http://www.google.com/favicon");
938   const SkColor kOldColor = SK_ColorBLUE;
939   const SkColor kNewColor = SK_ColorGREEN;
940 
941   favicon_service_.fake()->Store(
942       kPageURL, kIconURL,
943       CreateRawBitmapResult(kIconURL, kFavicon, /*expired=*/true,
944                             gfx::kFaviconSize, kOldColor));
945 
946   delegate_.fake_image_downloader().Add(kIconURL, IntVector{gfx::kFaviconSize},
947                                         kNewColor);
948 
949   EXPECT_CALL(favicon_service_,
950               SetFavicons(_, kIconURL, _, ImageColorIs(kNewColor)));
951 
952   InSequence seq;
953   EXPECT_CALL(delegate_,
954               OnFaviconUpdated(_, _, kIconURL, _, ImageColorIs(kOldColor)));
955   EXPECT_CALL(delegate_,
956               OnFaviconUpdated(_, _, kIconURL, _, ImageColorIs(kNewColor)));
957 
958   RunHandlerWithSimpleFaviconCandidates({kIconURL});
959   // We know from the |kPageUrl| database request that |kIconURL| has expired. A
960   // second request for |kIconURL| should not have been made because it is
961   // redundant.
962   EXPECT_THAT(favicon_service_.fake()->db_requests(), ElementsAre(kPageURL));
963   EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL));
964 }
965 
966 // Test that FaviconHandler requests the new data when:
967 // - There is valid data in the database for the page URL.
968 // AND
969 // - The icon URL used by the page has changed.
970 // AND
971 // - There is no data in database for the new icon URL.
TEST_F(FaviconHandlerTest,UpdateAndDownloadFavicon)972 TEST_F(FaviconHandlerTest, UpdateAndDownloadFavicon) {
973   const GURL kOldIconURL("http://www.google.com/old_favicon");
974   const GURL kNewIconURL = kIconURL16x16;
975 
976   favicon_service_.fake()->Store(kPageURL, kOldIconURL,
977                                  CreateRawBitmapResult(kOldIconURL));
978 
979   InSequence seq;
980   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kOldIconURL, _, _));
981   EXPECT_CALL(favicon_service_, SetFavicons(_, kNewIconURL, _, _));
982   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kNewIconURL, _, _));
983 
984   RunHandlerWithSimpleFaviconCandidates({kNewIconURL});
985   EXPECT_THAT(delegate_.downloads(), ElementsAre(kNewIconURL));
986 }
987 
988 // If there is data for the page URL in history which is invalid, test that:
989 // - The invalid data is not sent to the UI.
990 // - The icon is redownloaded.
TEST_F(FaviconHandlerTest,FaviconInHistoryInvalid)991 TEST_F(FaviconHandlerTest, FaviconInHistoryInvalid) {
992   const GURL kIconURL("http://www.google.com/favicon");
993 
994   delegate_.fake_image_downloader().Add(kIconURL, IntVector{gfx::kFaviconSize},
995                                         SK_ColorBLUE);
996 
997   // Set non-empty but invalid data.
998   std::vector<FaviconRawBitmapResult> bitmap_result =
999       CreateRawBitmapResult(kIconURL);
1000   // Empty bitmap data is invalid.
1001   bitmap_result[0].bitmap_data = new base::RefCountedBytes();
1002 
1003   favicon_service_.fake()->Store(kPageURL, kIconURL, bitmap_result);
1004 
1005   EXPECT_CALL(delegate_,
1006               OnFaviconUpdated(_, _, kIconURL, _, ImageColorIs(SK_ColorBLUE)));
1007 
1008   RunHandlerWithSimpleFaviconCandidates({kIconURL});
1009 
1010   EXPECT_THAT(favicon_service_.fake()->db_requests(), ElementsAre(kPageURL));
1011   EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL));
1012 }
1013 
1014 // Test that no downloads are done if a user visits a page which changed its
1015 // favicon URL to a favicon URL which is already cached in the database.
TEST_F(FaviconHandlerTest,UpdateFavicon)1016 TEST_F(FaviconHandlerTest, UpdateFavicon) {
1017   const GURL kSomePreviousPageURL("https://www.google.com/previous");
1018   const GURL kIconURL("http://www.google.com/favicon");
1019   const GURL kNewIconURL("http://www.google.com/new_favicon");
1020 
1021   favicon_service_.fake()->Store(kPageURL, kIconURL,
1022                                  CreateRawBitmapResult(kIconURL));
1023   favicon_service_.fake()->Store(kSomePreviousPageURL, kNewIconURL,
1024                                  CreateRawBitmapResult(kNewIconURL));
1025 
1026   EXPECT_CALL(favicon_service_, SetFavicons(_, _, _, _)).Times(0);
1027 
1028   InSequence seq;
1029   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kIconURL, _, _));
1030   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kNewIconURL, _, _));
1031 
1032   RunHandlerWithSimpleFaviconCandidates({kNewIconURL});
1033   EXPECT_THAT(favicon_service_.fake()->db_requests(),
1034               ElementsAre(kPageURL, kNewIconURL));
1035   EXPECT_THAT(delegate_.downloads(), IsEmpty());
1036 }
1037 
TEST_F(FaviconHandlerTest,Download2ndFaviconURLCandidate)1038 TEST_F(FaviconHandlerTest, Download2ndFaviconURLCandidate) {
1039   const GURL kIconURLReturning500("http://www.google.com/500.png");
1040 
1041   delegate_.fake_image_downloader().AddError(kIconURLReturning500, 500);
1042 
1043   favicon_service_.fake()->Store(
1044       kPageURL, kIconURL64x64,
1045       CreateRawBitmapResult(kIconURL64x64, kTouchIcon,
1046                             /*expired=*/true));
1047 
1048   EXPECT_CALL(delegate_,
1049               OnFaviconUpdated(kPageURL, FaviconDriverObserver::TOUCH_LARGEST,
1050                                kIconURL64x64, /*icon_url_changed=*/true, _));
1051   EXPECT_CALL(delegate_,
1052               OnFaviconUpdated(kPageURL, FaviconDriverObserver::TOUCH_LARGEST,
1053                                kIconURL64x64, /*icon_url_changed=*/false, _));
1054 
1055   RunHandlerWithCandidates(
1056       FaviconDriverObserver::TOUCH_LARGEST,
1057       {
1058           FaviconURL(kIconURLReturning500, kTouchPrecomposedIcon, kEmptySizes),
1059           FaviconURL(kIconURL64x64, kTouchIcon, kEmptySizes),
1060       });
1061   // First download fails, second succeeds.
1062   EXPECT_THAT(delegate_.downloads(),
1063               ElementsAre(kIconURLReturning500, kIconURL64x64));
1064 }
1065 
1066 // Test that download data for icon URLs other than the current favicon
1067 // candidate URLs is ignored. This test tests the scenario where a download is
1068 // in flight when FaviconHandler::OnUpdateCandidates() is called.
1069 // TODO(mastiz): Make this test deal with FaviconURLs of type
1070 // favicon_base::IconType::kFavicon and add new ones like
1071 // OnlyDownloadMatchingIconType and CallSetFaviconsWithCorrectIconType.
TEST_F(FaviconHandlerTest,UpdateDuringDownloading)1072 TEST_F(FaviconHandlerTest, UpdateDuringDownloading) {
1073   const GURL kIconURL1("http://www.google.com/favicon");
1074   const GURL kIconURL2 = kIconURL16x16;
1075   const GURL kIconURL3 = kIconURL12x12;
1076 
1077   // Defer the download completion such that RunUntilIdle() doesn't complete
1078   // the download.
1079   delegate_.fake_image_downloader().SetRunCallbackManuallyForUrl(kIconURL1);
1080 
1081   delegate_.fake_image_downloader().Add(kIconURL1, IntVector{16});
1082   delegate_.fake_image_downloader().Add(kIconURL3, IntVector{12});
1083 
1084   std::unique_ptr<FaviconHandler> handler =
1085       RunHandlerWithSimpleFaviconCandidates({kIconURL1, kIconURL2});
1086 
1087   ASSERT_TRUE(VerifyAndClearExpectations());
1088   ASSERT_TRUE(delegate_.fake_image_downloader().HasPendingManualCallback());
1089 
1090   // Favicon update should invalidate the ongoing download.
1091   EXPECT_CALL(favicon_service_, SetFavicons(_, kIconURL3, _, _));
1092   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kIconURL3, _, _));
1093 
1094   handler->OnUpdateCandidates(
1095       kPageURL, {FaviconURL(kIconURL3, kFavicon, kEmptySizes)}, GURL());
1096 
1097   // Finalizes download, which should be thrown away as the favicon URLs were
1098   // updated.
1099   EXPECT_TRUE(delegate_.fake_image_downloader().RunCallbackManually());
1100   base::RunLoop().RunUntilIdle();
1101 
1102   EXPECT_THAT(favicon_service_.fake()->db_requests(), ElementsAre(kIconURL3));
1103   EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL3));
1104 }
1105 
1106 // Test that sending an icon URL update different to the previous icon URL
1107 // update during a database lookup ignores the first icon URL and processes the
1108 // second.
TEST_F(FaviconHandlerTest,UpdateDuringDatabaseLookup)1109 TEST_F(FaviconHandlerTest, UpdateDuringDatabaseLookup) {
1110   const GURL kIconURL1 = kIconURL16x16;
1111   const GURL kIconURL2 = kIconURL12x12;
1112 
1113   // Defer the lookup completion such that RunUntilIdle() doesn't complete the
1114   // lookup.
1115   favicon_service_.fake()->SetRunCallbackManuallyForUrl(kIconURL1);
1116 
1117   delegate_.fake_image_downloader().Add(kIconURL1, IntVector{16});
1118   delegate_.fake_image_downloader().Add(kIconURL2, IntVector{12});
1119 
1120   std::unique_ptr<FaviconHandler> handler =
1121       RunHandlerWithSimpleFaviconCandidates(URLVector{kIconURL1});
1122 
1123   ASSERT_TRUE(VerifyAndClearExpectations());
1124   ASSERT_TRUE(favicon_service_.fake()->HasPendingManualCallback());
1125 
1126   // SetFavicons() and OnFaviconUpdated() should be called for the new icon URL
1127   // and not |kIconURL1|.
1128   EXPECT_CALL(favicon_service_, SetFavicons(_, kIconURL2, _, _));
1129   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kIconURL2, _, _));
1130 
1131   handler->OnUpdateCandidates(
1132       kPageURL, {FaviconURL(kIconURL2, kFavicon, kEmptySizes)}, GURL());
1133 
1134   // Finalizes the DB lookup, which should be thrown away as the favicon URLs
1135   // were updated.
1136   EXPECT_TRUE(favicon_service_.fake()->RunCallbackManually());
1137   base::RunLoop().RunUntilIdle();
1138 
1139   EXPECT_THAT(favicon_service_.fake()->db_requests(), ElementsAre(kIconURL2));
1140   EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL2));
1141 }
1142 
1143 // Test that sending an icon URL update identical to the previous icon URL
1144 // update during image download is a no-op.
TEST_F(FaviconHandlerTest,UpdateSameIconURLsWhileDownloadingShouldBeNoop)1145 TEST_F(FaviconHandlerTest, UpdateSameIconURLsWhileDownloadingShouldBeNoop) {
1146   const GURL kSlowLoadingIconURL("http://www.google.com/slow_favicon");
1147 
1148   const std::vector<FaviconURL> favicon_urls = {
1149       FaviconURL(kIconURL12x12, kFavicon, kEmptySizes),
1150       FaviconURL(kSlowLoadingIconURL, kFavicon, kEmptySizes),
1151   };
1152 
1153   // Defer the download completion such that RunUntilIdle() doesn't complete
1154   // the download.
1155   delegate_.fake_image_downloader().SetRunCallbackManuallyForUrl(
1156       kSlowLoadingIconURL);
1157   delegate_.fake_image_downloader().Add(kSlowLoadingIconURL, IntVector{16});
1158 
1159   std::unique_ptr<FaviconHandler> handler = RunHandlerWithCandidates(
1160       FaviconDriverObserver::NON_TOUCH_16_DIP, favicon_urls);
1161 
1162   ASSERT_THAT(favicon_service_.fake()->db_requests(),
1163               ElementsAre(kPageURL, kIconURL12x12, kSlowLoadingIconURL));
1164   ASSERT_TRUE(VerifyAndClearExpectations());
1165   ASSERT_TRUE(delegate_.fake_image_downloader().HasPendingManualCallback());
1166 
1167   // Calling OnUpdateCandidates() with the same icon URLs should have no effect,
1168   // despite the ongoing download.
1169   handler->OnUpdateCandidates(kPageURL, favicon_urls, GURL());
1170   base::RunLoop().RunUntilIdle();
1171   EXPECT_THAT(favicon_service_.fake()->db_requests(), IsEmpty());
1172   EXPECT_THAT(delegate_.downloads(), IsEmpty());
1173 
1174   // Complete the download.
1175   EXPECT_CALL(favicon_service_, SetFavicons(_, _, _, _));
1176   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, _, _, _));
1177   EXPECT_TRUE(delegate_.fake_image_downloader().RunCallbackManually());
1178   base::RunLoop().RunUntilIdle();
1179   EXPECT_THAT(delegate_.downloads(), IsEmpty());
1180 }
1181 
1182 // Test that sending an icon URL update identical to the previous icon URL
1183 // update during a database lookup is a no-op.
TEST_F(FaviconHandlerTest,UpdateSameIconURLsWhileDatabaseLookupShouldBeNoop)1184 TEST_F(FaviconHandlerTest, UpdateSameIconURLsWhileDatabaseLookupShouldBeNoop) {
1185   const std::vector<FaviconURL> favicon_urls = {
1186       FaviconURL(kIconURL12x12, kFavicon, kEmptySizes),
1187   };
1188 
1189   favicon_service_.fake()->SetRunCallbackManuallyForUrl(kIconURL12x12);
1190 
1191   std::unique_ptr<FaviconHandler> handler = RunHandlerWithCandidates(
1192       FaviconDriverObserver::NON_TOUCH_16_DIP, favicon_urls);
1193 
1194   // Ongoing database lookup.
1195   ASSERT_THAT(favicon_service_.fake()->db_requests(),
1196               ElementsAre(kPageURL, kIconURL12x12));
1197   ASSERT_THAT(delegate_.downloads(), IsEmpty());
1198   ASSERT_TRUE(VerifyAndClearExpectations());
1199   ASSERT_TRUE(favicon_service_.fake()->HasPendingManualCallback());
1200 
1201   // Calling OnUpdateCandidates() with the same icon URLs should have no effect,
1202   // despite the ongoing DB lookup.
1203   handler->OnUpdateCandidates(kPageURL, favicon_urls, GURL());
1204   base::RunLoop().RunUntilIdle();
1205   EXPECT_THAT(favicon_service_.fake()->db_requests(), IsEmpty());
1206   EXPECT_THAT(delegate_.downloads(), IsEmpty());
1207 
1208   // Complete the lookup.
1209   EXPECT_CALL(favicon_service_, SetFavicons(_, _, _, _));
1210   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, _, _, _));
1211   EXPECT_TRUE(favicon_service_.fake()->RunCallbackManually());
1212   base::RunLoop().RunUntilIdle();
1213   EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL12x12));
1214 }
1215 
1216 // Test that calling OnUpdateFaviconUrl() with the same icon URLs as before is a
1217 // no-op. This is important because OnUpdateFaviconUrl() is called when the page
1218 // finishes loading. This can occur several times for pages with iframes.
TEST_F(FaviconHandlerTest,UpdateSameIconURLsAfterFinishedShouldBeNoop)1219 TEST_F(FaviconHandlerTest, UpdateSameIconURLsAfterFinishedShouldBeNoop) {
1220   const std::vector<FaviconURL> favicon_urls = {
1221       FaviconURL(kIconURL10x10, kFavicon, kEmptySizes),
1222       FaviconURL(kIconURL16x16, kFavicon, kEmptySizes),
1223   };
1224 
1225   std::unique_ptr<FaviconHandler> handler = RunHandlerWithCandidates(
1226       FaviconDriverObserver::NON_TOUCH_16_DIP, favicon_urls);
1227 
1228   ASSERT_TRUE(VerifyAndClearExpectations());
1229 
1230   // Calling OnUpdateCandidates() with identical data should be a no-op.
1231   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, _, _, _)).Times(0);
1232   EXPECT_CALL(favicon_service_, SetFavicons(_, _, _, _)).Times(0);
1233 
1234   handler->OnUpdateCandidates(kPageURL, favicon_urls, GURL());
1235   base::RunLoop().RunUntilIdle();
1236   EXPECT_THAT(favicon_service_.fake()->db_requests(), IsEmpty());
1237   EXPECT_THAT(delegate_.downloads(), IsEmpty());
1238 }
1239 
1240 // Fixes crbug.com/544560
1241 // Tests that Delegate::OnFaviconUpdated() is called if:
1242 // - The best icon on the initial page is not the last icon.
1243 // - All of the initial page's icons are downloaded.
1244 // AND
1245 // - JavaScript modifies the page's <link rel="icon"> tags to contain only the
1246 //   last icon.
TEST_F(FaviconHandlerTest,OnFaviconAvailableNotificationSentAfterIconURLChange)1247 TEST_F(FaviconHandlerTest,
1248        OnFaviconAvailableNotificationSentAfterIconURLChange) {
1249   const GURL kIconURL1(
1250       "http://wwww.page_which_animates_favicon.com/frame1.png");
1251   const GURL kIconURL2(
1252       "http://wwww.page_which_animates_favicon.com/frame2.png");
1253 
1254   // |kIconURL1| is the better match.
1255   delegate_.fake_image_downloader().Add(kIconURL1, IntVector{15});
1256   delegate_.fake_image_downloader().Add(kIconURL2, IntVector{10});
1257 
1258   // Two FaviconDriver::OnFaviconUpdated() notifications should be sent for
1259   // |kIconURL1|, one before and one after the download.
1260   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kIconURL1, _, _));
1261 
1262   std::unique_ptr<FaviconHandler> handler =
1263       RunHandlerWithSimpleFaviconCandidates({kIconURL1, kIconURL2});
1264 
1265   // Both |kIconURL1| and |kIconURL2| should have been requested from the
1266   // database and downloaded. |kIconURL2| should have been fetched from the
1267   // database and downloaded last.
1268   ASSERT_THAT(delegate_.downloads(), ElementsAre(kIconURL1, kIconURL2));
1269   ASSERT_THAT(favicon_service_.fake()->db_requests(),
1270               ElementsAre(kPageURL, kIconURL1, kIconURL2));
1271   ASSERT_TRUE(VerifyAndClearExpectations());
1272 
1273   // Simulate the page changing it's icon URL to just |kIconURL2| via
1274   // Javascript.
1275   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kIconURL2, _, _));
1276   handler->OnUpdateCandidates(
1277       kPageURL, {FaviconURL(kIconURL2, kFavicon, kEmptySizes)}, GURL());
1278   base::RunLoop().RunUntilIdle();
1279 }
1280 
1281 // Test that favicon mappings are removed if the page initially lists a favicon
1282 // and later uses Javascript to remove it.
TEST_F(FaviconHandlerTest,RemoveFaviconViaJavascript)1283 TEST_F(FaviconHandlerTest, RemoveFaviconViaJavascript) {
1284   EXPECT_CALL(favicon_service_, SetFavicons(base::flat_set<GURL>{kPageURL},
1285                                             kIconURL16x16, kFavicon, _));
1286 
1287   // Setup: the page initially lists a favicon.
1288   std::unique_ptr<FaviconHandler> handler =
1289       RunHandlerWithSimpleFaviconCandidates(URLVector{kIconURL16x16});
1290   ASSERT_TRUE(VerifyAndClearExpectations());
1291 
1292   // Simulate the page removing its icon URL via Javascript.
1293   EXPECT_CALL(favicon_service_,
1294               DeleteFaviconMappings(base::flat_set<GURL>{kPageURL}, kFavicon));
1295   handler->OnUpdateCandidates(kPageURL, std::vector<FaviconURL>(), GURL());
1296   base::RunLoop().RunUntilIdle();
1297 }
1298 
1299 // Tests that there is not crash and SetFavicons() is called with the
1300 // appropriate icon URL in the following scenario:
1301 // - The database initially has a cached but expired icon for the page.
1302 // - Initial favicon candidates are received fast, before the history lookup
1303 //   completes.
1304 // - Before the history lookup completes, favicon candidates are updated via
1305 //   javascript to include a different set of icons.
TEST_F(FaviconHandlerTest,UpdateIconsViaJavascriptAfterFastCandidatesAndExpiredIcon)1306 TEST_F(FaviconHandlerTest,
1307        UpdateIconsViaJavascriptAfterFastCandidatesAndExpiredIcon) {
1308   EXPECT_CALL(favicon_service_, DeleteFaviconMappings(_, _)).Times(0);
1309   EXPECT_CALL(favicon_service_, SetFavicons(_, kIconURL64x64, _, _));
1310 
1311   // Initial database contains a cached by expired icon for |kPageURL|.
1312   favicon_service_.fake()->Store(
1313       kPageURL, kIconURL16x16,
1314       CreateRawBitmapResult(kIconURL16x16, kTouchIcon, /*expired=*/true));
1315 
1316   // Initial candidates are received before the history lookup for |kPageURL| is
1317   // finished.
1318   favicon_service_.fake()->SetRunCallbackManuallyForUrl(kPageURL);
1319   std::unique_ptr<FaviconHandler> handler =
1320       RunHandlerWithSimpleFaviconCandidates(URLVector{kIconURL16x16});
1321   ASSERT_TRUE(favicon_service_.fake()->HasPendingManualCallback());
1322   // Update candidates, now containing a different set of icons.
1323   handler->OnUpdateCandidates(
1324       kPageURL, {FaviconURL(kIconURL64x64, kFavicon, kEmptySizes)},
1325       /*manifest_url=*/GURL());
1326   base::RunLoop().RunUntilIdle();
1327   // Complete the history lookup for |kPageURL| now.
1328   ASSERT_TRUE(favicon_service_.fake()->RunCallbackManually());
1329   base::RunLoop().RunUntilIdle();
1330 
1331   EXPECT_THAT(favicon_service_.fake()->db_requests(), ElementsAre(kPageURL));
1332   EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL64x64));
1333 }
1334 
1335 // Test the favicon which is selected when the web page provides several
1336 // favicons and none of the favicons are cached in history.
1337 // The goal of this test is to be more of an integration test than
1338 // SelectFaviconFramesTest.*.
1339 class FaviconHandlerMultipleFaviconsTest : public FaviconHandlerTest {
1340  protected:
FaviconHandlerMultipleFaviconsTest()1341   FaviconHandlerMultipleFaviconsTest() {
1342     // Set the supported scale factors to 1x and 2x. This affects the behavior
1343     // of SelectFaviconFrames().
1344     scoped_set_supported_scale_factors_.reset();  // Need to delete first.
1345     scoped_set_supported_scale_factors_.reset(
1346         new ui::test::ScopedSetSupportedScaleFactors(
1347             {ui::SCALE_FACTOR_100P, ui::SCALE_FACTOR_200P}));
1348   }
1349 
1350   // Simulates requesting a favicon for |page_url| given:
1351   // - We have not previously cached anything in history for |page_url| or for
1352   //   any of candidates.
1353   // - The page provides favicons with edge pixel sizes of
1354   //   |candidate_icon_sizes|.
1355   // - Candidates are assumed of type kFavicon and the URLs are generated
1356   //   internally for testing purposes.
1357   //
1358   // Returns the chosen size among |candidate_icon_sizes| or -1 if none was
1359   // chosen.
DownloadTillDoneIgnoringHistory(const IntVector & candidate_icon_sizes)1360   int DownloadTillDoneIgnoringHistory(const IntVector& candidate_icon_sizes) {
1361     std::vector<FaviconURL> candidate_icons;
1362     int chosen_icon_size = -1;
1363 
1364     for (int icon_size : candidate_icon_sizes) {
1365       const GURL icon_url(base::StringPrintf(
1366           "https://www.google.com/generated/%dx%d", icon_size, icon_size));
1367       // Set up 200 responses for all images, and the corresponding size.
1368       delegate_.fake_image_downloader().Add(icon_url, IntVector{icon_size});
1369       // Create test candidates of type kFavicon and a fake URL.
1370       candidate_icons.emplace_back(icon_url, kFavicon, kEmptySizes);
1371 
1372       ON_CALL(delegate_, OnFaviconUpdated(_, _, icon_url, _, _))
1373           .WillByDefault(Assign(&chosen_icon_size, icon_size));
1374     }
1375 
1376     RunHandlerWithCandidates(FaviconDriverObserver::NON_TOUCH_16_DIP,
1377                              candidate_icons);
1378     return chosen_icon_size;
1379   }
1380 };
1381 
1382 // Tests that running FaviconHandler
1383 // - On an OS which supports the 1x and 2x scale factor
1384 // - On a page with <link rel="icon"> tags with no "sizes" information.
1385 // Selects the largest exact match. Note that a 32x32 PNG image is not a "true
1386 // exact match" on an OS which supports an 1x and 2x. A "true exact match" is
1387 // a .ico file with 16x16 and 32x32 bitmaps.
TEST_F(FaviconHandlerMultipleFaviconsTest,ChooseLargestExactMatch)1388 TEST_F(FaviconHandlerMultipleFaviconsTest, ChooseLargestExactMatch) {
1389   EXPECT_EQ(32,
1390             DownloadTillDoneIgnoringHistory(IntVector{16, 24, 32, 48, 256}));
1391 }
1392 
1393 // Test that if there are several single resolution favicons to choose
1394 // from, the exact match is preferred even if it results in upsampling.
TEST_F(FaviconHandlerMultipleFaviconsTest,ChooseExactMatchDespiteUpsampling)1395 TEST_F(FaviconHandlerMultipleFaviconsTest, ChooseExactMatchDespiteUpsampling) {
1396   EXPECT_EQ(16, DownloadTillDoneIgnoringHistory(IntVector{16, 24, 48, 256}));
1397 }
1398 
1399 // Test that favicons which need to be upsampled a little or downsampled
1400 // a little are preferred over huge favicons.
TEST_F(FaviconHandlerMultipleFaviconsTest,ChooseMinorDownsamplingOverHugeIcon)1401 TEST_F(FaviconHandlerMultipleFaviconsTest,
1402        ChooseMinorDownsamplingOverHugeIcon) {
1403   EXPECT_EQ(48, DownloadTillDoneIgnoringHistory(IntVector{256, 48}));
1404 }
1405 
TEST_F(FaviconHandlerMultipleFaviconsTest,ChooseMinorUpsamplingOverHugeIcon)1406 TEST_F(FaviconHandlerMultipleFaviconsTest, ChooseMinorUpsamplingOverHugeIcon) {
1407   EXPECT_EQ(17, DownloadTillDoneIgnoringHistory(IntVector{17, 256}));
1408 }
1409 
1410 // Test a page with multiple favicon candidates with explicit sizes information.
1411 // Only the best one should be downloaded.
TEST_F(FaviconHandlerMultipleFaviconsTest,StopsDownloadingWhenRemainingCandidatesWorse)1412 TEST_F(FaviconHandlerMultipleFaviconsTest,
1413        StopsDownloadingWhenRemainingCandidatesWorse) {
1414   RunHandlerWithCandidates(FaviconDriverObserver::NON_TOUCH_16_DIP,
1415                            {
1416                                FaviconURL(kIconURL16x16, kFavicon,
1417                                           SizeVector(1U, gfx::Size(16, 16))),
1418                                FaviconURL(kIconURL64x64, kFavicon,
1419                                           SizeVector(1U, gfx::Size(64, 64))),
1420                            });
1421 
1422   EXPECT_THAT(delegate_.downloads(), SizeIs(1));
1423 }
1424 
1425 // Mostly for behavioral documentation purposes: test that downloads stops when
1426 // remaining candidates are worse or equal, for the following advanced scenario:
1427 // - The page provides multiple favicons: various with explicit sizes
1428 //   information and one without.
1429 // - Among the ones with explicit sizes information, downloading the best
1430 //   returns a 404.
1431 // - The remaining ones (with explicit sizes information) are worse than the one
1432 //   without sizes information, and shouldn't be downloaded.
TEST_F(FaviconHandlerTest,StopsDownloadingWhenRemainingCandidatesWorseDespite404)1433 TEST_F(FaviconHandlerTest,
1434        StopsDownloadingWhenRemainingCandidatesWorseDespite404) {
1435   const GURL k404IconURL("http://www.google.com/404.png");
1436   const GURL kIconURL192x192 = GURL("http://www.google.com/favicon192x192");
1437 
1438   RunHandlerWithCandidates(
1439       FaviconDriverObserver::NON_TOUCH_16_DIP,
1440       {
1441           FaviconURL(kIconURL64x64, kFavicon, kEmptySizes),
1442           FaviconURL(k404IconURL, kFavicon, SizeVector(1U, gfx::Size(32, 32))),
1443           FaviconURL(kIconURL192x192, kFavicon,
1444                      SizeVector(1U, gfx::Size(192, 192))),
1445       });
1446 
1447   EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL64x64, k404IconURL));
1448 }
1449 
TEST_F(FaviconHandlerMultipleFaviconsTest,DownloadsAllIconsWithoutSizesAttributeIfNotWantsLargest)1450 TEST_F(FaviconHandlerMultipleFaviconsTest,
1451        DownloadsAllIconsWithoutSizesAttributeIfNotWantsLargest) {
1452   RunHandlerWithCandidates(FaviconDriverObserver::NON_TOUCH_16_DIP,
1453                            {
1454                                FaviconURL(kIconURL16x16, kFavicon, kEmptySizes),
1455                                FaviconURL(kIconURL64x64, kFavicon, kEmptySizes),
1456                            });
1457 
1458   EXPECT_THAT(delegate_.downloads(), SizeIs(2));
1459 }
1460 
TEST_F(FaviconHandlerMultipleFaviconsTest,DownloadsOnlyOneIconWithoutSizesAttributeIfWantsLargest)1461 TEST_F(FaviconHandlerMultipleFaviconsTest,
1462        DownloadsOnlyOneIconWithoutSizesAttributeIfWantsLargest) {
1463   RunHandlerWithCandidates(FaviconDriverObserver::NON_TOUCH_LARGEST,
1464                            {
1465                                FaviconURL(kIconURL16x16, kFavicon, kEmptySizes),
1466                                FaviconURL(kIconURL64x64, kFavicon, kEmptySizes),
1467                            });
1468 
1469   EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL16x16));
1470 }
1471 
TEST_F(FaviconHandlerTest,Report404)1472 TEST_F(FaviconHandlerTest, Report404) {
1473   const GURL k404IconURL("http://www.google.com/404.png");
1474 
1475   EXPECT_CALL(favicon_service_, UnableToDownloadFavicon(k404IconURL));
1476 
1477   RunHandlerWithSimpleFaviconCandidates({k404IconURL});
1478   EXPECT_THAT(delegate_.downloads(), ElementsAre(k404IconURL));
1479 }
1480 
1481 // Test that WasUnableToDownloadFavicon() is not called if a download returns
1482 // HTTP status 503.
TEST_F(FaviconHandlerTest,NotReport503)1483 TEST_F(FaviconHandlerTest, NotReport503) {
1484   const GURL k503IconURL("http://www.google.com/503.png");
1485 
1486   delegate_.fake_image_downloader().AddError(k503IconURL, 503);
1487 
1488   EXPECT_CALL(favicon_service_, UnableToDownloadFavicon(_)).Times(0);
1489 
1490   RunHandlerWithSimpleFaviconCandidates({k503IconURL});
1491   EXPECT_THAT(delegate_.downloads(), ElementsAre(k503IconURL));
1492 }
1493 
1494 // Test that the best favicon is selected when:
1495 // - The page provides several favicons.
1496 // - Downloading one of the page's icon URLs previously returned a 404.
1497 // - None of the favicons are cached in the Favicons database.
TEST_F(FaviconHandlerTest,MultipleFavicons404)1498 TEST_F(FaviconHandlerTest, MultipleFavicons404) {
1499   const GURL k404IconURL("http://www.google.com/404.png");
1500 
1501   ON_CALL(favicon_service_, WasUnableToDownloadFavicon(k404IconURL))
1502       .WillByDefault(Return(true));
1503 
1504   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kIconURL12x12, _, _));
1505   RunHandlerWithSimpleFaviconCandidates({k404IconURL, kIconURL12x12});
1506   EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL12x12));
1507 }
1508 
1509 // Test that the best favicon is selected when:
1510 // - The page provides several favicons.
1511 // - Downloading the last page icon URL previously returned a 404.
1512 // - None of the favicons are cached in the Favicons database.
1513 // - All of the icons are downloaded because none of the icons have the ideal
1514 //   size.
1515 // - The 404 icon is last.
TEST_F(FaviconHandlerTest,MultipleFaviconsLast404)1516 TEST_F(FaviconHandlerTest, MultipleFaviconsLast404) {
1517   const GURL k404IconURL("http://www.google.com/404.png");
1518 
1519   ON_CALL(favicon_service_, WasUnableToDownloadFavicon(k404IconURL))
1520       .WillByDefault(Return(true));
1521 
1522   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kIconURL12x12, _, _));
1523   RunHandlerWithSimpleFaviconCandidates({kIconURL12x12, k404IconURL});
1524   EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL12x12));
1525 }
1526 
1527 // Test that no favicon is selected when:
1528 // - The page provides several favicons.
1529 // - Downloading the page's icons has previously returned a 404.
1530 // - None of the favicons are cached in the Favicons database.
TEST_F(FaviconHandlerTest,MultipleFaviconsAll404)1531 TEST_F(FaviconHandlerTest, MultipleFaviconsAll404) {
1532   const GURL k404IconURL1("http://www.google.com/a/404.png");
1533   const GURL k404IconURL2("http://www.google.com/b/404.png");
1534 
1535   ON_CALL(favicon_service_, WasUnableToDownloadFavicon(k404IconURL1))
1536       .WillByDefault(Return(true));
1537   ON_CALL(favicon_service_, WasUnableToDownloadFavicon(k404IconURL2))
1538       .WillByDefault(Return(true));
1539 
1540   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, _, _, _)).Times(0);
1541   RunHandlerWithSimpleFaviconCandidates({k404IconURL1, k404IconURL2});
1542   EXPECT_THAT(delegate_.downloads(), IsEmpty());
1543 }
1544 
1545 // Test that favicon mappings are removed if the page initially lists a favicon
1546 // and later uses Javascript to change it to another icon that returns a 404.
TEST_F(FaviconHandlerTest,ChangeFaviconViaJavascriptTo404)1547 TEST_F(FaviconHandlerTest, ChangeFaviconViaJavascriptTo404) {
1548   const GURL k404IconURL("http://www.google.com/404.png");
1549 
1550   EXPECT_CALL(favicon_service_, SetFavicons(base::flat_set<GURL>{kPageURL},
1551                                             kIconURL16x16, kFavicon, _));
1552 
1553   // Setup: the page initially lists a favicon.
1554   std::unique_ptr<FaviconHandler> handler =
1555       RunHandlerWithSimpleFaviconCandidates(URLVector{kIconURL16x16});
1556   ASSERT_TRUE(VerifyAndClearExpectations());
1557 
1558   // Simulate the page changing its icon URL via Javascript, using a URL that
1559   // returns a 404 (the most likely scenario for this is the implicit
1560   // /favicon.ico path that the site didn't actually list).
1561   EXPECT_CALL(favicon_service_,
1562               DeleteFaviconMappings(base::flat_set<GURL>{kPageURL}, kFavicon));
1563   handler->OnUpdateCandidates(
1564       kPageURL, {FaviconURL(k404IconURL, kFavicon, kEmptySizes)}, GURL());
1565   base::RunLoop().RunUntilIdle();
1566 }
1567 
1568 // Test that favicon mappings are not removed in incognito if the page initially
1569 // lists a favicon and later uses Javascript to change it to another icon that
1570 // returns a 404.
TEST_F(FaviconHandlerTest,ChangeFaviconViaJavascriptTo404InIncognito)1571 TEST_F(FaviconHandlerTest, ChangeFaviconViaJavascriptTo404InIncognito) {
1572   const GURL k404IconURL("http://www.google.com/404.png");
1573 
1574   ON_CALL(delegate_, IsOffTheRecord()).WillByDefault(Return(true));
1575   favicon_service_.fake()->Store(kPageURL, kIconURL16x16,
1576                                  CreateRawBitmapResult(kIconURL16x16));
1577 
1578   EXPECT_CALL(favicon_service_, DeleteFaviconMappings(_, _)).Times(0);
1579 
1580   // Setup: the page initially lists a favicon.
1581   std::unique_ptr<FaviconHandler> handler =
1582       RunHandlerWithSimpleFaviconCandidates(URLVector{kIconURL16x16});
1583 
1584   // Simulate the page changing its icon URL via Javascript, using a URL that
1585   // returns a 404 (the most likely scenario for this is the implicit
1586   // /favicon.ico path that the site didn't actually list).
1587   handler->OnUpdateCandidates(
1588       kPageURL, {FaviconURL(k404IconURL, kFavicon, kEmptySizes)}, GURL());
1589   base::RunLoop().RunUntilIdle();
1590 }
1591 
1592 // Test that no favicon is selected when the page's only icon uses an invalid
1593 // URL syntax.
TEST_F(FaviconHandlerTest,FaviconInvalidURL)1594 TEST_F(FaviconHandlerTest, FaviconInvalidURL) {
1595   const GURL kInvalidFormatURL("invalid");
1596   ASSERT_TRUE(kInvalidFormatURL.is_empty());
1597 
1598   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, _, _, _)).Times(0);
1599 
1600   RunHandlerWithSimpleFaviconCandidates({kInvalidFormatURL});
1601   EXPECT_THAT(delegate_.downloads(), IsEmpty());
1602 }
1603 
TEST_F(FaviconHandlerTest,TestSortFavicon)1604 TEST_F(FaviconHandlerTest, TestSortFavicon) {
1605   // Names represent the bitmap sizes per icon.
1606   const GURL kIconURL1_17("http://www.google.com/a");
1607   const GURL kIconURL1024_512("http://www.google.com/b");
1608   const GURL kIconURL16_14("http://www.google.com/c");
1609   const GURL kIconURLWithoutSize1("http://www.google.com/d");
1610   const GURL kIconURLWithoutSize2("http://www.google.com/e");
1611 
1612   const std::vector<favicon::FaviconURL> kSourceIconURLs{
1613       FaviconURL(kIconURL1_17, kFavicon, {gfx::Size(1, 1), gfx::Size(17, 17)}),
1614       FaviconURL(kIconURL1024_512, kFavicon,
1615                  {gfx::Size(1024, 1024), gfx::Size(512, 512)}),
1616       FaviconURL(kIconURL16_14, kFavicon,
1617                  {gfx::Size(16, 16), gfx::Size(14, 14)}),
1618       FaviconURL(kIconURLWithoutSize1, kFavicon, kEmptySizes),
1619       FaviconURL(kIconURLWithoutSize2, kFavicon, kEmptySizes)};
1620 
1621   std::unique_ptr<FaviconHandler> handler = RunHandlerWithCandidates(
1622       FaviconDriverObserver::NON_TOUCH_LARGEST, kSourceIconURLs);
1623 
1624   EXPECT_THAT(
1625       handler->GetIconURLs(),
1626       ElementsAre(
1627           // The 512x512 bitmap is the best match for the desired size.
1628           kIconURL1024_512, kIconURL1_17, kIconURL16_14,
1629           // The rest of bitmaps come in order, there is no "sizes" attribute.
1630           kIconURLWithoutSize1, kIconURLWithoutSize2));
1631 }
1632 
TEST_F(FaviconHandlerTest,TestSortTouchIconLargest)1633 TEST_F(FaviconHandlerTest, TestSortTouchIconLargest) {
1634   const GURL kIconURLWithoutSize("http://www.google.com/touchicon-nosize");
1635   const GURL kIconURL144x144("http://www.google.com/touchicon144x144");
1636   const GURL kIconURL192x192("http://www.google.com/touchicon192x192");
1637 
1638   const std::vector<favicon::FaviconURL> kSourceIconURLs{
1639       FaviconURL(kIconURLWithoutSize, kTouchIcon, kEmptySizes),
1640       FaviconURL(kIconURL144x144, kTouchIcon,
1641                  SizeVector(1U, gfx::Size(144, 144))),
1642       FaviconURL(kIconURL192x192, kTouchIcon,
1643                  SizeVector(1U, gfx::Size(192, 192))),
1644   };
1645 
1646   std::unique_ptr<FaviconHandler> handler = RunHandlerWithCandidates(
1647       FaviconDriverObserver::TOUCH_LARGEST, kSourceIconURLs);
1648 
1649   EXPECT_THAT(
1650       handler->GetIconURLs(),
1651       ElementsAre(kIconURL192x192, kIconURL144x144, kIconURLWithoutSize));
1652 }
1653 
TEST_F(FaviconHandlerTest,TestDownloadLargestFavicon)1654 TEST_F(FaviconHandlerTest, TestDownloadLargestFavicon) {
1655   // Names represent the bitmap sizes per icon.
1656   const GURL kIconURL1024_512("http://www.google.com/a");
1657   const GURL kIconURL15_14("http://www.google.com/b");
1658   const GURL kIconURL16_512("http://www.google.com/c");
1659   const GURL kIconURLWithoutSize1("http://www.google.com/d");
1660   const GURL kIconURLWithoutSize2("http://www.google.com/e");
1661 
1662   RunHandlerWithCandidates(
1663       FaviconDriverObserver::NON_TOUCH_LARGEST,
1664       {FaviconURL(kIconURL1024_512, kFavicon,
1665                   {gfx::Size(1024, 1024), gfx::Size(512, 512)}),
1666        FaviconURL(kIconURL15_14, kFavicon,
1667                   {gfx::Size(15, 15), gfx::Size(14, 14)}),
1668        FaviconURL(kIconURL16_512, kFavicon,
1669                   {gfx::Size(16, 16), gfx::Size(512, 512)}),
1670        FaviconURL(kIconURLWithoutSize1, kFavicon, kEmptySizes),
1671        FaviconURL(kIconURLWithoutSize2, kFavicon, kEmptySizes)});
1672 
1673   // Icon URLs are not registered and hence 404s will be produced, which
1674   // allows checking whether the icons were requested according to their size.
1675   // The favicons should have been requested in decreasing order of their sizes.
1676   // Favicons without any <link sizes=""> attribute should have been downloaded
1677   // last.
1678   EXPECT_THAT(delegate_.downloads(),
1679               ElementsAre(kIconURL1024_512, kIconURL16_512, kIconURL15_14,
1680                           kIconURLWithoutSize1, kIconURLWithoutSize2));
1681 }
1682 
TEST_F(FaviconHandlerTest,TestSelectLargestFavicon)1683 TEST_F(FaviconHandlerTest, TestSelectLargestFavicon) {
1684   const GURL kIconURL1("http://www.google.com/b");
1685   const GURL kIconURL2("http://www.google.com/c");
1686 
1687   delegate_.fake_image_downloader().Add(kIconURL1, IntVector{15});
1688   delegate_.fake_image_downloader().Add(kIconURL2, IntVector{14, 16});
1689 
1690   // Verify NotifyFaviconAvailable().
1691   EXPECT_CALL(delegate_,
1692               OnFaviconUpdated(_, FaviconDriverObserver::NON_TOUCH_LARGEST,
1693                                kIconURL2, _, _));
1694 
1695   RunHandlerWithCandidates(
1696       FaviconDriverObserver::NON_TOUCH_LARGEST,
1697       {FaviconURL(kIconURL1, kFavicon, {gfx::Size(15, 15)}),
1698        FaviconURL(kIconURL2, kFavicon,
1699                   {gfx::Size(14, 14), gfx::Size(16, 16)})});
1700 
1701   EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL2));
1702 }
1703 
TEST_F(FaviconHandlerTest,TestFaviconWasScaledAfterDownload)1704 TEST_F(FaviconHandlerTest, TestFaviconWasScaledAfterDownload) {
1705   const int kMaximalSize = FaviconHandler::GetMaximalIconSize(
1706       FaviconDriverObserver::NON_TOUCH_LARGEST,
1707       /*candidates_from_web_manifest=*/false);
1708 
1709   const GURL kIconURL1("http://www.google.com/b");
1710   const GURL kIconURL2("http://www.google.com/c");
1711 
1712   const int kOriginalSize1 = kMaximalSize + 1;
1713   const int kOriginalSize2 = kMaximalSize + 2;
1714 
1715   delegate_.fake_image_downloader().Add(kIconURL1, IntVector{kOriginalSize1},
1716                                         SK_ColorBLUE);
1717   delegate_.fake_image_downloader().Add(kIconURL2, IntVector{kOriginalSize2},
1718                                         SK_ColorBLUE);
1719 
1720   // Verify the best bitmap was selected (although smaller than |kIconURL2|)
1721   // and that it was scaled down to |kMaximalSize|.
1722   EXPECT_CALL(delegate_,
1723               OnFaviconUpdated(_, _, kIconURL1, _,
1724                                ImageSizeIs(kMaximalSize, kMaximalSize)));
1725 
1726   RunHandlerWithCandidates(
1727       FaviconDriverObserver::NON_TOUCH_LARGEST,
1728       {FaviconURL(kIconURL1, kFavicon,
1729                   SizeVector{gfx::Size(kOriginalSize1, kOriginalSize1)}),
1730        FaviconURL(kIconURL2, kFavicon,
1731                   SizeVector{gfx::Size(kOriginalSize2, kOriginalSize2)})});
1732 
1733   EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL1));
1734 }
1735 
1736 // Test that if several icons are downloaded because the icons are smaller than
1737 // expected that OnFaviconUpdated() is called with the largest downloaded
1738 // bitmap.
TEST_F(FaviconHandlerTest,TestKeepDownloadedLargestFavicon)1739 TEST_F(FaviconHandlerTest, TestKeepDownloadedLargestFavicon) {
1740   EXPECT_CALL(delegate_,
1741               OnFaviconUpdated(_, _, kIconURL12x12, _, ImageSizeIs(12, 12)));
1742 
1743   RunHandlerWithCandidates(
1744       FaviconDriverObserver::NON_TOUCH_LARGEST,
1745       {FaviconURL(kIconURL10x10, kFavicon, SizeVector{gfx::Size(16, 16)}),
1746        FaviconURL(kIconURL12x12, kFavicon, SizeVector{gfx::Size(15, 15)}),
1747        FaviconURL(kIconURL16x16, kFavicon, kEmptySizes)});
1748 }
1749 
1750 // Test that if a page URL is followed by another page URL which is not
1751 // considered the same document, favicon candidates listed in the second page
1752 // get associated to that second page only.
TEST_F(FaviconHandlerTest,SetFaviconsForLastPageUrlOnly)1753 TEST_F(FaviconHandlerTest, SetFaviconsForLastPageUrlOnly) {
1754   const GURL kDifferentPageURL = GURL("http://www.google.com/other");
1755 
1756   EXPECT_CALL(favicon_service_,
1757               SetFavicons(base::flat_set<GURL>{kDifferentPageURL},
1758                           kIconURL12x12, _, _));
1759   EXPECT_CALL(delegate_,
1760               OnFaviconUpdated(kDifferentPageURL,
1761                                FaviconDriverObserver::NON_TOUCH_16_DIP,
1762                                kIconURL12x12, _, _));
1763 
1764   std::unique_ptr<FaviconHandler> handler = std::make_unique<FaviconHandler>(
1765       &favicon_service_, &delegate_, FaviconDriverObserver::NON_TOUCH_16_DIP);
1766   handler->FetchFavicon(kPageURL, /*is_same_document=*/false);
1767   base::RunLoop().RunUntilIdle();
1768   // Load a new URL (different document) without feeding any candidates for the
1769   // first URL.
1770   handler->FetchFavicon(kDifferentPageURL, /*is_same_document=*/false);
1771   base::RunLoop().RunUntilIdle();
1772   handler->OnUpdateCandidates(
1773       kDifferentPageURL, {FaviconURL(kIconURL12x12, kFavicon, kEmptySizes)},
1774       /*manifest_url=*/GURL());
1775   base::RunLoop().RunUntilIdle();
1776 }
1777 
1778 // Test that if a page URL is followed by another page URL which is considered
1779 // the same document (e.g. fragment navigation), favicon candidates listed in
1780 // the second page get associated to both page URLs.
TEST_F(FaviconHandlerTest,SetFaviconsForMultipleUrlsWithinDocument)1781 TEST_F(FaviconHandlerTest, SetFaviconsForMultipleUrlsWithinDocument) {
1782   const GURL kDifferentPageURL = GURL("http://www.google.com/other");
1783 
1784   EXPECT_CALL(favicon_service_,
1785               SetFavicons(base::flat_set<GURL>{kPageURL, kDifferentPageURL},
1786                           kIconURL12x12, _, _));
1787   EXPECT_CALL(delegate_,
1788               OnFaviconUpdated(kDifferentPageURL,
1789                                FaviconDriverObserver::NON_TOUCH_16_DIP,
1790                                kIconURL12x12, _, _));
1791 
1792   std::unique_ptr<FaviconHandler> handler = std::make_unique<FaviconHandler>(
1793       &favicon_service_, &delegate_, FaviconDriverObserver::NON_TOUCH_16_DIP);
1794   handler->FetchFavicon(kPageURL, /*is_same_document=*/false);
1795   base::RunLoop().RunUntilIdle();
1796   // Load a new URL (same document) without feeding any candidates for the first
1797   // URL.
1798   handler->FetchFavicon(kDifferentPageURL, /*is_same_document=*/true);
1799   base::RunLoop().RunUntilIdle();
1800   handler->OnUpdateCandidates(
1801       kDifferentPageURL, {FaviconURL(kIconURL12x12, kFavicon, kEmptySizes)},
1802       /*manifest_url=*/GURL());
1803   base::RunLoop().RunUntilIdle();
1804 }
1805 
1806 // Manifests are currently enabled by default. Leaving this fixture for
1807 // logical grouping and blame layer.
1808 class FaviconHandlerManifestsEnabledTest : public FaviconHandlerTest {
1809  protected:
1810   const GURL kManifestURL = GURL("http://www.google.com/manifest.json");
1811 
1812   FaviconHandlerManifestsEnabledTest() = default;
1813 
1814   // Exercises the handler for the simplest case where all types are kTouchIcon
1815   // and no sizes are provided, using a FaviconHandler of type TOUCH_LARGETS.
RunHandlerWithSimpleTouchIconCandidates(const std::vector<GURL> & urls,const GURL & manifest_url)1816   std::unique_ptr<FaviconHandler> RunHandlerWithSimpleTouchIconCandidates(
1817       const std::vector<GURL>& urls,
1818       const GURL& manifest_url) {
1819     std::vector<favicon::FaviconURL> candidates;
1820     for (const GURL& url : urls) {
1821       candidates.emplace_back(url, kTouchIcon, kEmptySizes);
1822     }
1823     return RunHandlerWithCandidates(FaviconDriverObserver::TOUCH_LARGEST,
1824                                     candidates, manifest_url);
1825   }
1826 
1827  private:
1828   // Avoid accidental use of kFavicon type, since Web Manifests are handled by
1829   // the FaviconHandler of type TOUCH_LARGEST.
1830   using FaviconHandlerTest::RunHandlerWithSimpleFaviconCandidates;
1831 
1832   DISALLOW_COPY_AND_ASSIGN(FaviconHandlerManifestsEnabledTest);
1833 };
1834 
1835 // Test that favicon mappings are deleted when a manifest previously cached in
1836 // the DB is no longer referenced by the page and the page lists no regular
1837 // icons.
TEST_F(FaviconHandlerManifestsEnabledTest,RemovedWebManifestAndNoRegularIcons)1838 TEST_F(FaviconHandlerManifestsEnabledTest,
1839        RemovedWebManifestAndNoRegularIcons) {
1840   favicon_service_.fake()->Store(
1841       kPageURL, kManifestURL,
1842       CreateRawBitmapResult(kManifestURL, kWebManifestIcon));
1843 
1844   EXPECT_CALL(
1845       favicon_service_,
1846       DeleteFaviconMappings(base::flat_set<GURL>{kPageURL}, kWebManifestIcon));
1847 
1848   RunHandlerWithSimpleTouchIconCandidates(URLVector(), /*manifest_url=*/GURL());
1849 }
1850 
1851 // Test that favicon mappings are updated (but not deleted) when a manifest
1852 // previously cached in the DB is no longer referenced by the page and the page
1853 // lists regular icons.
TEST_F(FaviconHandlerManifestsEnabledTest,RemovedWebManifestAndRegularIcons)1854 TEST_F(FaviconHandlerManifestsEnabledTest, RemovedWebManifestAndRegularIcons) {
1855   favicon_service_.fake()->Store(
1856       kPageURL, kManifestURL,
1857       CreateRawBitmapResult(kManifestURL, kWebManifestIcon));
1858 
1859   EXPECT_CALL(favicon_service_, DeleteFaviconMappings(_, _)).Times(0);
1860   EXPECT_CALL(favicon_service_, SetFavicons(_, kIconURL12x12, kTouchIcon, _));
1861 
1862   RunHandlerWithSimpleTouchIconCandidates({kIconURL12x12},
1863                                           /*manifest_url=*/GURL());
1864 }
1865 
1866 // Test that favicon mappings are updated (but not deleted) when a manifest
1867 // previously cached in the DB (but expired) is no longer referenced by the page
1868 // and the page lists regular icons.
TEST_F(FaviconHandlerManifestsEnabledTest,ExpiredAndRemovedWebManifestAndRegularIcons)1869 TEST_F(FaviconHandlerManifestsEnabledTest,
1870        ExpiredAndRemovedWebManifestAndRegularIcons) {
1871   favicon_service_.fake()->Store(
1872       kPageURL, kManifestURL,
1873       CreateRawBitmapResult(kManifestURL, kWebManifestIcon, /*expired=*/true));
1874 
1875   EXPECT_CALL(favicon_service_, DeleteFaviconMappings(_, _)).Times(0);
1876   EXPECT_CALL(favicon_service_, SetFavicons(_, kIconURL12x12, kTouchIcon, _));
1877 
1878   RunHandlerWithSimpleTouchIconCandidates({kIconURL12x12},
1879                                           /*manifest_url=*/GURL());
1880 }
1881 
1882 // Test that a favicon corresponding to a web manifest is reported when:
1883 // - There is data in the favicon database for the manifest URL.
1884 // AND
1885 // - FaviconService::OnFaviconDataForManifestFromFaviconService() runs before
1886 //   FaviconHandler::OnUpdateCandidates() is called.
TEST_F(FaviconHandlerManifestsEnabledTest,GetFaviconFromManifestInHistoryIfCandidatesSlower)1887 TEST_F(FaviconHandlerManifestsEnabledTest,
1888        GetFaviconFromManifestInHistoryIfCandidatesSlower) {
1889   favicon_service_.fake()->Store(
1890       kPageURL, kManifestURL,
1891       CreateRawBitmapResult(kManifestURL, kWebManifestIcon));
1892 
1893   EXPECT_CALL(favicon_service_, UnableToDownloadFavicon(_)).Times(0);
1894 
1895   EXPECT_CALL(favicon_service_,
1896               UpdateFaviconMappingsAndFetch(_, kManifestURL, kWebManifestIcon,
1897                                             /*desired_size_in_dip=*/0, _, _));
1898   EXPECT_CALL(delegate_,
1899               OnFaviconUpdated(_, FaviconDriverObserver::TOUCH_LARGEST,
1900                                kManifestURL, _, _));
1901 
1902   RunHandlerWithSimpleTouchIconCandidates({kIconURL12x12}, kManifestURL);
1903   EXPECT_THAT(favicon_service_.fake()->db_requests(),
1904               ElementsAre(kPageURL, kManifestURL));
1905   EXPECT_THAT(delegate_.downloads(), IsEmpty());
1906 }
1907 
1908 // Test that a favicon corresponding to a web manifest is reported when:
1909 // - There is data in the favicon database for the manifest URL.
1910 // AND
1911 // - FaviconHandler::OnUpdateCandidates() is called before
1912 //   FaviconService::OnFaviconDataForManifestFromFaviconService() runs.
TEST_F(FaviconHandlerManifestsEnabledTest,GetFaviconFromManifestInHistoryIfCandidatesFaster)1913 TEST_F(FaviconHandlerManifestsEnabledTest,
1914        GetFaviconFromManifestInHistoryIfCandidatesFaster) {
1915   favicon_service_.fake()->Store(
1916       kPageURL, kManifestURL,
1917       CreateRawBitmapResult(kManifestURL, kWebManifestIcon));
1918   // Defer the database lookup completion to control the exact timing.
1919   favicon_service_.fake()->SetRunCallbackManuallyForUrl(kManifestURL);
1920 
1921   EXPECT_CALL(favicon_service_, UnableToDownloadFavicon(_)).Times(0);
1922 
1923   EXPECT_CALL(favicon_service_,
1924               UpdateFaviconMappingsAndFetch(_, kManifestURL, kWebManifestIcon,
1925                                             /*desired_size_in_dip=*/0, _, _));
1926   EXPECT_CALL(delegate_,
1927               OnFaviconUpdated(_, FaviconDriverObserver::TOUCH_LARGEST,
1928                                kManifestURL, _, _));
1929 
1930   std::unique_ptr<FaviconHandler> handler =
1931       RunHandlerWithSimpleTouchIconCandidates({kIconURL12x12}, kManifestURL);
1932   ASSERT_TRUE(favicon_service_.fake()->HasPendingManualCallback());
1933 
1934   // Complete the lookup.
1935   EXPECT_TRUE(favicon_service_.fake()->RunCallbackManually());
1936   base::RunLoop().RunUntilIdle();
1937 
1938   EXPECT_THAT(favicon_service_.fake()->db_requests(),
1939               ElementsAre(kPageURL, kManifestURL));
1940   EXPECT_THAT(delegate_.downloads(), IsEmpty());
1941 }
1942 
1943 // Believed to fix crbug.com/544560.
1944 // Tests that there is not crash and SetFavicons() is called with the
1945 // appropriate icon URL in the following scenario:
1946 // - The database initially has a cached icon for the page (not expired).
1947 // - Two initial favicon candidates are received fast, before the history lookup
1948 //   completes. There is no manifest URL initially.
1949 // - Before the history lookup completes, favicon candidates are updated via
1950 //   javascript to include a manifest URL.
1951 // - The manifest lists at least one icon.
TEST_F(FaviconHandlerManifestsEnabledTest,AddManifestWithIconsViaJavascriptAfterFastCandidates)1952 TEST_F(FaviconHandlerManifestsEnabledTest,
1953        AddManifestWithIconsViaJavascriptAfterFastCandidates) {
1954   EXPECT_CALL(favicon_service_, DeleteFaviconMappings(_, _)).Times(0);
1955   EXPECT_CALL(favicon_service_, SetFavicons(_, kManifestURL, _, _));
1956 
1957   // Initial database contains a cached by expired icon for |kPageURL|.
1958   favicon_service_.fake()->Store(
1959       kPageURL, kIconURL16x16,
1960       CreateRawBitmapResult(kIconURL16x16, kTouchIcon));
1961 
1962   // Manifest with icons.
1963   const std::vector<favicon::FaviconURL> kManifestIcons = {
1964       FaviconURL(kIconURL64x64, kWebManifestIcon, kEmptySizes),
1965   };
1966   delegate_.fake_manifest_downloader().Add(kManifestURL, kManifestIcons);
1967 
1968   // Initial load does NOT contain a manifest. Regular candidates are received
1969   // before the history lookup for |kPageURL| is finished.
1970   favicon_service_.fake()->SetRunCallbackManuallyForUrl(kPageURL);
1971   std::unique_ptr<FaviconHandler> handler =
1972       RunHandlerWithSimpleTouchIconCandidates({kIconURL12x12, kIconURL16x16},
1973                                               /*manifest_url=*/GURL());
1974   ASSERT_TRUE(favicon_service_.fake()->HasPendingManualCallback());
1975   // Update candidates, now containing a manifest URL.
1976   handler->OnUpdateCandidates(
1977       kPageURL, {FaviconURL(kIconURL16x16, kTouchIcon, kEmptySizes)},
1978       kManifestURL);
1979   base::RunLoop().RunUntilIdle();
1980   // Complete the history lookup for |kPageURL| now.
1981   ASSERT_TRUE(favicon_service_.fake()->RunCallbackManually());
1982   base::RunLoop().RunUntilIdle();
1983 
1984   EXPECT_THAT(favicon_service_.fake()->db_requests(),
1985               ElementsAre(kPageURL, kManifestURL));
1986   EXPECT_THAT(delegate_.downloads(), ElementsAre(kManifestURL, kIconURL64x64));
1987 }
1988 
1989 // Believed to fix crbug.com/544560.
1990 // Tests that there is not crash and SetFavicons() is called with the
1991 // appropriate icon URL in the following scenario:
1992 // - The database initially has a cached but expired icon for the page.
1993 // - Initial favicon candidates are received fast, before the history lookup
1994 //   completes. There is no manifest URL initially.
1995 // - Before the history lookup completes, favicon candidates are updated via
1996 //   javascript to include a manifest URL.
1997 // - The manifest lists at least one icon.
TEST_F(FaviconHandlerManifestsEnabledTest,AddManifestWithIconsViaJavascriptAfterFastCandidatesAndExpiredIcon)1998 TEST_F(FaviconHandlerManifestsEnabledTest,
1999        AddManifestWithIconsViaJavascriptAfterFastCandidatesAndExpiredIcon) {
2000   EXPECT_CALL(favicon_service_, DeleteFaviconMappings(_, _)).Times(0);
2001   EXPECT_CALL(favicon_service_, SetFavicons(_, kManifestURL, _, _));
2002 
2003   // Initial database contains a cached by expired icon for |kPageURL|.
2004   favicon_service_.fake()->Store(
2005       kPageURL, kIconURL16x16,
2006       CreateRawBitmapResult(kIconURL16x16, kTouchIcon, /*expired=*/true));
2007 
2008   // Manifest with icons.
2009   const std::vector<favicon::FaviconURL> kManifestIcons = {
2010       FaviconURL(kIconURL64x64, kWebManifestIcon, kEmptySizes),
2011   };
2012   delegate_.fake_manifest_downloader().Add(kManifestURL, kManifestIcons);
2013 
2014   // Initial load does NOT contain a manifest. Regular candidates are received
2015   // before the history lookup for |kPageURL| is finished.
2016   favicon_service_.fake()->SetRunCallbackManuallyForUrl(kPageURL);
2017   std::unique_ptr<FaviconHandler> handler =
2018       RunHandlerWithSimpleTouchIconCandidates({kIconURL16x16},
2019                                               /*manifest_url=*/GURL());
2020   ASSERT_TRUE(favicon_service_.fake()->HasPendingManualCallback());
2021   // Update candidates, now containing a manifest URL.
2022   handler->OnUpdateCandidates(
2023       kPageURL, {FaviconURL(kIconURL16x16, kTouchIcon, kEmptySizes)},
2024       kManifestURL);
2025   base::RunLoop().RunUntilIdle();
2026   // Complete the history lookup for |kPageURL| now.
2027   ASSERT_TRUE(favicon_service_.fake()->RunCallbackManually());
2028   base::RunLoop().RunUntilIdle();
2029 
2030   EXPECT_THAT(favicon_service_.fake()->db_requests(),
2031               ElementsAre(kPageURL, kManifestURL));
2032   EXPECT_THAT(delegate_.downloads(), ElementsAre(kManifestURL, kIconURL64x64));
2033 }
2034 
2035 // Believed to fix crbug.com/544560.
2036 // Same as the test above with the difference that the manifest contains no
2037 // icons.
TEST_F(FaviconHandlerManifestsEnabledTest,AddManifestWithoutIconsViaJavascriptAfterFastCandidatesAndExpiredIcon)2038 TEST_F(FaviconHandlerManifestsEnabledTest,
2039        AddManifestWithoutIconsViaJavascriptAfterFastCandidatesAndExpiredIcon) {
2040   EXPECT_CALL(favicon_service_, DeleteFaviconMappings(_, _)).Times(0);
2041   EXPECT_CALL(favicon_service_, SetFavicons(_, kIconURL16x16, _, _));
2042 
2043   // Initial database contains a cached by expired icon for |kPageURL|.
2044   favicon_service_.fake()->Store(
2045       kPageURL, kIconURL16x16,
2046       CreateRawBitmapResult(kIconURL16x16, kTouchIcon, /*expired=*/true));
2047 
2048   // Manifest without icons.
2049   delegate_.fake_manifest_downloader().Add(kManifestURL,
2050                                            std::vector<favicon::FaviconURL>());
2051 
2052   // Initial load does NOT contain a manifest. Regular candidates are received
2053   // before the history lookup for |kPageURL| is finished.
2054   favicon_service_.fake()->SetRunCallbackManuallyForUrl(kPageURL);
2055   std::unique_ptr<FaviconHandler> handler =
2056       RunHandlerWithSimpleTouchIconCandidates({kIconURL16x16},
2057                                               /*manifest_url=*/GURL());
2058   ASSERT_TRUE(favicon_service_.fake()->HasPendingManualCallback());
2059   // Update candidates, now containing a manifest URL.
2060   handler->OnUpdateCandidates(
2061       kPageURL, {FaviconURL(kIconURL16x16, kTouchIcon, kEmptySizes)},
2062       kManifestURL);
2063   base::RunLoop().RunUntilIdle();
2064   // Complete the history lookup for |kPageURL| now.
2065   ASSERT_TRUE(favicon_service_.fake()->RunCallbackManually());
2066   base::RunLoop().RunUntilIdle();
2067 
2068   EXPECT_THAT(favicon_service_.fake()->db_requests(),
2069               ElementsAre(kPageURL, kManifestURL));
2070   EXPECT_THAT(delegate_.downloads(), ElementsAre(kManifestURL, kIconURL16x16));
2071 }
2072 
2073 // Test that a favicon corresponding to a web manifest is reported when there is
2074 // data in the database for neither the page URL nor the manifest URL.
TEST_F(FaviconHandlerManifestsEnabledTest,GetFaviconFromUnknownManifest)2075 TEST_F(FaviconHandlerManifestsEnabledTest, GetFaviconFromUnknownManifest) {
2076   const std::vector<favicon::FaviconURL> kManifestIcons = {
2077       FaviconURL(kIconURL16x16, kWebManifestIcon, kEmptySizes),
2078   };
2079 
2080   delegate_.fake_manifest_downloader().Add(kManifestURL, kManifestIcons);
2081 
2082   EXPECT_CALL(favicon_service_, UnableToDownloadFavicon(_)).Times(0);
2083 
2084   EXPECT_CALL(favicon_service_,
2085               SetFavicons(_, kManifestURL, kWebManifestIcon, _));
2086   EXPECT_CALL(delegate_,
2087               OnFaviconUpdated(_, FaviconDriverObserver::TOUCH_LARGEST,
2088                                kManifestURL, _, _));
2089 
2090   RunHandlerWithSimpleTouchIconCandidates({kIconURL12x12}, kManifestURL);
2091   EXPECT_THAT(favicon_service_.fake()->db_requests(),
2092               ElementsAre(kPageURL, kManifestURL));
2093   EXPECT_THAT(delegate_.downloads(), ElementsAre(kManifestURL, kIconURL16x16));
2094 }
2095 
2096 // Test that icons from a web manifest use a desired size of 192x192.
TEST_F(FaviconHandlerManifestsEnabledTest,Prefer192x192IconFromManifest)2097 TEST_F(FaviconHandlerManifestsEnabledTest, Prefer192x192IconFromManifest) {
2098   const GURL kIconURL144x144 = GURL("http://www.google.com/favicon144x144");
2099   const GURL kIconURL192x192 = GURL("http://www.google.com/favicon192x192");
2100 
2101   delegate_.fake_image_downloader().Add(kIconURL144x144, IntVector{144});
2102   delegate_.fake_image_downloader().Add(kIconURL192x192, IntVector{192});
2103 
2104   const std::vector<favicon::FaviconURL> kManifestIcons = {
2105       FaviconURL(kIconURL144x144, kWebManifestIcon,
2106                  SizeVector(1U, gfx::Size(144, 144))),
2107       FaviconURL(kIconURL192x192, kWebManifestIcon,
2108                  SizeVector(1U, gfx::Size(192, 192))),
2109   };
2110 
2111   delegate_.fake_manifest_downloader().Add(kManifestURL, kManifestIcons);
2112 
2113   RunHandlerWithSimpleTouchIconCandidates(URLVector(), kManifestURL);
2114 
2115   EXPECT_THAT(delegate_.downloads(),
2116               ElementsAre(kManifestURL, kIconURL192x192));
2117 }
2118 
2119 // Test that a 192x192 favicon corresponding to a web manifest is reported with
2120 // the appropriate size when there is data in the database for neither the page
2121 // URL nor the manifest URL.
TEST_F(FaviconHandlerManifestsEnabledTest,GetNonResized192x192FaviconFromUnknownManifest)2122 TEST_F(FaviconHandlerManifestsEnabledTest,
2123        GetNonResized192x192FaviconFromUnknownManifest) {
2124   const GURL kIconURL192x192 = GURL("http://www.google.com/favicon192x192");
2125   const std::vector<favicon::FaviconURL> kManifestIcons = {
2126       FaviconURL(kIconURL192x192, kWebManifestIcon, kEmptySizes),
2127   };
2128   delegate_.fake_image_downloader().Add(kIconURL192x192, IntVector{192});
2129   delegate_.fake_manifest_downloader().Add(kManifestURL, kManifestIcons);
2130 
2131   EXPECT_CALL(favicon_service_, SetFavicons(_, kManifestURL, kWebManifestIcon,
2132                                             ImageSizeIs(192, 192)));
2133 
2134   RunHandlerWithSimpleTouchIconCandidates(URLVector(), kManifestURL);
2135 }
2136 
2137 // Test that the manifest and icon are redownloaded if the icon cached for the
2138 // page URL expired.
TEST_F(FaviconHandlerManifestsEnabledTest,GetFaviconFromExpiredManifest)2139 TEST_F(FaviconHandlerManifestsEnabledTest, GetFaviconFromExpiredManifest) {
2140   const std::vector<favicon::FaviconURL> kManifestIcons = {
2141       FaviconURL(kIconURL64x64, kWebManifestIcon, kEmptySizes),
2142   };
2143 
2144   favicon_service_.fake()->Store(
2145       kPageURL, kManifestURL,
2146       CreateRawBitmapResult(kManifestURL, kWebManifestIcon,
2147                             /*expired=*/true));
2148   delegate_.fake_manifest_downloader().Add(kManifestURL, kManifestIcons);
2149 
2150   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kManifestURL, _, _)).Times(2);
2151   EXPECT_CALL(favicon_service_, SetFavicons(_, kManifestURL, _, _));
2152 
2153   RunHandlerWithSimpleTouchIconCandidates({kIconURL12x12}, kManifestURL);
2154   EXPECT_THAT(favicon_service_.fake()->db_requests(),
2155               ElementsAre(kPageURL, kManifestURL));
2156   EXPECT_THAT(delegate_.downloads(), ElementsAre(kManifestURL, kIconURL64x64));
2157 }
2158 
2159 // Test that the manifest and icon are redownloaded if the icon cached for the
2160 // manifest URL expired, which was observed during a visit to a different page
2161 // URL.
TEST_F(FaviconHandlerManifestsEnabledTest,GetFaviconFromExpiredManifestLinkedFromOtherPage)2162 TEST_F(FaviconHandlerManifestsEnabledTest,
2163        GetFaviconFromExpiredManifestLinkedFromOtherPage) {
2164   const GURL kSomePreviousPageURL("https://www.google.com/previous");
2165   const std::vector<favicon::FaviconURL> kManifestIcons = {
2166       FaviconURL(kIconURL64x64, kWebManifestIcon, kEmptySizes),
2167   };
2168 
2169   favicon_service_.fake()->Store(
2170       kSomePreviousPageURL, kManifestURL,
2171       CreateRawBitmapResult(kManifestURL, kWebManifestIcon,
2172                             /*expired=*/true));
2173   delegate_.fake_manifest_downloader().Add(kManifestURL, kManifestIcons);
2174 
2175   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kManifestURL, _, _)).Times(2);
2176   EXPECT_CALL(favicon_service_, SetFavicons(_, kManifestURL, _, _));
2177 
2178   RunHandlerWithSimpleTouchIconCandidates({kIconURL12x12}, kManifestURL);
2179   EXPECT_THAT(favicon_service_.fake()->db_requests(),
2180               ElementsAre(kPageURL, kManifestURL));
2181   EXPECT_THAT(delegate_.downloads(), ElementsAre(kManifestURL, kIconURL64x64));
2182 }
2183 
2184 // Test that a favicon corresponding to a web manifest is reported when:
2185 // - There is data in the database for neither the page URL nor the manifest
2186 //   URL.
2187 // - There is data in the database for the icon URL listed in the manifest.
TEST_F(FaviconHandlerManifestsEnabledTest,GetFaviconFromUnknownManifestButKnownIcon)2188 TEST_F(FaviconHandlerManifestsEnabledTest,
2189        GetFaviconFromUnknownManifestButKnownIcon) {
2190   const GURL kSomePreviousPageURL("https://www.google.com/previous");
2191   const std::vector<favicon::FaviconURL> kManifestIcons = {
2192       FaviconURL(kIconURL16x16, kWebManifestIcon, kEmptySizes),
2193   };
2194 
2195   favicon_service_.fake()->Store(
2196       kSomePreviousPageURL, kIconURL16x16,
2197       CreateRawBitmapResult(kIconURL16x16, kTouchIcon));
2198   delegate_.fake_manifest_downloader().Add(kManifestURL, kManifestIcons);
2199 
2200   EXPECT_CALL(favicon_service_, SetFavicons(_, kManifestURL, _, _));
2201   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kManifestURL, _, _));
2202 
2203   RunHandlerWithSimpleTouchIconCandidates(URLVector(), kManifestURL);
2204   EXPECT_THAT(favicon_service_.fake()->db_requests(),
2205               ElementsAre(kPageURL, kManifestURL));
2206   // This is because, in the current implementation, FaviconHandler only checks
2207   // whether there is an icon cached with the manifest URL as the "icon URL"
2208   // when a page has a non-empty Web Manifest.
2209   EXPECT_THAT(delegate_.downloads(), ElementsAre(kManifestURL, kIconURL16x16));
2210 }
2211 
2212 // Test a manifest that returns a 404 gets blacklisted via
2213 // UnableToDownloadFavicon() AND that the regular favicon is selected as
2214 // fallback.
TEST_F(FaviconHandlerManifestsEnabledTest,UnknownManifestReturning404)2215 TEST_F(FaviconHandlerManifestsEnabledTest, UnknownManifestReturning404) {
2216   EXPECT_CALL(favicon_service_, DeleteFaviconMappings(_, _)).Times(0);
2217 
2218   EXPECT_CALL(favicon_service_, UnableToDownloadFavicon(kManifestURL));
2219   EXPECT_CALL(favicon_service_, SetFavicons(_, kIconURL12x12, _, _));
2220 
2221   RunHandlerWithSimpleTouchIconCandidates({kIconURL12x12}, kManifestURL);
2222   EXPECT_THAT(favicon_service_.fake()->db_requests(),
2223               ElementsAre(kPageURL, kManifestURL, kIconURL12x12));
2224   EXPECT_THAT(delegate_.downloads(), ElementsAre(kManifestURL, kIconURL12x12));
2225 }
2226 
2227 // Test that a manifest that was previously blacklisted via
2228 // UnableToDownloadFavicon() is ignored and that the regular favicon is selected
2229 // as fallback.
TEST_F(FaviconHandlerManifestsEnabledTest,IgnoreManifestWithPrior404)2230 TEST_F(FaviconHandlerManifestsEnabledTest, IgnoreManifestWithPrior404) {
2231   ON_CALL(favicon_service_, WasUnableToDownloadFavicon(kManifestURL))
2232       .WillByDefault(Return(true));
2233 
2234   EXPECT_CALL(favicon_service_, DeleteFaviconMappings(_, _)).Times(0);
2235 
2236   EXPECT_CALL(favicon_service_, SetFavicons(_, kIconURL12x12, _, _));
2237 
2238   RunHandlerWithSimpleTouchIconCandidates({kIconURL12x12}, kManifestURL);
2239   EXPECT_THAT(favicon_service_.fake()->db_requests(),
2240               ElementsAre(kPageURL, kIconURL12x12));
2241   EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL12x12));
2242 }
2243 
2244 // Test that favicon mappings are deleted when a manifest previously cached in
2245 // the DB (but expired) returns a 404, when the page lists no regular icons.
TEST_F(FaviconHandlerManifestsEnabledTest,ExpiredManifestReturning404AndNoRegularIcons)2246 TEST_F(FaviconHandlerManifestsEnabledTest,
2247        ExpiredManifestReturning404AndNoRegularIcons) {
2248   favicon_service_.fake()->Store(
2249       kPageURL, kManifestURL,
2250       CreateRawBitmapResult(kManifestURL, kWebManifestIcon, /*expired=*/true));
2251 
2252   EXPECT_CALL(
2253       favicon_service_,
2254       DeleteFaviconMappings(base::flat_set<GURL>{kPageURL}, kWebManifestIcon));
2255 
2256   RunHandlerWithSimpleTouchIconCandidates(URLVector(), kManifestURL);
2257 }
2258 
2259 // Test that favicon mappings are updated (but not deleted) when a manifest
2260 // previously cached in the DB (but expired) returns a 404, when the page lists
2261 // regular icons that haven't been cached before.
TEST_F(FaviconHandlerManifestsEnabledTest,ExpiredManifestReturning404AndRegularIcons)2262 TEST_F(FaviconHandlerManifestsEnabledTest,
2263        ExpiredManifestReturning404AndRegularIcons) {
2264   favicon_service_.fake()->Store(
2265       kPageURL, kManifestURL,
2266       CreateRawBitmapResult(kManifestURL, kWebManifestIcon, /*expired=*/true));
2267 
2268   EXPECT_CALL(favicon_service_, DeleteFaviconMappings(_, _)).Times(0);
2269 
2270   EXPECT_CALL(favicon_service_, SetFavicons(_, kIconURL12x12, kTouchIcon, _));
2271 
2272   RunHandlerWithSimpleTouchIconCandidates({kIconURL12x12}, kManifestURL);
2273 }
2274 
2275 // Test that favicon mappings are deleted when a manifest previously cached in
2276 // the DB (but expired) contains no icons, when the page lists no regular icons.
TEST_F(FaviconHandlerManifestsEnabledTest,ExpiredManifestWithoutIconsAndNoRegularIcons)2277 TEST_F(FaviconHandlerManifestsEnabledTest,
2278        ExpiredManifestWithoutIconsAndNoRegularIcons) {
2279   delegate_.fake_manifest_downloader().Add(kManifestURL,
2280                                            std::vector<favicon::FaviconURL>());
2281   favicon_service_.fake()->Store(
2282       kPageURL, kManifestURL,
2283       CreateRawBitmapResult(kManifestURL, kWebManifestIcon, /*expired=*/true));
2284 
2285   EXPECT_CALL(
2286       favicon_service_,
2287       DeleteFaviconMappings(base::flat_set<GURL>{kPageURL}, kWebManifestIcon));
2288 
2289   RunHandlerWithSimpleTouchIconCandidates(URLVector(), kManifestURL);
2290 }
2291 
2292 // Test that favicon mappings are updated (but not deleted) when a manifest
2293 // previously cached in the DB (but expired) contains no icons, when the page
2294 // lists regular icons that haven't been cached before.
TEST_F(FaviconHandlerManifestsEnabledTest,ExpiredManifestWithoutIconsAndRegularIcons)2295 TEST_F(FaviconHandlerManifestsEnabledTest,
2296        ExpiredManifestWithoutIconsAndRegularIcons) {
2297   delegate_.fake_manifest_downloader().Add(kManifestURL,
2298                                            std::vector<favicon::FaviconURL>());
2299   favicon_service_.fake()->Store(
2300       kPageURL, kManifestURL,
2301       CreateRawBitmapResult(kManifestURL, kWebManifestIcon, /*expired=*/true));
2302 
2303   EXPECT_CALL(favicon_service_, DeleteFaviconMappings(_, _)).Times(0);
2304 
2305   EXPECT_CALL(favicon_service_, SetFavicons(_, kIconURL12x12, kTouchIcon, _));
2306 
2307   RunHandlerWithSimpleTouchIconCandidates({kIconURL12x12}, kManifestURL);
2308 }
2309 
2310 // Test that the regular favicon is selected when:
2311 // - The page links to a Web Manifest.
2312 // - The Web Manifest does not contain any icon URLs (it is not a 404).
2313 // - The page has an icon URL provided via a <link rel="icon"> tag.
2314 // - The database does not know about the page URL, manifest URL or icon URL.
TEST_F(FaviconHandlerManifestsEnabledTest,UnknownManifestWithoutIcons)2315 TEST_F(FaviconHandlerManifestsEnabledTest, UnknownManifestWithoutIcons) {
2316   delegate_.fake_manifest_downloader().Add(kManifestURL,
2317                                            std::vector<favicon::FaviconURL>());
2318 
2319   EXPECT_CALL(favicon_service_, DeleteFaviconMappings(_, _)).Times(0);
2320 
2321   // UnableToDownloadFavicon() is expected to prevent repeated downloads of the
2322   // same manifest (which is not otherwise cached, since it doesn't contain
2323   // icons).
2324   EXPECT_CALL(favicon_service_, UnableToDownloadFavicon(kManifestURL));
2325   EXPECT_CALL(favicon_service_, SetFavicons(_, kIconURL12x12, _, _));
2326 
2327   RunHandlerWithSimpleTouchIconCandidates({kIconURL12x12}, kManifestURL);
2328   EXPECT_THAT(favicon_service_.fake()->db_requests(),
2329               ElementsAre(kPageURL, kManifestURL, kIconURL12x12));
2330   EXPECT_THAT(delegate_.downloads(), ElementsAre(kManifestURL, kIconURL12x12));
2331 }
2332 
2333 // Test that the regular favicon is selected when:
2334 // - The page links to a Web Manifest.
2335 // - The Web Manifest does not contain any icon URLs (it is not a 404).
2336 // - The page has an icon URL provided via a <link rel="icon"> tag.
2337 // - The database does not know about the page URL.
2338 // - The database does not know about the manifest URL.
2339 // - The database knows about the icon URL.
TEST_F(FaviconHandlerManifestsEnabledTest,UnknownManifestWithoutIconsAndKnownRegularIcons)2340 TEST_F(FaviconHandlerManifestsEnabledTest,
2341        UnknownManifestWithoutIconsAndKnownRegularIcons) {
2342   const GURL kSomePreviousPageURL("https://www.google.com/previous");
2343 
2344   delegate_.fake_manifest_downloader().Add(kManifestURL,
2345                                            std::vector<favicon::FaviconURL>());
2346   favicon_service_.fake()->Store(
2347       kSomePreviousPageURL, kIconURL12x12,
2348       CreateRawBitmapResult(kIconURL12x12, kTouchIcon));
2349 
2350   EXPECT_CALL(favicon_service_, SetFavicons(_, _, _, _)).Times(0);
2351   EXPECT_CALL(favicon_service_, DeleteFaviconMappings(_, _)).Times(0);
2352 
2353   // UnableToDownloadFavicon() is expected to prevent repeated downloads of the
2354   // same manifest (which is not otherwise cached, since it doesn't contain
2355   // icons).
2356   EXPECT_CALL(favicon_service_, UnableToDownloadFavicon(kManifestURL));
2357   EXPECT_CALL(favicon_service_,
2358               UpdateFaviconMappingsAndFetch(_, kManifestURL, _, _, _, _));
2359   EXPECT_CALL(favicon_service_,
2360               UpdateFaviconMappingsAndFetch(_, kIconURL12x12, _, _, _, _));
2361   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kIconURL12x12, _, _));
2362 
2363   RunHandlerWithSimpleTouchIconCandidates({kIconURL12x12}, kManifestURL);
2364   EXPECT_THAT(favicon_service_.fake()->db_requests(),
2365               ElementsAre(kPageURL, kManifestURL, kIconURL12x12));
2366   EXPECT_THAT(delegate_.downloads(), ElementsAre(kManifestURL));
2367 }
2368 
2369 // Test that the database remains unmodified when:
2370 // - The page links to a Web Manifest.
2371 // - The Web Manifest does not contain any icon URLs (it is not a 404).
2372 // - The page has an icon URL provided via a <link rel="icon"> tag.
2373 // - The database has a mapping between the page URL to the favicon URL.
TEST_F(FaviconHandlerManifestsEnabledTest,UnknownManifestWithoutIconsAndRegularIconInHistory)2374 TEST_F(FaviconHandlerManifestsEnabledTest,
2375        UnknownManifestWithoutIconsAndRegularIconInHistory) {
2376   delegate_.fake_manifest_downloader().Add(kManifestURL,
2377                                            std::vector<favicon::FaviconURL>());
2378   favicon_service_.fake()->Store(
2379       kPageURL, kIconURL16x16,
2380       CreateRawBitmapResult(kIconURL16x16, kTouchIcon));
2381 
2382   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kIconURL16x16, _, _));
2383   EXPECT_CALL(favicon_service_,
2384               UpdateFaviconMappingsAndFetch(_, kManifestURL, _, _, _, _));
2385 
2386   RunHandlerWithSimpleTouchIconCandidates({kIconURL16x16}, kManifestURL);
2387 
2388   ASSERT_THAT(favicon_service_.fake()->db_requests(),
2389               ElementsAre(kPageURL, kManifestURL));
2390   EXPECT_THAT(delegate_.downloads(), ElementsAre(kManifestURL));
2391 }
2392 
2393 // Test that Delegate::OnFaviconUpdated() is called if a page uses Javascript to
2394 // modify the page's <link rel="manifest"> tag to point to a different manifest.
TEST_F(FaviconHandlerManifestsEnabledTest,ManifestUpdateViaJavascript)2395 TEST_F(FaviconHandlerManifestsEnabledTest, ManifestUpdateViaJavascript) {
2396   const GURL kManifestURL1("http://www.google.com/manifest1.json");
2397   const GURL kManifestURL2("http://www.google.com/manifest2.json");
2398   const std::vector<favicon::FaviconURL> kManifestIcons1 = {
2399       FaviconURL(kIconURL64x64, kWebManifestIcon, kEmptySizes),
2400   };
2401   const std::vector<favicon::FaviconURL> kManifestIcons2 = {
2402       FaviconURL(kIconURL10x10, kWebManifestIcon, kEmptySizes),
2403   };
2404 
2405   delegate_.fake_manifest_downloader().Add(kManifestURL1, kManifestIcons1);
2406   delegate_.fake_manifest_downloader().Add(kManifestURL2, kManifestIcons2);
2407 
2408   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kManifestURL1, _, _));
2409 
2410   std::unique_ptr<FaviconHandler> handler =
2411       RunHandlerWithSimpleTouchIconCandidates({kIconURL12x12}, kManifestURL1);
2412   ASSERT_THAT(favicon_service_.fake()->db_requests(),
2413               ElementsAre(kPageURL, kManifestURL1));
2414   EXPECT_THAT(delegate_.downloads(), ElementsAre(kManifestURL1, kIconURL64x64));
2415   ASSERT_TRUE(VerifyAndClearExpectations());
2416 
2417   // Simulate the page changing it's manifest URL via Javascript.
2418   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kManifestURL2, _, _));
2419   handler->OnUpdateCandidates(
2420       kPageURL, {FaviconURL(kIconURL12x12, kTouchIcon, kEmptySizes)},
2421       kManifestURL2);
2422   base::RunLoop().RunUntilIdle();
2423   ASSERT_THAT(favicon_service_.fake()->db_requests(),
2424               ElementsAre(kManifestURL2));
2425   EXPECT_THAT(delegate_.downloads(), ElementsAre(kManifestURL2, kIconURL10x10));
2426 }
2427 
2428 // Test that Delegate::OnFaviconUpdated() is called if a page uses Javascript to
2429 // remove the page's <link rel="manifest"> tag (i.e. no web manifest) WHILE a
2430 // lookup to the history database is ongoing for the manifest URL.
TEST_F(FaviconHandlerManifestsEnabledTest,RemoveManifestViaJavascriptWhileDatabaseLookup)2431 TEST_F(FaviconHandlerManifestsEnabledTest,
2432        RemoveManifestViaJavascriptWhileDatabaseLookup) {
2433   const std::vector<favicon::FaviconURL> kManifestIcons = {
2434       FaviconURL(kIconURL64x64, kWebManifestIcon, kEmptySizes),
2435   };
2436 
2437   delegate_.fake_manifest_downloader().Add(kManifestURL, kManifestIcons);
2438   // Defer the database lookup completion to control the exact timing.
2439   favicon_service_.fake()->SetRunCallbackManuallyForUrl(kManifestURL);
2440 
2441   std::unique_ptr<FaviconHandler> handler =
2442       RunHandlerWithSimpleTouchIconCandidates({kIconURL12x12}, kManifestURL);
2443   ASSERT_THAT(favicon_service_.fake()->db_requests(),
2444               ElementsAre(kPageURL, kManifestURL));
2445   // Database lookup for |kManifestURL| is ongoing.
2446   ASSERT_TRUE(favicon_service_.fake()->HasPendingManualCallback());
2447 
2448   // Simulate the page changing it's manifest URL to empty via Javascript.
2449   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kIconURL12x12, _, _));
2450   handler->OnUpdateCandidates(
2451       kPageURL, {FaviconURL(kIconURL12x12, kTouchIcon, kEmptySizes)}, GURL());
2452   // Complete the lookup.
2453   EXPECT_TRUE(favicon_service_.fake()->RunCallbackManually());
2454   base::RunLoop().RunUntilIdle();
2455   ASSERT_THAT(favicon_service_.fake()->db_requests(),
2456               ElementsAre(kPageURL, kManifestURL, kIconURL12x12));
2457   EXPECT_THAT(delegate_.downloads(), ElementsAre(kIconURL12x12));
2458 }
2459 
2460 // Tests that favicon mappings are removed if a page initially lists no regular
2461 // favicons but does link to a web manifest, and later uses Javascript to remove
2462 // the manifest URL.
TEST_F(FaviconHandlerManifestsEnabledTest,RemoveManifestViaJavascriptDeletesMappings)2463 TEST_F(FaviconHandlerManifestsEnabledTest,
2464        RemoveManifestViaJavascriptDeletesMappings) {
2465   const std::vector<favicon::FaviconURL> kManifestIcons = {
2466       FaviconURL(kIconURL64x64, kWebManifestIcon, kEmptySizes),
2467   };
2468 
2469   delegate_.fake_manifest_downloader().Add(kManifestURL, kManifestIcons);
2470 
2471   EXPECT_CALL(favicon_service_, SetFavicons(base::flat_set<GURL>{kPageURL},
2472                                             kManifestURL, kWebManifestIcon, _));
2473 
2474   std::unique_ptr<FaviconHandler> handler =
2475       RunHandlerWithSimpleTouchIconCandidates(URLVector(), kManifestURL);
2476   ASSERT_THAT(favicon_service_.fake()->db_requests(),
2477               ElementsAre(kPageURL, kManifestURL));
2478   EXPECT_THAT(delegate_.downloads(), ElementsAre(kManifestURL, kIconURL64x64));
2479   ASSERT_TRUE(VerifyAndClearExpectations());
2480 
2481   // Simulate the page removing it's manifest URL via Javascript.
2482   EXPECT_CALL(
2483       favicon_service_,
2484       DeleteFaviconMappings(base::flat_set<GURL>{kPageURL}, kWebManifestIcon));
2485   handler->OnUpdateCandidates(kPageURL, std::vector<FaviconURL>(), GURL());
2486   base::RunLoop().RunUntilIdle();
2487   ASSERT_THAT(favicon_service_.fake()->db_requests(), IsEmpty());
2488   EXPECT_THAT(delegate_.downloads(), IsEmpty());
2489 }
2490 
2491 // Test that Delegate::OnFaviconUpdated() is called a page without manifest uses
2492 // Javascript to add a <link rel="manifest"> tag (i.e. a new web manifest) WHILE
2493 // a lookup to the history database is ongoing for the icon URL.
TEST_F(FaviconHandlerManifestsEnabledTest,AddManifestViaJavascriptWhileDatabaseLookup)2494 TEST_F(FaviconHandlerManifestsEnabledTest,
2495        AddManifestViaJavascriptWhileDatabaseLookup) {
2496   const std::vector<favicon::FaviconURL> kManifestIcons = {
2497       FaviconURL(kIconURL64x64, kWebManifestIcon, kEmptySizes),
2498   };
2499 
2500   delegate_.fake_manifest_downloader().Add(kManifestURL, kManifestIcons);
2501   // Defer the database lookup completion to control the exact timing.
2502   favicon_service_.fake()->SetRunCallbackManuallyForUrl(kIconURL12x12);
2503 
2504   std::unique_ptr<FaviconHandler> handler =
2505       RunHandlerWithSimpleTouchIconCandidates({kIconURL12x12},
2506                                               /*manifest_url=*/GURL());
2507   ASSERT_THAT(favicon_service_.fake()->db_requests(),
2508               ElementsAre(kPageURL, kIconURL12x12));
2509   // Database lookup for |kIconURL12x12| is ongoing.
2510   ASSERT_TRUE(favicon_service_.fake()->HasPendingManualCallback());
2511 
2512   // Simulate the page changing it's manifest URL to |kManifestURL| via
2513   // Javascript.
2514   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kManifestURL, _, _));
2515   handler->OnUpdateCandidates(
2516       kPageURL, {FaviconURL(kIconURL12x12, kTouchIcon, kEmptySizes)},
2517       kManifestURL);
2518   // Complete the lookup.
2519   EXPECT_TRUE(favicon_service_.fake()->RunCallbackManually());
2520   base::RunLoop().RunUntilIdle();
2521   ASSERT_THAT(favicon_service_.fake()->db_requests(),
2522               ElementsAre(kPageURL, kIconURL12x12, kManifestURL));
2523   EXPECT_THAT(delegate_.downloads(), ElementsAre(kManifestURL, kIconURL64x64));
2524 }
2525 
2526 // Test that SetFavicons() is not called when:
2527 // - The page doesn't initially link to a Web Manifest.
2528 // - The page has an icon URL provided via a <link rel="icon"> tag.
2529 // - The database does not know about the page URL or icon URL.
2530 // - While the icon is being downloaded, the page uses Javascript to add a
2531 //   <link rel="manifest"> tag.
2532 // - The database has bitmap data for the manifest URL.
TEST_F(FaviconHandlerManifestsEnabledTest,AddKnownManifestViaJavascriptWhileImageDownload)2533 TEST_F(FaviconHandlerManifestsEnabledTest,
2534        AddKnownManifestViaJavascriptWhileImageDownload) {
2535   const GURL kSomePreviousPageURL("https://www.google.com/previous");
2536 
2537   favicon_service_.fake()->Store(
2538       kSomePreviousPageURL, kManifestURL,
2539       CreateRawBitmapResult(kManifestURL, kWebManifestIcon));
2540 
2541   // Defer the image download completion to control the exact timing.
2542   delegate_.fake_image_downloader().SetRunCallbackManuallyForUrl(kIconURL16x16);
2543 
2544   std::unique_ptr<FaviconHandler> handler =
2545       RunHandlerWithSimpleTouchIconCandidates({kIconURL16x16},
2546                                               /*manifest_url=*/GURL());
2547 
2548   ASSERT_TRUE(VerifyAndClearExpectations());
2549   ASSERT_TRUE(delegate_.fake_image_downloader().HasPendingManualCallback());
2550 
2551   // Simulate the page changing it's manifest URL to |kManifestURL| via
2552   // Javascript. Should invalidate the ongoing image download.
2553   EXPECT_CALL(favicon_service_, SetFavicons(_, _, _, _)).Times(0);
2554   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kManifestURL, _, _));
2555 
2556   handler->OnUpdateCandidates(
2557       kPageURL, {FaviconURL(kIconURL16x16, kTouchIcon, kEmptySizes)},
2558       kManifestURL);
2559 
2560   // Finalizes download, which should be thrown away as the manifest URL was
2561   // provided.
2562   EXPECT_TRUE(delegate_.fake_image_downloader().RunCallbackManually());
2563   base::RunLoop().RunUntilIdle();
2564 }
2565 
2566 // Test that SetFavicons() is called with the icon URL when:
2567 // - The page doesn't initially link to a Web Manifest.
2568 // - The page has an icon URL provided via a <link rel="icon"> tag.
2569 // - The database does not know about the page URL or icon URL.
2570 // - During the database lookup, the page uses Javascript to add a
2571 //   <link rel="manifest"> tag.
2572 // - The database does not know about the manifest URL.
2573 // - The manifest contains no icons.
TEST_F(FaviconHandlerManifestsEnabledTest,AddManifestWithoutIconsViaJavascriptWhileDatabaseLookup)2574 TEST_F(FaviconHandlerManifestsEnabledTest,
2575        AddManifestWithoutIconsViaJavascriptWhileDatabaseLookup) {
2576   delegate_.fake_manifest_downloader().Add(kManifestURL,
2577                                            std::vector<favicon::FaviconURL>());
2578 
2579   // Defer the database lookup completion to control the exact timing.
2580   favicon_service_.fake()->SetRunCallbackManuallyForUrl(kIconURL16x16);
2581 
2582   EXPECT_CALL(favicon_service_, SetFavicons(_, _, _, _)).Times(0);
2583   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, _, _, _)).Times(0);
2584 
2585   std::unique_ptr<FaviconHandler> handler =
2586       RunHandlerWithSimpleTouchIconCandidates({kIconURL16x16},
2587                                               /*manifest_url=*/GURL());
2588 
2589   ASSERT_TRUE(VerifyAndClearExpectations());
2590   ASSERT_TRUE(favicon_service_.fake()->HasPendingManualCallback());
2591 
2592   EXPECT_CALL(favicon_service_, SetFavicons(_, kIconURL16x16, _, _));
2593   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kIconURL16x16, _, _));
2594 
2595   handler->OnUpdateCandidates(
2596       kPageURL, {FaviconURL(kIconURL16x16, kTouchIcon, kEmptySizes)},
2597       kManifestURL);
2598 
2599   // Finalizes lookup, which should be thrown away as the manifest URLs was
2600   // provided.
2601   EXPECT_TRUE(favicon_service_.fake()->RunCallbackManually());
2602   base::RunLoop().RunUntilIdle();
2603 
2604   // The manifest URL interrupted the original processing of kIconURL16x16, but
2605   // a second one should have been started.
2606   EXPECT_TRUE(favicon_service_.fake()->RunCallbackManually());
2607   base::RunLoop().RunUntilIdle();
2608 }
2609 
2610 // Test that SetFavicons() is called when:
2611 // - The page links to one Web Manifest, which contains one icon.
2612 // - The database does not know about the page URL, icon URL or manifest URL.
2613 // - During image download, the page updates the manifest URL to point to
2614 //   another manifest.
2615 // - The second manifest contains the same icons as the first.
TEST_F(FaviconHandlerManifestsEnabledTest,UpdateManifestWithSameIconURLsWhileDownloading)2616 TEST_F(FaviconHandlerManifestsEnabledTest,
2617        UpdateManifestWithSameIconURLsWhileDownloading) {
2618   const GURL kManifestURL1("http://www.google.com/manifest1.json");
2619   const GURL kManifestURL2("http://www.google.com/manifest2.json");
2620   const std::vector<favicon::FaviconURL> kManifestIcons = {
2621       FaviconURL(kIconURL64x64, kWebManifestIcon, kEmptySizes),
2622   };
2623 
2624   delegate_.fake_manifest_downloader().Add(kManifestURL1, kManifestIcons);
2625   delegate_.fake_manifest_downloader().Add(kManifestURL2, kManifestIcons);
2626 
2627   // Defer the download completion to control the exact timing.
2628   delegate_.fake_image_downloader().SetRunCallbackManuallyForUrl(kIconURL64x64);
2629 
2630   std::unique_ptr<FaviconHandler> handler =
2631       RunHandlerWithSimpleTouchIconCandidates(URLVector(), kManifestURL1);
2632 
2633   EXPECT_THAT(delegate_.downloads(), ElementsAre(kManifestURL1, kIconURL64x64));
2634   ASSERT_TRUE(VerifyAndClearExpectations());
2635   ASSERT_TRUE(delegate_.fake_image_downloader().HasPendingManualCallback());
2636 
2637   // Calling OnUpdateCandidates() with a different manifest URL should trigger
2638   // its download.
2639   handler->OnUpdateCandidates(kPageURL, std::vector<favicon::FaviconURL>(),
2640                               kManifestURL2);
2641   base::RunLoop().RunUntilIdle();
2642   EXPECT_THAT(delegate_.downloads(), ElementsAre(kManifestURL2, kIconURL64x64));
2643 
2644   // Complete the download.
2645   EXPECT_CALL(favicon_service_, SetFavicons(_, kManifestURL2, _, _));
2646   EXPECT_CALL(delegate_, OnFaviconUpdated(_, _, kManifestURL2, _, _));
2647   EXPECT_TRUE(delegate_.fake_image_downloader().RunCallbackManually());
2648   base::RunLoop().RunUntilIdle();
2649 }
2650 
2651 }  // namespace
2652 }  // namespace favicon
2653