Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(421)

Side by Side Diff: chrome/browser/manifest/manifest_icon_downloader.cc

Issue 2933743002: Move chrome/browser/manifest to content/browser. (Closed)
Patch Set: rebased Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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/manifest/manifest_icon_downloader.h"
6
7 #include <stddef.h>
8
9 #include <limits>
10
11 #include "chrome/browser/manifest/manifest_icon_selector.h"
12 #include "content/public/browser/browser_thread.h"
13 #include "content/public/browser/render_frame_host.h"
14 #include "content/public/browser/web_contents.h"
15 #include "content/public/browser/web_contents_observer.h"
16 #include "content/public/common/console_message_level.h"
17 #include "skia/ext/image_operations.h"
18
19 // DevToolsConsoleHelper is a class that holds a WebContents in order to be able
20 // to send a message to the WebContents' main frame. It is used so
21 // ManifestIconDownloader and the callers do not have to worry about
22 // |web_contents| lifetime. If the |web_contents| is invalidated before the
23 // message can be sent, the message will simply be ignored.
24 class ManifestIconDownloader::DevToolsConsoleHelper
25 : public content::WebContentsObserver {
26 public:
27 explicit DevToolsConsoleHelper(content::WebContents* web_contents);
28 ~DevToolsConsoleHelper() override = default;
29
30 void AddMessage(content::ConsoleMessageLevel level,
31 const std::string& message);
32 };
33
34 ManifestIconDownloader::DevToolsConsoleHelper::DevToolsConsoleHelper(
35 content::WebContents* web_contents)
36 : WebContentsObserver(web_contents) {
37 }
38
39 void ManifestIconDownloader::DevToolsConsoleHelper::AddMessage(
40 content::ConsoleMessageLevel level,
41 const std::string& message) {
42 if (!web_contents())
43 return;
44 web_contents()->GetMainFrame()->AddMessageToConsole(level, message);
45 }
46
47 bool ManifestIconDownloader::Download(
48 content::WebContents* web_contents,
49 const GURL& icon_url,
50 int ideal_icon_size_in_px,
51 int minimum_icon_size_in_px,
52 const ManifestIconDownloader::IconFetchCallback& callback) {
53 DCHECK(minimum_icon_size_in_px <= ideal_icon_size_in_px);
54 if (!web_contents || !icon_url.is_valid())
55 return false;
56
57 web_contents->DownloadImage(
58 icon_url,
59 false, // is_favicon
60 0, // max_bitmap_size - 0 means no maximum size.
61 false, // bypass_cache
62 base::Bind(&ManifestIconDownloader::OnIconFetched,
63 ideal_icon_size_in_px,
64 minimum_icon_size_in_px,
65 base::Owned(new DevToolsConsoleHelper(web_contents)),
66 callback));
67 return true;
68 }
69
70 void ManifestIconDownloader::OnIconFetched(
71 int ideal_icon_size_in_px,
72 int minimum_icon_size_in_px,
73 DevToolsConsoleHelper* console_helper,
74 const ManifestIconDownloader::IconFetchCallback& callback,
75 int id,
76 int http_status_code,
77 const GURL& url,
78 const std::vector<SkBitmap>& bitmaps,
79 const std::vector<gfx::Size>& sizes) {
80 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
81
82 if (bitmaps.empty()) {
83 console_helper->AddMessage(
84 content::CONSOLE_MESSAGE_LEVEL_ERROR,
85 "Error while trying to use the following icon from the Manifest: "
86 + url.spec() + " (Download error or resource isn't a valid image)");
87
88 callback.Run(SkBitmap());
89 return;
90 }
91
92 const int closest_index = FindClosestBitmapIndex(
93 ideal_icon_size_in_px, minimum_icon_size_in_px, bitmaps);
94
95 if (closest_index == -1) {
96 console_helper->AddMessage(
97 content::CONSOLE_MESSAGE_LEVEL_ERROR,
98 "Error while trying to use the following icon from the Manifest: "
99 + url.spec()
100 + " (Resource size is not correct - typo in the Manifest?)");
101
102 callback.Run(SkBitmap());
103 return;
104 }
105
106 const SkBitmap& chosen = bitmaps[closest_index];
107
108 // Only scale if we need to scale down. For scaling up we will let the system
109 // handle that when it is required to display it. This saves space in the
110 // webapp storage system as well.
111 if (chosen.height() > ideal_icon_size_in_px ||
112 chosen.width() > ideal_icon_size_in_px) {
113 content::BrowserThread::PostTask(
114 content::BrowserThread::IO, FROM_HERE,
115 base::BindOnce(&ManifestIconDownloader::ScaleIcon,
116 ideal_icon_size_in_px, chosen, callback));
117 return;
118 }
119
120 callback.Run(chosen);
121 }
122
123 void ManifestIconDownloader::ScaleIcon(
124 int ideal_icon_size_in_px,
125 const SkBitmap& bitmap,
126 const ManifestIconDownloader::IconFetchCallback& callback) {
127 DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
128
129 const SkBitmap& scaled = skia::ImageOperations::Resize(
130 bitmap,
131 skia::ImageOperations::RESIZE_BEST,
132 ideal_icon_size_in_px,
133 ideal_icon_size_in_px);
134
135 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
136 base::BindOnce(callback, scaled));
137 }
138
139 int ManifestIconDownloader::FindClosestBitmapIndex(
140 int ideal_icon_size_in_px,
141 int minimum_icon_size_in_px,
142 const std::vector<SkBitmap>& bitmaps) {
143 int best_index = -1;
144 int best_delta = std::numeric_limits<int>::min();
145 const int max_negative_delta =
146 minimum_icon_size_in_px - ideal_icon_size_in_px;
147
148 for (size_t i = 0; i < bitmaps.size(); ++i) {
149 if (bitmaps[i].height() != bitmaps[i].width())
150 continue;
151
152 int delta = bitmaps[i].width() - ideal_icon_size_in_px;
153 if (delta == 0)
154 return i;
155
156 if (best_delta > 0 && delta < 0)
157 continue;
158
159 if ((best_delta > 0 && delta < best_delta) ||
160 (best_delta < 0 && delta > best_delta && delta >= max_negative_delta)) {
161 best_index = i;
162 best_delta = delta;
163 }
164 }
165
166 if (best_index != -1)
167 return best_index;
168
169 // There was no square icon of a correct size found. Try to find the most
170 // square-like icon which has both dimensions greater than the minimum size.
171 float best_ratio_difference = std::numeric_limits<float>::infinity();
172 for (size_t i = 0; i < bitmaps.size(); ++i) {
173 if (bitmaps[i].height() < minimum_icon_size_in_px ||
174 bitmaps[i].width() < minimum_icon_size_in_px) {
175 continue;
176 }
177
178 float height = static_cast<float>(bitmaps[i].height());
179 float width = static_cast<float>(bitmaps[i].width());
180 float ratio = height / width;
181 float ratio_difference = fabs(ratio - 1);
182 if (ratio_difference < best_ratio_difference) {
183 best_index = i;
184 best_ratio_difference = ratio_difference;
185 }
186 }
187
188 return best_index;
189 }
OLDNEW
« no previous file with comments | « chrome/browser/manifest/manifest_icon_downloader.h ('k') | chrome/browser/manifest/manifest_icon_downloader_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698