summaryrefslogtreecommitdiffstats
path: root/chrome/browser/ui/webui/large_icon_source.cc
blob: dfbcc1655a00ac9636703a4fcb1b99ba8e4ea7af (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/webui/large_icon_source.h"

#include <vector>

#include "base/memory/ref_counted_memory.h"
#include "chrome/browser/search/instant_io_context.h"
#include "chrome/common/favicon/large_icon_url_parser.h"
#include "chrome/common/url_constants.h"
#include "components/favicon/core/fallback_icon_service.h"
#include "components/favicon/core/large_icon_service.h"
#include "components/favicon_base/fallback_icon_style.h"
#include "components/favicon_base/favicon_types.h"
#include "net/url_request/url_request.h"

namespace {

const int kMaxLargeIconSize = 192;  // Arbitrary bound to safeguard endpoint.

}  // namespace

LargeIconSource::LargeIconSource(
    favicon::FallbackIconService* fallback_icon_service,
    favicon::LargeIconService* large_icon_service)
    : fallback_icon_service_(fallback_icon_service),
      large_icon_service_(large_icon_service) {
}

LargeIconSource::~LargeIconSource() {
}

std::string LargeIconSource::GetSource() const {
  return chrome::kChromeUILargeIconHost;
}

void LargeIconSource::StartDataRequest(
    const std::string& path,
    int render_process_id,
    int render_frame_id,
    const content::URLDataSource::GotDataCallback& callback) {
  if (!large_icon_service_) {
    SendNotFoundResponse(callback);
    return;
  }

  LargeIconUrlParser parser;
  bool success = parser.Parse(path);
  if (!success ||
      parser.size_in_pixels() <= 0 ||
      parser.size_in_pixels() > kMaxLargeIconSize) {
    SendNotFoundResponse(callback);
    return;
  }

  GURL url(parser.url_string());
  if (!url.is_valid()) {
    SendNotFoundResponse(callback);
    return;
  }

  // TODO(beaudoin): Potentially allow icon to be scaled up.
  large_icon_service_->GetLargeIconOrFallbackStyle(
      url,
      parser.size_in_pixels(),  // Reducing this will enable scale up.
      parser.size_in_pixels(),
      base::Bind(&LargeIconSource::OnLargeIconDataAvailable,
                 base::Unretained(this), callback, url,
                 parser.size_in_pixels()),
      &cancelable_task_tracker_);
}

std::string LargeIconSource::GetMimeType(const std::string&) const {
  // We need to explicitly return a mime type, otherwise if the user tries to
  // drag the image they get no extension.
  return "image/png";
}

bool LargeIconSource::ShouldReplaceExistingSource() const {
  // Leave the existing DataSource in place, otherwise we'll drop any pending
  // requests on the floor.
  return false;
}

bool LargeIconSource::ShouldServiceRequest(
    const net::URLRequest* request) const {
  if (request->url().SchemeIs(chrome::kChromeSearchScheme))
    return InstantIOContext::ShouldServiceRequest(request);
  return URLDataSource::ShouldServiceRequest(request);
}

void LargeIconSource::OnLargeIconDataAvailable(
    const content::URLDataSource::GotDataCallback& callback,
    const GURL& url,
    int size,
    const favicon_base::LargeIconResult& result) {
  if (result.bitmap.is_valid()) {
    callback.Run(result.bitmap.bitmap_data.get());
    return;
  }

  // Bitmap is invalid, use the fallback if service is available.
  if (!fallback_icon_service_ || !result.fallback_icon_style) {
    SendNotFoundResponse(callback);
    return;
  }
  std::vector<unsigned char> bitmap_data =
      fallback_icon_service_->RenderFallbackIconBitmap(
          url, size, *result.fallback_icon_style);
  callback.Run(base::RefCountedBytes::TakeVector(&bitmap_data));
}

void LargeIconSource::SendNotFoundResponse(
    const content::URLDataSource::GotDataCallback& callback) {
  callback.Run(nullptr);
}