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