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
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/webui/favicon_source.h"
8 #include "base/bind_helpers.h"
9 #include "base/strings/string_number_conversions.h"
10 #include "chrome/browser/favicon/favicon_service_factory.h"
11 #include "chrome/browser/history/top_sites.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/search/instant_io_context.h"
14 #include "chrome/browser/sync/open_tabs_ui_delegate.h"
15 #include "chrome/browser/sync/profile_sync_service.h"
16 #include "chrome/browser/sync/profile_sync_service_factory.h"
17 #include "chrome/common/favicon/favicon_url_parser.h"
18 #include "chrome/common/url_constants.h"
19 #include "grit/locale_settings.h"
20 #include "grit/ui_resources.h"
21 #include "net/url_request/url_request.h"
22 #include "ui/base/l10n/l10n_util.h"
23 #include "ui/base/layout.h"
24 #include "ui/base/resource/resource_bundle.h"
25 #include "ui/base/webui/web_ui_util.h"
27 FaviconSource::IconRequest::IconRequest()
28 : size_in_dip(gfx::kFaviconSize
),
29 scale_factor(ui::SCALE_FACTOR_NONE
) {
32 FaviconSource::IconRequest::IconRequest(
33 const content::URLDataSource::GotDataCallback
& cb
,
36 ui::ScaleFactor scale
)
43 FaviconSource::IconRequest::~IconRequest() {
46 FaviconSource::FaviconSource(Profile
* profile
, IconType type
)
47 : profile_(profile
->GetOriginalProfile()),
48 icon_types_(type
== FAVICON
? chrome::FAVICON
:
49 chrome::TOUCH_PRECOMPOSED_ICON
| chrome::TOUCH_ICON
|
53 FaviconSource::~FaviconSource() {
56 std::string
FaviconSource::GetSource() const {
57 return icon_types_
== chrome::FAVICON
?
58 chrome::kChromeUIFaviconHost
: chrome::kChromeUITouchIconHost
;
61 void FaviconSource::StartDataRequest(
62 const std::string
& path
,
63 int render_process_id
,
65 const content::URLDataSource::GotDataCallback
& callback
) {
66 FaviconService
* favicon_service
=
67 FaviconServiceFactory::GetForProfile(profile_
, Profile::EXPLICIT_ACCESS
);
68 if (!favicon_service
) {
69 SendDefaultResponse(callback
);
73 chrome::ParsedFaviconPath parsed
;
74 bool success
= chrome::ParseFaviconPath(path
, icon_types_
, &parsed
);
76 SendDefaultResponse(callback
);
82 if (parsed
.is_icon_url
) {
83 // TODO(michaelbai): Change GetRawFavicon to support combination of
85 favicon_service
->GetRawFavicon(
90 base::Bind(&FaviconSource::OnFaviconDataAvailable
,
91 base::Unretained(this),
95 parsed
.scale_factor
)),
96 &cancelable_task_tracker_
);
98 // Intercept requests for prepopulated pages.
99 for (size_t i
= 0; i
< arraysize(history::kPrepopulatedPages
); i
++) {
101 l10n_util::GetStringUTF8(history::kPrepopulatedPages
[i
].url_id
)) {
103 ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
104 history::kPrepopulatedPages
[i
].favicon_id
,
105 parsed
.scale_factor
));
110 favicon_service
->GetRawFaviconForURL(
111 FaviconService::FaviconForURLParams(url
, icon_types_
,
114 base::Bind(&FaviconSource::OnFaviconDataAvailable
,
115 base::Unretained(this),
116 IconRequest(callback
,
119 parsed
.scale_factor
)),
120 &cancelable_task_tracker_
);
124 std::string
FaviconSource::GetMimeType(const std::string
&) const {
125 // We need to explicitly return a mime type, otherwise if the user tries to
126 // drag the image they get no extension.
130 bool FaviconSource::ShouldReplaceExistingSource() const {
131 // Leave the existing DataSource in place, otherwise we'll drop any pending
132 // requests on the floor.
136 bool FaviconSource::ShouldServiceRequest(const net::URLRequest
* request
) const {
137 if (request
->url().SchemeIs(chrome::kChromeSearchScheme
))
138 return InstantIOContext::ShouldServiceRequest(request
);
139 return URLDataSource::ShouldServiceRequest(request
);
142 bool FaviconSource::HandleMissingResource(const IconRequest
& request
) {
143 // If the favicon is not available, try to use the synced favicon.
144 ProfileSyncService
* sync_service
=
145 ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile_
);
146 browser_sync::OpenTabsUIDelegate
* open_tabs
= sync_service
?
147 sync_service
->GetOpenTabsUIDelegate() : NULL
;
149 scoped_refptr
<base::RefCountedMemory
> response
;
151 open_tabs
->GetSyncedFaviconForPageURL(request
.request_path
.spec(),
153 request
.callback
.Run(response
.get());
159 void FaviconSource::OnFaviconDataAvailable(
160 const IconRequest
& request
,
161 const chrome::FaviconBitmapResult
& bitmap_result
) {
162 if (bitmap_result
.is_valid()) {
163 // Forward the data along to the networking system.
164 request
.callback
.Run(bitmap_result
.bitmap_data
.get());
165 } else if (!HandleMissingResource(request
)) {
166 SendDefaultResponse(request
);
170 void FaviconSource::SendDefaultResponse(
171 const content::URLDataSource::GotDataCallback
& callback
) {
173 IconRequest(callback
, GURL(), 16, ui::SCALE_FACTOR_100P
));
176 void FaviconSource::SendDefaultResponse(const IconRequest
& icon_request
) {
179 switch (icon_request
.size_in_dip
) {
181 favicon_index
= SIZE_64
;
182 resource_id
= IDR_DEFAULT_FAVICON_64
;
185 favicon_index
= SIZE_32
;
186 resource_id
= IDR_DEFAULT_FAVICON_32
;
189 favicon_index
= SIZE_16
;
190 resource_id
= IDR_DEFAULT_FAVICON
;
193 base::RefCountedMemory
* default_favicon
=
194 default_favicons_
[favicon_index
].get();
196 if (!default_favicon
) {
197 ui::ScaleFactor scale_factor
= icon_request
.scale_factor
;
198 default_favicon
= ResourceBundle::GetSharedInstance()
199 .LoadDataResourceBytesForScale(resource_id
, scale_factor
);
200 default_favicons_
[favicon_index
] = default_favicon
;
203 icon_request
.callback
.Run(default_favicon
);