1 // Copyright (c) 2011 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.
4
5 #include "chrome/browser/ui/webui/favicon_source.h"
6
7 #include "base/callback.h"
8 #include "chrome/browser/profiles/profile.h"
9 #include "chrome/common/url_constants.h"
10 #include "grit/app_resources.h"
11 #include "ui/base/resource/resource_bundle.h"
12
FaviconSource(Profile * profile)13 FaviconSource::FaviconSource(Profile* profile)
14 : DataSource(chrome::kChromeUIFaviconHost, MessageLoop::current()),
15 profile_(profile->GetOriginalProfile()) {
16 }
17
~FaviconSource()18 FaviconSource::~FaviconSource() {
19 }
20
StartDataRequest(const std::string & path,bool is_incognito,int request_id)21 void FaviconSource::StartDataRequest(const std::string& path,
22 bool is_incognito,
23 int request_id) {
24 FaviconService* favicon_service =
25 profile_->GetFaviconService(Profile::EXPLICIT_ACCESS);
26 if (favicon_service) {
27 FaviconService::Handle handle;
28 if (path.empty()) {
29 SendDefaultResponse(request_id);
30 return;
31 }
32
33 if (path.size() > 8 && path.substr(0, 8) == "iconurl/") {
34 handle = favicon_service->GetFavicon(
35 GURL(path.substr(8)),
36 history::FAVICON,
37 &cancelable_consumer_,
38 NewCallback(this, &FaviconSource::OnFaviconDataAvailable));
39 } else {
40 handle = favicon_service->GetFaviconForURL(
41 GURL(path),
42 history::FAVICON,
43 &cancelable_consumer_,
44 NewCallback(this, &FaviconSource::OnFaviconDataAvailable));
45 }
46 // Attach the ChromeURLDataManager request ID to the history request.
47 cancelable_consumer_.SetClientData(favicon_service, handle, request_id);
48 } else {
49 SendResponse(request_id, NULL);
50 }
51 }
52
GetMimeType(const std::string &) const53 std::string FaviconSource::GetMimeType(const std::string&) const {
54 // We need to explicitly return a mime type, otherwise if the user tries to
55 // drag the image they get no extension.
56 return "image/png";
57 }
58
ShouldReplaceExistingSource() const59 bool FaviconSource::ShouldReplaceExistingSource() const {
60 // Leave the existing DataSource in place, otherwise we'll drop any pending
61 // requests on the floor.
62 return false;
63 }
64
OnFaviconDataAvailable(FaviconService::Handle request_handle,history::FaviconData favicon)65 void FaviconSource::OnFaviconDataAvailable(
66 FaviconService::Handle request_handle,
67 history::FaviconData favicon) {
68 FaviconService* favicon_service =
69 profile_->GetFaviconService(Profile::EXPLICIT_ACCESS);
70 int request_id = cancelable_consumer_.GetClientData(favicon_service,
71 request_handle);
72
73 if (favicon.is_valid()) {
74 // Forward the data along to the networking system.
75 SendResponse(request_id, favicon.image_data);
76 } else {
77 SendDefaultResponse(request_id);
78 }
79 }
80
SendDefaultResponse(int request_id)81 void FaviconSource::SendDefaultResponse(int request_id) {
82 if (!default_favicon_.get()) {
83 default_favicon_ =
84 ResourceBundle::GetSharedInstance().LoadDataResourceBytes(
85 IDR_DEFAULT_FAVICON);
86 }
87
88 SendResponse(request_id, default_favicon_);
89 }
90