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