Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(44)

Side by Side Diff: chrome/browser/ui/webui/favicon_source.cc

Issue 15388002: Supporting high dpi favicons in Instant Extended. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Sync and rebase Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/ui/webui/favicon_source.h" 5 #include "chrome/browser/ui/webui/favicon_source.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/strings/string_number_conversions.h" 9 #include "base/strings/string_number_conversions.h"
10 #include "chrome/browser/favicon/favicon_service_factory.h" 10 #include "chrome/browser/favicon/favicon_service_factory.h"
11 #include "chrome/browser/history/top_sites.h" 11 #include "chrome/browser/history/top_sites.h"
12 #include "chrome/browser/profiles/profile.h" 12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/search/instant_io_context.h" 13 #include "chrome/browser/search/instant_io_context.h"
14 #include "chrome/browser/search/instant_service.h" 14 #include "chrome/browser/search/instant_service.h"
15 #include "chrome/browser/search/instant_service_factory.h" 15 #include "chrome/browser/search/instant_service_factory.h"
16 #include "chrome/common/favicon/favicon_url_parser.h"
16 #include "chrome/common/url_constants.h" 17 #include "chrome/common/url_constants.h"
17 #include "grit/locale_settings.h" 18 #include "grit/locale_settings.h"
18 #include "grit/ui_resources.h" 19 #include "grit/ui_resources.h"
19 #include "net/url_request/url_request.h" 20 #include "net/url_request/url_request.h"
20 #include "ui/base/l10n/l10n_util.h" 21 #include "ui/base/l10n/l10n_util.h"
21 #include "ui/base/layout.h" 22 #include "ui/base/layout.h"
22 #include "ui/base/resource/resource_bundle.h" 23 #include "ui/base/resource/resource_bundle.h"
23 #include "ui/webui/web_ui_util.h" 24 #include "ui/webui/web_ui_util.h"
24 25
25 namespace {
26
27 // Parameters which can be used in chrome://favicon path. See .h file for a
28 // description of what each does.
29 const char kIconURLParameter[] = "iconurl/";
30 const char kLargestParameter[] = "largest/";
31 const char kOriginParameter[] = "origin/";
32 const char kSizeParameter[] = "size/";
33
34 // Returns true if |search| is a substring of |path| which starts at
35 // |start_index|.
36 bool HasSubstringAt(const std::string& path,
37 size_t start_index,
38 const std::string& search) {
39 if (search.empty())
40 return false;
41
42 if (start_index + search.size() >= path.size())
43 return false;
44
45 return (path.compare(start_index, search.size(), search) == 0);
46 }
47
48 } // namespace
49
50 FaviconSource::IconRequest::IconRequest() 26 FaviconSource::IconRequest::IconRequest()
51 : size_in_dip(gfx::kFaviconSize), 27 : size_in_dip(gfx::kFaviconSize),
52 scale_factor(ui::SCALE_FACTOR_NONE) { 28 scale_factor(ui::SCALE_FACTOR_NONE) {
53 } 29 }
54 30
55 FaviconSource::IconRequest::IconRequest( 31 FaviconSource::IconRequest::IconRequest(
56 const content::URLDataSource::GotDataCallback& cb, 32 const content::URLDataSource::GotDataCallback& cb,
57 const GURL& path, 33 const GURL& path,
58 int size, 34 int size,
59 ui::ScaleFactor scale) 35 ui::ScaleFactor scale)
(...skipping 26 matching lines...) Expand all
86 int render_process_id, 62 int render_process_id,
87 int render_view_id, 63 int render_view_id,
88 const content::URLDataSource::GotDataCallback& callback) { 64 const content::URLDataSource::GotDataCallback& callback) {
89 FaviconService* favicon_service = 65 FaviconService* favicon_service =
90 FaviconServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS); 66 FaviconServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS);
91 if (!favicon_service) { 67 if (!favicon_service) {
92 SendDefaultResponse(callback); 68 SendDefaultResponse(callback);
93 return; 69 return;
94 } 70 }
95 71
96 bool is_icon_url = false; 72 chrome::ParsedFaviconPath parsed;
97 GURL url; 73 bool success = chrome::ParseFaviconPath(path, icon_types_, &parsed);
98 int size_in_dip = 16;
99 ui::ScaleFactor scale_factor = ui::SCALE_FACTOR_100P;
100 bool success = ParsePath(path, &is_icon_url, &url, &size_in_dip,
101 &scale_factor);
102
103 if (!success) { 74 if (!success) {
104 SendDefaultResponse(callback); 75 SendDefaultResponse(callback);
105 return; 76 return;
106 } 77 }
107 78
108 if (is_icon_url) { 79 GURL url(parsed.url);
80
81 if (parsed.is_icon_url) {
109 // TODO(michaelbai): Change GetRawFavicon to support combination of 82 // TODO(michaelbai): Change GetRawFavicon to support combination of
110 // IconType. 83 // IconType.
111 favicon_service->GetRawFavicon( 84 favicon_service->GetRawFavicon(
112 url, 85 url,
113 chrome::FAVICON, 86 chrome::FAVICON,
114 size_in_dip, 87 parsed.size_in_dip,
115 scale_factor, 88 parsed.scale_factor,
116 base::Bind(&FaviconSource::OnFaviconDataAvailable, 89 base::Bind(&FaviconSource::OnFaviconDataAvailable,
117 base::Unretained(this), 90 base::Unretained(this),
118 IconRequest(callback, 91 IconRequest(callback,
119 url, 92 url,
120 size_in_dip, 93 parsed.size_in_dip,
121 scale_factor)), 94 parsed.scale_factor)),
122 &cancelable_task_tracker_); 95 &cancelable_task_tracker_);
123 } else { 96 } else {
124 // Intercept requests for prepopulated pages. 97 // Intercept requests for prepopulated pages.
125 for (size_t i = 0; i < arraysize(history::kPrepopulatedPages); i++) { 98 for (size_t i = 0; i < arraysize(history::kPrepopulatedPages); i++) {
126 if (url.spec() == 99 if (url.spec() ==
127 l10n_util::GetStringUTF8(history::kPrepopulatedPages[i].url_id)) { 100 l10n_util::GetStringUTF8(history::kPrepopulatedPages[i].url_id)) {
128 callback.Run( 101 callback.Run(
129 ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale( 102 ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
130 history::kPrepopulatedPages[i].favicon_id, 103 history::kPrepopulatedPages[i].favicon_id,
131 scale_factor)); 104 parsed.scale_factor));
132 return; 105 return;
133 } 106 }
134 } 107 }
135 108
136 favicon_service->GetRawFaviconForURL( 109 favicon_service->GetRawFaviconForURL(
137 FaviconService::FaviconForURLParams( 110 FaviconService::FaviconForURLParams(
138 profile_, url, icon_types_, size_in_dip), 111 profile_, url, icon_types_, parsed.size_in_dip),
139 scale_factor, 112 parsed.scale_factor,
140 base::Bind(&FaviconSource::OnFaviconDataAvailable, 113 base::Bind(&FaviconSource::OnFaviconDataAvailable,
141 base::Unretained(this), 114 base::Unretained(this),
142 IconRequest(callback, 115 IconRequest(callback,
143 url, 116 url,
144 size_in_dip, 117 parsed.size_in_dip,
145 scale_factor)), 118 parsed.scale_factor)),
146 &cancelable_task_tracker_); 119 &cancelable_task_tracker_);
147 } 120 }
148 } 121 }
149 122
150 std::string FaviconSource::GetMimeType(const std::string&) const { 123 std::string FaviconSource::GetMimeType(const std::string&) const {
151 // We need to explicitly return a mime type, otherwise if the user tries to 124 // We need to explicitly return a mime type, otherwise if the user tries to
152 // drag the image they get no extension. 125 // drag the image they get no extension.
153 return "image/png"; 126 return "image/png";
154 } 127 }
155 128
156 bool FaviconSource::ShouldReplaceExistingSource() const { 129 bool FaviconSource::ShouldReplaceExistingSource() const {
157 // Leave the existing DataSource in place, otherwise we'll drop any pending 130 // Leave the existing DataSource in place, otherwise we'll drop any pending
158 // requests on the floor. 131 // requests on the floor.
159 return false; 132 return false;
160 } 133 }
161 134
162 bool FaviconSource::ShouldServiceRequest(const net::URLRequest* request) const { 135 bool FaviconSource::ShouldServiceRequest(const net::URLRequest* request) const {
163 if (request->url().SchemeIs(chrome::kChromeSearchScheme)) 136 if (request->url().SchemeIs(chrome::kChromeSearchScheme))
164 return InstantIOContext::ShouldServiceRequest(request); 137 return InstantIOContext::ShouldServiceRequest(request);
165 return URLDataSource::ShouldServiceRequest(request); 138 return URLDataSource::ShouldServiceRequest(request);
166 } 139 }
167 140
168 bool FaviconSource::HandleMissingResource(const IconRequest& request) { 141 bool FaviconSource::HandleMissingResource(const IconRequest& request) {
169 // No additional checks to locate the favicon resource in the base 142 // No additional checks to locate the favicon resource in the base
170 // implementation. 143 // implementation.
171 return false; 144 return false;
172 } 145 }
173 146
174 bool FaviconSource::ParsePath(const std::string& path,
175 bool* is_icon_url,
176 GURL* url,
177 int* size_in_dip,
178 ui::ScaleFactor* scale_factor) const {
179 DCHECK_EQ(16, gfx::kFaviconSize);
180
181 *is_icon_url = false;
182 *url = GURL();
183 *size_in_dip = 16;
184 *scale_factor = ui::SCALE_FACTOR_100P;
185
186 if (path.empty())
187 return false;
188
189 size_t parsed_index = 0;
190 if (HasSubstringAt(path, parsed_index, kLargestParameter)) {
191 parsed_index += strlen(kLargestParameter);
192 *size_in_dip = 0;
193 } else if (HasSubstringAt(path, parsed_index, kSizeParameter)) {
194 parsed_index += strlen(kSizeParameter);
195
196 size_t slash = path.find("/", parsed_index);
197 if (slash == std::string::npos)
198 return false;
199
200 size_t scale_delimiter = path.find("@", parsed_index);
201 std::string size_str;
202 std::string scale_str;
203 if (scale_delimiter == std::string::npos) {
204 // Support the legacy size format of 'size/aa/' where 'aa' is the desired
205 // size in DIP for the sake of not regressing the extensions which use it.
206 size_str = path.substr(parsed_index, slash - parsed_index);
207 } else {
208 size_str = path.substr(parsed_index, scale_delimiter - parsed_index);
209 scale_str = path.substr(scale_delimiter + 1, slash - scale_delimiter - 1);
210 }
211
212 if (!base::StringToInt(size_str, size_in_dip))
213 return false;
214
215 if (*size_in_dip != 64 && *size_in_dip != 32) {
216 // Only 64x64, 32x32 and 16x16 icons are supported.
217 *size_in_dip = 16;
218 }
219
220 if (!scale_str.empty())
221 webui::ParseScaleFactor(scale_str, scale_factor);
222
223 // Return the default favicon (as opposed to a resized favicon) for
224 // favicon sizes which are not cached by the favicon service.
225 // Currently the favicon service caches:
226 // - favicons of sizes "16 * scale factor" px of type FAVICON
227 // where scale factor is one of FaviconUtil::GetFaviconScaleFactors().
228 // - the largest TOUCH_ICON / TOUCH_PRECOMPOSED_ICON
229 if (*size_in_dip != 16 && icon_types_ == chrome::FAVICON)
230 return false;
231
232 parsed_index = slash + 1;
233 }
234
235 if (HasSubstringAt(path, parsed_index, kIconURLParameter)) {
236 parsed_index += strlen(kIconURLParameter);
237 *is_icon_url = true;
238 *url = GURL(path.substr(parsed_index));
239 } else {
240 // URL requests prefixed with "origin/" are converted to a form with an
241 // empty path and a valid scheme. (e.g., example.com -->
242 // http://example.com/ or http://example.com/a --> http://example.com/)
243 if (HasSubstringAt(path, parsed_index, kOriginParameter)) {
244 parsed_index += strlen(kOriginParameter);
245 std::string possibly_invalid_url = path.substr(parsed_index);
246
247 // If the URL does not specify a scheme (e.g., example.com instead of
248 // http://example.com), add "http://" as a default.
249 if (!GURL(possibly_invalid_url).has_scheme())
250 possibly_invalid_url = "http://" + possibly_invalid_url;
251
252 // Strip the path beyond the top-level domain.
253 *url = GURL(possibly_invalid_url).GetOrigin();
254 } else {
255 *url = GURL(path.substr(parsed_index));
256 }
257 }
258 return true;
259 }
260
261 void FaviconSource::OnFaviconDataAvailable( 147 void FaviconSource::OnFaviconDataAvailable(
262 const IconRequest& request, 148 const IconRequest& request,
263 const chrome::FaviconBitmapResult& bitmap_result) { 149 const chrome::FaviconBitmapResult& bitmap_result) {
264 if (bitmap_result.is_valid()) { 150 if (bitmap_result.is_valid()) {
265 // Forward the data along to the networking system. 151 // Forward the data along to the networking system.
266 request.callback.Run(bitmap_result.bitmap_data.get()); 152 request.callback.Run(bitmap_result.bitmap_data.get());
267 } else if (!HandleMissingResource(request)) { 153 } else if (!HandleMissingResource(request)) {
268 SendDefaultResponse(request); 154 SendDefaultResponse(request);
269 } 155 }
270 } 156 }
(...skipping 26 matching lines...) Expand all
297 183
298 if (!default_favicon) { 184 if (!default_favicon) {
299 ui::ScaleFactor scale_factor = icon_request.scale_factor; 185 ui::ScaleFactor scale_factor = icon_request.scale_factor;
300 default_favicon = ResourceBundle::GetSharedInstance() 186 default_favicon = ResourceBundle::GetSharedInstance()
301 .LoadDataResourceBytesForScale(resource_id, scale_factor); 187 .LoadDataResourceBytesForScale(resource_id, scale_factor);
302 default_favicons_[favicon_index] = default_favicon; 188 default_favicons_[favicon_index] = default_favicon;
303 } 189 }
304 190
305 icon_request.callback.Run(default_favicon); 191 icon_request.callback.Run(default_favicon);
306 } 192 }
OLDNEW
« no previous file with comments | « chrome/browser/ui/webui/favicon_source.h ('k') | chrome/browser/ui/webui/favicon_source_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698