web_app.cc revision a02191e04bc25c4935f804f2c080ae28663d096d
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"
21a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "chrome/common/extensions/api/file_handlers/file_handlers_parser.h"
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/common/extensions/manifest_handlers/app_launch_info.h"
23e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "chrome/common/pref_names.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/constants.h"
27f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h"
28c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "extensions/common/manifest_handlers/icons_handler.h"
29e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "grit/theme_resources.h"
30e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "skia/ext/image_operations.h"
31e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "third_party/skia/include/core/SkBitmap.h"
32e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "ui/base/resource/resource_bundle.h"
33e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "ui/gfx/image/image.h"
34e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "ui/gfx/image/image_family.h"
35e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "ui/gfx/image/image_skia.h"
36e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
37e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#if defined(OS_WIN)
38e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#include "ui/gfx/icon_util.h"
39e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#endif
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
45a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochtypedef base::Callback<void(const web_app::ShortcutInfo&,
46a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                            const extensions::FileHandlersInfo&)> InfoCallback;
47a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
48e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#if defined(OS_MACOSX)
49e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst int kDesiredSizes[] = {16, 32, 128, 256, 512};
50e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst size_t kNumDesiredSizes = arraysize(kDesiredSizes);
51e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#elif defined(OS_LINUX)
52e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// Linux supports icons of any size. FreeDesktop Icon Theme Specification states
53e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch// that "Minimally you should install a 48x48 icon in the hicolor theme."
54e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst int kDesiredSizes[] = {16, 32, 48, 128, 256, 512};
55e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst size_t kNumDesiredSizes = arraysize(kDesiredSizes);
56e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#elif defined(OS_WIN)
57e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst int* kDesiredSizes = IconUtil::kIconDimensions;
58e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst size_t kNumDesiredSizes = IconUtil::kNumIconDimensions;
59e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#else
60e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst int kDesiredSizes[] = {32};
61e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochconst size_t kNumDesiredSizes = arraysize(kDesiredSizes);
62e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch#endif
63e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(TOOLKIT_VIEWS)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Predicator for sorting images from largest to smallest.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IconPrecedes(const WebApplicationInfo::IconInfo& left,
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const WebApplicationInfo::IconInfo& right) {
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return left.width < right.width;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochbool CreateShortcutsWithInfoOnFileThread(
73a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    web_app::ShortcutCreationReason reason,
74a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const web_app::ShortcutLocations& locations,
75a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const web_app::ShortcutInfo& shortcut_info,
76a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const extensions::FileHandlersInfo& file_handlers_info) {
77a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
78a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
79a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  base::FilePath shortcut_data_dir =
80a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      web_app::GetWebAppDataDirectory(shortcut_info.profile_path,
81a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                      shortcut_info.extension_id,
82a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                                      shortcut_info.url);
83a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return web_app::internals::CreatePlatformShortcuts(
84a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      shortcut_data_dir, shortcut_info, file_handlers_info, locations, reason);
85a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
86a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DeleteShortcutsOnFileThread(
88a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const web_app::ShortcutInfo& shortcut_info) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath shortcut_data_dir = web_app::GetWebAppDataDirectory(
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shortcut_info.profile_path, shortcut_info.extension_id, GURL());
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return web_app::internals::DeletePlatformShortcuts(
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shortcut_data_dir, shortcut_info);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void UpdateShortcutsOnFileThread(
98a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    const base::string16& old_app_title,
99a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const web_app::ShortcutInfo& shortcut_info,
100a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const extensions::FileHandlersInfo& file_handlers_info) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath shortcut_data_dir = web_app::GetWebAppDataDirectory(
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      shortcut_info.profile_path, shortcut_info.extension_id, GURL());
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return web_app::internals::UpdatePlatformShortcuts(
106a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      shortcut_data_dir, old_app_title, shortcut_info, file_handlers_info);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
109a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid CreateShortcutsWithInfo(
110a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    web_app::ShortcutCreationReason reason,
111a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const web_app::ShortcutLocations& locations,
112a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const web_app::ShortcutInfo& shortcut_info,
113a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const extensions::FileHandlersInfo& file_handlers_info) {
114c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
115c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
116c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  BrowserThread::PostTask(
117c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      BrowserThread::FILE,
118c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      FROM_HERE,
119a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      base::Bind(
120a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          base::IgnoreResult(&CreateShortcutsWithInfoOnFileThread),
121a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          reason, locations, shortcut_info, file_handlers_info));
122c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
123c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
124a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid UpdateAllShortcutsForShortcutInfo(
125a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const base::string16& old_app_title,
126a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const web_app::ShortcutInfo& shortcut_info,
127a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const extensions::FileHandlersInfo& file_handlers_info) {
128a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  BrowserThread::PostTask(
129a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      BrowserThread::FILE,
130a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      FROM_HERE,
131a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      base::Bind(&UpdateShortcutsOnFileThread,
132a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                 old_app_title, shortcut_info, file_handlers_info));
133a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
134a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
135a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid OnImageLoaded(web_app::ShortcutInfo shortcut_info,
136a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   extensions::FileHandlersInfo file_handlers_info,
137a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   InfoCallback callback,
138e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch                   const gfx::ImageFamily& image_family) {
139e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // If the image failed to load (e.g. if the resource being loaded was empty)
140e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  // use the standard application icon.
141e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  if (image_family.empty()) {
142e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    gfx::Image default_icon =
143e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch        ResourceBundle::GetSharedInstance().GetImageNamed(IDR_APP_DEFAULT_ICON);
144e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    int size = kDesiredSizes[kNumDesiredSizes - 1];
145e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    SkBitmap bmp = skia::ImageOperations::Resize(
146e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          *default_icon.ToSkBitmap(), skia::ImageOperations::RESIZE_BEST,
147e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch          size, size);
148e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bmp);
149e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // We are on the UI thread, and this image is needed from the FILE thread,
150e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    // for creating shortcut icon files.
151e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    image_skia.MakeThreadSafe();
152e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    shortcut_info.favicon.Add(gfx::Image(image_skia));
153e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  } else {
154e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    shortcut_info.favicon = image_family;
155e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  }
156e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
157a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  callback.Run(shortcut_info, file_handlers_info);
158a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
159a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
160a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid GetInfoForApp(const extensions::Extension* extension,
161a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   Profile* profile,
162a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                   const InfoCallback& callback) {
163a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  web_app::ShortcutInfo shortcut_info =
164a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      web_app::ShortcutInfoForExtensionAndProfile(extension, profile);
165a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  extensions::FileHandlersInfo file_handlers_info(
166a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      extensions::FileHandlers::GetFileHandlers(extension));
167a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
168a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  std::vector<extensions::ImageLoader::ImageRepresentation> info_list;
169a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  for (size_t i = 0; i < kNumDesiredSizes; ++i) {
170a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    int size = kDesiredSizes[i];
171a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    extensions::ExtensionResource resource =
172a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        extensions::IconsInfo::GetIconResource(
173a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            extension, size, ExtensionIconSet::MATCH_EXACTLY);
174a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (!resource.empty()) {
175a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      info_list.push_back(extensions::ImageLoader::ImageRepresentation(
176a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          resource,
177a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          extensions::ImageLoader::ImageRepresentation::ALWAYS_RESIZE,
178a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          gfx::Size(size, size),
179a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          ui::SCALE_FACTOR_100P));
180a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    }
181a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
182a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
183a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  if (info_list.empty()) {
184a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    size_t i = kNumDesiredSizes - 1;
185a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    int size = kDesiredSizes[i];
186a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
187a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // If there is no icon at the desired sizes, we will resize what we can get.
188a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // Making a large icon smaller is preferred to making a small icon larger,
189a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    // so look for a larger icon first:
190a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    extensions::ExtensionResource resource =
191a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        extensions::IconsInfo::GetIconResource(
192a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch            extension, size, ExtensionIconSet::MATCH_BIGGER);
193a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    if (resource.empty()) {
194a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      resource = extensions::IconsInfo::GetIconResource(
195a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch          extension, size, ExtensionIconSet::MATCH_SMALLER);
196a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    }
197a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    info_list.push_back(extensions::ImageLoader::ImageRepresentation(
198a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        resource,
199a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        extensions::ImageLoader::ImageRepresentation::ALWAYS_RESIZE,
200a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        gfx::Size(size, size),
201a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch        ui::SCALE_FACTOR_100P));
202a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
203a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
204a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // |info_list| may still be empty at this point, in which case
205a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // LoadImageFamilyAsync will call the OnImageLoaded callback with an empty
206a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  // image and exit immediately.
207a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  extensions::ImageLoader::Get(profile)->LoadImageFamilyAsync(
208a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      extension,
209a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      info_list,
210a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      base::Bind(&OnImageLoaded, shortcut_info, file_handlers_info, callback));
211a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
212a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
213a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochvoid IgnoreFileHandlersInfo(
214a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const web_app::ShortcutInfoCallback& shortcut_info_callback,
215a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const web_app::ShortcutInfo& shortcut_info,
216a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const extensions::FileHandlersInfo& file_handlers_info) {
217a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  shortcut_info_callback.Run(shortcut_info);
218e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
219e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace web_app {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The following string is used to build the directory name for
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// shortcuts to chrome applications (the kind which are installed
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from a CRX).  Application shortcuts to URLs use the {host}_{path}
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// for the name of this directory.  Hosts can't include an underscore.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// By starting this string with an underscore, we ensure that there
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are no naming conflicts.
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const char* kCrxAppPrefix = "_crx_";
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace internals {
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
234a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)base::FilePath GetSanitizedFileName(const base::string16& name) {
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
236a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::string16 file_name = name;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  std::string file_name = base::UTF16ToUTF8(name);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_util::ReplaceIllegalCharactersInPath(&file_name, '_');
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::FilePath(file_name);
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
244c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochbool CreateShortcutsOnFileThread(
245c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ShortcutCreationReason reason,
246a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const web_app::ShortcutLocations& locations,
247a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const web_app::ShortcutInfo& shortcut_info) {
248c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
249c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
250a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return CreateShortcutsWithInfoOnFileThread(
251a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      reason, locations, shortcut_info, extensions::FileHandlersInfo(NULL));
252c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
253c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace internals
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
256a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochweb_app::ShortcutInfo::ShortcutInfo()
257a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    : is_platform_app(false) {
258a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
259a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
260a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochweb_app::ShortcutInfo::~ShortcutInfo() {}
261a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
262a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochweb_app::ShortcutLocations::ShortcutLocations()
263a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    : on_desktop(false),
264a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      applications_menu_location(APP_MENU_LOCATION_NONE),
265a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      in_quick_launch_bar(false)
266a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#if defined(OS_POSIX)
267a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      , hidden(false)
268a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#endif
269a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      {
270a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch}
271a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
272c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid GetShortcutInfoForTab(content::WebContents* web_contents,
273a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                           web_app::ShortcutInfo* info) {
274c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(info);  // Must provide a valid info.
275c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
276c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const FaviconTabHelper* favicon_tab_helper =
277c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      FaviconTabHelper::FromWebContents(web_contents);
278c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const extensions::TabHelper* extensions_tab_helper =
279c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      extensions::TabHelper::FromWebContents(web_contents);
280c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  const WebApplicationInfo& app_info = extensions_tab_helper->web_app_info();
281c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
282c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  info->url = app_info.app_url.is_empty() ? web_contents->GetURL() :
283c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                            app_info.app_url;
284c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  info->title = app_info.title.empty() ?
285c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      (web_contents->GetTitle().empty() ? base::UTF8ToUTF16(info->url.spec()) :
286c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                                          web_contents->GetTitle()) :
287c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      app_info.title;
288c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  info->description = app_info.description;
289c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  info->favicon.Add(favicon_tab_helper->GetFavicon());
290c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
291c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  Profile* profile =
292c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      Profile::FromBrowserContext(web_contents->GetBrowserContext());
293c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  info->profile_path = profile->GetPath();
294c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch}
295c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
296c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#if !defined(OS_WIN)
297c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid UpdateShortcutForTabContents(content::WebContents* web_contents) {}
298c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#endif
299c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
300a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochweb_app::ShortcutInfo ShortcutInfoForExtensionAndProfile(
301e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const extensions::Extension* app, Profile* profile) {
302a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  web_app::ShortcutInfo shortcut_info;
303e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  shortcut_info.extension_id = app->id();
304e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  shortcut_info.is_platform_app = app->is_platform_app();
305e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  shortcut_info.url = extensions::AppLaunchInfo::GetLaunchWebURL(app);
306e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  shortcut_info.title = base::UTF8ToUTF16(app->name());
307e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  shortcut_info.description = base::UTF8ToUTF16(app->description());
308e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  shortcut_info.extension_path = app->path();
309e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  shortcut_info.profile_path = profile->GetPath();
310e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  shortcut_info.profile_name =
311e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch      profile->GetPrefs()->GetString(prefs::kProfileName);
312e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch  return shortcut_info;
313e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
314e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
315e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdochvoid UpdateShortcutInfoAndIconForApp(
316e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const extensions::Extension* extension,
317e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    Profile* profile,
318e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch    const web_app::ShortcutInfoCallback& callback) {
319a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  GetInfoForApp(extension,
320a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                profile,
321a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                base::Bind(&IgnoreFileHandlersInfo, callback));
322e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch}
323e5d81f57cb97b3b6b7fccc9c5610d21eb81db09dBen Murdoch
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetWebAppDataDirectory(const base::FilePath& profile_path,
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      const std::string& extension_id,
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      const GURL& url) {
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!profile_path.empty());
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath app_data_dir(profile_path.Append(chrome::kWebAppDirname));
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!extension_id.empty()) {
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return app_data_dir.AppendASCII(
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GenerateApplicationNameFromExtensionId(extension_id));
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string host(url.host());
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string scheme(url.has_scheme() ? url.scheme() : "http");
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string port(url.has_port() ? url.port() : "80");
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string scheme_port(scheme + "_" + port);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
3415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::FilePath::StringType host_path(base::UTF8ToUTF16(host));
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::FilePath::StringType scheme_port_path(base::UTF8ToUTF16(scheme_port));
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath::StringType host_path(host);
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath::StringType scheme_port_path(scheme_port);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return app_data_dir.Append(host_path).Append(scheme_port_path);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath GetWebAppDataDirectory(const base::FilePath& profile_path,
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      const extensions::Extension& extension) {
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetWebAppDataDirectory(
354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      profile_path,
355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      extension.id(),
356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      GURL(extensions::AppLaunchInfo::GetLaunchWebURL(&extension)));
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GenerateApplicationNameFromInfo(
360a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const web_app::ShortcutInfo& shortcut_info) {
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!shortcut_info.extension_id.empty()) {
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return web_app::GenerateApplicationNameFromExtensionId(
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        shortcut_info.extension_id);
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return web_app::GenerateApplicationNameFromURL(
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        shortcut_info.url);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GenerateApplicationNameFromURL(const GURL& url) {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string t;
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t.append(url.host());
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t.append("_");
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t.append(url.path());
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return t;
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GenerateApplicationNameFromExtensionId(const std::string& id) {
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string t(web_app::kCrxAppPrefix);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  t.append(id);
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return t;
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetExtensionIdFromApplicationName(const std::string& app_name) {
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string prefix(kCrxAppPrefix);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (app_name.substr(0, prefix.length()) != prefix)
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return std::string();
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return app_name.substr(prefix.length());
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
391c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid CreateShortcutsForShortcutInfo(
392c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    web_app::ShortcutCreationReason reason,
393a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const web_app::ShortcutLocations& locations,
394a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const web_app::ShortcutInfo& shortcut_info) {
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::FILE,
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
400c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      base::Bind(
401c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          base::IgnoreResult(&web_app::internals::CreateShortcutsOnFileThread),
402c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch          reason, locations, shortcut_info));
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid CreateShortcuts(
406c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    ShortcutCreationReason reason,
407a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch    const web_app::ShortcutLocations& locations,
408c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    Profile* profile,
409c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    const extensions::Extension* app) {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
412a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  GetInfoForApp(app,
413a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                profile,
414a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                base::Bind(&CreateShortcutsWithInfo, reason, locations));
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
417c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid DeleteAllShortcuts(Profile* profile, const extensions::Extension* app) {
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::FILE,
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FROM_HERE,
423c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      base::Bind(&DeleteShortcutsOnFileThread,
424c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                 web_app::ShortcutInfoForExtensionAndProfile(app, profile)));
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
427c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid UpdateAllShortcuts(const base::string16& old_app_title,
428c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                        Profile* profile,
429c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch                        const extensions::Extension* app) {
430c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
432a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  GetInfoForApp(app,
433a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                profile,
434a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch                base::Bind(&UpdateAllShortcutsForShortcutInfo, old_app_title));
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsValidUrl(const GURL& url) {
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const char* const kValidUrlSchemes[] = {
4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      content::kFileScheme,
4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      content::kFileSystemScheme,
441a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      content::kFtpScheme,
442d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)      content::kHttpScheme,
443424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)      content::kHttpsScheme,
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      extensions::kExtensionScheme,
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kValidUrlSchemes); ++i) {
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (url.SchemeIs(kValidUrlSchemes[i]))
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(TOOLKIT_VIEWS)
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetIconsInfo(const WebApplicationInfo& app_info,
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  IconInfoList* icons) {
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(icons);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  icons->clear();
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < app_info.icons.size(); ++i) {
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We only take square shaped icons (i.e. width == height).
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (app_info.icons[i].width == app_info.icons[i].height) {
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      icons->push_back(app_info.icons[i]);
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::sort(icons->begin(), icons->end(), &IconPrecedes);
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#if defined(OS_LINUX)
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetWMClassFromAppName(std::string app_name) {
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_util::ReplaceIllegalCharactersInPath(&app_name, '_');
475a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::TrimString(app_name, "_", &app_name);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return app_name;
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace web_app
481