15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/web_applications/web_app_ui.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind_helpers.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/path_service.h" 11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/prefs/pref_service.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string16.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/extensions/image_loader.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/tab_helper.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/favicon/favicon_tab_helper.h" 18d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)#include "chrome/browser/history/select_favicon_frames.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/web_applications/web_app.h" 21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/extensions/manifest_handlers/app_launch_info.h" 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/extensions/manifest_handlers/icons_handler.h" 23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/pref_names.h" 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_details.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_registrar.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_source.h" 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/web_contents.h" 29f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "grit/theme_resources.h" 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "skia/ext/image_operations.h" 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/skia/include/core/SkBitmap.h" 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gfx/image/image.h" 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gfx/image/image_family.h" 36c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gfx/image/image_skia.h" 377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_POSIX) && !defined(OS_MACOSX) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/environment.h" 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/shortcut.h" 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/windows_version.h" 46eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "chrome/browser/web_applications/web_app_win.h" 47c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "ui/gfx/icon_util.h" 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::NavigationController; 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_MACOSX) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kDesiredSizes[] = {16, 32, 128, 256, 512}; 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const size_t kNumDesiredSizes = arraysize(kDesiredSizes); 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#elif defined(OS_LINUX) 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Linux supports icons of any size. FreeDesktop Icon Theme Specification states 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// that "Minimally you should install a 48x48 icon in the hicolor theme." 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kDesiredSizes[] = {16, 32, 48, 128, 256, 512}; 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const size_t kNumDesiredSizes = arraysize(kDesiredSizes); 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#elif defined(OS_WIN) 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const int* kDesiredSizes = IconUtil::kIconDimensions; 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const size_t kNumDesiredSizes = IconUtil::kNumIconDimensions; 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kDesiredSizes[] = {32}; 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)const size_t kNumDesiredSizes = arraysize(kDesiredSizes); 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// UpdateShortcutWorker holds all context data needed for update shortcut. 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It schedules a pre-update check to find all shortcuts that needs to be 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// updated. If there are such shortcuts, it schedules icon download and 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// update them when icons are downloaded. It observes TAB_CLOSING notification 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and cancels all the work when the underlying tab is closing. 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class UpdateShortcutWorker : public content::NotificationObserver { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) explicit UpdateShortcutWorker(WebContents* web_contents); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Run(); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Overridden from content::NotificationObserver: 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Observe(int type, 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details); 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Downloads icon via the FaviconTabHelper. 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DownloadIcon(); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Favicon download callback. 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void DidDownloadFavicon( 95d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int requested_size, 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int id, 9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int http_status_code, 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& image_url, 99d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<SkBitmap>& bitmaps, 100d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<gfx::Size>& original_bitmap_sizes); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Checks if shortcuts exists on desktop, start menu and quick launch. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void CheckExistingShortcuts(); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update shortcut files and icons. 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void UpdateShortcuts(); 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void UpdateShortcutsOnFileThread(); 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Callback after shortcuts are updated. 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnShortcutsUpdated(bool); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Deletes the worker on UI thread where it gets created. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DeleteMe(); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DeleteMeOnUIThread(); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::NotificationRegistrar registrar_; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Underlying WebContents whose shortcuts will be updated. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WebContents* web_contents_; 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Icons info from web_contents_'s web app data. 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_app::IconInfoList unprocessed_icons_; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Cached shortcut data from the web_contents_. 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellIntegration::ShortcutInfo shortcut_info_; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Our copy of profile path. 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath profile_path_; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // File name of shortcut/ico file based on app title. 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath file_name_; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Existing shortcuts. 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<base::FilePath> shortcut_files_; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(UpdateShortcutWorker); 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)UpdateShortcutWorker::UpdateShortcutWorker(WebContents* web_contents) 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : web_contents_(web_contents), 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_path_(Profile::FromBrowserContext( 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_contents->GetBrowserContext())->GetPath()) { 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::TabHelper* extensions_tab_helper = 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::TabHelper::FromWebContents(web_contents); 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_app::GetShortcutInfoForTab(web_contents_, &shortcut_info_); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_app::GetIconsInfo(extensions_tab_helper->web_app_info(), 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &unprocessed_icons_); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_name_ = web_app::internals::GetSanitizedFileName(shortcut_info_.title); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) registrar_.Add( 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) this, 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome::NOTIFICATION_TAB_CLOSING, 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<NavigationController>(&web_contents->GetController())); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UpdateShortcutWorker::Run() { 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Starting by downloading app icon. 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadIcon(); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UpdateShortcutWorker::Observe( 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int type, 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationSource& source, 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const content::NotificationDetails& details) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type == chrome::NOTIFICATION_TAB_CLOSING && 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content::Source<NavigationController>(source).ptr() == 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &web_contents_->GetController()) { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Underlying tab is closing. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_contents_ = NULL; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UpdateShortcutWorker::DownloadIcon() { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FetchIcon must run on UI thread because it relies on WebContents 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to download the icon. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (web_contents_ == NULL) { 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteMe(); // We are done if underlying WebContents is gone. 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unprocessed_icons_.empty()) { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // No app icon. Just use the favicon from WebContents. 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateShortcuts(); 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch int preferred_size = std::max(unprocessed_icons_.back().width, 190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch unprocessed_icons_.back().height); 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) web_contents_->DownloadImage( 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) unprocessed_icons_.back().url, 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) true, // favicon 194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch 0, // no maximum size 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&UpdateShortcutWorker::DidDownloadFavicon, 196d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) base::Unretained(this), 197d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) preferred_size)); 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unprocessed_icons_.pop_back(); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void UpdateShortcutWorker::DidDownloadFavicon( 202d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) int requested_size, 2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int id, 20490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) int http_status_code, 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& image_url, 206d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<SkBitmap>& bitmaps, 207d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const std::vector<gfx::Size>& original_sizes) { 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<ui::ScaleFactor> scale_factors; 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) scale_factors.push_back(ui::SCALE_FACTOR_100P); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 211d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) std::vector<size_t> closest_indices; 212d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SelectFaviconFrameIndices(original_sizes, 213d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) scale_factors, 214d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) requested_size, 215d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) &closest_indices, 216d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) NULL); 217d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) size_t closest_index = closest_indices[0]; 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!bitmaps.empty() && !bitmaps[closest_index].isNull()) { 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update icon with download image and update shortcut. 221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) shortcut_info_.favicon.Add( 222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::Image::CreateFrom1xBitmap(bitmaps[closest_index])); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::TabHelper* extensions_tab_helper = 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::TabHelper::FromWebContents(web_contents_); 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions_tab_helper->SetAppIcon(bitmaps[closest_index]); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateShortcuts(); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Try the next icon otherwise. 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DownloadIcon(); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UpdateShortcutWorker::CheckExistingShortcuts() { 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Locations to check to shortcut_paths. 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct { 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int location_id; 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const wchar_t* sub_dir; 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } locations[] = { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::DIR_USER_DESKTOP, 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::DIR_START_MENU, 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }, { 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For Win7, create_in_quick_launch_bar means pinning to taskbar. 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::DIR_APP_DATA, 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (base::win::GetVersion() >= base::win::VERSION_WIN7) ? 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"Microsoft\\Internet Explorer\\Quick Launch\\User Pinned\\TaskBar" : 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"Microsoft\\Internet Explorer\\Quick Launch" 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (int i = 0; i < arraysize(locations); ++i) { 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath path; 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!PathService::Get(locations[i].location_id, &path)) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (locations[i].sub_dir != NULL) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) path = path.Append(locations[i].sub_dir); 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath shortcut_file = path.Append(file_name_). 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ReplaceExtension(FILE_PATH_LITERAL(".lnk")); 2687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (base::PathExists(shortcut_file)) { 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_files_.push_back(shortcut_file); 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UpdateShortcutWorker::UpdateShortcuts() { 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&UpdateShortcutWorker::UpdateShortcutsOnFileThread, 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(this))); 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UpdateShortcutWorker::UpdateShortcutsOnFileThread() { 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath web_app_path = web_app::GetWebAppDataDirectory( 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_path_, shortcut_info_.extension_id, shortcut_info_.url); 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Ensure web_app_path exists. web_app_path could be missing for a legacy 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // shortcut created by Gears. 2887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch if (!base::PathExists(web_app_path) && 289a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) !base::CreateDirectory(web_app_path)) { 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath icon_file = web_app_path.Append(file_name_).ReplaceExtension( 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FILE_PATH_LITERAL(".ico")); 296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) web_app::internals::CheckAndSaveIcon(icon_file, shortcut_info_.favicon); 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Update existing shortcuts' description, icon and app id. 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckExistingShortcuts(); 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!shortcut_files_.empty()) { 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Generates app id from web app url and profile path. 302a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 app_id = ShellIntegration::GetAppModelIdForProfile( 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UTF8ToWide(web_app::GenerateApplicationNameFromURL(shortcut_info_.url)), 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_path_); 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Sanitize description 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shortcut_info_.description.length() >= MAX_PATH) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_info_.description.resize(MAX_PATH - 1); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < shortcut_files_.size(); ++i) { 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::ShortcutProperties shortcut_properties; 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_properties.set_target(shortcut_files_[i]); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_properties.set_description(shortcut_info_.description); 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_properties.set_icon(icon_file, 0); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_properties.set_app_id(app_id); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::CreateOrUpdateShortcutLink( 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_files_[i], shortcut_properties, 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::win::SHORTCUT_UPDATE_EXISTING); 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) OnShortcutsUpdated(true); 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UpdateShortcutWorker::OnShortcutsUpdated(bool) { 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteMe(); // We are done. 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UpdateShortcutWorker::DeleteMe() { 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeleteMeOnUIThread(); 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&UpdateShortcutWorker::DeleteMeOnUIThread, 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Unretained(this))); 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UpdateShortcutWorker::DeleteMeOnUIThread() { 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) delete this; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(OS_WIN) 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void OnImageLoaded(ShellIntegration::ShortcutInfo shortcut_info, 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) web_app::ShortcutInfoCallback callback, 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::Image& image) { 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If the image failed to load (e.g. if the resource being loaded was empty) 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // use the standard application icon. 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (image.IsEmpty()) { 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Image default_icon = 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ResourceBundle::GetSharedInstance().GetImageNamed(IDR_APP_DEFAULT_ICON); 353c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int size = kDesiredSizes[kNumDesiredSizes - 1]; 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SkBitmap bmp = skia::ImageOperations::Resize( 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *default_icon.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST, 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size, size); 357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bmp); 358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We are on the UI thread, and this image is needed from the FILE thread, 359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // for creating shortcut icon files. 360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) image_skia.MakeThreadSafe(); 361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) shortcut_info.favicon.Add(gfx::Image(image_skia)); 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // As described in UpdateShortcutInfoAndIconForApp, image contains all of 364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // the icons, hackily put into a single ImageSkia. Separate them out into 365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // individual ImageSkias and insert them into the icon family. 366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const gfx::ImageSkia& multires_image_skia = image.AsImageSkia(); 36768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // NOTE: We do not call ImageSkia::EnsureRepsForSupportedScales here. 368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // The image reps here are not really for different scale factors (ImageSkia 369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // is just being used as a handy container for multiple images). 370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::vector<gfx::ImageSkiaRep> image_reps = 371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) multires_image_skia.image_reps(); 372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (std::vector<gfx::ImageSkiaRep>::const_iterator it = image_reps.begin(); 373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) it != image_reps.end(); ++it) { 374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) gfx::ImageSkia image_skia(*it); 375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) image_skia.MakeThreadSafe(); 376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) shortcut_info.favicon.Add(image_skia); 377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) callback.Run(shortcut_info); 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace web_app { 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ShellIntegration::ShortcutInfo ShortcutInfoForExtensionAndProfile( 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const extensions::Extension* extension, Profile* profile) { 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ShellIntegration::ShortcutInfo shortcut_info; 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) web_app::UpdateShortcutInfoForApp(*extension, profile, &shortcut_info); 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return shortcut_info; 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetShortcutInfoForTab(WebContents* web_contents, 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ShellIntegration::ShortcutInfo* info) { 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(info); // Must provide a valid info. 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const FaviconTabHelper* favicon_tab_helper = 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FaviconTabHelper::FromWebContents(web_contents); 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const extensions::TabHelper* extensions_tab_helper = 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::TabHelper::FromWebContents(web_contents); 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebApplicationInfo& app_info = extensions_tab_helper->web_app_info(); 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->url = app_info.app_url.is_empty() ? web_contents->GetURL() : 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) app_info.app_url; 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->title = app_info.title.empty() ? 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (web_contents->GetTitle().empty() ? UTF8ToUTF16(info->url.spec()) : 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) web_contents->GetTitle()) : 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) app_info.title; 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->description = app_info.description; 411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) info->favicon.Add(favicon_tab_helper->GetFavicon()); 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile* profile = 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Profile::FromBrowserContext(web_contents->GetBrowserContext()); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) info->profile_path = profile->GetPath(); 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UpdateShortcutForTabContents(WebContents* web_contents) { 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // UpdateShortcutWorker will delete itself when it's done. 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) UpdateShortcutWorker* worker = new UpdateShortcutWorker(web_contents); 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) worker->Run(); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(OS_WIN) 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void UpdateShortcutInfoForApp(const extensions::Extension& app, 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Profile* profile, 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ShellIntegration::ShortcutInfo* shortcut_info) { 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) shortcut_info->extension_id = app.id(); 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) shortcut_info->is_platform_app = app.is_platform_app(); 431868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) shortcut_info->url = extensions::AppLaunchInfo::GetLaunchWebURL(&app); 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) shortcut_info->title = UTF8ToUTF16(app.name()); 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) shortcut_info->description = UTF8ToUTF16(app.description()); 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) shortcut_info->extension_path = app.path(); 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) shortcut_info->profile_path = profile->GetPath(); 436868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) shortcut_info->profile_name = 437868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) profile->GetPrefs()->GetString(prefs::kProfileName); 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void UpdateShortcutInfoAndIconForApp( 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const extensions::Extension& extension, 4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Profile* profile, 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const web_app::ShortcutInfoCallback& callback) { 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ShellIntegration::ShortcutInfo shortcut_info = 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ShortcutInfoForExtensionAndProfile(&extension, profile); 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 447c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We want to load each icon into a separate ImageSkia to insert into an 448c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // ImageFamily, but LoadImagesAsync currently only builds a single ImageSkia. 449c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Hack around this by loading all images into the ImageSkia as 100% 450c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // representations, and later (in OnImageLoaded), pulling them out and 451c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // individually inserting them into an ImageFamily. 452c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // TODO(mgiuca): Have ImageLoader build the ImageFamily directly 453c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // (http://crbug.com/230184). 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) std::vector<extensions::ImageLoader::ImageRepresentation> info_list; 455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < kNumDesiredSizes; ++i) { 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int size = kDesiredSizes[i]; 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::ExtensionResource resource = 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::IconsInfo::GetIconResource( 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &extension, size, ExtensionIconSet::MATCH_EXACTLY); 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!resource.empty()) { 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) info_list.push_back(extensions::ImageLoader::ImageRepresentation( 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) resource, 4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::ImageLoader::ImageRepresentation::RESIZE_WHEN_LARGER, 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Size(size, size), 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::SCALE_FACTOR_100P)); 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (info_list.empty()) { 470c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) size_t i = kNumDesiredSizes - 1; 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int size = kDesiredSizes[i]; 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // If there is no icon at the desired sizes, we will resize what we can get. 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Making a large icon smaller is preferred to making a small icon larger, 4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // so look for a larger icon first: 4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::ExtensionResource resource = 4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::IconsInfo::GetIconResource( 4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &extension, size, ExtensionIconSet::MATCH_BIGGER); 4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (resource.empty()) { 4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) resource = extensions::IconsInfo::GetIconResource( 4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &extension, size, ExtensionIconSet::MATCH_SMALLER); 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) info_list.push_back(extensions::ImageLoader::ImageRepresentation( 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) resource, 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::ImageLoader::ImageRepresentation::RESIZE_WHEN_LARGER, 4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::Size(size, size), 4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::SCALE_FACTOR_100P)); 4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // |info_list| may still be empty at this point, in which case LoadImage 4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // will call the OnImageLoaded callback with an empty image and exit 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // immediately. 4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::ImageLoader::Get(profile)->LoadImagesAsync(&extension, info_list, 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::Bind(&OnImageLoaded, shortcut_info, callback)); 4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace web_app 498