| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/ui/web_applications/web_app_ui.h" | 5 #include "chrome/browser/ui/web_applications/web_app_ui.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
| 9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
| 10 #include "base/path_service.h" | 10 #include "base/path_service.h" |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 #include "content/public/browser/browser_thread.h" | 22 #include "content/public/browser/browser_thread.h" |
| 23 #include "content/public/browser/notification_details.h" | 23 #include "content/public/browser/notification_details.h" |
| 24 #include "content/public/browser/notification_registrar.h" | 24 #include "content/public/browser/notification_registrar.h" |
| 25 #include "content/public/browser/notification_source.h" | 25 #include "content/public/browser/notification_source.h" |
| 26 #include "content/public/browser/web_contents.h" | 26 #include "content/public/browser/web_contents.h" |
| 27 #include "googleurl/src/gurl.h" | 27 #include "googleurl/src/gurl.h" |
| 28 #include "grit/theme_resources.h" | 28 #include "grit/theme_resources.h" |
| 29 #include "skia/ext/image_operations.h" | 29 #include "skia/ext/image_operations.h" |
| 30 #include "third_party/skia/include/core/SkBitmap.h" | 30 #include "third_party/skia/include/core/SkBitmap.h" |
| 31 #include "ui/base/resource/resource_bundle.h" | 31 #include "ui/base/resource/resource_bundle.h" |
| 32 #include "ui/gfx/image/image.h" |
| 33 #include "ui/gfx/image/image_family.h" |
| 32 #include "ui/gfx/image/image_skia.h" | 34 #include "ui/gfx/image/image_skia.h" |
| 33 | 35 |
| 34 #if defined(OS_POSIX) && !defined(OS_MACOSX) | 36 #if defined(OS_POSIX) && !defined(OS_MACOSX) |
| 35 #include "base/environment.h" | 37 #include "base/environment.h" |
| 36 #endif | 38 #endif |
| 37 | 39 |
| 38 #if defined(OS_WIN) | 40 #if defined(OS_WIN) |
| 39 #include "base/win/shortcut.h" | 41 #include "base/win/shortcut.h" |
| 40 #include "base/win/windows_version.h" | 42 #include "base/win/windows_version.h" |
| 41 #endif | 43 #endif |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 std::vector<ui::ScaleFactor> scale_factors; | 191 std::vector<ui::ScaleFactor> scale_factors; |
| 190 scale_factors.push_back(ui::SCALE_FACTOR_100P); | 192 scale_factors.push_back(ui::SCALE_FACTOR_100P); |
| 191 | 193 |
| 192 size_t closest_index = | 194 size_t closest_index = |
| 193 FaviconUtil::SelectBestFaviconFromBitmaps(bitmaps, | 195 FaviconUtil::SelectBestFaviconFromBitmaps(bitmaps, |
| 194 scale_factors, | 196 scale_factors, |
| 195 requested_size); | 197 requested_size); |
| 196 | 198 |
| 197 if (!bitmaps.empty() && !bitmaps[closest_index].isNull()) { | 199 if (!bitmaps.empty() && !bitmaps[closest_index].isNull()) { |
| 198 // Update icon with download image and update shortcut. | 200 // Update icon with download image and update shortcut. |
| 199 shortcut_info_.favicon = | 201 shortcut_info_.favicon.Add( |
| 200 gfx::Image::CreateFrom1xBitmap(bitmaps[closest_index]); | 202 gfx::Image::CreateFrom1xBitmap(bitmaps[closest_index])); |
| 201 extensions::TabHelper* extensions_tab_helper = | 203 extensions::TabHelper* extensions_tab_helper = |
| 202 extensions::TabHelper::FromWebContents(web_contents_); | 204 extensions::TabHelper::FromWebContents(web_contents_); |
| 203 extensions_tab_helper->SetAppIcon(bitmaps[closest_index]); | 205 extensions_tab_helper->SetAppIcon(bitmaps[closest_index]); |
| 204 UpdateShortcuts(); | 206 UpdateShortcuts(); |
| 205 } else { | 207 } else { |
| 206 // Try the next icon otherwise. | 208 // Try the next icon otherwise. |
| 207 DownloadIcon(); | 209 DownloadIcon(); |
| 208 } | 210 } |
| 209 } | 211 } |
| 210 | 212 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 264 // Ensure web_app_path exists. web_app_path could be missing for a legacy | 266 // Ensure web_app_path exists. web_app_path could be missing for a legacy |
| 265 // shortcut created by Gears. | 267 // shortcut created by Gears. |
| 266 if (!file_util::PathExists(web_app_path) && | 268 if (!file_util::PathExists(web_app_path) && |
| 267 !file_util::CreateDirectory(web_app_path)) { | 269 !file_util::CreateDirectory(web_app_path)) { |
| 268 NOTREACHED(); | 270 NOTREACHED(); |
| 269 return; | 271 return; |
| 270 } | 272 } |
| 271 | 273 |
| 272 base::FilePath icon_file = web_app_path.Append(file_name_).ReplaceExtension( | 274 base::FilePath icon_file = web_app_path.Append(file_name_).ReplaceExtension( |
| 273 FILE_PATH_LITERAL(".ico")); | 275 FILE_PATH_LITERAL(".ico")); |
| 274 web_app::internals::CheckAndSaveIcon(icon_file, | 276 web_app::internals::CheckAndSaveIcon(icon_file, shortcut_info_.favicon); |
| 275 *shortcut_info_.favicon.ToSkBitmap()); | |
| 276 | 277 |
| 277 // Update existing shortcuts' description, icon and app id. | 278 // Update existing shortcuts' description, icon and app id. |
| 278 CheckExistingShortcuts(); | 279 CheckExistingShortcuts(); |
| 279 if (!shortcut_files_.empty()) { | 280 if (!shortcut_files_.empty()) { |
| 280 // Generates app id from web app url and profile path. | 281 // Generates app id from web app url and profile path. |
| 281 string16 app_id = ShellIntegration::GetAppModelIdForProfile( | 282 string16 app_id = ShellIntegration::GetAppModelIdForProfile( |
| 282 UTF8ToWide(web_app::GenerateApplicationNameFromURL(shortcut_info_.url)), | 283 UTF8ToWide(web_app::GenerateApplicationNameFromURL(shortcut_info_.url)), |
| 283 profile_path_); | 284 profile_path_); |
| 284 | 285 |
| 285 // Sanitize description | 286 // Sanitize description |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 330 gfx::Image default_icon = | 331 gfx::Image default_icon = |
| 331 ResourceBundle::GetSharedInstance().GetImageNamed(IDR_APP_DEFAULT_ICON); | 332 ResourceBundle::GetSharedInstance().GetImageNamed(IDR_APP_DEFAULT_ICON); |
| 332 int size = kDesiredSizes[arraysize(kDesiredSizes) - 1]; | 333 int size = kDesiredSizes[arraysize(kDesiredSizes) - 1]; |
| 333 SkBitmap bmp = skia::ImageOperations::Resize( | 334 SkBitmap bmp = skia::ImageOperations::Resize( |
| 334 *default_icon.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST, | 335 *default_icon.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST, |
| 335 size, size); | 336 size, size); |
| 336 gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bmp); | 337 gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bmp); |
| 337 // We are on the UI thread, and this image is needed from the FILE thread, | 338 // We are on the UI thread, and this image is needed from the FILE thread, |
| 338 // for creating shortcut icon files. | 339 // for creating shortcut icon files. |
| 339 image_skia.MakeThreadSafe(); | 340 image_skia.MakeThreadSafe(); |
| 340 shortcut_info.favicon = gfx::Image(image_skia); | 341 shortcut_info.favicon.Add(gfx::Image(image_skia)); |
| 341 } else { | 342 } else { |
| 342 shortcut_info.favicon = image; | 343 // As described in UpdateShortcutInfoAndIconForApp, image contains all of |
| 344 // the icons, hackily put into a single ImageSkia. Separate them out into |
| 345 // individual ImageSkias and insert them into the icon family. |
| 346 const gfx::ImageSkia& multires_image_skia = image.AsImageSkia(); |
| 347 // NOTE: We do not call ImageSkia::EnsureRepsForSupportedScaleFactors here. |
| 348 // The image reps here are not really for different scale factors (ImageSkia |
| 349 // is just being used as a handy container for multiple images). |
| 350 std::vector<gfx::ImageSkiaRep> image_reps = |
| 351 multires_image_skia.image_reps(); |
| 352 for (std::vector<gfx::ImageSkiaRep>::const_iterator it = image_reps.begin(); |
| 353 it != image_reps.end(); ++it) { |
| 354 gfx::ImageSkia image_skia(*it); |
| 355 image_skia.MakeThreadSafe(); |
| 356 shortcut_info.favicon.Add(image_skia); |
| 357 } |
| 343 } | 358 } |
| 344 | 359 |
| 345 callback.Run(shortcut_info); | 360 callback.Run(shortcut_info); |
| 346 } | 361 } |
| 347 | 362 |
| 348 } // namespace | 363 } // namespace |
| 349 | 364 |
| 350 namespace web_app { | 365 namespace web_app { |
| 351 | 366 |
| 352 ShellIntegration::ShortcutInfo ShortcutInfoForExtensionAndProfile( | 367 ShellIntegration::ShortcutInfo ShortcutInfoForExtensionAndProfile( |
| (...skipping 13 matching lines...) Expand all Loading... |
| 366 extensions::TabHelper::FromWebContents(web_contents); | 381 extensions::TabHelper::FromWebContents(web_contents); |
| 367 const WebApplicationInfo& app_info = extensions_tab_helper->web_app_info(); | 382 const WebApplicationInfo& app_info = extensions_tab_helper->web_app_info(); |
| 368 | 383 |
| 369 info->url = app_info.app_url.is_empty() ? web_contents->GetURL() : | 384 info->url = app_info.app_url.is_empty() ? web_contents->GetURL() : |
| 370 app_info.app_url; | 385 app_info.app_url; |
| 371 info->title = app_info.title.empty() ? | 386 info->title = app_info.title.empty() ? |
| 372 (web_contents->GetTitle().empty() ? UTF8ToUTF16(info->url.spec()) : | 387 (web_contents->GetTitle().empty() ? UTF8ToUTF16(info->url.spec()) : |
| 373 web_contents->GetTitle()) : | 388 web_contents->GetTitle()) : |
| 374 app_info.title; | 389 app_info.title; |
| 375 info->description = app_info.description; | 390 info->description = app_info.description; |
| 376 info->favicon = gfx::Image(favicon_tab_helper->GetFavicon()); | 391 info->favicon.Add(favicon_tab_helper->GetFavicon()); |
| 377 | 392 |
| 378 Profile* profile = | 393 Profile* profile = |
| 379 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | 394 Profile::FromBrowserContext(web_contents->GetBrowserContext()); |
| 380 info->profile_path = profile->GetPath(); | 395 info->profile_path = profile->GetPath(); |
| 381 } | 396 } |
| 382 | 397 |
| 383 void UpdateShortcutForTabContents(WebContents* web_contents) { | 398 void UpdateShortcutForTabContents(WebContents* web_contents) { |
| 384 #if defined(OS_WIN) | 399 #if defined(OS_WIN) |
| 385 // UpdateShortcutWorker will delete itself when it's done. | 400 // UpdateShortcutWorker will delete itself when it's done. |
| 386 UpdateShortcutWorker* worker = new UpdateShortcutWorker(web_contents); | 401 UpdateShortcutWorker* worker = new UpdateShortcutWorker(web_contents); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 400 shortcut_info->profile_path = profile->GetPath(); | 415 shortcut_info->profile_path = profile->GetPath(); |
| 401 } | 416 } |
| 402 | 417 |
| 403 void UpdateShortcutInfoAndIconForApp( | 418 void UpdateShortcutInfoAndIconForApp( |
| 404 const extensions::Extension& extension, | 419 const extensions::Extension& extension, |
| 405 Profile* profile, | 420 Profile* profile, |
| 406 const web_app::ShortcutInfoCallback& callback) { | 421 const web_app::ShortcutInfoCallback& callback) { |
| 407 ShellIntegration::ShortcutInfo shortcut_info = | 422 ShellIntegration::ShortcutInfo shortcut_info = |
| 408 ShortcutInfoForExtensionAndProfile(&extension, profile); | 423 ShortcutInfoForExtensionAndProfile(&extension, profile); |
| 409 | 424 |
| 425 // We want to load each icon into a separate ImageSkia to insert into an |
| 426 // ImageFamily, but LoadImagesAsync currently only builds a single ImageSkia. |
| 427 // Hack around this by loading all images into the ImageSkia as 100% |
| 428 // representations, and later (in OnImageLoaded), pulling them out and |
| 429 // individually inserting them into an ImageFamily. |
| 430 // TODO(mgiuca): Have ImageLoader build the ImageFamily directly |
| 431 // (http://crbug.com/230184). |
| 410 std::vector<extensions::ImageLoader::ImageRepresentation> info_list; | 432 std::vector<extensions::ImageLoader::ImageRepresentation> info_list; |
| 411 for (size_t i = 0; i < arraysize(kDesiredSizes); ++i) { | 433 for (size_t i = 0; i < arraysize(kDesiredSizes); ++i) { |
| 412 int size = kDesiredSizes[i]; | 434 int size = kDesiredSizes[i]; |
| 413 extensions::ExtensionResource resource = | 435 extensions::ExtensionResource resource = |
| 414 extensions::IconsInfo::GetIconResource( | 436 extensions::IconsInfo::GetIconResource( |
| 415 &extension, size, ExtensionIconSet::MATCH_EXACTLY); | 437 &extension, size, ExtensionIconSet::MATCH_EXACTLY); |
| 416 if (!resource.empty()) { | 438 if (!resource.empty()) { |
| 417 info_list.push_back(extensions::ImageLoader::ImageRepresentation( | 439 info_list.push_back(extensions::ImageLoader::ImageRepresentation( |
| 418 resource, | 440 resource, |
| 419 extensions::ImageLoader::ImageRepresentation::RESIZE_WHEN_LARGER, | 441 extensions::ImageLoader::ImageRepresentation::RESIZE_WHEN_LARGER, |
| (...skipping 24 matching lines...) Expand all Loading... |
| 444 } | 466 } |
| 445 | 467 |
| 446 // |info_list| may still be empty at this point, in which case LoadImage | 468 // |info_list| may still be empty at this point, in which case LoadImage |
| 447 // will call the OnImageLoaded callback with an empty image and exit | 469 // will call the OnImageLoaded callback with an empty image and exit |
| 448 // immediately. | 470 // immediately. |
| 449 extensions::ImageLoader::Get(profile)->LoadImagesAsync(&extension, info_list, | 471 extensions::ImageLoader::Get(profile)->LoadImagesAsync(&extension, info_list, |
| 450 base::Bind(&OnImageLoaded, shortcut_info, callback)); | 472 base::Bind(&OnImageLoaded, shortcut_info, callback)); |
| 451 } | 473 } |
| 452 | 474 |
| 453 } // namespace web_app | 475 } // namespace web_app |
| OLD | NEW |