bookmark_app_helper.cc revision e5d81f57cb97b3b6b7fccc9c5610d21eb81db09d
1effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Copyright 2014 The Chromium Authors. All rights reserved. 2effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// found in the LICENSE file. 4effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 5effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/extensions/bookmark_app_helper.h" 6effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 7effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "base/strings/utf_string_conversions.h" 8effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/chrome_notification_types.h" 9effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/extensions/crx_installer.h" 10effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/extensions/extension_service.h" 11effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/extensions/favicon_downloader.h" 12effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/browser/extensions/tab_helper.h" 13effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/common/extensions/extension_constants.h" 14effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "chrome/common/extensions/manifest_handlers/app_launch_info.h" 15e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chrome/common/extensions/manifest_handlers/icons_handler.h" 16effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "content/public/browser/notification_service.h" 17effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "content/public/browser/notification_source.h" 18effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "content/public/browser/web_contents.h" 19effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "extensions/common/extension.h" 20effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "skia/ext/image_operations.h" 21effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "skia/ext/platform_canvas.h" 22effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "third_party/skia/include/core/SkBitmap.h" 23effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "ui/gfx/color_analysis.h" 24effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include "ui/gfx/image/image.h" 25effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 26effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochnamespace extensions { 27effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 28effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// static 29effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochstd::map<int, SkBitmap> BookmarkAppHelper::ConstrainBitmapsToSizes( 30effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const std::vector<SkBitmap>& bitmaps, 31effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const std::set<int>& sizes) { 32effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::map<int, SkBitmap> output_bitmaps; 33effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::map<int, SkBitmap> ordered_bitmaps; 34effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (std::vector<SkBitmap>::const_iterator it = bitmaps.begin(); 35effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch it != bitmaps.end(); 36effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ++it) { 37effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(it->width() == it->height()); 38effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ordered_bitmaps[it->width()] = *it; 39effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 40effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 41effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::set<int>::const_iterator sizes_it = sizes.begin(); 42effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::map<int, SkBitmap>::const_iterator bitmaps_it = ordered_bitmaps.begin(); 43effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch while (sizes_it != sizes.end() && bitmaps_it != ordered_bitmaps.end()) { 44effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int size = *sizes_it; 45effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Find the closest not-smaller bitmap. 46effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch bitmaps_it = ordered_bitmaps.lower_bound(size); 47effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ++sizes_it; 48effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Ensure the bitmap is valid and smaller than the next allowed size. 49effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (bitmaps_it != ordered_bitmaps.end() && 50effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch (sizes_it == sizes.end() || bitmaps_it->second.width() < *sizes_it)) { 51effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Resize the bitmap if it does not exactly match the desired size. 52effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch output_bitmaps[size] = bitmaps_it->second.width() == size 53effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ? bitmaps_it->second 54effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch : skia::ImageOperations::Resize( 55effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch bitmaps_it->second, 56effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch skia::ImageOperations::RESIZE_LANCZOS3, 57effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch size, 58effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch size); 59effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 60effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 61effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return output_bitmaps; 62effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 63effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 64effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// static 65effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid BookmarkAppHelper::GenerateContainerIcon(std::map<int, SkBitmap>* bitmaps, 66effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch int output_size) { 67effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::map<int, SkBitmap>::const_iterator it = 68effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch bitmaps->lower_bound(output_size); 69effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Do nothing if there is no icon smaller than the desired size or there is 70effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // already an icon of |output_size|. 71effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (it == bitmaps->begin() || bitmaps->count(output_size)) 72effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 73effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 74effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch --it; 75effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // This is the biggest icon smaller than |output_size|. 76effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const SkBitmap& base_icon = it->second; 77effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 78effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const size_t kBorderRadius = 5; 79effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const size_t kColorStripHeight = 3; 80effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const SkColor kBorderColor = 0xFFD5D5D5; 81effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const SkColor kBackgroundColor = 0xFFFFFFFF; 82effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 83effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Create a separate canvas for the color strip. 84effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_ptr<SkCanvas> color_strip_canvas( 85effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch skia::CreateBitmapCanvas(output_size, output_size, false)); 86effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(color_strip_canvas); 87effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 88effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Draw a rounded rect of the |base_icon|'s dominant color. 89effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SkPaint color_strip_paint; 90effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch color_utils::GridSampler sampler; 91effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch color_strip_paint.setFlags(SkPaint::kAntiAlias_Flag); 92effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch color_strip_paint.setColor(color_utils::CalculateKMeanColorOfPNG( 93effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch gfx::Image::CreateFrom1xBitmap(base_icon).As1xPNGBytes(), 94effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 100, 95effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 665, 96effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch &sampler)); 97effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch color_strip_canvas->drawRoundRect(SkRect::MakeWH(output_size, output_size), 98effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch kBorderRadius, 99effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch kBorderRadius, 100effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch color_strip_paint); 101effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 102effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Erase the top of the rounded rect to leave a color strip. 103effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SkPaint clear_paint; 104effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch clear_paint.setColor(SK_ColorTRANSPARENT); 105effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch clear_paint.setXfermodeMode(SkXfermode::kSrc_Mode); 106effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch color_strip_canvas->drawRect( 107effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SkRect::MakeWH(output_size, output_size - kColorStripHeight), 108effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch clear_paint); 109effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 110effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Draw each element to an output canvas. 111effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_ptr<SkCanvas> canvas( 112effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch skia::CreateBitmapCanvas(output_size, output_size, false)); 113effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(canvas); 114effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 115effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Draw the background. 116effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SkPaint background_paint; 117effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch background_paint.setColor(kBackgroundColor); 118effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch background_paint.setFlags(SkPaint::kAntiAlias_Flag); 119effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch canvas->drawRoundRect(SkRect::MakeWH(output_size, output_size), 120effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch kBorderRadius, 121effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch kBorderRadius, 122effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch background_paint); 123effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 124effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Draw the color strip. 125effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch canvas->drawBitmap( 126effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch color_strip_canvas->getDevice()->accessBitmap(false), 0, 0); 127effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 128effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Draw the border. 129effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch SkPaint border_paint; 130effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch border_paint.setColor(kBorderColor); 131effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch border_paint.setStyle(SkPaint::kStroke_Style); 132effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch border_paint.setFlags(SkPaint::kAntiAlias_Flag); 133effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch canvas->drawRoundRect(SkRect::MakeWH(output_size, output_size), 134effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch kBorderRadius, 135effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch kBorderRadius, 136effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch border_paint); 137effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 138effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Draw the centered base icon to the output canvas. 139effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch canvas->drawBitmap(base_icon, 140effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch (output_size - base_icon.width()) / 2, 141effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch (output_size - base_icon.height()) / 2); 142effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const SkBitmap& generated_icon = canvas->getDevice()->accessBitmap(false); 144effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch generated_icon.deepCopyTo(&(*bitmaps)[output_size]); 145effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 146effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 147effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochBookmarkAppHelper::BookmarkAppHelper(ExtensionService* service, 148effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch WebApplicationInfo web_app_info, 149effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch content::WebContents* contents) 150effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch : web_app_info_(web_app_info), 151effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch crx_installer_(extensions::CrxInstaller::CreateSilent(service)) { 152effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch registrar_.Add(this, 153effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch chrome::NOTIFICATION_CRX_INSTALLER_DONE, 154effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch content::Source<CrxInstaller>(crx_installer_.get())); 155effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 156effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch registrar_.Add(this, 157effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR, 158effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch content::Source<CrxInstaller>(crx_installer_.get())); 159effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 160effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch crx_installer_->set_error_on_unsupported_requirements(true); 161effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 162effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Add urls from the WebApplicationInfo. 163effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::vector<GURL> web_app_info_icon_urls; 164effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (std::vector<WebApplicationInfo::IconInfo>::const_iterator it = 165effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch web_app_info_.icons.begin(); 166effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch it != web_app_info_.icons.end(); 167effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ++it) { 168effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (it->url.is_valid()) 169effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch web_app_info_icon_urls.push_back(it->url); 170effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 171effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 172effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch favicon_downloader_.reset( 173effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch new FaviconDownloader(contents, 174effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch web_app_info_icon_urls, 175effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Bind(&BookmarkAppHelper::OnIconsDownloaded, 176effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::Unretained(this)))); 177effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 178effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 179effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochBookmarkAppHelper::~BookmarkAppHelper() {} 180effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 181effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid BookmarkAppHelper::Create(const CreateBookmarkAppCallback& callback) { 182effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch callback_ = callback; 183effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch favicon_downloader_->Start(); 184effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 185effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 186effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid BookmarkAppHelper::OnIconsDownloaded( 187effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch bool success, 188effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const std::map<GURL, std::vector<SkBitmap> >& bitmaps) { 189effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // The tab has navigated away during the icon download. Cancel the bookmark 190effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // app creation. 191effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (!success) { 192effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch favicon_downloader_.reset(); 193effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch callback_.Run(NULL, web_app_info_); 194effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch return; 195effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 196effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 197effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Add the downloaded icons. Extensions only allow certain icon sizes. First 198effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // populate icons that match the allowed sizes exactly and then downscale 199effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // remaining icons to the closest allowed size that doesn't yet have an icon. 200effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::set<int> allowed_sizes(extension_misc::kExtensionIconSizes, 201effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch extension_misc::kExtensionIconSizes + 202effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch extension_misc::kNumExtensionIconSizes); 203effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::vector<SkBitmap> downloaded_icons; 204effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (FaviconDownloader::FaviconMap::const_iterator map_it = bitmaps.begin(); 205effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch map_it != bitmaps.end(); 206effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ++map_it) { 207effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (std::vector<SkBitmap>::const_iterator bitmap_it = 208effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch map_it->second.begin(); 209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch bitmap_it != map_it->second.end(); 210effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ++bitmap_it) { 211effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (bitmap_it->empty() || bitmap_it->width() != bitmap_it->height()) 212effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch continue; 213effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 214effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch downloaded_icons.push_back(*bitmap_it); 215effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 216effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 217effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 218effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // If there are icons that don't match the accepted icon sizes, find the 219effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // closest bigger icon to the accepted sizes and resize the icon to it. An 220effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // icon will be resized and used for at most one size. 221effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch std::map<int, SkBitmap> resized_bitmaps( 222effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ConstrainBitmapsToSizes(downloaded_icons, allowed_sizes)); 223effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 224effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Generate container icons from smaller icons. 225effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const int kIconSizesToGenerate[] = {extension_misc::EXTENSION_ICON_SMALL, 226effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch extension_misc::EXTENSION_ICON_MEDIUM, }; 227effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const std::set<int> generate_sizes( 228effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch kIconSizesToGenerate, 229effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch kIconSizesToGenerate + arraysize(kIconSizesToGenerate)); 230effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 231effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Only generate icons if larger icons don't exist. This means the app 232effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // launcher and the taskbar will do their best downsizing large icons and 233effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // these container icons are only generated as a last resort against upscaling 234effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // a smaller icon. 235effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch if (resized_bitmaps.lower_bound(*generate_sizes.rbegin()) == 236effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch resized_bitmaps.end()) { 237effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Generate these from biggest to smallest so we don't end up with 238effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // concentric container icons. 239effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (std::set<int>::const_reverse_iterator it = generate_sizes.rbegin(); 240effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch it != generate_sizes.rend(); 241effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ++it) { 242effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch GenerateContainerIcon(&resized_bitmaps, *it); 243effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 244effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 245effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 246effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Populate the icon data into the WebApplicationInfo we are using to 247effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // install the bookmark app. 248effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch for (std::map<int, SkBitmap>::const_iterator resized_bitmaps_it = 249effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch resized_bitmaps.begin(); 250effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch resized_bitmaps_it != resized_bitmaps.end(); 251effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch ++resized_bitmaps_it) { 252effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch WebApplicationInfo::IconInfo icon_info; 253effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch icon_info.data = resized_bitmaps_it->second; 254effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch icon_info.width = icon_info.data.width(); 255effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch icon_info.height = icon_info.data.height(); 256effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch web_app_info_.icons.push_back(icon_info); 257effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 258effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 259effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Install the app. 260effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch crx_installer_->InstallWebApp(web_app_info_); 261effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch favicon_downloader_.reset(); 262effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 263effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 264effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochvoid BookmarkAppHelper::Observe(int type, 265effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const content::NotificationSource& source, 266effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const content::NotificationDetails& details) { 267effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch switch (type) { 268effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch case chrome::NOTIFICATION_CRX_INSTALLER_DONE: { 269effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch const Extension* extension = 270effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch content::Details<const Extension>(details).ptr(); 271effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK(extension); 272effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch DCHECK_EQ(AppLaunchInfo::GetLaunchWebURL(extension), 273effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch web_app_info_.app_url); 274effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch callback_.Run(extension, web_app_info_); 275effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch break; 276effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 277effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch case chrome::NOTIFICATION_EXTENSION_INSTALL_ERROR: 278effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch callback_.Run(NULL, web_app_info_); 279effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch break; 280effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch default: 281effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NOTREACHED(); 282effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch break; 283effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 284effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 285effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 286e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid CreateOrUpdateBookmarkApp(ExtensionService* service, 287e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch WebApplicationInfo& web_app_info) { 288e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch scoped_refptr<extensions::CrxInstaller> installer( 289e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch extensions::CrxInstaller::CreateSilent(service)); 290e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch installer->set_error_on_unsupported_requirements(true); 291e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch installer->InstallWebApp(web_app_info); 292e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 293e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 294effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} // namespace extensions 295