web_app.cc revision e5d81f57cb97b3b6b7fccc9c5610d21eb81db09d
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/web_applications/web_app.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/i18n/file_util_icu.h" 11e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "base/prefs/pref_service.h" 12868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 13868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h" 15e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chrome/browser/extensions/image_loader.h" 16e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chrome/browser/profiles/profile.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_constants.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/chrome_version_info.h" 19868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/extensions/manifest_handlers/app_launch_info.h" 20e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chrome/common/extensions/manifest_handlers/icons_handler.h" 21e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chrome/common/pref_names.h" 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h" 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h" 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/constants.h" 25f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 26e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "grit/theme_resources.h" 27e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "skia/ext/image_operations.h" 28e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "third_party/skia/include/core/SkBitmap.h" 29e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "ui/base/resource/resource_bundle.h" 30e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "ui/gfx/image/image.h" 31e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "ui/gfx/image/image_family.h" 32e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "ui/gfx/image/image_skia.h" 33e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 34e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#if defined(OS_WIN) 35e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "ui/gfx/icon_util.h" 36e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#endif 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread; 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 42e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#if defined(OS_MACOSX) 43e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst int kDesiredSizes[] = {16, 32, 128, 256, 512}; 44e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst size_t kNumDesiredSizes = arraysize(kDesiredSizes); 45e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#elif defined(OS_LINUX) 46e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Linux supports icons of any size. FreeDesktop Icon Theme Specification states 47e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// that "Minimally you should install a 48x48 icon in the hicolor theme." 48e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst int kDesiredSizes[] = {16, 32, 48, 128, 256, 512}; 49e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst size_t kNumDesiredSizes = arraysize(kDesiredSizes); 50e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#elif defined(OS_WIN) 51e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst int* kDesiredSizes = IconUtil::kIconDimensions; 52e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst size_t kNumDesiredSizes = IconUtil::kNumIconDimensions; 53e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#else 54e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst int kDesiredSizes[] = {32}; 55e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst size_t kNumDesiredSizes = arraysize(kDesiredSizes); 56e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#endif 57e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(TOOLKIT_VIEWS) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Predicator for sorting images from largest to smallest. 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IconPrecedes(const WebApplicationInfo::IconInfo& left, 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const WebApplicationInfo::IconInfo& right) { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return left.width < right.width; 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeleteShortcutsOnFileThread( 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ShellIntegration::ShortcutInfo& shortcut_info) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath shortcut_data_dir = web_app::GetWebAppDataDirectory( 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_info.profile_path, shortcut_info.extension_id, GURL()); 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return web_app::internals::DeletePlatformShortcuts( 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_data_dir, shortcut_info); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UpdateShortcutsOnFileThread( 77a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& old_app_title, 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ShellIntegration::ShortcutInfo& shortcut_info) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath shortcut_data_dir = web_app::GetWebAppDataDirectory( 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_info.profile_path, shortcut_info.extension_id, GURL()); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return web_app::internals::UpdatePlatformShortcuts( 8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) shortcut_data_dir, old_app_title, shortcut_info); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 87e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid OnImageLoaded(ShellIntegration::ShortcutInfo shortcut_info, 88e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch web_app::ShortcutInfoCallback callback, 89e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const gfx::ImageFamily& image_family) { 90e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // If the image failed to load (e.g. if the resource being loaded was empty) 91e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // use the standard application icon. 92e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (image_family.empty()) { 93e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch gfx::Image default_icon = 94e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ResourceBundle::GetSharedInstance().GetImageNamed(IDR_APP_DEFAULT_ICON); 95e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch int size = kDesiredSizes[kNumDesiredSizes - 1]; 96e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch SkBitmap bmp = skia::ImageOperations::Resize( 97e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch *default_icon.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST, 98e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch size, size); 99e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bmp); 100e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // We are on the UI thread, and this image is needed from the FILE thread, 101e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // for creating shortcut icon files. 102e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch image_skia.MakeThreadSafe(); 103e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch shortcut_info.favicon.Add(gfx::Image(image_skia)); 104e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } else { 105e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch shortcut_info.favicon = image_family; 106e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 107e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 108e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch callback.Run(shortcut_info); 109e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 110e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace web_app { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following string is used to build the directory name for 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// shortcuts to chrome applications (the kind which are installed 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from a CRX). Application shortcuts to URLs use the {host}_{path} 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for the name of this directory. Hosts can't include an underscore. 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// By starting this string with an underscore, we ensure that there 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are no naming conflicts. 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char* kCrxAppPrefix = "_crx_"; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internals { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::FilePath GetSanitizedFileName(const base::string16& name) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 127a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::string16 file_name = name; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) std::string file_name = base::UTF16ToUTF8(name); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_util::ReplaceIllegalCharactersInPath(&file_name, '_'); 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return base::FilePath(file_name); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace internals 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 137e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen MurdochShellIntegration::ShortcutInfo ShortcutInfoForExtensionAndProfile( 138e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const extensions::Extension* app, Profile* profile) { 139e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ShellIntegration::ShortcutInfo shortcut_info; 140e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch shortcut_info.extension_id = app->id(); 141e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch shortcut_info.is_platform_app = app->is_platform_app(); 142e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch shortcut_info.url = extensions::AppLaunchInfo::GetLaunchWebURL(app); 143e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch shortcut_info.title = base::UTF8ToUTF16(app->name()); 144e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch shortcut_info.description = base::UTF8ToUTF16(app->description()); 145e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch shortcut_info.extension_path = app->path(); 146e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch shortcut_info.profile_path = profile->GetPath(); 147e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch shortcut_info.profile_name = 148e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch profile->GetPrefs()->GetString(prefs::kProfileName); 149e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch return shortcut_info; 150e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 151e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 152e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid UpdateShortcutInfoAndIconForApp( 153e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const extensions::Extension* extension, 154e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch Profile* profile, 155e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch const web_app::ShortcutInfoCallback& callback) { 156e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ShellIntegration::ShortcutInfo shortcut_info = 157e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ShortcutInfoForExtensionAndProfile(extension, profile); 158e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 159e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch std::vector<extensions::ImageLoader::ImageRepresentation> info_list; 160e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch for (size_t i = 0; i < kNumDesiredSizes; ++i) { 161e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch int size = kDesiredSizes[i]; 162e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch extensions::ExtensionResource resource = 163e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch extensions::IconsInfo::GetIconResource( 164e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch extension, size, ExtensionIconSet::MATCH_EXACTLY); 165e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (!resource.empty()) { 166e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch info_list.push_back(extensions::ImageLoader::ImageRepresentation( 167e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch resource, 168e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch extensions::ImageLoader::ImageRepresentation::ALWAYS_RESIZE, 169e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch gfx::Size(size, size), 170e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ui::SCALE_FACTOR_100P)); 171e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 172e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 173e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 174e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (info_list.empty()) { 175e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch size_t i = kNumDesiredSizes - 1; 176e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch int size = kDesiredSizes[i]; 177e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 178e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // If there is no icon at the desired sizes, we will resize what we can get. 179e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // Making a large icon smaller is preferred to making a small icon larger, 180e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // so look for a larger icon first: 181e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch extensions::ExtensionResource resource = 182e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch extensions::IconsInfo::GetIconResource( 183e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch extension, size, ExtensionIconSet::MATCH_BIGGER); 184e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch if (resource.empty()) { 185e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch resource = extensions::IconsInfo::GetIconResource( 186e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch extension, size, ExtensionIconSet::MATCH_SMALLER); 187e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 188e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch info_list.push_back(extensions::ImageLoader::ImageRepresentation( 189e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch resource, 190e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch extensions::ImageLoader::ImageRepresentation::ALWAYS_RESIZE, 191e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch gfx::Size(size, size), 192e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch ui::SCALE_FACTOR_100P)); 193e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch } 194e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 195e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // |info_list| may still be empty at this point, in which case 196e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // LoadImageFamilyAsync will call the OnImageLoaded callback with an empty 197e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch // image and exit immediately. 198e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch extensions::ImageLoader::Get(profile)->LoadImageFamilyAsync( 199e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch extension, 200e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch info_list, 201e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch base::Bind(&OnImageLoaded, shortcut_info, callback)); 202e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch} 203e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetWebAppDataDirectory(const base::FilePath& profile_path, 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& extension_id, 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& url) { 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(!profile_path.empty()); 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath app_data_dir(profile_path.Append(chrome::kWebAppDirname)); 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!extension_id.empty()) { 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return app_data_dir.AppendASCII( 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) GenerateApplicationNameFromExtensionId(extension_id)); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string host(url.host()); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string scheme(url.has_scheme() ? url.scheme() : "http"); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string port(url.has_port() ? url.port() : "80"); 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string scheme_port(scheme + "_" + port); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN) 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath::StringType host_path(base::UTF8ToUTF16(host)); 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::FilePath::StringType scheme_port_path(base::UTF8ToUTF16(scheme_port)); 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX) 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath::StringType host_path(host); 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath::StringType scheme_port_path(scheme_port); 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return app_data_dir.Append(host_path).Append(scheme_port_path); 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetWebAppDataDirectory(const base::FilePath& profile_path, 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const extensions::Extension& extension) { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return GetWebAppDataDirectory( 234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) profile_path, 235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) extension.id(), 236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) GURL(extensions::AppLaunchInfo::GetLaunchWebURL(&extension))); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GenerateApplicationNameFromInfo( 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ShellIntegration::ShortcutInfo& shortcut_info) { 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!shortcut_info.extension_id.empty()) { 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return web_app::GenerateApplicationNameFromExtensionId( 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_info.extension_id); 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return web_app::GenerateApplicationNameFromURL( 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_info.url); 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GenerateApplicationNameFromURL(const GURL& url) { 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string t; 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t.append(url.host()); 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t.append("_"); 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t.append(url.path()); 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return t; 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GenerateApplicationNameFromExtensionId(const std::string& id) { 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string t(web_app::kCrxAppPrefix); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) t.append(id); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return t; 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetExtensionIdFromApplicationName(const std::string& app_name) { 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string prefix(kCrxAppPrefix); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (app_name.substr(0, prefix.length()) != prefix) 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return std::string(); 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return app_name.substr(prefix.length()); 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CreateShortcuts( 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ShellIntegration::ShortcutInfo& shortcut_info, 273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const ShellIntegration::ShortcutLocations& creation_locations, 274558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch ShortcutCreationReason creation_reason) { 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::FILE, 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(base::IgnoreResult(&CreateShortcutsOnFileThread), 281558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch shortcut_info, creation_locations, creation_reason)); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeleteAllShortcuts(const ShellIntegration::ShortcutInfo& shortcut_info) { 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::FILE, 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::Bind(&DeleteShortcutsOnFileThread, shortcut_info)); 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 293a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)void UpdateAllShortcuts(const base::string16& old_app_title, 29490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) const ShellIntegration::ShortcutInfo& shortcut_info) { 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::PostTask( 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BrowserThread::FILE, 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FROM_HERE, 30090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) base::Bind(&UpdateShortcutsOnFileThread, old_app_title, shortcut_info)); 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CreateShortcutsOnFileThread( 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ShellIntegration::ShortcutInfo& shortcut_info, 305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch const ShellIntegration::ShortcutLocations& creation_locations, 306558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch ShortcutCreationReason creation_reason) { 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::FilePath shortcut_data_dir = GetWebAppDataDirectory( 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_info.profile_path, shortcut_info.extension_id, 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shortcut_info.url); 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return internals::CreatePlatformShortcuts(shortcut_data_dir, shortcut_info, 313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch creation_locations, 314558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch creation_reason); 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsValidUrl(const GURL& url) { 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char* const kValidUrlSchemes[] = { 3195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::kFileScheme, 3205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) content::kFileSystemScheme, 321a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) content::kFtpScheme, 322d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) content::kHttpScheme, 323424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) content::kHttpsScheme, 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::kExtensionScheme, 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < arraysize(kValidUrlSchemes); ++i) { 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (url.SchemeIs(kValidUrlSchemes[i])) 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(TOOLKIT_VIEWS) 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetIconsInfo(const WebApplicationInfo& app_info, 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IconInfoList* icons) { 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(icons); 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icons->clear(); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < app_info.icons.size(); ++i) { 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We only take square shaped icons (i.e. width == height). 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (app_info.icons[i].width == app_info.icons[i].height) { 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) icons->push_back(app_info.icons[i]); 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::sort(icons->begin(), icons->end(), &IconPrecedes); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 35258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if defined(OS_LINUX) 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetWMClassFromAppName(std::string app_name) { 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) file_util::ReplaceIllegalCharactersInPath(&app_name, '_'); 355a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) base::TrimString(app_name, "_", &app_name); 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return app_name; 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace web_app 361