web_app.cc revision 6d86b77056ed63eb6871182f42a9fd5f07550f90
115efc4d597a47e6ba5794d4fd8d561bf6947233cRichard Smith// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith// Use of this source code is governed by a BSD-style license that can be 3c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith// found in the LICENSE file. 4c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 5c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "chrome/browser/web_applications/web_app.h" 6c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 7c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "base/bind.h" 8c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "base/bind_helpers.h" 9c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "base/file_util.h" 10c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "base/i18n/file_util_icu.h" 11c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "base/prefs/pref_service.h" 12c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "base/strings/string_util.h" 13c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "base/strings/utf_string_conversions.h" 14c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "base/threading/thread.h" 15c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "chrome/browser/extensions/extension_ui_util.h" 16c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "chrome/browser/extensions/tab_helper.h" 17c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "chrome/browser/favicon/favicon_tab_helper.h" 18c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "chrome/browser/profiles/profile.h" 19c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "chrome/common/chrome_constants.h" 20c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "chrome/common/chrome_version_info.h" 21c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "chrome/common/extensions/manifest_handlers/app_launch_info.h" 22c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "chrome/common/pref_names.h" 23c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "content/public/browser/browser_thread.h" 24c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "extensions/browser/extension_registry.h" 25c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "extensions/browser/image_loader.h" 26c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "extensions/common/constants.h" 27c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "extensions/common/extension.h" 28c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "extensions/common/extension_set.h" 29c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "extensions/common/manifest_handlers/icons_handler.h" 30c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "grit/theme_resources.h" 31c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "skia/ext/image_operations.h" 32c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "third_party/skia/include/core/SkBitmap.h" 33c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "ui/base/resource/resource_bundle.h" 34c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "ui/gfx/image/image.h" 35c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "ui/gfx/image/image_family.h" 3651201882382fb40c9456a06c7f93d6ddd4a57712Richard Smith#include "ui/gfx/image/image_skia.h" 37c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#include "url/url_constants.h" 38c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 39c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#if defined(OS_WIN) 4051201882382fb40c9456a06c7f93d6ddd4a57712Richard Smith#include "ui/gfx/icon_util.h" 41c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#endif 42c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 43c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithusing content::BrowserThread; 44c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 45c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithnamespace { 46c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 47c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#if defined(OS_MACOSX) 48c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithconst int kDesiredSizes[] = {16, 32, 128, 256, 512}; 49c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithconst size_t kNumDesiredSizes = arraysize(kDesiredSizes); 50c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#elif defined(OS_LINUX) 51c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith// Linux supports icons of any size. FreeDesktop Icon Theme Specification states 52c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith// that "Minimally you should install a 48x48 icon in the hicolor theme." 53c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithconst int kDesiredSizes[] = {16, 32, 48, 128, 256, 512}; 54c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithconst size_t kNumDesiredSizes = arraysize(kDesiredSizes); 55c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#elif defined(OS_WIN) 56c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithconst int* kDesiredSizes = IconUtil::kIconDimensions; 57c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithconst size_t kNumDesiredSizes = IconUtil::kNumIconDimensions; 58c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#else 5908d6e032a2a0a8656d12b3b7b93942987bb12eb7Richard Smithconst int kDesiredSizes[] = {32}; 60c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithconst size_t kNumDesiredSizes = arraysize(kDesiredSizes); 61c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#endif 62c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 63c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#if defined(TOOLKIT_VIEWS) 64c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith// Predicator for sorting images from largest to smallest. 65c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithbool IconPrecedes(const WebApplicationInfo::IconInfo& left, 66c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith const WebApplicationInfo::IconInfo& right) { 6708d6e032a2a0a8656d12b3b7b93942987bb12eb7Richard Smith return left.width < right.width; 68c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith} 69c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#endif 7008d6e032a2a0a8656d12b3b7b93942987bb12eb7Richard Smith 71c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithbase::FilePath GetShortcutDataDir(const web_app::ShortcutInfo& shortcut_info) { 72c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith return web_app::GetWebAppDataDirectory(shortcut_info.profile_path, 73c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith shortcut_info.extension_id, 74c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith shortcut_info.url); 75c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith} 76c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 77c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithvoid CreateShortcutsWithInfo( 78c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith web_app::ShortcutCreationReason reason, 79c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith const web_app::ShortcutLocations& locations, 80c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith const web_app::ShortcutInfo& shortcut_info, 81099e7f647ccda915513f2b2ec53352dc756082d3Richard Smith const extensions::FileHandlersInfo& file_handlers_info) { 82c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 83c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 84c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith BrowserThread::PostTask( 85c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith BrowserThread::FILE, 86c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith FROM_HERE, 87099e7f647ccda915513f2b2ec53352dc756082d3Richard Smith base::Bind( 88c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith base::IgnoreResult(&web_app::internals::CreatePlatformShortcuts), 89c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith GetShortcutDataDir(shortcut_info), 9008d6e032a2a0a8656d12b3b7b93942987bb12eb7Richard Smith shortcut_info, file_handlers_info, locations, reason)); 91c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith} 92c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 93c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithvoid UpdateAllShortcutsForShortcutInfo( 94c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith const base::string16& old_app_title, 95c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith const web_app::ShortcutInfo& shortcut_info, 96c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith const extensions::FileHandlersInfo& file_handlers_info) { 97c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith BrowserThread::PostTask( 981e7fc3d31e17fbe314f86de96aac6e9a2f297167Richard Smith BrowserThread::FILE, 99c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith FROM_HERE, 100c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith base::Bind(&web_app::internals::UpdatePlatformShortcuts, 101c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith GetShortcutDataDir(shortcut_info), 1021e7fc3d31e17fbe314f86de96aac6e9a2f297167Richard Smith old_app_title, shortcut_info, file_handlers_info)); 103c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith} 104c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 105c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithvoid OnImageLoaded(web_app::ShortcutInfo shortcut_info, 106c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith extensions::FileHandlersInfo file_handlers_info, 10708d6e032a2a0a8656d12b3b7b93942987bb12eb7Richard Smith web_app::InfoCallback callback, 10808d6e032a2a0a8656d12b3b7b93942987bb12eb7Richard Smith const gfx::ImageFamily& image_family) { 109c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith // If the image failed to load (e.g. if the resource being loaded was empty) 110c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith // use the standard application icon. 111c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith if (image_family.empty()) { 112c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith gfx::Image default_icon = 113c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith ResourceBundle::GetSharedInstance().GetImageNamed(IDR_APP_DEFAULT_ICON); 114c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith int size = kDesiredSizes[kNumDesiredSizes - 1]; 115c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith SkBitmap bmp = skia::ImageOperations::Resize( 116c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith *default_icon.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST, 117c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith size, size); 118c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bmp); 119c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith // We are on the UI thread, and this image is needed from the FILE thread, 120395f1c08ff720be7df6535a86df14b6d36a2d57aRichard Smith // for creating shortcut icon files. 121395f1c08ff720be7df6535a86df14b6d36a2d57aRichard Smith image_skia.MakeThreadSafe(); 122f72fccf533bca206af8e75d041c29db99e6a7f2cRichard Smith shortcut_info.favicon.Add(gfx::Image(image_skia)); 123c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith } else { 1248ef7b203332b0c8d65876a1f5e6d1db4e6f40e4bRichard Smith shortcut_info.favicon = image_family; 125c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith } 126c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 127c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith callback.Run(shortcut_info, file_handlers_info); 128c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith} 129c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 130c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithvoid IgnoreFileHandlersInfo( 131789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smith const web_app::ShortcutInfoCallback& shortcut_info_callback, 132789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smith const web_app::ShortcutInfo& shortcut_info, 133789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smith const extensions::FileHandlersInfo& file_handlers_info) { 134789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smith shortcut_info_callback.Run(shortcut_info); 135789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smith} 1363df61308ddfbdba0897b762a129b5a38750c87d0Richard Smith 137789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smith} // namespace 138789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smith 139789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smithnamespace web_app { 140789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smith 141789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smith// The following string is used to build the directory name for 142789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smith// shortcuts to chrome applications (the kind which are installed 143789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smith// from a CRX). Application shortcuts to URLs use the {host}_{path} 144789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smith// for the name of this directory. Hosts can't include an underscore. 145789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smith// By starting this string with an underscore, we ensure that there 146789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smith// are no naming conflicts. 147925d8e7c0f18e03dc4bc634b3c6c1ec09373d993Richard Smithstatic const char kCrxAppPrefix[] = "_crx_"; 148925d8e7c0f18e03dc4bc634b3c6c1ec09373d993Richard Smith 149925d8e7c0f18e03dc4bc634b3c6c1ec09373d993Richard Smithnamespace internals { 150925d8e7c0f18e03dc4bc634b3c6c1ec09373d993Richard Smith 151925d8e7c0f18e03dc4bc634b3c6c1ec09373d993Richard Smithvoid GetInfoForApp(const extensions::Extension* extension, 152789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smith Profile* profile, 153789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smith const InfoCallback& callback) { 154789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smith web_app::ShortcutInfo shortcut_info = 155789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smith web_app::ShortcutInfoForExtensionAndProfile(extension, profile); 156789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smith const std::vector<extensions::FileHandlerInfo>* file_handlers = 157789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smith extensions::FileHandlers::GetFileHandlers(extension); 158789f9b6be5df6e5151ac35e68416cdf550db1196Richard Smith extensions::FileHandlersInfo file_handlers_info = 159c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith file_handlers ? *file_handlers : extensions::FileHandlersInfo(); 160c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 161c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith std::vector<extensions::ImageLoader::ImageRepresentation> info_list; 162c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith for (size_t i = 0; i < kNumDesiredSizes; ++i) { 163c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith int size = kDesiredSizes[i]; 164c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith extensions::ExtensionResource resource = 165c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith extensions::IconsInfo::GetIconResource( 166c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith extension, size, ExtensionIconSet::MATCH_EXACTLY); 16761e616206413d1779c7545c7a8ad1ce1129ad9c1Richard Smith if (!resource.empty()) { 168c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith info_list.push_back(extensions::ImageLoader::ImageRepresentation( 169244ee7b89a483fd3764637abdf95de2893b437d0Richard Smith resource, 170c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith extensions::ImageLoader::ImageRepresentation::ALWAYS_RESIZE, 171b4e85ed51905fc94378d7b4ff62b06e0d08042b7Richard Smith gfx::Size(size, size), 172b4e85ed51905fc94378d7b4ff62b06e0d08042b7Richard Smith ui::SCALE_FACTOR_100P)); 173b4e85ed51905fc94378d7b4ff62b06e0d08042b7Richard Smith } 174b4e85ed51905fc94378d7b4ff62b06e0d08042b7Richard Smith } 175b4e85ed51905fc94378d7b4ff62b06e0d08042b7Richard Smith 176b4e85ed51905fc94378d7b4ff62b06e0d08042b7Richard Smith if (info_list.empty()) { 177b4e85ed51905fc94378d7b4ff62b06e0d08042b7Richard Smith size_t i = kNumDesiredSizes - 1; 178b4e85ed51905fc94378d7b4ff62b06e0d08042b7Richard Smith int size = kDesiredSizes[i]; 179b4e85ed51905fc94378d7b4ff62b06e0d08042b7Richard Smith 180b4e85ed51905fc94378d7b4ff62b06e0d08042b7Richard Smith // If there is no icon at the desired sizes, we will resize what we can get. 181b4e85ed51905fc94378d7b4ff62b06e0d08042b7Richard Smith // Making a large icon smaller is preferred to making a small icon larger, 182b4e85ed51905fc94378d7b4ff62b06e0d08042b7Richard Smith // so look for a larger icon first: 183b4e85ed51905fc94378d7b4ff62b06e0d08042b7Richard Smith extensions::ExtensionResource resource = 184b4e85ed51905fc94378d7b4ff62b06e0d08042b7Richard Smith extensions::IconsInfo::GetIconResource( 185b4e85ed51905fc94378d7b4ff62b06e0d08042b7Richard Smith extension, size, ExtensionIconSet::MATCH_BIGGER); 186b4e85ed51905fc94378d7b4ff62b06e0d08042b7Richard Smith if (resource.empty()) { 187b4e85ed51905fc94378d7b4ff62b06e0d08042b7Richard Smith resource = extensions::IconsInfo::GetIconResource( 188b4e85ed51905fc94378d7b4ff62b06e0d08042b7Richard Smith extension, size, ExtensionIconSet::MATCH_SMALLER); 189b4e85ed51905fc94378d7b4ff62b06e0d08042b7Richard Smith } 190b4e85ed51905fc94378d7b4ff62b06e0d08042b7Richard Smith info_list.push_back(extensions::ImageLoader::ImageRepresentation( 191b04035a7b1a3c9b93cea72ae56dd2ea6e787bae9Richard Smith resource, 192b04035a7b1a3c9b93cea72ae56dd2ea6e787bae9Richard Smith extensions::ImageLoader::ImageRepresentation::ALWAYS_RESIZE, 193b04035a7b1a3c9b93cea72ae56dd2ea6e787bae9Richard Smith gfx::Size(size, size), 194b04035a7b1a3c9b93cea72ae56dd2ea6e787bae9Richard Smith ui::SCALE_FACTOR_100P)); 195b04035a7b1a3c9b93cea72ae56dd2ea6e787bae9Richard Smith } 196b04035a7b1a3c9b93cea72ae56dd2ea6e787bae9Richard Smith 197b04035a7b1a3c9b93cea72ae56dd2ea6e787bae9Richard Smith // |info_list| may still be empty at this point, in which case 198b04035a7b1a3c9b93cea72ae56dd2ea6e787bae9Richard Smith // LoadImageFamilyAsync will call the OnImageLoaded callback with an empty 199b04035a7b1a3c9b93cea72ae56dd2ea6e787bae9Richard Smith // image and exit immediately. 200f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith extensions::ImageLoader::Get(profile)->LoadImageFamilyAsync( 201f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith extension, 202f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith info_list, 203f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith base::Bind(&OnImageLoaded, shortcut_info, file_handlers_info, callback)); 204f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith} 205f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith 206f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smithbase::FilePath GetSanitizedFileName(const base::string16& name) { 207f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith#if defined(OS_WIN) 208f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith base::string16 file_name = name; 209b4e85ed51905fc94378d7b4ff62b06e0d08042b7Richard Smith#else 2107b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith std::string file_name = base::UTF16ToUTF8(name); 2117b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith#endif 2127b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith file_util::ReplaceIllegalCharactersInPath(&file_name, '_'); 2137b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith return base::FilePath(file_name); 2147b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith} 2157b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith 2167b48a2986345480241f3b8209f71bb21b0530b4fRichard Smithbool CreateShortcutsOnFileThread(ShortcutCreationReason reason, 2177b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith const ShortcutLocations& locations, 2187b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith const ShortcutInfo& shortcut_info) { 2197b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 2207b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith 2217b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith return CreatePlatformShortcuts( 2227b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith GetShortcutDataDir(shortcut_info), 2237b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith shortcut_info, extensions::FileHandlersInfo(), locations, reason); 2247b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith} 2257b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith 2267b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith} // namespace internals 2277b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith 2287b48a2986345480241f3b8209f71bb21b0530b4fRichard SmithShortcutInfo::ShortcutInfo() 2297b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith : is_platform_app(false) { 2307b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith} 2317b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith 2327b48a2986345480241f3b8209f71bb21b0530b4fRichard SmithShortcutInfo::~ShortcutInfo() {} 2337b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith 2347b48a2986345480241f3b8209f71bb21b0530b4fRichard SmithShortcutLocations::ShortcutLocations() 2357b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith : on_desktop(false), 23615efc4d597a47e6ba5794d4fd8d561bf6947233cRichard Smith applications_menu_location(APP_MENU_LOCATION_NONE), 23715efc4d597a47e6ba5794d4fd8d561bf6947233cRichard Smith in_quick_launch_bar(false) { 23815efc4d597a47e6ba5794d4fd8d561bf6947233cRichard Smith} 23915efc4d597a47e6ba5794d4fd8d561bf6947233cRichard Smith 24015efc4d597a47e6ba5794d4fd8d561bf6947233cRichard Smithvoid GetShortcutInfoForTab(content::WebContents* web_contents, 24115efc4d597a47e6ba5794d4fd8d561bf6947233cRichard Smith ShortcutInfo* info) { 24215efc4d597a47e6ba5794d4fd8d561bf6947233cRichard Smith DCHECK(info); // Must provide a valid info. 24315efc4d597a47e6ba5794d4fd8d561bf6947233cRichard Smith 2447b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith const FaviconTabHelper* favicon_tab_helper = 2457b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith FaviconTabHelper::FromWebContents(web_contents); 2467b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith const extensions::TabHelper* extensions_tab_helper = 2477b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith extensions::TabHelper::FromWebContents(web_contents); 2487b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith const WebApplicationInfo& app_info = extensions_tab_helper->web_app_info(); 2497b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith 2507b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith info->url = app_info.app_url.is_empty() ? web_contents->GetURL() : 2517b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith app_info.app_url; 2527b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith info->title = app_info.title.empty() ? 2537b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith (web_contents->GetTitle().empty() ? base::UTF8ToUTF16(info->url.spec()) : 2547b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith web_contents->GetTitle()) : 2557b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith app_info.title; 2567b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith info->description = app_info.description; 2577b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith info->favicon.Add(favicon_tab_helper->GetFavicon()); 2587b48a2986345480241f3b8209f71bb21b0530b4fRichard Smith 259c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith Profile* profile = 260c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith Profile::FromBrowserContext(web_contents->GetBrowserContext()); 261c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith info->profile_path = profile->GetPath(); 262c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith} 263c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 264c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#if !defined(OS_WIN) 265c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithvoid UpdateShortcutForTabContents(content::WebContents* web_contents) {} 266c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#endif 267c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 268c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard SmithShortcutInfo ShortcutInfoForExtensionAndProfile( 2697098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith const extensions::Extension* app, Profile* profile) { 2707098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith ShortcutInfo shortcut_info; 2717098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith shortcut_info.extension_id = app->id(); 2727098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith shortcut_info.is_platform_app = app->is_platform_app(); 2737098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith shortcut_info.url = extensions::AppLaunchInfo::GetLaunchWebURL(app); 2749ec7197796a2730d54ae7f632553b5311b2ba3b5Richard Smith shortcut_info.title = base::UTF8ToUTF16(app->name()); 2757098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith shortcut_info.description = base::UTF8ToUTF16(app->description()); 2767098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith shortcut_info.extension_path = app->path(); 2779ec7197796a2730d54ae7f632553b5311b2ba3b5Richard Smith shortcut_info.profile_path = profile->GetPath(); 2787098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith shortcut_info.profile_name = 2799ec7197796a2730d54ae7f632553b5311b2ba3b5Richard Smith profile->GetPrefs()->GetString(prefs::kProfileName); 2807098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith return shortcut_info; 2817098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith} 2827098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith 2837098cbd601ad915aed22d4b5850da99359f25bf3Richard Smithvoid UpdateShortcutInfoAndIconForApp(const extensions::Extension* extension, 2847098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith Profile* profile, 2857098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith const ShortcutInfoCallback& callback) { 2867098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith web_app::internals::GetInfoForApp( 2877098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith extension, profile, base::Bind(&IgnoreFileHandlersInfo, callback)); 288282e7e66748cc6dd14d6f7f2cb52e5373c531e61Richard Smith} 2897098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith 2907098cbd601ad915aed22d4b5850da99359f25bf3Richard Smithbool ShouldCreateShortcutFor(Profile* profile, 2919ec7197796a2730d54ae7f632553b5311b2ba3b5Richard Smith const extensions::Extension* extension) { 2927098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith return extension->is_platform_app() && 2937098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith extension->location() != extensions::Manifest::COMPONENT && 2949ec7197796a2730d54ae7f632553b5311b2ba3b5Richard Smith extensions::ui_util::CanDisplayInAppLauncher(extension, profile); 2959ec7197796a2730d54ae7f632553b5311b2ba3b5Richard Smith} 2969ec7197796a2730d54ae7f632553b5311b2ba3b5Richard Smith 2977098cbd601ad915aed22d4b5850da99359f25bf3Richard Smithbase::FilePath GetWebAppDataDirectory(const base::FilePath& profile_path, 2989ec7197796a2730d54ae7f632553b5311b2ba3b5Richard Smith const std::string& extension_id, 2997098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith const GURL& url) { 3007098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith DCHECK(!profile_path.empty()); 3017098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith base::FilePath app_data_dir(profile_path.Append(chrome::kWebAppDirname)); 3027098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith 3037098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith if (!extension_id.empty()) { 3047098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith return app_data_dir.AppendASCII( 305282e7e66748cc6dd14d6f7f2cb52e5373c531e61Richard Smith GenerateApplicationNameFromExtensionId(extension_id)); 3067098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith } 307c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 3087098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith std::string host(url.host()); 3097098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith std::string scheme(url.has_scheme() ? url.scheme() : "http"); 3107098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith std::string port(url.has_port() ? url.port() : "80"); 311c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith std::string scheme_port(scheme + "_" + port); 312c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 313c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#if defined(OS_WIN) 314c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith base::FilePath::StringType host_path(base::UTF8ToUTF16(host)); 315c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith base::FilePath::StringType scheme_port_path(base::UTF8ToUTF16(scheme_port)); 316c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#elif defined(OS_POSIX) 317c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith base::FilePath::StringType host_path(host); 318f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith base::FilePath::StringType scheme_port_path(scheme_port); 319f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith#endif 320f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith 321f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith return app_data_dir.Append(host_path).Append(scheme_port_path); 322f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith} 323f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith 324f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smithbase::FilePath GetWebAppDataDirectory(const base::FilePath& profile_path, 325f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith const extensions::Extension& extension) { 326f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith return GetWebAppDataDirectory( 327f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith profile_path, 328f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith extension.id(), 329f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith GURL(extensions::AppLaunchInfo::GetLaunchWebURL(&extension))); 330f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith} 331f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smith 332f15fda02e9c8c82b4a716618f4010b9af8bff796Richard Smithstd::string GenerateApplicationNameFromInfo(const ShortcutInfo& shortcut_info) { 333c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith if (!shortcut_info.extension_id.empty()) 334c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith return GenerateApplicationNameFromExtensionId(shortcut_info.extension_id); 335c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith else 336c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith return GenerateApplicationNameFromURL(shortcut_info.url); 337c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith} 338c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 339c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithstd::string GenerateApplicationNameFromURL(const GURL& url) { 3407098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith std::string t; 341c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith t.append(url.host()); 342c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith t.append("_"); 343c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith t.append(url.path()); 344c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith return t; 345099e7f647ccda915513f2b2ec53352dc756082d3Richard Smith} 346099e7f647ccda915513f2b2ec53352dc756082d3Richard Smith 347c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithstd::string GenerateApplicationNameFromExtensionId(const std::string& id) { 348c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith std::string t(kCrxAppPrefix); 349c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith t.append(id); 350c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith return t; 351c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith} 352c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 3537098cbd601ad915aed22d4b5850da99359f25bf3Richard Smithstd::string GetExtensionIdFromApplicationName(const std::string& app_name) { 3547098cbd601ad915aed22d4b5850da99359f25bf3Richard Smith std::string prefix(kCrxAppPrefix); 355c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith if (app_name.substr(0, prefix.length()) != prefix) 356c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith return std::string(); 357c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith return app_name.substr(prefix.length()); 358c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith} 359c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 360099e7f647ccda915513f2b2ec53352dc756082d3Richard Smithvoid CreateShortcutsForShortcutInfo(ShortcutCreationReason reason, 361c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith const ShortcutLocations& locations, 362c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith const ShortcutInfo& shortcut_info) { 363c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 364c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 365c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith BrowserThread::PostTask( 366c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith BrowserThread::FILE, 367c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith FROM_HERE, 368c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith base::Bind( 369c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith base::IgnoreResult(&web_app::internals::CreateShortcutsOnFileThread), 370c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith reason, locations, shortcut_info)); 371c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith} 372c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 373c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithvoid CreateShortcuts(ShortcutCreationReason reason, 374c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith const ShortcutLocations& locations, 375c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith Profile* profile, 376c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith const extensions::Extension* app) { 377c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 378c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 379c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith if (!ShouldCreateShortcutFor(profile, app)) 380c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith return; 381c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 382c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith internals::GetInfoForApp( 383c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith app, profile, base::Bind(&CreateShortcutsWithInfo, reason, locations)); 384c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith} 385c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 386c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithvoid DeleteAllShortcuts(Profile* profile, const extensions::Extension* app) { 387c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 388c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 389c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith ShortcutInfo shortcut_info = 390c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith ShortcutInfoForExtensionAndProfile(app, profile); 391c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith BrowserThread::PostTask( 392282e7e66748cc6dd14d6f7f2cb52e5373c531e61Richard Smith BrowserThread::FILE, 393c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith FROM_HERE, 394c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith base::Bind(&web_app::internals::DeletePlatformShortcuts, 395c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith GetShortcutDataDir(shortcut_info), shortcut_info)); 396c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith} 397c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 398c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithvoid UpdateAllShortcuts(const base::string16& old_app_title, 399c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith Profile* profile, 400c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith const extensions::Extension* app) { 401c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 402c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 403c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith internals::GetInfoForApp( 404c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith app, 405c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith profile, 406c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith base::Bind(&UpdateAllShortcutsForShortcutInfo, old_app_title)); 407c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith} 408c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 409c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithbool IsValidUrl(const GURL& url) { 410c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith static const char* const kValidUrlSchemes[] = { 411c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith url::kFileScheme, 412c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith url::kFileSystemScheme, 413c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith url::kFtpScheme, 414c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith url::kHttpScheme, 41547d2145675099893d702be4bc06bd9f26d8ddd13Richard Smith url::kHttpsScheme, 416c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith extensions::kExtensionScheme, 417c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith }; 41847d2145675099893d702be4bc06bd9f26d8ddd13Richard Smith 419c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith for (size_t i = 0; i < arraysize(kValidUrlSchemes); ++i) { 420c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith if (url.SchemeIs(kValidUrlSchemes[i])) 421c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith return true; 422c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith } 423c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 424c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith return false; 425c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith} 426282e7e66748cc6dd14d6f7f2cb52e5373c531e61Richard Smith 427282e7e66748cc6dd14d6f7f2cb52e5373c531e61Richard Smith#if defined(TOOLKIT_VIEWS) 428c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithvoid GetIconsInfo(const WebApplicationInfo& app_info, 429c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith IconInfoList* icons) { 430c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith DCHECK(icons); 431c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 432c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith icons->clear(); 433c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith for (size_t i = 0; i < app_info.icons.size(); ++i) { 434c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith // We only take square shaped icons (i.e. width == height). 435c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith if (app_info.icons[i].width == app_info.icons[i].height) { 436c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith icons->push_back(app_info.icons[i]); 437c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith } 438c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith } 439c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 440c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith std::sort(icons->begin(), icons->end(), &IconPrecedes); 441c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith} 442c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#endif 443c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 444c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#if defined(OS_LINUX) 445c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smithstd::string GetWMClassFromAppName(std::string app_name) { 446c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith file_util::ReplaceIllegalCharactersInPath(&app_name, '_'); 447c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith base::TrimString(app_name, "_", &app_name); 448c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith return app_name; 449c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith} 450c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith#endif 451c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith 452c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith} // namespace web_app 453c1c5f27c64dfc3332d53ad30e44d626e4f9afac3Richard Smith