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/core/favicon_driver_impl.h"
7 #include "base/command_line.h"
8 #include "base/logging.h"
9 #include "base/metrics/field_trial.h"
10 #include "base/strings/string_util.h"
11 #include "components/bookmarks/browser/bookmark_model.h"
12 #include "components/favicon/core/favicon_driver_observer.h"
13 #include "components/favicon/core/favicon_handler.h"
14 #include "components/favicon/core/favicon_service.h"
15 #include "components/history/core/browser/history_service.h"
16 #include "ui/base/ui_base_switches.h"
21 // Returns whether icon NTP is enabled by experiment.
22 // TODO(huangs): Remove all 3 copies of this routine once Icon NTP launches.
23 bool IsIconNTPEnabled() {
24 // Note: It's important to query the field trial state first, to ensure that
25 // UMA reports the correct group.
26 const std::string group_name
= base::FieldTrialList::FindFullName("IconNTP");
27 using base::CommandLine
;
28 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableIconNtp
))
30 if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableIconNtp
))
33 return base::StartsWith(group_name
, "Enabled", base::CompareCase::SENSITIVE
);
36 #if defined(OS_ANDROID) || defined(OS_IOS)
37 const bool kEnableTouchIcon
= true;
39 const bool kEnableTouchIcon
= false;
44 FaviconDriverImpl::FaviconDriverImpl(FaviconService
* favicon_service
,
45 history::HistoryService
* history_service
,
46 bookmarks::BookmarkModel
* bookmark_model
)
47 : favicon_service_(favicon_service
),
48 history_service_(history_service
),
49 bookmark_model_(bookmark_model
) {
50 favicon_handler_
.reset(new FaviconHandler(
51 favicon_service_
, this, FaviconHandler::FAVICON
, kEnableTouchIcon
));
52 if (kEnableTouchIcon
) {
53 touch_icon_handler_
.reset(new FaviconHandler(favicon_service_
, this,
54 FaviconHandler::TOUCH
, true));
56 if (IsIconNTPEnabled()) {
57 large_icon_handler_
.reset(new FaviconHandler(favicon_service_
, this,
58 FaviconHandler::LARGE
, true));
62 FaviconDriverImpl::~FaviconDriverImpl() {
65 void FaviconDriverImpl::FetchFavicon(const GURL
& url
) {
66 favicon_handler_
->FetchFavicon(url
);
67 if (touch_icon_handler_
.get())
68 touch_icon_handler_
->FetchFavicon(url
);
69 if (large_icon_handler_
.get())
70 large_icon_handler_
->FetchFavicon(url
);
73 void FaviconDriverImpl::SaveFavicon() {
74 GURL active_url
= GetActiveURL();
75 if (active_url
.is_empty())
78 // Make sure the page is in history, otherwise adding the favicon does
80 if (!history_service_
)
82 history_service_
->AddPageNoVisitForBookmark(active_url
, GetActiveTitle());
84 if (!favicon_service_
)
86 if (!GetActiveFaviconValidity())
88 GURL favicon_url
= GetActiveFaviconURL();
89 if (favicon_url
.is_empty())
91 gfx::Image image
= GetActiveFaviconImage();
94 favicon_service_
->SetFavicons(active_url
, favicon_url
, favicon_base::FAVICON
,
98 void FaviconDriverImpl::DidDownloadFavicon(
100 int http_status_code
,
101 const GURL
& image_url
,
102 const std::vector
<SkBitmap
>& bitmaps
,
103 const std::vector
<gfx::Size
>& original_bitmap_sizes
) {
104 if (bitmaps
.empty() && http_status_code
== 404) {
105 DVLOG(1) << "Failed to Download Favicon:" << image_url
;
106 if (favicon_service_
)
107 favicon_service_
->UnableToDownloadFavicon(image_url
);
110 favicon_handler_
->OnDidDownloadFavicon(id
, image_url
, bitmaps
,
111 original_bitmap_sizes
);
112 if (touch_icon_handler_
.get()) {
113 touch_icon_handler_
->OnDidDownloadFavicon(id
, image_url
, bitmaps
,
114 original_bitmap_sizes
);
116 if (large_icon_handler_
.get()) {
117 large_icon_handler_
->OnDidDownloadFavicon(id
, image_url
, bitmaps
,
118 original_bitmap_sizes
);
122 bool FaviconDriverImpl::IsBookmarked(const GURL
& url
) {
123 return bookmark_model_
&& bookmark_model_
->IsBookmarked(url
);
126 void FaviconDriverImpl::OnFaviconAvailable(const gfx::Image
& image
,
127 const GURL
& icon_url
,
128 bool is_active_favicon
) {
129 if (is_active_favicon
) {
130 bool icon_url_changed
= GetActiveFaviconURL() != icon_url
;
131 // No matter what happens, we need to mark the favicon as being set.
132 SetActiveFaviconValidity(true);
133 SetActiveFaviconURL(icon_url
);
138 SetActiveFaviconImage(image
);
139 NotifyFaviconUpdated(icon_url_changed
);
141 if (!image
.IsEmpty())
142 NotifyFaviconAvailable(image
);
145 bool FaviconDriverImpl::HasPendingTasksForTest() {
146 if (favicon_handler_
->HasPendingTasksForTest())
148 if (touch_icon_handler_
&& touch_icon_handler_
->HasPendingTasksForTest())
150 if (large_icon_handler_
&& large_icon_handler_
->HasPendingTasksForTest())
155 bool FaviconDriverImpl::WasUnableToDownloadFavicon(const GURL
& url
) {
156 return favicon_service_
&& favicon_service_
->WasUnableToDownloadFavicon(url
);
159 void FaviconDriverImpl::SetFaviconOutOfDateForPage(const GURL
& url
,
161 if (favicon_service_
) {
162 favicon_service_
->SetFaviconOutOfDateForPage(url
);
164 favicon_service_
->ClearUnableToDownloadFavicons();
168 void FaviconDriverImpl::OnUpdateFaviconURL(
169 const std::vector
<FaviconURL
>& candidates
) {
170 DCHECK(!candidates
.empty());
171 favicon_handler_
->OnUpdateFaviconURL(candidates
);
172 if (touch_icon_handler_
.get())
173 touch_icon_handler_
->OnUpdateFaviconURL(candidates
);
174 if (large_icon_handler_
.get())
175 large_icon_handler_
->OnUpdateFaviconURL(candidates
);
178 } // namespace favicon