web_app.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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"
16c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/extensions/tab_helper.h"
17c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "chrome/browser/favicon/favicon_tab_helper.h"
18e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chrome/browser/profiles/profile.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_constants.h"
20c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/common/chrome_version_info.h"
21868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
22e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chrome/common/pref_names.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"
26c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/manifest_handlers/icons_handler.h"
27e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "grit/theme_resources.h"
28e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "skia/ext/image_operations.h"
29e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "third_party/skia/include/core/SkBitmap.h"
30e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "ui/base/resource/resource_bundle.h"
31e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "ui/gfx/image/image.h"
32e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "ui/gfx/image/image_family.h"
33e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "ui/gfx/image/image_skia.h"
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "url/url_constants.h"
35e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
36e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#if defined(OS_WIN)
37e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "ui/gfx/icon_util.h"
38e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#endif
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
44a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochtypedef base::Callback<void(const web_app::ShortcutInfo&,
45a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            const extensions::FileHandlersInfo&)> InfoCallback;
46a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
47e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#if defined(OS_MACOSX)
48e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst int kDesiredSizes[] = {16, 32, 128, 256, 512};
49e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst size_t kNumDesiredSizes = arraysize(kDesiredSizes);
50e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#elif defined(OS_LINUX)
51e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Linux supports icons of any size. FreeDesktop Icon Theme Specification states
52e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// that "Minimally you should install a 48x48 icon in the hicolor theme."
53e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst int kDesiredSizes[] = {16, 32, 48, 128, 256, 512};
54e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst size_t kNumDesiredSizes = arraysize(kDesiredSizes);
55e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#elif defined(OS_WIN)
56e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst int* kDesiredSizes = IconUtil::kIconDimensions;
57e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst size_t kNumDesiredSizes = IconUtil::kNumIconDimensions;
58e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#else
59e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst int kDesiredSizes[] = {32};
60e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst size_t kNumDesiredSizes = arraysize(kDesiredSizes);
61e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#endif
62e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(TOOLKIT_VIEWS)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Predicator for sorting images from largest to smallest.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IconPrecedes(const WebApplicationInfo::IconInfo& left,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const WebApplicationInfo::IconInfo& right) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return left.width < right.width;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)base::FilePath GetShortcutDataDir(const web_app::ShortcutInfo& shortcut_info) {
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return web_app::GetWebAppDataDirectory(shortcut_info.profile_path,
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                         shortcut_info.extension_id,
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                         shortcut_info.url);
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
77a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid CreateShortcutsWithInfo(
78a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    web_app::ShortcutCreationReason reason,
79a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const web_app::ShortcutLocations& locations,
80a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const web_app::ShortcutInfo& shortcut_info,
81a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const extensions::FileHandlersInfo& file_handlers_info) {
82c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
83c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
84c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  BrowserThread::PostTask(
85c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      BrowserThread::FILE,
86c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      FROM_HERE,
87a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      base::Bind(
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          base::IgnoreResult(&web_app::internals::CreatePlatformShortcuts),
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          GetShortcutDataDir(shortcut_info),
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          shortcut_info, file_handlers_info, locations, reason));
91c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
92c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
93a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid UpdateAllShortcutsForShortcutInfo(
94a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const base::string16& old_app_title,
95a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const web_app::ShortcutInfo& shortcut_info,
96a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const extensions::FileHandlersInfo& file_handlers_info) {
97a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  BrowserThread::PostTask(
98a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      BrowserThread::FILE,
99a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      FROM_HERE,
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&web_app::internals::UpdatePlatformShortcuts,
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 GetShortcutDataDir(shortcut_info),
102a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 old_app_title, shortcut_info, file_handlers_info));
103a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
104a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
105a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid OnImageLoaded(web_app::ShortcutInfo shortcut_info,
106a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   extensions::FileHandlersInfo file_handlers_info,
107a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   InfoCallback callback,
108e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   const gfx::ImageFamily& image_family) {
109e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // If the image failed to load (e.g. if the resource being loaded was empty)
110e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // use the standard application icon.
111e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (image_family.empty()) {
112e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    gfx::Image default_icon =
113e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        ResourceBundle::GetSharedInstance().GetImageNamed(IDR_APP_DEFAULT_ICON);
114e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    int size = kDesiredSizes[kNumDesiredSizes - 1];
115e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    SkBitmap bmp = skia::ImageOperations::Resize(
116e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          *default_icon.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST,
117e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          size, size);
118e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bmp);
119e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // We are on the UI thread, and this image is needed from the FILE thread,
120e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // for creating shortcut icon files.
121e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    image_skia.MakeThreadSafe();
122e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    shortcut_info.favicon.Add(gfx::Image(image_skia));
123e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  } else {
124e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    shortcut_info.favicon = image_family;
125e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
126e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
127a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  callback.Run(shortcut_info, file_handlers_info);
128a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
129a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
130a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid GetInfoForApp(const extensions::Extension* extension,
131a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   Profile* profile,
132a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   const InfoCallback& callback) {
133a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  web_app::ShortcutInfo shortcut_info =
134a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      web_app::ShortcutInfoForExtensionAndProfile(extension, profile);
1355c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const std::vector<extensions::FileHandlerInfo>* file_handlers =
1365c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      extensions::FileHandlers::GetFileHandlers(extension);
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  extensions::FileHandlersInfo file_handlers_info =
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      file_handlers ? *file_handlers : extensions::FileHandlersInfo();
139a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
140a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  std::vector<extensions::ImageLoader::ImageRepresentation> info_list;
141a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  for (size_t i = 0; i < kNumDesiredSizes; ++i) {
142a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    int size = kDesiredSizes[i];
143a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    extensions::ExtensionResource resource =
144a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        extensions::IconsInfo::GetIconResource(
145a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            extension, size, ExtensionIconSet::MATCH_EXACTLY);
146a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (!resource.empty()) {
147a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      info_list.push_back(extensions::ImageLoader::ImageRepresentation(
148a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          resource,
149a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          extensions::ImageLoader::ImageRepresentation::ALWAYS_RESIZE,
150a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          gfx::Size(size, size),
151a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          ui::SCALE_FACTOR_100P));
152a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    }
153a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
154a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
155a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (info_list.empty()) {
156a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    size_t i = kNumDesiredSizes - 1;
157a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    int size = kDesiredSizes[i];
158a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
159a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // If there is no icon at the desired sizes, we will resize what we can get.
160a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // Making a large icon smaller is preferred to making a small icon larger,
161a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // so look for a larger icon first:
162a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    extensions::ExtensionResource resource =
163a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        extensions::IconsInfo::GetIconResource(
164a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            extension, size, ExtensionIconSet::MATCH_BIGGER);
165a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (resource.empty()) {
166a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      resource = extensions::IconsInfo::GetIconResource(
167a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          extension, size, ExtensionIconSet::MATCH_SMALLER);
168a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    }
169a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    info_list.push_back(extensions::ImageLoader::ImageRepresentation(
170a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        resource,
171a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        extensions::ImageLoader::ImageRepresentation::ALWAYS_RESIZE,
172a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        gfx::Size(size, size),
173a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        ui::SCALE_FACTOR_100P));
174a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
175a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
176a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // |info_list| may still be empty at this point, in which case
177a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // LoadImageFamilyAsync will call the OnImageLoaded callback with an empty
178a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // image and exit immediately.
179a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  extensions::ImageLoader::Get(profile)->LoadImageFamilyAsync(
180a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      extension,
181a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      info_list,
182a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      base::Bind(&OnImageLoaded, shortcut_info, file_handlers_info, callback));
183a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
184a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
185a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid IgnoreFileHandlersInfo(
186a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const web_app::ShortcutInfoCallback& shortcut_info_callback,
187a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const web_app::ShortcutInfo& shortcut_info,
188a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const extensions::FileHandlersInfo& file_handlers_info) {
189a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  shortcut_info_callback.Run(shortcut_info);
190e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
191e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace web_app {
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following string is used to build the directory name for
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// shortcuts to chrome applications (the kind which are installed
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from a CRX).  Application shortcuts to URLs use the {host}_{path}
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for the name of this directory.  Hosts can't include an underscore.
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// By starting this string with an underscore, we ensure that there
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are no naming conflicts.
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char* kCrxAppPrefix = "_crx_";
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internals {
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
206a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::FilePath GetSanitizedFileName(const base::string16& name) {
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
208a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 file_name = name;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string file_name = base::UTF16ToUTF8(name);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_util::ReplaceIllegalCharactersInPath(&file_name, '_');
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::FilePath(file_name);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool CreateShortcutsOnFileThread(ShortcutCreationReason reason,
217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 const ShortcutLocations& locations,
218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 const ShortcutInfo& shortcut_info) {
219c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
220c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return CreatePlatformShortcuts(
222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      GetShortcutDataDir(shortcut_info),
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      shortcut_info, extensions::FileHandlersInfo(), locations, reason);
224c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
225c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace internals
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ShortcutInfo::ShortcutInfo()
229a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    : is_platform_app(false) {
230a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
231a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ShortcutInfo::~ShortcutInfo() {}
233a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ShortcutLocations::ShortcutLocations()
235a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    : on_desktop(false),
236a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      applications_menu_location(APP_MENU_LOCATION_NONE),
237a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      in_quick_launch_bar(false)
238a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#if defined(OS_POSIX)
239a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      , hidden(false)
240a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#endif
241a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      {
242a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
243a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
244c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid GetShortcutInfoForTab(content::WebContents* web_contents,
245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                           ShortcutInfo* info) {
246c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(info);  // Must provide a valid info.
247c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
248c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const FaviconTabHelper* favicon_tab_helper =
249c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      FaviconTabHelper::FromWebContents(web_contents);
250c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const extensions::TabHelper* extensions_tab_helper =
251c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      extensions::TabHelper::FromWebContents(web_contents);
252c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const WebApplicationInfo& app_info = extensions_tab_helper->web_app_info();
253c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
254c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  info->url = app_info.app_url.is_empty() ? web_contents->GetURL() :
255c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                            app_info.app_url;
256c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  info->title = app_info.title.empty() ?
257c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      (web_contents->GetTitle().empty() ? base::UTF8ToUTF16(info->url.spec()) :
258c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                          web_contents->GetTitle()) :
259c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      app_info.title;
260c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  info->description = app_info.description;
261c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  info->favicon.Add(favicon_tab_helper->GetFavicon());
262c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
263c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  Profile* profile =
264c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      Profile::FromBrowserContext(web_contents->GetBrowserContext());
265c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  info->profile_path = profile->GetPath();
266c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
267c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
268c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#if !defined(OS_WIN)
269c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid UpdateShortcutForTabContents(content::WebContents* web_contents) {}
270c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#endif
271c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
272cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)ShortcutInfo ShortcutInfoForExtensionAndProfile(
273e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const extensions::Extension* app, Profile* profile) {
274cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ShortcutInfo shortcut_info;
275e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  shortcut_info.extension_id = app->id();
276e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  shortcut_info.is_platform_app = app->is_platform_app();
277e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  shortcut_info.url = extensions::AppLaunchInfo::GetLaunchWebURL(app);
278e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  shortcut_info.title = base::UTF8ToUTF16(app->name());
279e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  shortcut_info.description = base::UTF8ToUTF16(app->description());
280e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  shortcut_info.extension_path = app->path();
281e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  shortcut_info.profile_path = profile->GetPath();
282e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  shortcut_info.profile_name =
283e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      profile->GetPrefs()->GetString(prefs::kProfileName);
284e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return shortcut_info;
285e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
286e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void UpdateShortcutInfoAndIconForApp(const extensions::Extension* extension,
288cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                     Profile* profile,
289cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                     const ShortcutInfoCallback& callback) {
290a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  GetInfoForApp(extension,
291a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                profile,
292a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                base::Bind(&IgnoreFileHandlersInfo, callback));
293e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
294e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetWebAppDataDirectory(const base::FilePath& profile_path,
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      const std::string& extension_id,
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      const GURL& url) {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!profile_path.empty());
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath app_data_dir(profile_path.Append(chrome::kWebAppDirname));
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension_id.empty()) {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return app_data_dir.AppendASCII(
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GenerateApplicationNameFromExtensionId(extension_id));
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string host(url.host());
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string scheme(url.has_scheme() ? url.scheme() : "http");
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string port(url.has_port() ? url.port() : "80");
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string scheme_port(scheme + "_" + port);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::FilePath::StringType host_path(base::UTF8ToUTF16(host));
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::FilePath::StringType scheme_port_path(base::UTF8ToUTF16(scheme_port));
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath::StringType host_path(host);
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath::StringType scheme_port_path(scheme_port);
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return app_data_dir.Append(host_path).Append(scheme_port_path);
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetWebAppDataDirectory(const base::FilePath& profile_path,
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      const extensions::Extension& extension) {
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetWebAppDataDirectory(
325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      profile_path,
326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      extension.id(),
327868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      GURL(extensions::AppLaunchInfo::GetLaunchWebURL(&extension)));
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
330cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)std::string GenerateApplicationNameFromInfo(const ShortcutInfo& shortcut_info) {
331cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!shortcut_info.extension_id.empty())
332cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return GenerateApplicationNameFromExtensionId(shortcut_info.extension_id);
333cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  else
334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return GenerateApplicationNameFromURL(shortcut_info.url);
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GenerateApplicationNameFromURL(const GURL& url) {
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string t;
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t.append(url.host());
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t.append("_");
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t.append(url.path());
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return t;
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GenerateApplicationNameFromExtensionId(const std::string& id) {
346cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::string t(kCrxAppPrefix);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t.append(id);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return t;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetExtensionIdFromApplicationName(const std::string& app_name) {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string prefix(kCrxAppPrefix);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (app_name.substr(0, prefix.length()) != prefix)
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return std::string();
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return app_name.substr(prefix.length());
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
358cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void CreateShortcutsForShortcutInfo(ShortcutCreationReason reason,
359cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                    const ShortcutLocations& locations,
360cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                    const ShortcutInfo& shortcut_info) {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::FILE,
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
366c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      base::Bind(
367c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          base::IgnoreResult(&web_app::internals::CreateShortcutsOnFileThread),
368c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          reason, locations, shortcut_info));
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
371cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void CreateShortcuts(ShortcutCreationReason reason,
372cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     const ShortcutLocations& locations,
373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     Profile* profile,
374cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     const extensions::Extension* app) {
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
377a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  GetInfoForApp(app,
378a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                profile,
379a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                base::Bind(&CreateShortcutsWithInfo, reason, locations));
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
382c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid DeleteAllShortcuts(Profile* profile, const extensions::Extension* app) {
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ShortcutInfo shortcut_info =
386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ShortcutInfoForExtensionAndProfile(app, profile);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::FILE,
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      base::Bind(&web_app::internals::DeletePlatformShortcuts,
391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 GetShortcutDataDir(shortcut_info), shortcut_info));
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
394c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid UpdateAllShortcuts(const base::string16& old_app_title,
395c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                        Profile* profile,
396c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                        const extensions::Extension* app) {
397c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
399a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  GetInfoForApp(app,
400a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                profile,
401a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                base::Bind(&UpdateAllShortcutsForShortcutInfo, old_app_title));
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsValidUrl(const GURL& url) {
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* const kValidUrlSchemes[] = {
406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      url::kFileScheme,
407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      url::kFileSystemScheme,
408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      url::kFtpScheme,
409010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      url::kHttpScheme,
410010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      url::kHttpsScheme,
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extensions::kExtensionScheme,
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kValidUrlSchemes); ++i) {
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (url.SchemeIs(kValidUrlSchemes[i]))
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(TOOLKIT_VIEWS)
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetIconsInfo(const WebApplicationInfo& app_info,
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  IconInfoList* icons) {
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(icons);
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  icons->clear();
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < app_info.icons.size(); ++i) {
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We only take square shaped icons (i.e. width == height).
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (app_info.icons[i].width == app_info.icons[i].height) {
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      icons->push_back(app_info.icons[i]);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(icons->begin(), icons->end(), &IconPrecedes);
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
43958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if defined(OS_LINUX)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetWMClassFromAppName(std::string app_name) {
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_util::ReplaceIllegalCharactersInPath(&app_name, '_');
442a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::TrimString(app_name, "_", &app_name);
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return app_name;
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace web_app
448