forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Use high resolution icons where possible for streamlined hosted app i…
…cons. This adds a FaviconDownloader which downloads all icons when creating streamlined hosted apps from the current web contents, providing higher resolution icons. BUG=318607 Review URL: https://codereview.chromium.org/64853004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@241462 0039d316-1c4b-4281-b951-d872f2087c98
- Loading branch information
calamity@chromium.org
committed
Dec 18, 2013
1 parent
60e3030
commit 8986979
Showing
10 changed files
with
537 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
// Copyright 2013 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "chrome/browser/extensions/favicon_downloader.h" | ||
|
||
#include "base/bind.h" | ||
#include "chrome/browser/favicon/favicon_tab_helper.h" | ||
#include "content/public/browser/web_contents.h" | ||
#include "content/public/common/favicon_url.h" | ||
#include "third_party/skia/include/core/SkBitmap.h" | ||
#include "ui/gfx/size.h" | ||
|
||
FaviconDownloader::FaviconDownloader( | ||
content::WebContents* web_contents, | ||
const std::vector<GURL>& extra_favicon_urls, | ||
FaviconDownloaderCallback callback) | ||
: content::WebContentsObserver(web_contents), | ||
got_favicon_urls_(false), | ||
extra_favicon_urls_(extra_favicon_urls), | ||
callback_(callback), | ||
weak_ptr_factory_(this) { | ||
} | ||
|
||
FaviconDownloader::~FaviconDownloader() { | ||
} | ||
|
||
void FaviconDownloader::Start() { | ||
FetchIcons(extra_favicon_urls_); | ||
// If the candidates aren't loaded, icons will be fetched when | ||
// DidUpdateFaviconURL() is called. | ||
std::vector<content::FaviconURL> favicon_tab_helper_urls = | ||
GetFaviconURLsFromWebContents(); | ||
if (!favicon_tab_helper_urls.empty()) { | ||
got_favicon_urls_ = true; | ||
FetchIcons(favicon_tab_helper_urls); | ||
} | ||
} | ||
|
||
int FaviconDownloader::DownloadImage(const GURL& url) { | ||
return web_contents()->DownloadImage( | ||
url, | ||
true, // is_favicon | ||
0, // no max size | ||
base::Bind(&FaviconDownloader::DidDownloadFavicon, | ||
weak_ptr_factory_.GetWeakPtr())); | ||
} | ||
|
||
std::vector<content::FaviconURL> | ||
FaviconDownloader::GetFaviconURLsFromWebContents() { | ||
FaviconTabHelper* favicon_tab_helper = | ||
web_contents() ? FaviconTabHelper::FromWebContents(web_contents()) : NULL; | ||
// If favicon_urls() is empty, we are guaranteed that DidUpdateFaviconURLs has | ||
// not yet been called for the current page's navigation. | ||
return favicon_tab_helper ? favicon_tab_helper->favicon_urls() | ||
: std::vector<content::FaviconURL>(); | ||
} | ||
|
||
void FaviconDownloader::FetchIcons( | ||
const std::vector<content::FaviconURL>& favicon_urls) { | ||
std::vector<GURL> urls; | ||
for (std::vector<content::FaviconURL>::const_iterator it = | ||
favicon_urls.begin(); | ||
it != favicon_urls.end(); ++it) { | ||
if (it->icon_type != content::FaviconURL::INVALID_ICON) | ||
urls.push_back(it->icon_url); | ||
} | ||
FetchIcons(urls); | ||
} | ||
|
||
void FaviconDownloader::FetchIcons(const std::vector<GURL>& urls) { | ||
// Download icons; put their download ids into |in_progress_requests_| and | ||
// their urls into |processed_urls_|. | ||
for (std::vector<GURL>::const_iterator it = urls.begin(); | ||
it != urls.end(); ++it) { | ||
// Only start the download if the url hasn't been processed before. | ||
if (processed_urls_.insert(*it).second) | ||
in_progress_requests_.insert(DownloadImage(*it)); | ||
} | ||
|
||
// If no downloads were initiated, we can proceed directly to running the | ||
// callback. | ||
if (in_progress_requests_.empty() && got_favicon_urls_) | ||
callback_.Run(true, favicon_map_); | ||
} | ||
|
||
void FaviconDownloader::DidDownloadFavicon( | ||
int id, | ||
int http_status_code, | ||
const GURL& image_url, | ||
const std::vector<SkBitmap>& bitmaps, | ||
const std::vector<gfx::Size>& original_bitmap_sizes) { | ||
// Request may have been canceled by DidNavigateMainFrame(). | ||
if (in_progress_requests_.erase(id) == 0) | ||
return; | ||
|
||
favicon_map_[image_url] = bitmaps; | ||
|
||
// Once all requests have been resolved, perform post-download tasks. | ||
if (in_progress_requests_.empty() && got_favicon_urls_) | ||
callback_.Run(true, favicon_map_); | ||
} | ||
|
||
// content::WebContentsObserver overrides: | ||
void FaviconDownloader::DidNavigateMainFrame( | ||
const content::LoadCommittedDetails& details, | ||
const content::FrameNavigateParams& params) { | ||
// Clear all pending requests. | ||
in_progress_requests_.clear(); | ||
favicon_map_.clear(); | ||
callback_.Run(false, favicon_map_); | ||
} | ||
|
||
void FaviconDownloader::DidUpdateFaviconURL( | ||
int32 page_id, | ||
const std::vector<content::FaviconURL>& candidates) { | ||
// Only consider the first candidates we are given. This prevents pages that | ||
// change their favicon from spamming us. | ||
if (got_favicon_urls_) | ||
return; | ||
|
||
got_favicon_urls_ = true; | ||
FetchIcons(candidates); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// Copyright 2013 The Chromium Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef CHROME_BROWSER_EXTENSIONS_FAVICON_DOWNLOADER_H_ | ||
#define CHROME_BROWSER_EXTENSIONS_FAVICON_DOWNLOADER_H_ | ||
|
||
#include <map> | ||
#include <set> | ||
#include <vector> | ||
|
||
#include "base/callback.h" | ||
#include "base/memory/weak_ptr.h" | ||
#include "content/public/browser/web_contents_observer.h" | ||
|
||
class SkBitmap; | ||
|
||
namespace content { | ||
struct FaviconURL; | ||
} | ||
|
||
namespace gfx { | ||
class Size; | ||
} | ||
|
||
// Class to help download all favicons for a tab. | ||
class FaviconDownloader : public content::WebContentsObserver { | ||
public: | ||
typedef std::map<GURL, std::vector<SkBitmap> > FaviconMap; | ||
typedef base::Callback<void( | ||
bool, /* success */ | ||
/* A map of icon urls to the bitmaps provided by that url. */ | ||
const FaviconMap&)> | ||
FaviconDownloaderCallback; | ||
// |extra_favicon_urls| allows callers to provide icon urls that aren't | ||
// |provided by the renderer (e.g touch icons on non-android environments). | ||
FaviconDownloader(content::WebContents* web_contents, | ||
const std::vector<GURL>& extra_favicon_urls, | ||
FaviconDownloaderCallback callback); | ||
virtual ~FaviconDownloader(); | ||
|
||
void Start(); | ||
|
||
private: | ||
friend class TestFaviconDownloader; | ||
|
||
// Initiates a download of the image at |url| and returns the download id. | ||
// This is overridden in testing. | ||
virtual int DownloadImage(const GURL& url); | ||
|
||
// Queries FaviconTabHelper for the page's current favicon URLs. | ||
// This is overridden in testing. | ||
virtual std::vector<content::FaviconURL> GetFaviconURLsFromWebContents(); | ||
|
||
// Fetches icons for the given urls. | ||
// |callback_| is run when all downloads complete. | ||
void FetchIcons(const std::vector<content::FaviconURL>& favicon_urls); | ||
void FetchIcons(const std::vector<GURL>& urls); | ||
|
||
// Icon download callback. | ||
void DidDownloadFavicon(int id, | ||
int http_status_code, | ||
const GURL& image_url, | ||
const std::vector<SkBitmap>& bitmaps, | ||
const std::vector<gfx::Size>& original_bitmap_sizes); | ||
|
||
// content::WebContentsObserver overrides: | ||
virtual void DidNavigateMainFrame( | ||
const content::LoadCommittedDetails& details, | ||
const content::FrameNavigateParams& params) OVERRIDE; | ||
virtual void DidUpdateFaviconURL( | ||
int32 page_id, | ||
const std::vector<content::FaviconURL>& candidates) OVERRIDE; | ||
|
||
// Whether we have received favicons from the renderer. | ||
bool got_favicon_urls_; | ||
|
||
// URLs that aren't given by WebContentsObserver::DidUpdateFaviconURL() that | ||
// should be used for this favicon. This is necessary in order to get touch | ||
// icons on non-android environments. | ||
std::vector<GURL> extra_favicon_urls_; | ||
|
||
// The icons which were downloaded. Populated by FetchIcons(). | ||
FaviconMap favicon_map_; | ||
|
||
// Request ids of in-progress requests. | ||
std::set<int> in_progress_requests_; | ||
|
||
// Urls for which a download has already been initiated. Used to prevent | ||
// duplicate downloads of the same url. | ||
std::set<GURL> processed_urls_; | ||
|
||
// Callback to run on favicon download completion. | ||
FaviconDownloaderCallback callback_; | ||
|
||
base::WeakPtrFactory<FaviconDownloader> weak_ptr_factory_; | ||
|
||
DISALLOW_COPY_AND_ASSIGN(FaviconDownloader); | ||
}; | ||
|
||
#endif // CHROME_BROWSER_EXTENSIONS_FAVICON_DOWNLOADER_H_ |
Oops, something went wrong.