blob: f53b02a65e76e11a0503e1e52e695018f273ddbc [file] [log] [blame]
[email protected]2f7826a32012-04-18 00:29:541// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]f84645222009-03-30 23:06:272// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
[email protected]fd42ac30f2011-02-27 19:33:365#include "chrome/browser/ui/webui/favicon_source.h"
[email protected]f84645222009-03-30 23:06:276
[email protected]25244a932014-07-12 23:00:247#include <cmath>
8
[email protected]bbdd2982011-10-08 18:14:249#include "base/bind.h"
10#include "base/bind_helpers.h"
Victor Hugo Vianna Silva969aca62019-04-23 11:28:3411#include "base/metrics/histogram_macros.h"
[email protected]3ea1b182013-02-08 22:38:4112#include "base/strings/string_number_conversions.h"
[email protected]f3d2b312012-08-23 22:27:5913#include "chrome/browser/favicon/favicon_service_factory.h"
Victor Hugo Vianna Silvadf127bfc2019-07-03 00:02:1214#include "chrome/browser/favicon/history_ui_favicon_request_handler_factory.h"
sdefresne0da3bc02015-01-29 18:26:3515#include "chrome/browser/history/top_sites_factory.h"
[email protected]8ecad5e2010-12-02 21:18:3316#include "chrome/browser/profiles/profile.h"
[email protected]a7b8e43d2013-03-18 18:52:4317#include "chrome/browser/search/instant_io_context.h"
[email protected]f84645222009-03-30 23:06:2718#include "chrome/common/url_constants.h"
Dan Beam3c164702019-05-30 01:44:1019#include "chrome/common/webui_url_constants.h"
Victor Hugo Vianna Silvadf127bfc2019-07-03 00:02:1220#include "components/favicon/core/history_ui_favicon_request_handler.h"
blundellee0ade22015-07-08 10:07:4521#include "components/favicon_base/favicon_url_parser.h"
sdefresne0da3bc02015-01-29 18:26:3522#include "components/history/core/browser/top_sites.h"
Victor Hugo Vianna Silva969aca62019-04-23 11:28:3423#include "content/public/browser/web_contents.h"
[email protected]672c8c12013-03-07 12:30:0624#include "net/url_request/url_request.h"
[email protected]c49201a2012-05-24 11:04:5725#include "ui/base/layout.h"
[email protected]42ce29d2011-01-20 23:19:4626#include "ui/base/resource/resource_bundle.h"
[email protected]cd67ed52013-10-15 01:22:1327#include "ui/base/webui/web_ui_util.h"
Dan Beam75cd5b072019-02-23 01:04:4628#include "ui/native_theme/native_theme.h"
[email protected]b47dc492014-08-17 07:05:5729#include "ui/resources/grit/ui_resources.h"
Victor Hugo Vianna Silva969aca62019-04-23 11:28:3430#include "url/gurl.h"
31
32namespace {
Victor Hugo Vianna Silva55a7cd52019-07-14 17:34:2333
Victor Hugo Vianna Silvad611d2702019-07-16 10:11:2334// web_contents->GetLastCommittedURL in general will not necessarily yield the
35// original URL that started the request, but we're only interested in verifying
36// if it was issued by a history page, for whom this is the case. If it is not
37// possible to obtain the URL, we return the empty GURL.
John Abd-El-Malek92bf3602019-07-31 02:25:4838GURL GetUnsafeRequestOrigin(const content::WebContents::Getter& wc_getter) {
Victor Hugo Vianna Silva55a7cd52019-07-14 17:34:2339 content::WebContents* web_contents = wc_getter.Run();
Victor Hugo Vianna Silvad611d2702019-07-16 10:11:2340 return web_contents ? web_contents->GetLastCommittedURL() : GURL();
Victor Hugo Vianna Silva55a7cd52019-07-14 17:34:2341}
42
43bool ParseHistoryUiOrigin(const GURL& url,
Victor Hugo Vianna Silva9214a2292019-07-14 18:30:0444 favicon::HistoryUiFaviconRequestOrigin* origin) {
Victor Hugo Vianna Silva969aca62019-04-23 11:28:3445 GURL history_url(chrome::kChromeUIHistoryURL);
Victor Hugo Vianna Silva55a7cd52019-07-14 17:34:2346 if (url == history_url) {
Victor Hugo Vianna Silva64b38182019-07-20 21:19:5947 *origin = favicon::HistoryUiFaviconRequestOrigin::kHistory;
Victor Hugo Vianna Silva55a7cd52019-07-14 17:34:2348 return true;
49 }
50 if (url == history_url.Resolve(chrome::kChromeUIHistorySyncedTabs)) {
Victor Hugo Vianna Silva64b38182019-07-20 21:19:5951 *origin = favicon::HistoryUiFaviconRequestOrigin::kHistorySyncedTabs;
Victor Hugo Vianna Silva55a7cd52019-07-14 17:34:2352 return true;
53 }
54 return false;
Victor Hugo Vianna Silva969aca62019-04-23 11:28:3455}
Victor Hugo Vianna Silvaadf1af3d2019-05-20 09:01:1656
Victor Hugo Vianna Silva969aca62019-04-23 11:28:3457} // namespace
[email protected]f84645222009-03-30 23:06:2758
Victor Hugo Vianna Silvaed441482019-06-27 12:40:4059FaviconSource::FaviconSource(Profile* profile,
60 chrome::FaviconUrlFormat url_format)
61 : profile_(profile->GetOriginalProfile()), url_format_(url_format) {}
[email protected]f84645222009-03-30 23:06:2762
[email protected]16835e62011-03-16 14:13:0863FaviconSource::~FaviconSource() {
[email protected]3071754432010-07-28 00:09:5464}
65
Lucas Furukawa Gadani4b4eed02019-06-04 23:12:0466std::string FaviconSource::GetSource() {
Victor Hugo Vianna Silvaed441482019-06-27 12:40:4067 switch (url_format_) {
68 case chrome::FaviconUrlFormat::kFaviconLegacy:
69 return chrome::kChromeUIFaviconHost;
70 case chrome::FaviconUrlFormat::kFavicon2:
71 return chrome::kChromeUIFavicon2Host;
72 }
73 NOTREACHED();
74 return "";
[email protected]97642ce2012-04-30 17:05:2275}
76
[email protected]90d9f1e2013-01-16 02:46:4177void FaviconSource::StartDataRequest(
Wei-Yin Chen (陳威尹)39f4ff32019-10-22 17:59:0978 const GURL& url,
John Abd-El-Malek92bf3602019-07-31 02:25:4879 const content::WebContents::Getter& wc_getter,
danakjf4b9e942019-11-29 15:43:0480 content::URLDataSource::GotDataCallback callback) {
Wei-Yin Chen (陳威尹)39f4ff32019-10-22 17:59:0981 const std::string path = content::URLDataSource::URLToRequestPath(url);
hayatobe13e672015-03-31 04:51:3882 favicon::FaviconService* favicon_service =
83 FaviconServiceFactory::GetForProfile(profile_,
84 ServiceAccessType::EXPLICIT_ACCESS);
[email protected]89ba3862013-05-01 16:10:0985 if (!favicon_service) {
danakjf4b9e942019-11-29 15:43:0486 SendDefaultResponse(std::move(callback));
[email protected]b4ae88cc2011-10-26 04:26:5987 return;
[email protected]f84645222009-03-30 23:06:2788 }
[email protected]b4ae88cc2011-10-26 04:26:5989
[email protected]78dfe382013-07-17 18:05:4290 chrome::ParsedFaviconPath parsed;
Victor Hugo Vianna Silvaed441482019-06-27 12:40:4091 bool success = chrome::ParseFaviconPath(path, url_format_, &parsed);
[email protected]89ba3862013-05-01 16:10:0992 if (!success) {
danakjf4b9e942019-11-29 15:43:0493 SendDefaultResponse(std::move(callback));
[email protected]89ba3862013-05-01 16:10:0994 return;
[email protected]79eaee62013-01-22 22:33:4095 }
96
Victor Hugo Vianna Silva86363bfc2019-07-26 02:37:0597 GURL page_url(parsed.page_url);
98 GURL icon_url(parsed.icon_url);
99 if (!page_url.is_valid() && !icon_url.is_valid()) {
danakjf4b9e942019-11-29 15:43:04100 SendDefaultResponse(std::move(callback));
Dominick Ng4c85aa12018-01-09 02:39:13101 return;
102 }
103
[email protected]25244a932014-07-12 23:00:24104 int desired_size_in_pixel =
105 std::ceil(parsed.size_in_dip * parsed.device_scale_factor);
[email protected]78dfe382013-07-17 18:05:42106
Victor Hugo Vianna Silva86363bfc2019-07-26 02:37:05107 if (parsed.page_url.empty()) {
108 // Request by icon url.
109
[email protected]81883b02012-09-27 00:14:05110 // TODO(michaelbai): Change GetRawFavicon to support combination of
111 // IconType.
huangs5f6eca4c2015-01-27 17:47:22112 favicon_service->GetRawFavicon(
Victor Hugo Vianna Silva86363bfc2019-07-26 02:37:05113 icon_url, favicon_base::IconType::kFavicon, desired_size_in_pixel,
danakjf4b9e942019-11-29 15:43:04114 base::BindOnce(&FaviconSource::OnFaviconDataAvailable,
115 base::Unretained(this), std::move(callback),
116 parsed.size_in_dip, parsed.device_scale_factor),
[email protected]a55e85b2012-12-12 02:31:58117 &cancelable_task_tracker_);
[email protected]b4ae88cc2011-10-26 04:26:59118 } else {
sdefresne0da3bc02015-01-29 18:26:35119 // Intercept requests for prepopulated pages if TopSites exists.
120 scoped_refptr<history::TopSites> top_sites =
121 TopSitesFactory::GetForProfile(profile_);
122 if (top_sites) {
123 for (const auto& prepopulated_page : top_sites->GetPrepopulatedPages()) {
Victor Hugo Vianna Silva86363bfc2019-07-26 02:37:05124 if (page_url == prepopulated_page.most_visited.url) {
sdefresne0da3bc02015-01-29 18:26:35125 ui::ScaleFactor resource_scale_factor =
126 ui::GetSupportedScaleFactor(parsed.device_scale_factor);
danakjf4b9e942019-11-29 15:43:04127 std::move(callback).Run(
Lei Zhang7640d542017-10-03 16:26:49128 ui::ResourceBundle::GetSharedInstance()
129 .LoadDataResourceBytesForScale(prepopulated_page.favicon_id,
130 resource_scale_factor));
sdefresne0da3bc02015-01-29 18:26:35131 return;
132 }
[email protected]b4ae88cc2011-10-26 04:26:59133 }
134 }
Victor Hugo Vianna Silva1674fcbd2019-07-09 09:24:41135
Victor Hugo Vianna Silva9214a2292019-07-14 18:30:04136 favicon::HistoryUiFaviconRequestOrigin parsed_history_ui_origin;
Victor Hugo Vianna Silva55a7cd52019-07-14 17:34:23137 if (!parsed.allow_favicon_server_fallback ||
138 !ParseHistoryUiOrigin(GetUnsafeRequestOrigin(wc_getter),
139 &parsed_history_ui_origin)) {
Victor Hugo Vianna Silva1674fcbd2019-07-09 09:24:41140 // Request from local storage only.
141 // TODO(victorvianna): Expose fallback_to_host in FaviconRequestHandler
142 // API and move the explanatory comment for |fallback_to_host| here.
143 const bool fallback_to_host = true;
144 favicon_service->GetRawFaviconForPageURL(
Victor Hugo Vianna Silva86363bfc2019-07-26 02:37:05145 page_url, {favicon_base::IconType::kFavicon}, desired_size_in_pixel,
Victor Hugo Vianna Silva1674fcbd2019-07-09 09:24:41146 fallback_to_host,
danakjf4b9e942019-11-29 15:43:04147 base::BindOnce(&FaviconSource::OnFaviconDataAvailable,
148 base::Unretained(this), std::move(callback),
149 parsed.size_in_dip, parsed.device_scale_factor),
Victor Hugo Vianna Silva1674fcbd2019-07-09 09:24:41150 &cancelable_task_tracker_);
151 return;
152 }
153
154 // Request from both local storage and favicon server using
155 // HistoryUiFaviconRequestHandler.
Victor Hugo Vianna Silvadf127bfc2019-07-03 00:02:12156 favicon::HistoryUiFaviconRequestHandler*
157 history_ui_favicon_request_handler =
158 HistoryUiFaviconRequestHandlerFactory::GetForBrowserContext(
159 profile_);
160 if (!history_ui_favicon_request_handler) {
danakjf4b9e942019-11-29 15:43:04161 SendDefaultResponse(std::move(callback));
Victor Hugo Vianna Silva81d51242019-06-13 17:52:17162 return;
163 }
Victor Hugo Vianna Silvadf127bfc2019-07-03 00:02:12164 history_ui_favicon_request_handler->GetRawFaviconForPageURL(
Victor Hugo Vianna Silva86363bfc2019-07-26 02:37:05165 page_url, desired_size_in_pixel,
Victor Hugo Vianna Silvae7ba15a2019-06-04 21:04:15166 base::BindOnce(&FaviconSource::OnFaviconDataAvailable,
danakjf4b9e942019-11-29 15:43:04167 base::Unretained(this), std::move(callback),
168 parsed.size_in_dip, parsed.device_scale_factor),
Victor Hugo Vianna Silva64b38182019-07-20 21:19:59169 favicon::FaviconRequestPlatform::kDesktop, parsed_history_ui_origin,
Victor Hugo Vianna Silva6f1af5b2019-05-27 19:02:31170 /*icon_url_for_uma=*/
Victor Hugo Vianna Silva8d139662019-07-26 11:14:51171 GURL(parsed.icon_url), &cancelable_task_tracker_);
[email protected]b4ae88cc2011-10-26 04:26:59172 }
[email protected]f84645222009-03-30 23:06:27173}
174
Lucas Furukawa Gadani4b4eed02019-06-04 23:12:04175std::string FaviconSource::GetMimeType(const std::string&) {
[email protected]3071754432010-07-28 00:09:54176 // We need to explicitly return a mime type, otherwise if the user tries to
177 // drag the image they get no extension.
178 return "image/png";
179}
180
Lucas Furukawa Gadani4b4eed02019-06-04 23:12:04181bool FaviconSource::AllowCaching() {
treibc782ea52017-01-25 13:24:40182 return false;
183}
184
Lucas Furukawa Gadani4b4eed02019-06-04 23:12:04185bool FaviconSource::ShouldReplaceExistingSource() {
[email protected]ffe3d6f2011-02-23 16:42:52186 // Leave the existing DataSource in place, otherwise we'll drop any pending
187 // requests on the floor.
188 return false;
189}
190
jamcf6f7622017-05-03 22:16:28191bool FaviconSource::ShouldServiceRequest(
192 const GURL& url,
193 content::ResourceContext* resource_context,
Lucas Furukawa Gadani4b4eed02019-06-04 23:12:04194 int render_process_id) {
jamcf6f7622017-05-03 22:16:28195 if (url.SchemeIs(chrome::kChromeSearchScheme)) {
196 return InstantIOContext::ShouldServiceRequest(url, resource_context,
197 render_process_id);
198 }
199 return URLDataSource::ShouldServiceRequest(url, resource_context,
200 render_process_id);
[email protected]672c8c12013-03-07 12:30:06201}
202
Dan Beam75cd5b072019-02-23 01:04:46203ui::NativeTheme* FaviconSource::GetNativeTheme() {
204 return ui::NativeTheme::GetInstanceForNativeUi();
205}
206
[email protected]16835e62011-03-16 14:13:08207void FaviconSource::OnFaviconDataAvailable(
danakjf4b9e942019-11-29 15:43:04208 content::URLDataSource::GotDataCallback callback,
Victor Hugo Vianna Silva7be8d852019-07-22 09:15:41209 int size_in_dip,
210 float scale_factor,
[email protected]12b54c72014-06-14 00:38:48211 const favicon_base::FaviconRawBitmapResult& bitmap_result) {
[email protected]0ea3db52012-12-07 01:32:01212 if (bitmap_result.is_valid()) {
213 // Forward the data along to the networking system.
danakjf4b9e942019-11-29 15:43:04214 std::move(callback).Run(bitmap_result.bitmap_data.get());
Victor Hugo Vianna Silva969aca62019-04-23 11:28:34215 } else {
danakjf4b9e942019-11-29 15:43:04216 SendDefaultResponse(std::move(callback), size_in_dip, scale_factor);
[email protected]0ea3db52012-12-07 01:32:01217 }
218}
219
[email protected]79eaee62013-01-22 22:33:40220void FaviconSource::SendDefaultResponse(
danakjf4b9e942019-11-29 15:43:04221 content::URLDataSource::GotDataCallback callback) {
222 SendDefaultResponse(std::move(callback), 16, 1.0f);
[email protected]79eaee62013-01-22 22:33:40223}
224
Victor Hugo Vianna Silva7be8d852019-07-22 09:15:41225void FaviconSource::SendDefaultResponse(
danakjf4b9e942019-11-29 15:43:04226 content::URLDataSource::GotDataCallback callback,
Victor Hugo Vianna Silva7be8d852019-07-22 09:15:41227 int size_in_dip,
228 float scale_factor) {
minch1edd4d02019-08-05 19:10:56229 const bool dark = GetNativeTheme()->ShouldUseDarkColors();
[email protected]81883b02012-09-27 00:14:05230 int resource_id;
Victor Hugo Vianna Silva7be8d852019-07-22 09:15:41231 switch (size_in_dip) {
[email protected]81883b02012-09-27 00:14:05232 case 64:
Dan Beam75cd5b072019-02-23 01:04:46233 resource_id = dark ? IDR_DEFAULT_FAVICON_DARK_64 : IDR_DEFAULT_FAVICON_64;
[email protected]81883b02012-09-27 00:14:05234 break;
235 case 32:
Dan Beam75cd5b072019-02-23 01:04:46236 resource_id = dark ? IDR_DEFAULT_FAVICON_DARK_32 : IDR_DEFAULT_FAVICON_32;
[email protected]81883b02012-09-27 00:14:05237 break;
238 default:
Dan Beam75cd5b072019-02-23 01:04:46239 resource_id = dark ? IDR_DEFAULT_FAVICON_DARK : IDR_DEFAULT_FAVICON;
[email protected]81883b02012-09-27 00:14:05240 break;
[email protected]969894ab2010-08-29 00:35:01241 }
danakjf4b9e942019-11-29 15:43:04242 std::move(callback).Run(LoadIconBytes(scale_factor, resource_id));
Dan Beam75cd5b072019-02-23 01:04:46243}
[email protected]81883b02012-09-27 00:14:05244
Victor Hugo Vianna Silva7be8d852019-07-22 09:15:41245base::RefCountedMemory* FaviconSource::LoadIconBytes(float scale_factor,
Dan Beam75cd5b072019-02-23 01:04:46246 int resource_id) {
247 return ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
Victor Hugo Vianna Silva7be8d852019-07-22 09:15:41248 resource_id, ui::GetSupportedScaleFactor(scale_factor));
[email protected]969894ab2010-08-29 00:35:01249}