// Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "components/favicon/core/favicon_handler.h" #include <stddef.h> #include <map> #include <memory> #include <utility> #include <vector> #include "base/functional/bind.h" #include "base/functional/callback_helpers.h" #include "base/memory/raw_ptr.h" #include "base/run_loop.h" #include "base/strings/stringprintf.h" #include "base/task/single_thread_task_runner.h" #include "base/test/task_environment.h" #include "base/test/test_simple_task_runner.h" #include "components/favicon/core/favicon_driver.h" #include "components/favicon/core/test/mock_favicon_service.h" #include "skia/ext/image_operations.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/base/resource/resource_scale_factor.h" #include "ui/gfx/codec/png_codec.h" #include "ui/gfx/favicon_size.h" #include "ui/gfx/image/image.h" #include "ui/gfx/image/image_unittest_util.h" namespace favicon { namespace { FaviconRawBitmapResult; _; AnyNumber; Assign; Contains; ElementsAre; InSequence; Invoke; IsEmpty; Not; Return; SizeIs; IntVector; URLVector; BitmapVector; SizeVector; constexpr favicon_base::IconType kFavicon = …; constexpr favicon_base::IconType kTouchIcon = …; constexpr favicon_base::IconType kTouchPrecomposedIcon = …; constexpr favicon_base::IconType kWebManifestIcon = …; MATCHER_P2(ImageSizeIs, width, height, "") { … } // `arg` is a gfx::Image. MATCHER_P(ImageColorIs, expected_color, "") { … } // Fill the given data buffer with valid png data. std::vector<unsigned char> FillBitmapWithEdgeSize(int size, SkColor color) { … } std::vector<FaviconRawBitmapResult> CreateRawBitmapResult( const GURL& icon_url, favicon_base::IconType icon_type = kFavicon, bool expired = false, int edge_size = gfx::kFaviconSize, SkColor color = SK_ColorRED) { … } // Fake that implements the calls to FaviconHandler::Delegate's DownloadImage(), // delegated to this class through MockDelegate. class FakeImageDownloader { … }; // Fake that implements the calls to FaviconHandler::Delegate's // DownloadManifest(), delegated to this class through MockDelegate. class FakeManifestDownloader { … }; class MockDelegate : public FaviconHandler::Delegate { … }; // FakeFaviconService mimics a FaviconService backend that allows setting up // test data stored via Store(). If Store() has not been called for a // particular URL, the callback is called with empty database results. class FakeFaviconService { … }; // MockFaviconService subclass that delegates DB reads to FakeFaviconService. class MockFaviconServiceWithFake : public MockFaviconService { … }; class FaviconHandlerTest : public testing::Test { … }; TEST_F(FaviconHandlerTest, GetFaviconFromHistory) { … } TEST_F(FaviconHandlerTest, GetFaviconFromHistoryInIncognito) { … } // Test that UpdateFaviconsAndFetch() is called with the appropriate parameters // when there is no data in the database for the page URL. TEST_F(FaviconHandlerTest, UpdateFaviconMappingsAndFetch) { … } // Verifies same document navigation to the last page does not trigger fetch. TEST_F(FaviconHandlerTest, SameDocumentNavigationToLastUrlDoesNotFetchAgain) { … } // Test that we don't try to delete favicon mappings when a page URL is not in // history even if the page lists no favicons. TEST_F(FaviconHandlerTest, DoNotDeleteFaviconMappingsIfNotInHistory) { … } // Test that favicon mappings are deleted when: // - There is data in the favicon database for the page URL. // - The page lists no candidates. // AND // - FaviconService::OnFaviconDataForManifestFromFaviconService() runs before // FaviconHandler::OnUpdateCandidates() is called. TEST_F(FaviconHandlerTest, DeleteFaviconMappingsIfCandidatesSlower) { … } // Test that favicon mappings are deleted when: // - There is data in the favicon database for the page URL. // - The page lists no candidates. // AND // - FaviconHandler::OnUpdateCandidates() is called before // FaviconService::OnFaviconDataForManifestFromFaviconService() runs. TEST_F(FaviconHandlerTest, DeleteFaviconMappingsIfCandidatesFaster) { … } // Test that favicon mappings are deleted when a page in history lists a // candidate that is expired and is known to return a 404. TEST_F(FaviconHandlerTest, DeleteFaviconMappingsDespitePrior404) { … } // Test that favicon mappings are deleted for a page in history, when all icons // listed in the page return a 404. TEST_F(FaviconHandlerTest, DeleteFaviconMappingsDueTo404) { … } // Test that we don't try to delete favicon mappings when a page URL is not in // history even if all icons listed in the page return a 404. TEST_F(FaviconHandlerTest, DoNotDeleteFaviconMappingsIfNotInHistoryDespite404) { … } // Test that favicon mappings are not deleted for a page in history when all // icons listed in the page return a 503. TEST_F(FaviconHandlerTest, DoNotDeleteFaviconMappingsDueTo503) { … } // Test that UpdateFaviconsAndFetch() is called with the appropriate parameters // when there is no data in the database for the page URL, for the case where // multiple page URLs exist due to a quick in-same-document navigation (e.g. // fragment navigation). TEST_F(FaviconHandlerTest, UpdateFaviconMappingsAndFetchWithMultipleURLs) { … } // Test that CloneFaviconMappingsForPages() is called for the simplest case, // i.e. a single page without redirect URLs to update mappings for (no known // in-same-document navigation). This is important in case there are server-side // redirects to update (that are only known within HistoryService). TEST_F(FaviconHandlerTest, CloneFaviconMappingsForPageInHistory) { … } // Test that CloneFaviconMappingsForPages() is called when there is data in the // database for the page URL, for the case where multiple page URLs exist due to // a quick in-same-document navigation (e.g. fragment navigation). // FaviconService should be told to propagate the mappings from the last page // URL (lookup hit) to the rest of the URLs. TEST_F(FaviconHandlerTest, CloneFaviconMappingsWithMultipleURLs) { … } // Test that CloneFaviconMappingsForPages() is not called for incognito tabs. TEST_F(FaviconHandlerTest, NotCloneFaviconMappingsInIncognito) { … } // Test that the FaviconHandler process finishes when: // - There is data in the database for neither the page URL nor the icon URL. // AND // - FaviconService::GetFaviconForPageURL() callback returns before // FaviconHandler::OnUpdateCandidates() is called. TEST_F(FaviconHandlerTest, DownloadUnknownFaviconIfCandidatesSlower) { … } // Test that the FaviconHandler process finishes when: // - There is data in the database for neither the page URL nor the icon URL. // AND // - FaviconService::GetFaviconForPageURL() callback returns after // FaviconHandler::OnUpdateCandidates() is called. TEST_F(FaviconHandlerTest, DownloadUnknownFaviconIfCandidatesFaster) { … } // Test that the FaviconHandler process does not save anything to the database // for incognito tabs. TEST_F(FaviconHandlerTest, DownloadUnknownFaviconInIncognito) { … } // Test that favicon mappings are not deleted in incognito even if the page // lists no candidates. TEST_F(FaviconHandlerTest, DoNotDeleteFaviconMappingsInIncognito) { … } // Test that the icon is redownloaded if the icon cached for the page URL // expired. TEST_F(FaviconHandlerTest, RedownloadExpiredPageUrlFavicon) { … } // Test that FaviconHandler requests the new data when: // - There is valid data in the database for the page URL. // AND // - The icon URL used by the page has changed. // AND // - There is no data in database for the new icon URL. TEST_F(FaviconHandlerTest, UpdateAndDownloadFavicon) { … } // If there is data for the page URL in history which is invalid, test that: // - The invalid data is not sent to the UI. // - The icon is redownloaded. TEST_F(FaviconHandlerTest, FaviconInHistoryInvalid) { … } // Test that no downloads are done if a user visits a page which changed its // favicon URL to a favicon URL which is already cached in the database. TEST_F(FaviconHandlerTest, UpdateFavicon) { … } TEST_F(FaviconHandlerTest, Download2ndFaviconURLCandidate) { … } // Test that download data for icon URLs other than the current favicon // candidate URLs is ignored. This test tests the scenario where a download is // in flight when FaviconHandler::OnUpdateCandidates() is called. // TODO(mastiz): Make this test deal with FaviconURLs of type // favicon_base::IconType::kFavicon and add new ones like // OnlyDownloadMatchingIconType and CallSetFaviconsWithCorrectIconType. TEST_F(FaviconHandlerTest, UpdateDuringDownloading) { … } // Test that sending an icon URL update different to the previous icon URL // update during a database lookup ignores the first icon URL and processes the // second. TEST_F(FaviconHandlerTest, UpdateDuringDatabaseLookup) { … } // Test that sending an icon URL update identical to the previous icon URL // update during image download is a no-op. TEST_F(FaviconHandlerTest, UpdateSameIconURLsWhileDownloadingShouldBeNoop) { … } // Test that sending an icon URL update identical to the previous icon URL // update during a database lookup is a no-op. TEST_F(FaviconHandlerTest, UpdateSameIconURLsWhileDatabaseLookupShouldBeNoop) { … } // Test that calling OnUpdateFaviconUrl() with the same icon URLs as before is a // no-op. This is important because OnUpdateFaviconUrl() is called when the page // finishes loading. This can occur several times for pages with iframes. TEST_F(FaviconHandlerTest, UpdateSameIconURLsAfterFinishedShouldBeNoop) { … } // Fixes crbug.com/544560 // Tests that Delegate::OnFaviconUpdated() is called if: // - The best icon on the initial page is not the last icon. // - All of the initial page's icons are downloaded. // AND // - JavaScript modifies the page's <link rel="icon"> tags to contain only the // last icon. TEST_F(FaviconHandlerTest, OnFaviconAvailableNotificationSentAfterIconURLChange) { … } // Test that favicon mappings are removed if the page initially lists a favicon // and later uses Javascript to remove it. TEST_F(FaviconHandlerTest, RemoveFaviconViaJavascript) { … } // Tests that there is not crash and SetFavicons() is called with the // appropriate icon URL in the following scenario: // - The database initially has a cached but expired icon for the page. // - Initial favicon candidates are received fast, before the history lookup // completes. // - Before the history lookup completes, favicon candidates are updated via // javascript to include a different set of icons. TEST_F(FaviconHandlerTest, UpdateIconsViaJavascriptAfterFastCandidatesAndExpiredIcon) { … } // Test the favicon which is selected when the web page provides several // favicons and none of the favicons are cached in history. // The goal of this test is to be more of an integration test than // SelectFaviconFramesTest.*. class FaviconHandlerMultipleFaviconsTest : public FaviconHandlerTest { … }; // Tests that running FaviconHandler // - On an OS which supports the 1x and 2x scale factor // - On a page with <link rel="icon"> tags with no "sizes" information. // Selects the largest exact match. Note that a 32x32 PNG image is not a "true // exact match" on an OS which supports an 1x and 2x. A "true exact match" is // a .ico file with 16x16 and 32x32 bitmaps. TEST_F(FaviconHandlerMultipleFaviconsTest, ChooseLargestExactMatch) { … } // Test that if there are several single resolution favicons to choose // from, the exact match is preferred even if it results in upsampling. TEST_F(FaviconHandlerMultipleFaviconsTest, ChooseExactMatchDespiteUpsampling) { … } // Test that favicons which need to be upsampled a little or downsampled // a little are preferred over huge favicons. TEST_F(FaviconHandlerMultipleFaviconsTest, ChooseMinorDownsamplingOverHugeIcon) { … } TEST_F(FaviconHandlerMultipleFaviconsTest, ChooseMinorUpsamplingOverHugeIcon) { … } // Test a page with multiple favicon candidates with explicit sizes information. // Only the best one should be downloaded. TEST_F(FaviconHandlerMultipleFaviconsTest, StopsDownloadingWhenRemainingCandidatesWorse) { … } // Mostly for behavioral documentation purposes: test that downloads stops when // remaining candidates are worse or equal, for the following advanced scenario: // - The page provides multiple favicons: various with explicit sizes // information and one without. // - Among the ones with explicit sizes information, downloading the best // returns a 404. // - The remaining ones (with explicit sizes information) are worse than the one // without sizes information, and shouldn't be downloaded. TEST_F(FaviconHandlerTest, StopsDownloadingWhenRemainingCandidatesWorseDespite404) { … } TEST_F(FaviconHandlerMultipleFaviconsTest, DownloadsAllIconsWithoutSizesAttributeIfNotWantsLargest) { … } TEST_F(FaviconHandlerMultipleFaviconsTest, DownloadsOnlyOneIconWithoutSizesAttributeIfWantsLargest) { … } TEST_F(FaviconHandlerTest, Report404) { … } // Test that WasUnableToDownloadFavicon() is not called if a download returns // HTTP status 503. TEST_F(FaviconHandlerTest, NotReport503) { … } // Test that the best favicon is selected when: // - The page provides several favicons. // - Downloading one of the page's icon URLs previously returned a 404. // - None of the favicons are cached in the Favicons database. TEST_F(FaviconHandlerTest, MultipleFavicons404) { … } // Test that the best favicon is selected when: // - The page provides several favicons. // - Downloading the last page icon URL previously returned a 404. // - None of the favicons are cached in the Favicons database. // - All of the icons are downloaded because none of the icons have the ideal // size. // - The 404 icon is last. TEST_F(FaviconHandlerTest, MultipleFaviconsLast404) { … } // Test that no favicon is selected when: // - The page provides several favicons. // - Downloading the page's icons has previously returned a 404. // - None of the favicons are cached in the Favicons database. TEST_F(FaviconHandlerTest, MultipleFaviconsAll404) { … } // Test that favicon mappings are removed if the page initially lists a favicon // and later uses Javascript to change it to another icon that returns a 404. TEST_F(FaviconHandlerTest, ChangeFaviconViaJavascriptTo404) { … } // Test that favicon mappings are not removed in incognito if the page initially // lists a favicon and later uses Javascript to change it to another icon that // returns a 404. TEST_F(FaviconHandlerTest, ChangeFaviconViaJavascriptTo404InIncognito) { … } // Test that no favicon is selected when the page's only icon uses an invalid // URL syntax. TEST_F(FaviconHandlerTest, FaviconInvalidURL) { … } TEST_F(FaviconHandlerTest, TestSortFavicon) { … } TEST_F(FaviconHandlerTest, TestSortTouchIconLargest) { … } TEST_F(FaviconHandlerTest, TestDownloadLargestFavicon) { … } TEST_F(FaviconHandlerTest, TestSelectLargestFavicon) { … } TEST_F(FaviconHandlerTest, TestFaviconWasScaledAfterDownload) { … } // Test that if several icons are downloaded because the icons are smaller than // expected that OnFaviconUpdated() is called with the largest downloaded // bitmap. TEST_F(FaviconHandlerTest, TestKeepDownloadedLargestFavicon) { … } // Test that the special size keyword "any" (represented as a size of 0x0 in // FaviconURL) is handled. TEST_F(FaviconHandlerTest, TestConsiderAnySize) { … } // Test that if a page URL is followed by another page URL which is not // considered the same document, favicon candidates listed in the second page // get associated to that second page only. TEST_F(FaviconHandlerTest, SetFaviconsForLastPageUrlOnly) { … } // Test that if a page URL is followed by another page URL which is considered // the same document (e.g. fragment navigation), favicon candidates listed in // the second page get associated to both page URLs. TEST_F(FaviconHandlerTest, SetFaviconsForMultipleUrlsWithinDocument) { … } // Manifests are currently enabled by default. Leaving this fixture for // logical grouping and blame layer. class FaviconHandlerManifestsEnabledTest : public FaviconHandlerTest { … }; // Test that favicon mappings are deleted when a manifest previously cached in // the DB is no longer referenced by the page and the page lists no regular // icons. TEST_F(FaviconHandlerManifestsEnabledTest, RemovedWebManifestAndNoRegularIcons) { … } // Test that favicon mappings are updated (but not deleted) when a manifest // previously cached in the DB is no longer referenced by the page and the page // lists regular icons. TEST_F(FaviconHandlerManifestsEnabledTest, RemovedWebManifestAndRegularIcons) { … } // Test that favicon mappings are updated (but not deleted) when a manifest // previously cached in the DB (but expired) is no longer referenced by the page // and the page lists regular icons. TEST_F(FaviconHandlerManifestsEnabledTest, ExpiredAndRemovedWebManifestAndRegularIcons) { … } // Test that a favicon corresponding to a web manifest is reported when: // - There is data in the favicon database for the manifest URL. // AND // - FaviconService::OnFaviconDataForManifestFromFaviconService() runs before // FaviconHandler::OnUpdateCandidates() is called. TEST_F(FaviconHandlerManifestsEnabledTest, GetFaviconFromManifestInHistoryIfCandidatesSlower) { … } // Test that a favicon corresponding to a web manifest is reported when: // - There is data in the favicon database for the manifest URL. // AND // - FaviconHandler::OnUpdateCandidates() is called before // FaviconService::OnFaviconDataForManifestFromFaviconService() runs. TEST_F(FaviconHandlerManifestsEnabledTest, GetFaviconFromManifestInHistoryIfCandidatesFaster) { … } // Believed to fix crbug.com/544560. // Tests that there is not crash and SetFavicons() is called with the // appropriate icon URL in the following scenario: // - The database initially has a cached icon for the page (not expired). // - Two initial favicon candidates are received fast, before the history lookup // completes. There is no manifest URL initially. // - Before the history lookup completes, favicon candidates are updated via // javascript to include a manifest URL. // - The manifest lists at least one icon. TEST_F(FaviconHandlerManifestsEnabledTest, AddManifestWithIconsViaJavascriptAfterFastCandidates) { … } // Believed to fix crbug.com/544560. // Tests that there is not crash and SetFavicons() is called with the // appropriate icon URL in the following scenario: // - The database initially has a cached but expired icon for the page. // - Initial favicon candidates are received fast, before the history lookup // completes. There is no manifest URL initially. // - Before the history lookup completes, favicon candidates are updated via // javascript to include a manifest URL. // - The manifest lists at least one icon. TEST_F(FaviconHandlerManifestsEnabledTest, AddManifestWithIconsViaJavascriptAfterFastCandidatesAndExpiredIcon) { … } // Believed to fix crbug.com/544560. // Same as the test above with the difference that the manifest contains no // icons. TEST_F(FaviconHandlerManifestsEnabledTest, AddManifestWithoutIconsViaJavascriptAfterFastCandidatesAndExpiredIcon) { … } // Test that a favicon corresponding to a web manifest is reported when there is // data in the database for neither the page URL nor the manifest URL. TEST_F(FaviconHandlerManifestsEnabledTest, GetFaviconFromUnknownManifest) { … } // Test that icons from a web manifest use a desired size of 192x192. TEST_F(FaviconHandlerManifestsEnabledTest, Prefer192x192IconFromManifest) { … } // Test that a 192x192 favicon corresponding to a web manifest is reported with // the appropriate size when there is data in the database for neither the page // URL nor the manifest URL. TEST_F(FaviconHandlerManifestsEnabledTest, GetNonResized192x192FaviconFromUnknownManifest) { … } // Test that the manifest and icon are redownloaded if the icon cached for the // page URL expired. TEST_F(FaviconHandlerManifestsEnabledTest, GetFaviconFromExpiredManifest) { … } // Test that the manifest and icon are redownloaded if the icon cached for the // manifest URL expired, which was observed during a visit to a different page // URL. TEST_F(FaviconHandlerManifestsEnabledTest, GetFaviconFromExpiredManifestLinkedFromOtherPage) { … } // Test that a favicon corresponding to a web manifest is reported when: // - There is data in the database for neither the page URL nor the manifest // URL. // - There is data in the database for the icon URL listed in the manifest. TEST_F(FaviconHandlerManifestsEnabledTest, GetFaviconFromUnknownManifestButKnownIcon) { … } // Test a manifest that returns a 404 gets blacklisted via // UnableToDownloadFavicon() AND that the regular favicon is selected as // fallback. TEST_F(FaviconHandlerManifestsEnabledTest, UnknownManifestReturning404) { … } // Test that a manifest that was previously blacklisted via // UnableToDownloadFavicon() is ignored and that the regular favicon is selected // as fallback. TEST_F(FaviconHandlerManifestsEnabledTest, IgnoreManifestWithPrior404) { … } // Test that favicon mappings are deleted when a manifest previously cached in // the DB (but expired) returns a 404, when the page lists no regular icons. TEST_F(FaviconHandlerManifestsEnabledTest, ExpiredManifestReturning404AndNoRegularIcons) { … } // Test that favicon mappings are updated (but not deleted) when a manifest // previously cached in the DB (but expired) returns a 404, when the page lists // regular icons that haven't been cached before. TEST_F(FaviconHandlerManifestsEnabledTest, ExpiredManifestReturning404AndRegularIcons) { … } // Test that favicon mappings are deleted when a manifest previously cached in // the DB (but expired) contains no icons, when the page lists no regular icons. TEST_F(FaviconHandlerManifestsEnabledTest, ExpiredManifestWithoutIconsAndNoRegularIcons) { … } // Test that favicon mappings are updated (but not deleted) when a manifest // previously cached in the DB (but expired) contains no icons, when the page // lists regular icons that haven't been cached before. TEST_F(FaviconHandlerManifestsEnabledTest, ExpiredManifestWithoutIconsAndRegularIcons) { … } // Test that the regular favicon is selected when: // - The page links to a Web Manifest. // - The Web Manifest does not contain any icon URLs (it is not a 404). // - The page has an icon URL provided via a <link rel="icon"> tag. // - The database does not know about the page URL, manifest URL or icon URL. TEST_F(FaviconHandlerManifestsEnabledTest, UnknownManifestWithoutIcons) { … } // Test that the regular favicon is selected when: // - The page links to a Web Manifest. // - The Web Manifest does not contain any icon URLs (it is not a 404). // - The page has an icon URL provided via a <link rel="icon"> tag. // - The database does not know about the page URL. // - The database does not know about the manifest URL. // - The database knows about the icon URL. TEST_F(FaviconHandlerManifestsEnabledTest, UnknownManifestWithoutIconsAndKnownRegularIcons) { … } // Test that the database remains unmodified when: // - The page links to a Web Manifest. // - The Web Manifest does not contain any icon URLs (it is not a 404). // - The page has an icon URL provided via a <link rel="icon"> tag. // - The database has a mapping between the page URL to the favicon URL. TEST_F(FaviconHandlerManifestsEnabledTest, UnknownManifestWithoutIconsAndRegularIconInHistory) { … } // Test that Delegate::OnFaviconUpdated() is called if a page uses Javascript to // modify the page's <link rel="manifest"> tag to point to a different manifest. TEST_F(FaviconHandlerManifestsEnabledTest, ManifestUpdateViaJavascript) { … } // Test that Delegate::OnFaviconUpdated() is called if a page uses Javascript to // remove the page's <link rel="manifest"> tag (i.e. no web manifest) WHILE a // lookup to the history database is ongoing for the manifest URL. TEST_F(FaviconHandlerManifestsEnabledTest, RemoveManifestViaJavascriptWhileDatabaseLookup) { … } // Tests that favicon mappings are removed if a page initially lists no regular // favicons but does link to a web manifest, and later uses Javascript to remove // the manifest URL. TEST_F(FaviconHandlerManifestsEnabledTest, RemoveManifestViaJavascriptDeletesMappings) { … } // Test that Delegate::OnFaviconUpdated() is called a page without manifest uses // Javascript to add a <link rel="manifest"> tag (i.e. a new web manifest) WHILE // a lookup to the history database is ongoing for the icon URL. TEST_F(FaviconHandlerManifestsEnabledTest, AddManifestViaJavascriptWhileDatabaseLookup) { … } // Test that SetFavicons() is not called when: // - The page doesn't initially link to a Web Manifest. // - The page has an icon URL provided via a <link rel="icon"> tag. // - The database does not know about the page URL or icon URL. // - While the icon is being downloaded, the page uses Javascript to add a // <link rel="manifest"> tag. // - The database has bitmap data for the manifest URL. TEST_F(FaviconHandlerManifestsEnabledTest, AddKnownManifestViaJavascriptWhileImageDownload) { … } // Test that SetFavicons() is called with the icon URL when: // - The page doesn't initially link to a Web Manifest. // - The page has an icon URL provided via a <link rel="icon"> tag. // - The database does not know about the page URL or icon URL. // - During the database lookup, the page uses Javascript to add a // <link rel="manifest"> tag. // - The database does not know about the manifest URL. // - The manifest contains no icons. TEST_F(FaviconHandlerManifestsEnabledTest, AddManifestWithoutIconsViaJavascriptWhileDatabaseLookup) { … } // Test that SetFavicons() is called when: // - The page links to one Web Manifest, which contains one icon. // - The database does not know about the page URL, icon URL or manifest URL. // - During image download, the page updates the manifest URL to point to // another manifest. // - The second manifest contains the same icons as the first. TEST_F(FaviconHandlerManifestsEnabledTest, UpdateManifestWithSameIconURLsWhileDownloading) { … } } // namespace } // namespace favicon