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

Side by Side Diff: chrome/browser/extensions/bookmark_app_helper.cc

Issue 1066623008: Sync bookmark app icon urls and sizes, and download icons for new apps. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Feedback Created 5 years, 7 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
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/extensions/bookmark_app_helper.h" 5 #include "chrome/browser/extensions/bookmark_app_helper.h"
6 6
7 #include <cctype> 7 #include <cctype>
8 8
9 #include "base/prefs/pref_service.h" 9 #include "base/prefs/pref_service.h"
10 #include "base/strings/utf_string_conversions.h" 10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher.h"
12 #include "chrome/browser/bitmap_fetcher/bitmap_fetcher_delegate.h"
11 #include "chrome/browser/chrome_notification_types.h" 13 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/extensions/crx_installer.h" 14 #include "chrome/browser/extensions/crx_installer.h"
13 #include "chrome/browser/extensions/extension_service.h" 15 #include "chrome/browser/extensions/extension_service.h"
14 #include "chrome/browser/extensions/favicon_downloader.h" 16 #include "chrome/browser/extensions/favicon_downloader.h"
15 #include "chrome/browser/extensions/launch_util.h" 17 #include "chrome/browser/extensions/launch_util.h"
16 #include "chrome/browser/extensions/tab_helper.h" 18 #include "chrome/browser/extensions/tab_helper.h"
17 #include "chrome/browser/profiles/profile.h" 19 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/app_list/app_list_service.h" 20 #include "chrome/browser/ui/app_list/app_list_service.h"
19 #include "chrome/browser/ui/app_list/app_list_util.h" 21 #include "chrome/browser/ui/app_list/app_list_util.h"
20 #include "chrome/browser/ui/browser_finder.h" 22 #include "chrome/browser/ui/browser_finder.h"
21 #include "chrome/browser/ui/browser_window.h" 23 #include "chrome/browser/ui/browser_window.h"
22 #include "chrome/browser/ui/host_desktop.h" 24 #include "chrome/browser/ui/host_desktop.h"
23 #include "chrome/browser/web_applications/web_app.h" 25 #include "chrome/browser/web_applications/web_app.h"
24 #include "chrome/common/extensions/extension_constants.h" 26 #include "chrome/common/extensions/extension_constants.h"
25 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" 27 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
26 #include "chrome/common/url_constants.h" 28 #include "chrome/common/url_constants.h"
27 #include "content/public/browser/notification_service.h" 29 #include "content/public/browser/notification_service.h"
28 #include "content/public/browser/notification_source.h" 30 #include "content/public/browser/notification_source.h"
29 #include "content/public/browser/web_contents.h" 31 #include "content/public/browser/web_contents.h"
30 #include "extensions/browser/extension_system.h" 32 #include "extensions/browser/extension_system.h"
31 #include "extensions/browser/image_loader.h" 33 #include "extensions/browser/image_loader.h"
32 #include "extensions/browser/notification_types.h" 34 #include "extensions/browser/notification_types.h"
33 #include "extensions/browser/pref_names.h" 35 #include "extensions/browser/pref_names.h"
34 #include "extensions/common/constants.h" 36 #include "extensions/common/constants.h"
35 #include "extensions/common/extension.h" 37 #include "extensions/common/extension.h"
36 #include "extensions/common/manifest_handlers/icons_handler.h" 38 #include "extensions/common/manifest_handlers/icons_handler.h"
37 #include "extensions/common/url_pattern.h" 39 #include "extensions/common/url_pattern.h"
38 #include "grit/platform_locale_settings.h" 40 #include "grit/platform_locale_settings.h"
41 #include "net/base/load_flags.h"
39 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" 42 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
43 #include "net/url_request/url_request.h"
40 #include "skia/ext/image_operations.h" 44 #include "skia/ext/image_operations.h"
41 #include "skia/ext/platform_canvas.h" 45 #include "skia/ext/platform_canvas.h"
42 #include "third_party/skia/include/core/SkBitmap.h" 46 #include "third_party/skia/include/core/SkBitmap.h"
43 #include "ui/base/l10n/l10n_util.h" 47 #include "ui/base/l10n/l10n_util.h"
44 #include "ui/gfx/canvas.h" 48 #include "ui/gfx/canvas.h"
45 #include "ui/gfx/color_analysis.h" 49 #include "ui/gfx/color_analysis.h"
46 #include "ui/gfx/color_utils.h" 50 #include "ui/gfx/color_utils.h"
47 #include "ui/gfx/font.h" 51 #include "ui/gfx/font.h"
48 #include "ui/gfx/font_list.h" 52 #include "ui/gfx/font_list.h"
49 #include "ui/gfx/geometry/rect.h" 53 #include "ui/gfx/geometry/rect.h"
50 #include "ui/gfx/image/canvas_image_source.h" 54 #include "ui/gfx/image/canvas_image_source.h"
51 #include "ui/gfx/image/image.h" 55 #include "ui/gfx/image/image.h"
52 #include "ui/gfx/image/image_family.h" 56 #include "ui/gfx/image/image_family.h"
53 57
54 #if defined(OS_MACOSX) 58 #if defined(OS_MACOSX)
55 #include "base/command_line.h" 59 #include "base/command_line.h"
56 #include "chrome/browser/web_applications/web_app_mac.h" 60 #include "chrome/browser/web_applications/web_app_mac.h"
57 #include "chrome/common/chrome_switches.h" 61 #include "chrome/common/chrome_switches.h"
58 #endif 62 #endif
59 63
60 #if defined(USE_ASH) 64 #if defined(USE_ASH)
61 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" 65 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
62 #endif 66 #endif
63 67
64 namespace { 68 namespace {
65 69
70 using extensions::BookmarkAppHelper;
71
66 // Overlays a shortcut icon over the bottom left corner of a given image. 72 // Overlays a shortcut icon over the bottom left corner of a given image.
67 class GeneratedIconImageSource : public gfx::CanvasImageSource { 73 class GeneratedIconImageSource : public gfx::CanvasImageSource {
68 public: 74 public:
69 explicit GeneratedIconImageSource(char letter, SkColor color, int output_size) 75 explicit GeneratedIconImageSource(char letter, SkColor color, int output_size)
70 : gfx::CanvasImageSource(gfx::Size(output_size, output_size), false), 76 : gfx::CanvasImageSource(gfx::Size(output_size, output_size), false),
71 letter_(letter), 77 letter_(letter),
72 color_(color), 78 color_(color),
73 output_size_(output_size) {} 79 output_size_(output_size) {}
74 ~GeneratedIconImageSource() override {} 80 ~GeneratedIconImageSource() override {}
75 81
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
139 // Generate container icons from smaller icons. 145 // Generate container icons from smaller icons.
140 const int kIconSizesToGenerate[] = { 146 const int kIconSizesToGenerate[] = {
141 extension_misc::EXTENSION_ICON_SMALL, 147 extension_misc::EXTENSION_ICON_SMALL,
142 extension_misc::EXTENSION_ICON_MEDIUM, 148 extension_misc::EXTENSION_ICON_MEDIUM,
143 extension_misc::EXTENSION_ICON_LARGE, 149 extension_misc::EXTENSION_ICON_LARGE,
144 }; 150 };
145 return std::set<int>(kIconSizesToGenerate, 151 return std::set<int>(kIconSizesToGenerate,
146 kIconSizesToGenerate + arraysize(kIconSizesToGenerate)); 152 kIconSizesToGenerate + arraysize(kIconSizesToGenerate));
147 } 153 }
148 154
149 void GenerateIcons(std::set<int> generate_sizes, 155 void GenerateIcons(
150 const GURL& app_url, 156 std::set<int> generate_sizes,
151 SkColor generated_icon_color, 157 const GURL& app_url,
152 std::map<int, SkBitmap>* bitmap_map) { 158 SkColor generated_icon_color,
159 std::map<int, BookmarkAppHelper::BitmapAndSource>* bitmap_map) {
153 // The letter that will be painted on the generated icon. 160 // The letter that will be painted on the generated icon.
154 char icon_letter = ' '; 161 char icon_letter = ' ';
155 std::string domain_and_registry( 162 std::string domain_and_registry(
156 net::registry_controlled_domains::GetDomainAndRegistry( 163 net::registry_controlled_domains::GetDomainAndRegistry(
157 app_url, 164 app_url,
158 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES)); 165 net::registry_controlled_domains::INCLUDE_PRIVATE_REGISTRIES));
159 if (!domain_and_registry.empty()) { 166 if (!domain_and_registry.empty()) {
160 icon_letter = domain_and_registry[0]; 167 icon_letter = domain_and_registry[0];
161 } else if (!app_url.host().empty()) { 168 } else if (!app_url.host().empty()) {
162 icon_letter = app_url.host()[0]; 169 icon_letter = app_url.host()[0];
163 } 170 }
164 171
165 // If no color has been specified, use a dark gray so it will stand out on the 172 // If no color has been specified, use a dark gray so it will stand out on the
166 // black shelf. 173 // black shelf.
167 if (generated_icon_color == SK_ColorTRANSPARENT) 174 if (generated_icon_color == SK_ColorTRANSPARENT)
168 generated_icon_color = SK_ColorDKGRAY; 175 generated_icon_color = SK_ColorDKGRAY;
169 176
170 for (std::set<int>::const_iterator it = generate_sizes.begin(); 177 for (std::set<int>::const_iterator it = generate_sizes.begin();
171 it != generate_sizes.end(); ++it) { 178 it != generate_sizes.end(); ++it) {
172 extensions::BookmarkAppHelper::GenerateIcon( 179 extensions::BookmarkAppHelper::GenerateIcon(
173 bitmap_map, *it, generated_icon_color, icon_letter); 180 bitmap_map, *it, generated_icon_color, icon_letter);
174 // Also generate the 2x resource for this size. 181 // Also generate the 2x resource for this size.
175 extensions::BookmarkAppHelper::GenerateIcon( 182 extensions::BookmarkAppHelper::GenerateIcon(
176 bitmap_map, *it * 2, generated_icon_color, icon_letter); 183 bitmap_map, *it * 2, generated_icon_color, icon_letter);
177 } 184 }
178 } 185 }
179 186
180 void ReplaceWebAppIcons(std::map<int, SkBitmap> bitmap_map, 187 void ReplaceWebAppIcons(
181 WebApplicationInfo* web_app_info) { 188 std::map<int, BookmarkAppHelper::BitmapAndSource> bitmap_map,
189 WebApplicationInfo* web_app_info) {
182 web_app_info->icons.clear(); 190 web_app_info->icons.clear();
183 191
184 // Populate the icon data into the WebApplicationInfo we are using to 192 // Populate the icon data into the WebApplicationInfo we are using to
185 // install the bookmark app. 193 // install the bookmark app.
186 for (std::map<int, SkBitmap>::const_iterator bitmap_map_it = 194 for (const auto& pair : bitmap_map) {
187 bitmap_map.begin();
188 bitmap_map_it != bitmap_map.end(); ++bitmap_map_it) {
189 WebApplicationInfo::IconInfo icon_info; 195 WebApplicationInfo::IconInfo icon_info;
190 icon_info.data = bitmap_map_it->second; 196 icon_info.data = pair.second.bitmap;
197 icon_info.url = pair.second.source_url;
191 icon_info.width = icon_info.data.width(); 198 icon_info.width = icon_info.data.width();
192 icon_info.height = icon_info.data.height(); 199 icon_info.height = icon_info.data.height();
193 web_app_info->icons.push_back(icon_info); 200 web_app_info->icons.push_back(icon_info);
194 } 201 }
195 } 202 }
196 203
204 // Class to handle installing a bookmark app. Handles downloading and decoding
205 // the icons.
206 class BookmarkAppInstaller : public base::RefCounted<BookmarkAppInstaller>,
207 public chrome::BitmapFetcherDelegate {
208 public:
209 BookmarkAppInstaller(ExtensionService* service,
210 const WebApplicationInfo& web_app_info)
211 : service_(service), web_app_info_(web_app_info) {}
212
213 void Run() {
214 for (const auto& icon : web_app_info_.icons) {
215 if (icon.url.is_valid())
216 urls_to_download_.push_back(icon.url);
217 }
218
219 if (urls_to_download_.size()) {
220 DownloadNextImage();
221
222 // Matched in OnFetchComplete.
223 AddRef();
224 return;
225 }
226
227 FinishInstallation();
228 }
229
230 private:
231 friend class base::RefCounted<BookmarkAppInstaller>;
232 ~BookmarkAppInstaller() override {}
233
234 // BitmapFetcherDelegate:
235 void OnFetchComplete(const GURL& url, const SkBitmap* bitmap) override {
236 if (bitmap && !bitmap->empty() && bitmap->width() == bitmap->height()) {
237 downloaded_bitmaps_.push_back(
238 BookmarkAppHelper::BitmapAndSource(url, *bitmap));
239 }
240
241 if (urls_to_download_.size()) {
242 DownloadNextImage();
243 return;
244 }
245
246 FinishInstallation();
247 Release();
248 }
249
250 void DownloadNextImage() {
251 DCHECK(urls_to_download_.size());
252
253 bitmap_fetcher_.reset(
254 new chrome::BitmapFetcher(urls_to_download_.back(), this));
255 urls_to_download_.pop_back();
256 bitmap_fetcher_->Start(
257 service_->profile()->GetRequestContext(), std::string(),
258 net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
259 net::LOAD_DO_NOT_SAVE_COOKIES | net::LOAD_DO_NOT_SEND_COOKIES);
260 }
261
262 void FinishInstallation() {
263 std::map<int, BookmarkAppHelper::BitmapAndSource> size_map =
264 BookmarkAppHelper::ResizeIconsAndGenerateMissing(downloaded_bitmaps_,
265 &web_app_info_);
266 BookmarkAppHelper::UpdateWebAppIconsWithoutChangingLinks(size_map,
267 &web_app_info_);
268 scoped_refptr<extensions::CrxInstaller> installer(
269 extensions::CrxInstaller::CreateSilent(service_));
270 installer->set_error_on_unsupported_requirements(true);
271 installer->InstallWebApp(web_app_info_);
272 }
273
274 ExtensionService* service_;
275 WebApplicationInfo web_app_info_;
276
277 scoped_ptr<chrome::BitmapFetcher> bitmap_fetcher_;
278 std::vector<GURL> urls_to_download_;
279 std::vector<BookmarkAppHelper::BitmapAndSource> downloaded_bitmaps_;
280 };
281
197 } // namespace 282 } // namespace
198 283
199 namespace extensions { 284 namespace extensions {
200 285
201 // static 286 // static
202 void BookmarkAppHelper::UpdateWebAppInfoFromManifest( 287 void BookmarkAppHelper::UpdateWebAppInfoFromManifest(
203 const content::Manifest& manifest, 288 const content::Manifest& manifest,
204 WebApplicationInfo* web_app_info) { 289 WebApplicationInfo* web_app_info) {
205 if (!manifest.short_name.is_null()) 290 if (!manifest.short_name.is_null())
206 web_app_info->title = manifest.short_name.string(); 291 web_app_info->title = manifest.short_name.string();
(...skipping 13 matching lines...) Expand all
220 for (const auto& icon : manifest.icons) { 305 for (const auto& icon : manifest.icons) {
221 // TODO(benwells): Take the declared icon density and sizes into account. 306 // TODO(benwells): Take the declared icon density and sizes into account.
222 WebApplicationInfo::IconInfo info; 307 WebApplicationInfo::IconInfo info;
223 info.url = icon.src; 308 info.url = icon.src;
224 web_app_info->icons.push_back(info); 309 web_app_info->icons.push_back(info);
225 } 310 }
226 } 311 }
227 } 312 }
228 313
229 // static 314 // static
230 void BookmarkAppHelper::GenerateIcon(std::map<int, SkBitmap>* bitmaps, 315 std::map<int, BookmarkAppHelper::BitmapAndSource>
231 int output_size, 316 BookmarkAppHelper::ConstrainBitmapsToSizes(
232 SkColor color, 317 const std::vector<BookmarkAppHelper::BitmapAndSource>& bitmaps,
233 char letter) { 318 const std::set<int>& sizes) {
319 std::map<int, BitmapAndSource> output_bitmaps;
320 std::map<int, BitmapAndSource> ordered_bitmaps;
321 for (std::vector<BitmapAndSource>::const_iterator it = bitmaps.begin();
322 it != bitmaps.end(); ++it) {
323 DCHECK(it->bitmap.width() == it->bitmap.height());
324 ordered_bitmaps[it->bitmap.width()] = *it;
325 }
326
327 std::set<int>::const_iterator sizes_it = sizes.begin();
328 std::map<int, BitmapAndSource>::const_iterator bitmaps_it =
329 ordered_bitmaps.begin();
330 while (sizes_it != sizes.end() && bitmaps_it != ordered_bitmaps.end()) {
331 int size = *sizes_it;
332 // Find the closest not-smaller bitmap.
333 bitmaps_it = ordered_bitmaps.lower_bound(size);
334 ++sizes_it;
335 // Ensure the bitmap is valid and smaller than the next allowed size.
336 if (bitmaps_it != ordered_bitmaps.end() &&
337 (sizes_it == sizes.end() ||
338 bitmaps_it->second.bitmap.width() < *sizes_it)) {
339 output_bitmaps[size] = bitmaps_it->second;
340 // Resize the bitmap if it does not exactly match the desired size.
341 if (output_bitmaps[size].bitmap.width() != size) {
342 output_bitmaps[size].bitmap = skia::ImageOperations::Resize(
343 output_bitmaps[size].bitmap, skia::ImageOperations::RESIZE_LANCZOS3,
344 size, size);
345 }
346 }
347 }
348 return output_bitmaps;
349 }
350
351 // static
352 void BookmarkAppHelper::GenerateIcon(
353 std::map<int, BookmarkAppHelper::BitmapAndSource>* bitmaps,
354 int output_size,
355 SkColor color,
356 char letter) {
234 // Do nothing if there is already an icon of |output_size|. 357 // Do nothing if there is already an icon of |output_size|.
235 if (bitmaps->count(output_size)) 358 if (bitmaps->count(output_size))
236 return; 359 return;
237 360
238 gfx::ImageSkia icon_image( 361 gfx::ImageSkia icon_image(
239 new GeneratedIconImageSource(letter, color, output_size), 362 new GeneratedIconImageSource(letter, color, output_size),
240 gfx::Size(output_size, output_size)); 363 gfx::Size(output_size, output_size));
241 icon_image.bitmap()->deepCopyTo(&(*bitmaps)[output_size]); 364 icon_image.bitmap()->deepCopyTo(&(*bitmaps)[output_size].bitmap);
365 }
366
367 // static
368 std::map<int, BookmarkAppHelper::BitmapAndSource>
369 BookmarkAppHelper::ResizeIconsAndGenerateMissing(
370 std::vector<BookmarkAppHelper::BitmapAndSource> icons,
371 WebApplicationInfo* web_app_info) {
372 // Add the downloaded icons. Extensions only allow certain icon sizes. First
373 // populate icons that match the allowed sizes exactly and then downscale
374 // remaining icons to the closest allowed size that doesn't yet have an icon.
375 std::set<int> allowed_sizes(extension_misc::kExtensionIconSizes,
376 extension_misc::kExtensionIconSizes +
377 extension_misc::kNumExtensionIconSizes);
378
379 // If there are icons that don't match the accepted icon sizes, find the
380 // closest bigger icon to the accepted sizes and resize the icon to it. An
381 // icon will be resized and used for at most one size.
382 std::map<int, BitmapAndSource> resized_bitmaps(
383 ConstrainBitmapsToSizes(icons, allowed_sizes));
384
385 // Determine the color that will be used for the icon's background. For this
386 // the dominant color of the first icon found is used.
387 if (resized_bitmaps.size()) {
388 color_utils::GridSampler sampler;
389 web_app_info->generated_icon_color =
390 color_utils::CalculateKMeanColorOfBitmap(
391 resized_bitmaps.begin()->second.bitmap);
392 }
393
394 std::set<int> generate_sizes;
395 for (int size : SizesToGenerate()) {
396 if (resized_bitmaps.find(size) == resized_bitmaps.end())
397 generate_sizes.insert(size);
398 }
399 GenerateIcons(generate_sizes, web_app_info->app_url,
400 web_app_info->generated_icon_color, &resized_bitmaps);
401
402 return resized_bitmaps;
403 }
404
405 // static
406 void BookmarkAppHelper::UpdateWebAppIconsWithoutChangingLinks(
407 std::map<int, BookmarkAppHelper::BitmapAndSource> bitmap_map,
408 WebApplicationInfo* web_app_info) {
409 // First add in the icon data that have urls with the url / size data from the
410 // original web app info, and the data from the new icons (if any).
411 for (auto& icon : web_app_info->icons) {
412 if (!icon.url.is_empty() && icon.data.empty()) {
413 for (const auto& pair : bitmap_map) {
calamity 2015/04/28 06:56:35 Use bitmap_map.find(icon.width)?
benwells 2015/04/28 08:10:56 Done.
414 if (pair.first == icon.width && pair.second.source_url == icon.url) {
415 icon.data = pair.second.bitmap;
416 break;
417 }
418 }
419 }
420 }
421
422 // Now add in any icons from the updated list that don't have URls.
calamity 2015/04/28 06:56:35 nit: URLs
benwells 2015/04/28 08:10:56 Done.
423 for (const auto& pair : bitmap_map) {
424 if (pair.second.source_url.is_empty()) {
425 WebApplicationInfo::IconInfo icon_info;
426 icon_info.data = pair.second.bitmap;
427 icon_info.width = pair.first;
428 icon_info.height = pair.first;
429 web_app_info->icons.push_back(icon_info);
430 }
431 }
432 }
433
434 BookmarkAppHelper::BitmapAndSource::BitmapAndSource() {
435 }
436
437 BookmarkAppHelper::BitmapAndSource::BitmapAndSource(const GURL& source_url_p,
438 const SkBitmap& bitmap_p)
439 : source_url(source_url_p),
440 bitmap(bitmap_p) {
441 }
442
443 BookmarkAppHelper::BitmapAndSource::~BitmapAndSource() {
242 } 444 }
243 445
244 BookmarkAppHelper::BookmarkAppHelper(Profile* profile, 446 BookmarkAppHelper::BookmarkAppHelper(Profile* profile,
245 WebApplicationInfo web_app_info, 447 WebApplicationInfo web_app_info,
246 content::WebContents* contents) 448 content::WebContents* contents)
247 : profile_(profile), 449 : profile_(profile),
248 contents_(contents), 450 contents_(contents),
249 web_app_info_(web_app_info), 451 web_app_info_(web_app_info),
250 crx_installer_(extensions::CrxInstaller::CreateSilent( 452 crx_installer_(extensions::CrxInstaller::CreateSilent(
251 ExtensionSystem::Get(profile)->extension_service())) { 453 ExtensionSystem::Get(profile)->extension_service())) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
306 bool success, 508 bool success,
307 const std::map<GURL, std::vector<SkBitmap> >& bitmaps) { 509 const std::map<GURL, std::vector<SkBitmap> >& bitmaps) {
308 // The tab has navigated away during the icon download. Cancel the bookmark 510 // The tab has navigated away during the icon download. Cancel the bookmark
309 // app creation. 511 // app creation.
310 if (!success) { 512 if (!success) {
311 favicon_downloader_.reset(); 513 favicon_downloader_.reset();
312 callback_.Run(nullptr, web_app_info_); 514 callback_.Run(nullptr, web_app_info_);
313 return; 515 return;
314 } 516 }
315 517
316 std::vector<SkBitmap> downloaded_icons; 518 std::vector<BitmapAndSource> downloaded_icons;
317 for (FaviconDownloader::FaviconMap::const_iterator map_it = bitmaps.begin(); 519 for (FaviconDownloader::FaviconMap::const_iterator map_it = bitmaps.begin();
318 map_it != bitmaps.end(); 520 map_it != bitmaps.end();
319 ++map_it) { 521 ++map_it) {
320 for (std::vector<SkBitmap>::const_iterator bitmap_it = 522 for (std::vector<SkBitmap>::const_iterator bitmap_it =
321 map_it->second.begin(); 523 map_it->second.begin();
322 bitmap_it != map_it->second.end(); 524 bitmap_it != map_it->second.end();
323 ++bitmap_it) { 525 ++bitmap_it) {
324 if (bitmap_it->empty() || bitmap_it->width() != bitmap_it->height()) 526 if (bitmap_it->empty() || bitmap_it->width() != bitmap_it->height())
325 continue; 527 continue;
326 528
327 downloaded_icons.push_back(*bitmap_it); 529 downloaded_icons.push_back(BitmapAndSource(map_it->first, *bitmap_it));
328 } 530 }
329 } 531 }
330 532
331 // Add all existing icons from WebApplicationInfo. 533 // Add all existing icons from WebApplicationInfo.
332 for (std::vector<WebApplicationInfo::IconInfo>::const_iterator it = 534 for (std::vector<WebApplicationInfo::IconInfo>::const_iterator it =
333 web_app_info_.icons.begin(); 535 web_app_info_.icons.begin();
334 it != web_app_info_.icons.end(); 536 it != web_app_info_.icons.end();
335 ++it) { 537 ++it) {
336 const SkBitmap& icon = it->data; 538 const SkBitmap& icon = it->data;
337 if (!icon.drawsNothing() && icon.width() == icon.height()) 539 if (!icon.drawsNothing() && icon.width() == icon.height()) {
338 downloaded_icons.push_back(icon); 540 downloaded_icons.push_back(BitmapAndSource(it->url, icon));
541 }
339 } 542 }
340 543
341 // Add the downloaded icons. Extensions only allow certain icon sizes. First
342 // populate icons that match the allowed sizes exactly and then downscale
343 // remaining icons to the closest allowed size that doesn't yet have an icon.
344 std::set<int> allowed_sizes(extension_misc::kExtensionIconSizes,
345 extension_misc::kExtensionIconSizes +
346 extension_misc::kNumExtensionIconSizes);
347
348 web_app_info_.generated_icon_color = SK_ColorTRANSPARENT; 544 web_app_info_.generated_icon_color = SK_ColorTRANSPARENT;
349 // Determine the color that will be used for the icon's background. For this 545 std::map<int, BitmapAndSource> size_to_icons =
350 // the dominant color of the first icon found is used. 546 ResizeIconsAndGenerateMissing(downloaded_icons, &web_app_info_);
351 if (downloaded_icons.size()) { 547 ReplaceWebAppIcons(size_to_icons, &web_app_info_);
352 color_utils::GridSampler sampler;
353 web_app_info_.generated_icon_color =
354 color_utils::CalculateKMeanColorOfBitmap(downloaded_icons[0]);
355 }
356
357 std::set<int> generate_sizes = SizesToGenerate();
358
359 std::map<int, SkBitmap> generated_icons;
360 // Icons are always generated, replacing the icons that were downloaded. This
361 // is done so that the icons are consistent across machines.
362 // TODO(benwells): Use blob sync once it is available to sync the downloaded
363 // icons, and then only generate when there are required sizes missing.
364 GenerateIcons(generate_sizes, web_app_info_.app_url,
365 web_app_info_.generated_icon_color, &generated_icons);
366
367 ReplaceWebAppIcons(generated_icons, &web_app_info_);
368 favicon_downloader_.reset(); 548 favicon_downloader_.reset();
369 549
370 if (!contents_) { 550 if (!contents_) {
371 // The web contents can be null in tests. 551 // The web contents can be null in tests.
372 OnBubbleCompleted(true, web_app_info_); 552 OnBubbleCompleted(true, web_app_info_);
373 return; 553 return;
374 } 554 }
375 555
376 Browser* browser = chrome::FindBrowserWithWebContents(contents_); 556 Browser* browser = chrome::FindBrowserWithWebContents(contents_);
377 if (!browser) { 557 if (!browser) {
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 callback_.Run(nullptr, web_app_info_); 653 callback_.Run(nullptr, web_app_info_);
474 break; 654 break;
475 default: 655 default:
476 NOTREACHED(); 656 NOTREACHED();
477 break; 657 break;
478 } 658 }
479 } 659 }
480 660
481 void CreateOrUpdateBookmarkApp(ExtensionService* service, 661 void CreateOrUpdateBookmarkApp(ExtensionService* service,
482 WebApplicationInfo* web_app_info) { 662 WebApplicationInfo* web_app_info) {
483 scoped_refptr<extensions::CrxInstaller> installer( 663 scoped_refptr<BookmarkAppInstaller> installer(
484 extensions::CrxInstaller::CreateSilent(service)); 664 new BookmarkAppInstaller(service, *web_app_info));
485 installer->set_error_on_unsupported_requirements(true); 665 installer->Run();
486 if (web_app_info->icons.empty()) {
487 std::map<int, SkBitmap> bitmap_map;
488 GenerateIcons(SizesToGenerate(), web_app_info->app_url,
489 web_app_info->generated_icon_color, &bitmap_map);
490 ReplaceWebAppIcons(bitmap_map, web_app_info);
491 }
492
493 installer->InstallWebApp(*web_app_info);
494 } 666 }
495 667
496 void GetWebApplicationInfoFromApp( 668 void GetWebApplicationInfoFromApp(
497 content::BrowserContext* browser_context, 669 content::BrowserContext* browser_context,
498 const extensions::Extension* extension, 670 const extensions::Extension* extension,
499 const base::Callback<void(const WebApplicationInfo&)> callback) { 671 const base::Callback<void(const WebApplicationInfo&)> callback) {
500 if (!extension->from_bookmark()) { 672 if (!extension->from_bookmark()) {
501 callback.Run(WebApplicationInfo()); 673 callback.Run(WebApplicationInfo());
502 return; 674 return;
503 } 675 }
(...skipping 22 matching lines...) Expand all
526 extension, info_list, base::Bind(&OnIconsLoaded, web_app_info, callback)); 698 extension, info_list, base::Bind(&OnIconsLoaded, web_app_info, callback));
527 } 699 }
528 700
529 bool IsValidBookmarkAppUrl(const GURL& url) { 701 bool IsValidBookmarkAppUrl(const GURL& url) {
530 URLPattern origin_only_pattern(Extension::kValidWebExtentSchemes); 702 URLPattern origin_only_pattern(Extension::kValidWebExtentSchemes);
531 origin_only_pattern.SetMatchAllURLs(true); 703 origin_only_pattern.SetMatchAllURLs(true);
532 return url.is_valid() && origin_only_pattern.MatchesURL(url); 704 return url.is_valid() && origin_only_pattern.MatchesURL(url);
533 } 705 }
534 706
535 } // namespace extensions 707 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698