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" |
11 #include "base/prefs/pref_service.h" | |
12 #include "base/strings/string16.h" | |
13 #include "base/strings/utf_string_conversions.h" | 11 #include "base/strings/utf_string_conversions.h" |
14 #include "chrome/browser/chrome_notification_types.h" | 12 #include "chrome/browser/chrome_notification_types.h" |
15 #include "chrome/browser/extensions/image_loader.h" | |
16 #include "chrome/browser/extensions/tab_helper.h" | 13 #include "chrome/browser/extensions/tab_helper.h" |
17 #include "chrome/browser/favicon/favicon_tab_helper.h" | 14 #include "chrome/browser/favicon/favicon_tab_helper.h" |
18 #include "chrome/browser/history/select_favicon_frames.h" | 15 #include "chrome/browser/history/select_favicon_frames.h" |
19 #include "chrome/browser/profiles/profile.h" | 16 #include "chrome/browser/profiles/profile.h" |
20 #include "chrome/browser/web_applications/web_app.h" | 17 #include "chrome/browser/web_applications/web_app.h" |
21 #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" | |
22 #include "chrome/common/extensions/manifest_handlers/icons_handler.h" | |
23 #include "chrome/common/pref_names.h" | |
24 #include "content/public/browser/browser_thread.h" | 18 #include "content/public/browser/browser_thread.h" |
25 #include "content/public/browser/notification_details.h" | 19 #include "content/public/browser/notification_details.h" |
26 #include "content/public/browser/notification_registrar.h" | 20 #include "content/public/browser/notification_registrar.h" |
27 #include "content/public/browser/notification_source.h" | 21 #include "content/public/browser/notification_source.h" |
28 #include "content/public/browser/web_contents.h" | 22 #include "content/public/browser/web_contents.h" |
29 #include "extensions/common/extension.h" | |
30 #include "grit/theme_resources.h" | |
31 #include "skia/ext/image_operations.h" | |
32 #include "third_party/skia/include/core/SkBitmap.h" | |
33 #include "ui/base/resource/resource_bundle.h" | |
34 #include "ui/gfx/image/image.h" | |
35 #include "ui/gfx/image/image_family.h" | |
36 #include "ui/gfx/image/image_skia.h" | |
37 #include "url/gurl.h" | 23 #include "url/gurl.h" |
38 | 24 |
39 #if defined(OS_POSIX) && !defined(OS_MACOSX) | 25 #if defined(OS_POSIX) && !defined(OS_MACOSX) |
40 #include "base/environment.h" | 26 #include "base/environment.h" |
41 #endif | 27 #endif |
42 | 28 |
43 #if defined(OS_WIN) | 29 #if defined(OS_WIN) |
44 #include "base/win/shortcut.h" | 30 #include "base/win/shortcut.h" |
45 #include "base/win/windows_version.h" | 31 #include "base/win/windows_version.h" |
46 #include "chrome/browser/web_applications/web_app_win.h" | 32 #include "chrome/browser/web_applications/web_app_win.h" |
47 #include "ui/gfx/icon_util.h" | 33 #include "ui/gfx/icon_util.h" |
48 #endif | 34 #endif |
49 | 35 |
50 using content::BrowserThread; | 36 using content::BrowserThread; |
51 using content::NavigationController; | 37 using content::NavigationController; |
52 using content::WebContents; | 38 using content::WebContents; |
53 | 39 |
54 namespace { | 40 namespace { |
55 | 41 |
56 #if defined(OS_MACOSX) | 42 // TODO(jackhou): Move all win-specific code to web_app_win. |
57 const int kDesiredSizes[] = {16, 32, 128, 256, 512}; | |
58 const size_t kNumDesiredSizes = arraysize(kDesiredSizes); | |
59 #elif defined(OS_LINUX) | |
60 // Linux supports icons of any size. FreeDesktop Icon Theme Specification states | |
61 // that "Minimally you should install a 48x48 icon in the hicolor theme." | |
62 const int kDesiredSizes[] = {16, 32, 48, 128, 256, 512}; | |
63 const size_t kNumDesiredSizes = arraysize(kDesiredSizes); | |
64 #elif defined(OS_WIN) | |
65 const int* kDesiredSizes = IconUtil::kIconDimensions; | |
66 const size_t kNumDesiredSizes = IconUtil::kNumIconDimensions; | |
67 #else | |
68 const int kDesiredSizes[] = {32}; | |
69 const size_t kNumDesiredSizes = arraysize(kDesiredSizes); | |
70 #endif | |
71 | |
72 #if defined(OS_WIN) | 43 #if defined(OS_WIN) |
73 // UpdateShortcutWorker holds all context data needed for update shortcut. | 44 // UpdateShortcutWorker holds all context data needed for update shortcut. |
74 // It schedules a pre-update check to find all shortcuts that needs to be | 45 // It schedules a pre-update check to find all shortcuts that needs to be |
75 // updated. If there are such shortcuts, it schedules icon download and | 46 // updated. If there are such shortcuts, it schedules icon download and |
76 // update them when icons are downloaded. It observes TAB_CLOSING notification | 47 // update them when icons are downloaded. It observes TAB_CLOSING notification |
77 // and cancels all the work when the underlying tab is closing. | 48 // and cancels all the work when the underlying tab is closing. |
78 class UpdateShortcutWorker : public content::NotificationObserver { | 49 class UpdateShortcutWorker : public content::NotificationObserver { |
79 public: | 50 public: |
80 explicit UpdateShortcutWorker(WebContents* web_contents); | 51 explicit UpdateShortcutWorker(WebContents* web_contents); |
81 | 52 |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
336 base::Unretained(this))); | 307 base::Unretained(this))); |
337 } | 308 } |
338 } | 309 } |
339 | 310 |
340 void UpdateShortcutWorker::DeleteMeOnUIThread() { | 311 void UpdateShortcutWorker::DeleteMeOnUIThread() { |
341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 312 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
342 delete this; | 313 delete this; |
343 } | 314 } |
344 #endif // defined(OS_WIN) | 315 #endif // defined(OS_WIN) |
345 | 316 |
346 void OnImageLoaded(ShellIntegration::ShortcutInfo shortcut_info, | |
347 web_app::ShortcutInfoCallback callback, | |
348 const gfx::ImageFamily& image_family) { | |
349 // If the image failed to load (e.g. if the resource being loaded was empty) | |
350 // use the standard application icon. | |
351 if (image_family.empty()) { | |
352 gfx::Image default_icon = | |
353 ResourceBundle::GetSharedInstance().GetImageNamed(IDR_APP_DEFAULT_ICON); | |
354 int size = kDesiredSizes[kNumDesiredSizes - 1]; | |
355 SkBitmap bmp = skia::ImageOperations::Resize( | |
356 *default_icon.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST, | |
357 size, size); | |
358 gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bmp); | |
359 // We are on the UI thread, and this image is needed from the FILE thread, | |
360 // for creating shortcut icon files. | |
361 image_skia.MakeThreadSafe(); | |
362 shortcut_info.favicon.Add(gfx::Image(image_skia)); | |
363 } else { | |
364 shortcut_info.favicon = image_family; | |
365 } | |
366 | |
367 callback.Run(shortcut_info); | |
368 } | |
369 | |
370 } // namespace | 317 } // namespace |
371 | 318 |
372 namespace web_app { | 319 namespace web_app { |
373 | 320 |
374 ShellIntegration::ShortcutInfo ShortcutInfoForExtensionAndProfile( | |
375 const extensions::Extension* extension, Profile* profile) { | |
376 ShellIntegration::ShortcutInfo shortcut_info; | |
377 web_app::UpdateShortcutInfoForApp(*extension, profile, &shortcut_info); | |
378 return shortcut_info; | |
379 } | |
380 | |
381 void GetShortcutInfoForTab(WebContents* web_contents, | 321 void GetShortcutInfoForTab(WebContents* web_contents, |
382 ShellIntegration::ShortcutInfo* info) { | 322 ShellIntegration::ShortcutInfo* info) { |
383 DCHECK(info); // Must provide a valid info. | 323 DCHECK(info); // Must provide a valid info. |
384 | 324 |
385 const FaviconTabHelper* favicon_tab_helper = | 325 const FaviconTabHelper* favicon_tab_helper = |
386 FaviconTabHelper::FromWebContents(web_contents); | 326 FaviconTabHelper::FromWebContents(web_contents); |
387 const extensions::TabHelper* extensions_tab_helper = | 327 const extensions::TabHelper* extensions_tab_helper = |
388 extensions::TabHelper::FromWebContents(web_contents); | 328 extensions::TabHelper::FromWebContents(web_contents); |
389 const WebApplicationInfo& app_info = extensions_tab_helper->web_app_info(); | 329 const WebApplicationInfo& app_info = extensions_tab_helper->web_app_info(); |
390 | 330 |
(...skipping 12 matching lines...) Expand all Loading... |
403 } | 343 } |
404 | 344 |
405 void UpdateShortcutForTabContents(WebContents* web_contents) { | 345 void UpdateShortcutForTabContents(WebContents* web_contents) { |
406 #if defined(OS_WIN) | 346 #if defined(OS_WIN) |
407 // UpdateShortcutWorker will delete itself when it's done. | 347 // UpdateShortcutWorker will delete itself when it's done. |
408 UpdateShortcutWorker* worker = new UpdateShortcutWorker(web_contents); | 348 UpdateShortcutWorker* worker = new UpdateShortcutWorker(web_contents); |
409 worker->Run(); | 349 worker->Run(); |
410 #endif // defined(OS_WIN) | 350 #endif // defined(OS_WIN) |
411 } | 351 } |
412 | 352 |
413 void UpdateShortcutInfoForApp(const extensions::Extension& app, | |
414 Profile* profile, | |
415 ShellIntegration::ShortcutInfo* shortcut_info) { | |
416 shortcut_info->extension_id = app.id(); | |
417 shortcut_info->is_platform_app = app.is_platform_app(); | |
418 shortcut_info->url = extensions::AppLaunchInfo::GetLaunchWebURL(&app); | |
419 shortcut_info->title = base::UTF8ToUTF16(app.name()); | |
420 shortcut_info->description = base::UTF8ToUTF16(app.description()); | |
421 shortcut_info->extension_path = app.path(); | |
422 shortcut_info->profile_path = profile->GetPath(); | |
423 shortcut_info->profile_name = | |
424 profile->GetPrefs()->GetString(prefs::kProfileName); | |
425 } | |
426 | |
427 void UpdateShortcutInfoAndIconForApp( | |
428 const extensions::Extension* extension, | |
429 Profile* profile, | |
430 const web_app::ShortcutInfoCallback& callback) { | |
431 ShellIntegration::ShortcutInfo shortcut_info = | |
432 ShortcutInfoForExtensionAndProfile(extension, profile); | |
433 | |
434 std::vector<extensions::ImageLoader::ImageRepresentation> info_list; | |
435 for (size_t i = 0; i < kNumDesiredSizes; ++i) { | |
436 int size = kDesiredSizes[i]; | |
437 extensions::ExtensionResource resource = | |
438 extensions::IconsInfo::GetIconResource( | |
439 extension, size, ExtensionIconSet::MATCH_EXACTLY); | |
440 if (!resource.empty()) { | |
441 info_list.push_back(extensions::ImageLoader::ImageRepresentation( | |
442 resource, | |
443 extensions::ImageLoader::ImageRepresentation::ALWAYS_RESIZE, | |
444 gfx::Size(size, size), | |
445 ui::SCALE_FACTOR_100P)); | |
446 } | |
447 } | |
448 | |
449 if (info_list.empty()) { | |
450 size_t i = kNumDesiredSizes - 1; | |
451 int size = kDesiredSizes[i]; | |
452 | |
453 // If there is no icon at the desired sizes, we will resize what we can get. | |
454 // Making a large icon smaller is preferred to making a small icon larger, | |
455 // so look for a larger icon first: | |
456 extensions::ExtensionResource resource = | |
457 extensions::IconsInfo::GetIconResource( | |
458 extension, size, ExtensionIconSet::MATCH_BIGGER); | |
459 if (resource.empty()) { | |
460 resource = extensions::IconsInfo::GetIconResource( | |
461 extension, size, ExtensionIconSet::MATCH_SMALLER); | |
462 } | |
463 info_list.push_back(extensions::ImageLoader::ImageRepresentation( | |
464 resource, | |
465 extensions::ImageLoader::ImageRepresentation::ALWAYS_RESIZE, | |
466 gfx::Size(size, size), | |
467 ui::SCALE_FACTOR_100P)); | |
468 } | |
469 | |
470 // |info_list| may still be empty at this point, in which case | |
471 // LoadImageFamilyAsync will call the OnImageLoaded callback with an empty | |
472 // image and exit immediately. | |
473 extensions::ImageLoader::Get(profile)->LoadImageFamilyAsync( | |
474 extension, | |
475 info_list, | |
476 base::Bind(&OnImageLoaded, shortcut_info, callback)); | |
477 } | |
478 | |
479 } // namespace web_app | 353 } // namespace web_app |
OLD | NEW |