Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |