favicon_source.cc revision ddb351dbec246cf1fab5ec20d2d5520909041de1
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
13FaviconSource::FaviconSource(Profile* profile)
14    : DataSource(chrome::kChromeUIFaviconHost, MessageLoop::current()),
15      profile_(profile->GetOriginalProfile()) {
16}
17
18FaviconSource::~FaviconSource() {
19}
20
21void 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
53std::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
59bool 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
65void 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
81void 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