1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "components/favicon/content/content_favicon_driver.h"
8 #include "components/favicon/content/favicon_url_util.h"
9 #include "components/favicon/core/favicon_url.h"
10 #include "content/public/browser/browser_context.h"
11 #include "content/public/browser/favicon_status.h"
12 #include "content/public/browser/navigation_controller.h"
13 #include "content/public/browser/navigation_details.h"
14 #include "content/public/browser/navigation_entry.h"
15 #include "content/public/common/favicon_url.h"
16 #include "ui/gfx/image/image.h"
18 DEFINE_WEB_CONTENTS_USER_DATA_KEY(favicon::ContentFaviconDriver
);
23 void ContentFaviconDriver::CreateForWebContents(
24 content::WebContents
* web_contents
,
25 FaviconService
* favicon_service
,
26 history::HistoryService
* history_service
,
27 bookmarks::BookmarkModel
* bookmark_model
) {
28 if (FromWebContents(web_contents
))
31 web_contents
->SetUserData(
32 UserDataKey(), new ContentFaviconDriver(web_contents
, favicon_service
,
33 history_service
, bookmark_model
));
36 gfx::Image
ContentFaviconDriver::GetFavicon() const {
37 // Like GetTitle(), we also want to use the favicon for the last committed
38 // entry rather than a pending navigation entry.
39 const content::NavigationController
& controller
=
40 web_contents()->GetController();
41 content::NavigationEntry
* entry
= controller
.GetTransientEntry();
43 return entry
->GetFavicon().image
;
45 entry
= controller
.GetLastCommittedEntry();
47 return entry
->GetFavicon().image
;
51 bool ContentFaviconDriver::FaviconIsValid() const {
52 const content::NavigationController
& controller
=
53 web_contents()->GetController();
54 content::NavigationEntry
* entry
= controller
.GetTransientEntry();
56 return entry
->GetFavicon().valid
;
58 entry
= controller
.GetLastCommittedEntry();
60 return entry
->GetFavicon().valid
;
65 int ContentFaviconDriver::StartDownload(const GURL
& url
, int max_image_size
) {
66 if (WasUnableToDownloadFavicon(url
)) {
67 DVLOG(1) << "Skip Failed FavIcon: " << url
;
71 bool bypass_cache
= (bypass_cache_page_url_
== GetActiveURL());
72 bypass_cache_page_url_
= GURL();
74 return web_contents()->DownloadImage(
75 url
, true, max_image_size
, bypass_cache
,
76 base::Bind(&FaviconDriverImpl::DidDownloadFavicon
,
77 base::Unretained(this)));
80 bool ContentFaviconDriver::IsOffTheRecord() {
81 DCHECK(web_contents());
82 return web_contents()->GetBrowserContext()->IsOffTheRecord();
85 GURL
ContentFaviconDriver::GetActiveURL() {
86 content::NavigationEntry
* entry
=
87 web_contents()->GetController().GetActiveEntry();
88 return entry
? entry
->GetURL() : GURL();
91 base::string16
ContentFaviconDriver::GetActiveTitle() {
92 content::NavigationEntry
* entry
=
93 web_contents()->GetController().GetActiveEntry();
94 return entry
? entry
->GetTitle() : base::string16();
97 bool ContentFaviconDriver::GetActiveFaviconValidity() {
98 return GetFaviconStatus().valid
;
101 void ContentFaviconDriver::SetActiveFaviconValidity(bool valid
) {
102 GetFaviconStatus().valid
= valid
;
105 GURL
ContentFaviconDriver::GetActiveFaviconURL() {
106 return GetFaviconStatus().url
;
109 void ContentFaviconDriver::SetActiveFaviconURL(const GURL
& url
) {
110 GetFaviconStatus().url
= url
;
113 gfx::Image
ContentFaviconDriver::GetActiveFaviconImage() {
114 return GetFaviconStatus().image
;
117 void ContentFaviconDriver::SetActiveFaviconImage(const gfx::Image
& image
) {
118 GetFaviconStatus().image
= image
;
121 content::FaviconStatus
& ContentFaviconDriver::GetFaviconStatus() {
122 DCHECK(web_contents()->GetController().GetActiveEntry());
123 return web_contents()->GetController().GetActiveEntry()->GetFavicon();
126 ContentFaviconDriver::ContentFaviconDriver(
127 content::WebContents
* web_contents
,
128 FaviconService
* favicon_service
,
129 history::HistoryService
* history_service
,
130 bookmarks::BookmarkModel
* bookmark_model
)
131 : content::WebContentsObserver(web_contents
),
132 FaviconDriverImpl(favicon_service
, history_service
, bookmark_model
) {
135 ContentFaviconDriver::~ContentFaviconDriver() {
138 void ContentFaviconDriver::NotifyFaviconUpdated(bool icon_url_changed
) {
139 FaviconDriverImpl::NotifyFaviconUpdated(icon_url_changed
);
140 web_contents()->NotifyNavigationStateChanged(content::INVALIDATE_TYPE_TAB
);
143 void ContentFaviconDriver::DidUpdateFaviconURL(
144 const std::vector
<content::FaviconURL
>& candidates
) {
145 DCHECK(!candidates
.empty());
146 favicon_urls_
= candidates
;
147 OnUpdateFaviconURL(FaviconURLsFromContentFaviconURLs(candidates
));
150 void ContentFaviconDriver::DidStartNavigationToPendingEntry(
152 content::NavigationController::ReloadType reload_type
) {
153 if (reload_type
== content::NavigationController::NO_RELOAD
||
157 bypass_cache_page_url_
= url
;
158 SetFaviconOutOfDateForPage(
159 url
, reload_type
== content::NavigationController::RELOAD_IGNORING_CACHE
);
162 void ContentFaviconDriver::DidNavigateMainFrame(
163 const content::LoadCommittedDetails
& details
,
164 const content::FrameNavigateParams
& params
) {
165 favicon_urls_
.clear();
167 // Wait till the user navigates to a new URL to start checking the cache
168 // again. The cache may be ignored for non-reload navigations (e.g.
169 // history.replace() in-page navigation). This is allowed to increase the
170 // likelihood that "reloading a page ignoring the cache" redownloads the
171 // favicon. In particular, a page may do an in-page navigation before
172 // FaviconHandler has the time to determine that the favicon needs to be
174 GURL url
= details
.entry
->GetURL();
175 if (url
!= bypass_cache_page_url_
)
176 bypass_cache_page_url_
= GURL();
178 // Get the favicon, either from history or request it from the net.
182 } // namespace favicon