favicon_source.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/webui/favicon_source.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h"
92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/favicon/favicon_service_factory.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/top_sites.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/search/instant_io_context.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/search/instant_service.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/search/instant_service_factory.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/locale_settings.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/ui_resources.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/url_request/url_request.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/layout.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h"
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/webui/web_ui_util.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Parameters which can be used in chrome://favicon path. See .h file for a
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// description of what each does.
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kIconURLParameter[] = "iconurl/";
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kLargestParameter[] = "largest/";
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kOriginParameter[] = "origin/";
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char kSizeParameter[] = "size/";
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns true if |search| is a substring of |path| which starts at
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// |start_index|.
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool HasSubstringAt(const std::string& path,
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    size_t start_index,
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    const std::string& search) {
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (search.empty())
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (start_index + search.size() >= path.size())
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return (path.compare(start_index, search.size(), search) == 0);
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FaviconSource::IconRequest::IconRequest()
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : size_in_dip(gfx::kFaviconSize),
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scale_factor(ui::SCALE_FACTOR_NONE) {
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FaviconSource::IconRequest::IconRequest(
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::URLDataSource::GotDataCallback& cb,
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& path,
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int size,
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ui::ScaleFactor scale)
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : callback(cb),
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      request_path(path),
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      size_in_dip(size),
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      scale_factor(scale) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FaviconSource::IconRequest::~IconRequest() {
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)FaviconSource::FaviconSource(Profile* profile, IconType type)
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : profile_(profile->GetOriginalProfile()),
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      icon_types_(type == FAVICON ? history::FAVICON :
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          history::TOUCH_PRECOMPOSED_ICON | history::TOUCH_ICON |
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          history::FAVICON) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)FaviconSource::~FaviconSource() {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string FaviconSource::GetSource() {
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return icon_types_ == history::FAVICON ?
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      chrome::kChromeUIFaviconHost : chrome::kChromeUITouchIconHost;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FaviconSource::StartDataRequest(
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& raw_path,
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool is_incognito,
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::URLDataSource::GotDataCallback& callback) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FaviconService* favicon_service =
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FaviconServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS);
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!favicon_service || raw_path.empty()) {
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SendDefaultResponse(callback);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Translate to regular path if |raw_path| is of the form
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // chrome-search://favicon/<most_visited_item_id>, where
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // "most_visited_item_id" is a uint64.
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string path = InstantService::MaybeTranslateInstantPathOnUI(profile_,
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                                   raw_path);
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK_EQ(16, gfx::kFaviconSize);
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int size_in_dip = 16;
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ui::ScaleFactor scale_factor = ui::SCALE_FACTOR_100P;
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t parsed_index = 0;
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (HasSubstringAt(path, parsed_index, kLargestParameter)) {
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    parsed_index += strlen(kLargestParameter);
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size_in_dip = 0;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (HasSubstringAt(path, parsed_index, kSizeParameter)) {
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    parsed_index += strlen(kSizeParameter);
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size_t scale_delimiter = path.find("@", parsed_index);
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (scale_delimiter == std::string::npos) {
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SendDefaultResponse(callback);
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string size = path.substr(parsed_index,
1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                   scale_delimiter - parsed_index);
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!base::StringToInt(size, &size_in_dip)) {
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SendDefaultResponse(callback);
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (size_in_dip != 64 && size_in_dip != 32) {
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Only 64x64, 32x32 and 16x16 icons are supported.
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      size_in_dip = 16;
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size_t slash = path.find("/", scale_delimiter);
1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (slash == std::string::npos) {
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SendDefaultResponse(callback);
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string scale_str = path.substr(scale_delimiter + 1,
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        slash - scale_delimiter - 1);
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    webui::ParseScaleFactor(scale_str, &scale_factor);
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Return the default favicon (as opposed to a resized favicon) for
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // favicon sizes which are not cached by the favicon service.
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Currently the favicon service caches:
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // - favicons of sizes "16 * scale factor" px of type FAVICON
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    //   where scale factor is one of FaviconUtil::GetFaviconScaleFactors().
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // - the largest TOUCH_ICON / TOUCH_PRECOMPOSED_ICON
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (size_in_dip != 16 && icon_types_ == history::FAVICON) {
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      SendDefaultResponse(callback);
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    parsed_index = slash + 1;
1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (HasSubstringAt(path, parsed_index, kIconURLParameter)) {
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    parsed_index += strlen(kIconURLParameter);
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(michaelbai): Change GetRawFavicon to support combination of
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // IconType.
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    favicon_service->GetRawFavicon(
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        GURL(path.substr(parsed_index)),
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        history::FAVICON,
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        size_in_dip,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        scale_factor,
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&FaviconSource::OnFaviconDataAvailable,
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   base::Unretained(this),
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   IconRequest(callback,
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               path.substr(parsed_index),
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               size_in_dip,
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               scale_factor)),
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &cancelable_task_tracker_);
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string url;
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // URL requests prefixed with "origin/" are converted to a form with an
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // empty path and a valid scheme. (e.g., example.com -->
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // http://example.com/ or http://example.com/a --> http://example.com/)
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (HasSubstringAt(path, parsed_index, kOriginParameter)) {
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      parsed_index += strlen(kOriginParameter);
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url = path.substr(parsed_index);
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // If the URL does not specify a scheme (e.g., example.com instead of
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // http://example.com), add "http://" as a default.
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!GURL(url).has_scheme())
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        url = "http://" + url;
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      // Strip the path beyond the top-level domain.
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url = GURL(url).GetOrigin().spec();
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      url = path.substr(parsed_index);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Intercept requests for prepopulated pages.
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < arraysize(history::kPrepopulatedPages); i++) {
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (url ==
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          l10n_util::GetStringUTF8(history::kPrepopulatedPages[i].url_id)) {
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        callback.Run(
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            ResourceBundle::GetSharedInstance().LoadDataResourceBytesForScale(
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                history::kPrepopulatedPages[i].favicon_id,
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                scale_factor));
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    favicon_service->GetRawFaviconForURL(
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FaviconService::FaviconForURLParams(
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            profile_, GURL(url), icon_types_, size_in_dip),
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        scale_factor,
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::Bind(&FaviconSource::OnFaviconDataAvailable,
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   base::Unretained(this),
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                   IconRequest(callback,
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               url,
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               size_in_dip,
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               scale_factor)),
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &cancelable_task_tracker_);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string FaviconSource::GetMimeType(const std::string&) const {
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We need to explicitly return a mime type, otherwise if the user tries to
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // drag the image they get no extension.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "image/png";
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool FaviconSource::ShouldReplaceExistingSource() const {
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Leave the existing DataSource in place, otherwise we'll drop any pending
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // requests on the floor.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool FaviconSource::ShouldServiceRequest(const net::URLRequest* request) const {
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (request->url().SchemeIs(chrome::kChromeSearchScheme)) {
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return InstantService::IsInstantPath(request->url()) &&
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        InstantIOContext::ShouldServiceRequest(request);
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return URLDataSource::ShouldServiceRequest(request);
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool FaviconSource::HandleMissingResource(const IconRequest& request) {
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // No additional checks to locate the favicon resource in the base
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // implementation.
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconSource::OnFaviconDataAvailable(
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const IconRequest& request,
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const history::FaviconBitmapResult& bitmap_result) {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bitmap_result.is_valid()) {
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Forward the data along to the networking system.
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    request.callback.Run(bitmap_result.bitmap_data);
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (!HandleMissingResource(request)) {
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SendDefaultResponse(request);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void FaviconSource::SendDefaultResponse(
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const content::URLDataSource::GotDataCallback& callback) {
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SendDefaultResponse(IconRequest(callback,
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  "",
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  16,
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                  ui::SCALE_FACTOR_100P));
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void FaviconSource::SendDefaultResponse(const IconRequest& icon_request) {
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int favicon_index;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int resource_id;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (icon_request.size_in_dip) {
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 64:
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      favicon_index = SIZE_64;
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      resource_id = IDR_DEFAULT_FAVICON_64;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 32:
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      favicon_index = SIZE_32;
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      resource_id = IDR_DEFAULT_FAVICON_32;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      favicon_index = SIZE_16;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      resource_id = IDR_DEFAULT_FAVICON;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::RefCountedMemory* default_favicon = default_favicons_[favicon_index];
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!default_favicon) {
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ui::ScaleFactor scale_factor = icon_request.scale_factor;
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default_favicon = ResourceBundle::GetSharedInstance()
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        .LoadDataResourceBytesForScale(resource_id, scale_factor);
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default_favicons_[favicon_index] = default_favicon;
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  icon_request.callback.Run(default_favicon);
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
290