blob: aa895137766d01fd9f53b88f295bb36c5d904d96 [file] [log] [blame]
[email protected]178f8512012-02-09 01:49:361// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]ed5431872009-11-17 08:39:512// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/web_applications/web_app.h"
6
[email protected]87212702011-12-08 21:17:197#include "base/bind.h"
[email protected]8806d3b2012-04-13 06:46:348#include "base/bind_helpers.h"
[email protected]ed5431872009-11-17 08:39:519#include "base/file_util.h"
[email protected]a0b60cfd2011-04-06 18:02:4110#include "base/i18n/file_util_icu.h"
[email protected]a0b60cfd2011-04-06 18:02:4111#include "base/string_util.h"
[email protected]7f070d42011-03-09 20:25:3212#include "base/threading/thread.h"
[email protected]1cb92b82010-03-08 23:12:1513#include "base/utf_string_conversions.h"
[email protected]eabfdae92009-12-11 06:13:5114#include "chrome/common/chrome_constants.h"
[email protected]885c0e92012-11-13 20:27:4215#include "chrome/common/extensions/extension.h"
[email protected]12ea22a2009-11-19 07:17:2316#include "chrome/common/url_constants.h"
[email protected]c38831a12011-10-28 12:44:4917#include "content/public/browser/browser_thread.h"
[email protected]885c0e92012-11-13 20:27:4218#include "extensions/common/constants.h"
[email protected]ed5431872009-11-17 08:39:5119
[email protected]631bb742011-11-02 11:29:3920using content::BrowserThread;
21
[email protected]ed5431872009-11-17 08:39:5122namespace {
23
[email protected]16f765632010-09-21 21:31:2724#if defined(TOOLKIT_VIEWS)
[email protected]eabfdae92009-12-11 06:13:5125// Predicator for sorting images from largest to smallest.
[email protected]38789d82010-11-17 06:03:4426bool IconPrecedes(const WebApplicationInfo::IconInfo& left,
27 const WebApplicationInfo::IconInfo& right) {
[email protected]eabfdae92009-12-11 06:13:5128 return left.width < right.width;
29}
[email protected]16f765632010-09-21 21:31:2730#endif
[email protected]eabfdae92009-12-11 06:13:5131
[email protected]c002e752012-08-10 12:50:1132void DeleteShortcutsOnFileThread(
33 const ShellIntegration::ShortcutInfo& shortcut_info) {
34 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
35
36 FilePath shortcut_data_dir = web_app::GetWebAppDataDirectory(
37 shortcut_info.profile_path, shortcut_info.extension_id, GURL());
38 return web_app::internals::DeletePlatformShortcuts(
39 shortcut_data_dir, shortcut_info);
40}
41
[email protected]e66ba952012-10-09 09:59:4442void UpdateShortcutsOnFileThread(
43 const ShellIntegration::ShortcutInfo& shortcut_info) {
44 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
45
46 FilePath shortcut_data_dir = web_app::GetWebAppDataDirectory(
47 shortcut_info.profile_path, shortcut_info.extension_id, GURL());
48 return web_app::internals::UpdatePlatformShortcuts(
49 shortcut_data_dir, shortcut_info);
50}
51
[email protected]f847e6082011-03-24 00:08:2652} // namespace
[email protected]eabfdae92009-12-11 06:13:5153
[email protected]ed5431872009-11-17 08:39:5154namespace web_app {
55
[email protected]2f1c09d2011-01-14 14:58:1456// The following string is used to build the directory name for
57// shortcuts to chrome applications (the kind which are installed
58// from a CRX). Application shortcuts to URLs use the {host}_{path}
59// for the name of this directory. Hosts can't include an underscore.
60// By starting this string with an underscore, we ensure that there
61// are no naming conflicts.
62static const char* kCrxAppPrefix = "_crx_";
63
[email protected]f847e6082011-03-24 00:08:2664namespace internals {
65
[email protected]b6b72222012-02-11 02:04:1366FilePath GetSanitizedFileName(const string16& name) {
67#if defined(OS_WIN)
68 string16 file_name = name;
69#else
70 std::string file_name = UTF16ToUTF8(name);
71#endif
72 file_util::ReplaceIllegalCharactersInPath(&file_name, '_');
73 return FilePath(file_name);
74}
75
[email protected]f847e6082011-03-24 00:08:2676} // namespace internals
77
[email protected]2b80909f2012-02-24 04:50:2178FilePath GetWebAppDataDirectory(const FilePath& profile_path,
79 const std::string& extension_id,
80 const GURL& url) {
[email protected]c002e752012-08-10 12:50:1181 DCHECK(!profile_path.empty());
[email protected]2b80909f2012-02-24 04:50:2182 FilePath app_data_dir(profile_path.Append(chrome::kWebAppDirname));
83
84 if (!extension_id.empty()) {
85 return app_data_dir.AppendASCII(
86 GenerateApplicationNameFromExtensionId(extension_id));
87 }
88
89 std::string host(url.host());
90 std::string scheme(url.has_scheme() ? url.scheme() : "http");
91 std::string port(url.has_port() ? url.port() : "80");
92 std::string scheme_port(scheme + "_" + port);
93
94#if defined(OS_WIN)
95 FilePath::StringType host_path(UTF8ToUTF16(host));
96 FilePath::StringType scheme_port_path(UTF8ToUTF16(scheme_port));
97#elif defined(OS_POSIX)
98 FilePath::StringType host_path(host);
99 FilePath::StringType scheme_port_path(scheme_port);
100#endif
101
102 return app_data_dir.Append(host_path).Append(scheme_port_path);
103}
104
105FilePath GetWebAppDataDirectory(const FilePath& profile_path,
[email protected]1c321ee2012-05-21 03:02:34106 const extensions::Extension& extension) {
[email protected]2b80909f2012-02-24 04:50:21107 return GetWebAppDataDirectory(
108 profile_path, extension.id(), GURL(extension.launch_web_url()));
109}
110
[email protected]a0b60cfd2011-04-06 18:02:41111std::string GenerateApplicationNameFromInfo(
112 const ShellIntegration::ShortcutInfo& shortcut_info) {
113 if (!shortcut_info.extension_id.empty()) {
114 return web_app::GenerateApplicationNameFromExtensionId(
115 shortcut_info.extension_id);
116 } else {
117 return web_app::GenerateApplicationNameFromURL(
118 shortcut_info.url);
119 }
120}
121
[email protected]57ecc4b2010-08-11 03:02:51122std::string GenerateApplicationNameFromURL(const GURL& url) {
[email protected]86b54012009-11-19 09:18:50123 std::string t;
124 t.append(url.host());
125 t.append("_");
126 t.append(url.path());
[email protected]57ecc4b2010-08-11 03:02:51127 return t;
[email protected]86b54012009-11-19 09:18:50128}
129
[email protected]2f1c09d2011-01-14 14:58:14130std::string GenerateApplicationNameFromExtensionId(const std::string& id) {
131 std::string t(web_app::kCrxAppPrefix);
132 t.append(id);
133 return t;
134}
135
[email protected]edee3faf2011-05-25 21:40:10136std::string GetExtensionIdFromApplicationName(const std::string& app_name) {
137 std::string prefix(kCrxAppPrefix);
138 if (app_name.substr(0, prefix.length()) != prefix)
139 return std::string();
140 return app_name.substr(prefix.length());
141}
142
[email protected]c002e752012-08-10 12:50:11143void CreateShortcuts(const ShellIntegration::ShortcutInfo& shortcut_info) {
[email protected]8806d3b2012-04-13 06:46:34144 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
145
[email protected]87212702011-12-08 21:17:19146 BrowserThread::PostTask(
147 BrowserThread::FILE,
148 FROM_HERE,
[email protected]c002e752012-08-10 12:50:11149 base::Bind(base::IgnoreResult(&CreateShortcutsOnFileThread),
150 shortcut_info));
[email protected]0b7df36d2012-07-11 09:50:47151}
152
[email protected]c002e752012-08-10 12:50:11153void DeleteAllShortcuts(const ShellIntegration::ShortcutInfo& shortcut_info) {
[email protected]0b7df36d2012-07-11 09:50:47154 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
155
156 BrowserThread::PostTask(
157 BrowserThread::FILE,
158 FROM_HERE,
[email protected]c002e752012-08-10 12:50:11159 base::Bind(&DeleteShortcutsOnFileThread, shortcut_info));
[email protected]ed5431872009-11-17 08:39:51160}
161
[email protected]e66ba952012-10-09 09:59:44162void UpdateAllShortcuts(const ShellIntegration::ShortcutInfo& shortcut_info) {
163 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
164
165 BrowserThread::PostTask(
166 BrowserThread::FILE,
167 FROM_HERE,
168 base::Bind(&UpdateShortcutsOnFileThread, shortcut_info));
169}
170
[email protected]c002e752012-08-10 12:50:11171bool CreateShortcutsOnFileThread(
[email protected]8806d3b2012-04-13 06:46:34172 const ShellIntegration::ShortcutInfo& shortcut_info) {
173 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE));
174
175 FilePath shortcut_data_dir = GetWebAppDataDirectory(
[email protected]c002e752012-08-10 12:50:11176 shortcut_info.profile_path, shortcut_info.extension_id,
177 shortcut_info.url);
178 return internals::CreatePlatformShortcuts(shortcut_data_dir, shortcut_info);
[email protected]8806d3b2012-04-13 06:46:34179}
180
[email protected]12ea22a2009-11-19 07:17:23181bool IsValidUrl(const GURL& url) {
182 static const char* const kValidUrlSchemes[] = {
183 chrome::kFileScheme,
[email protected]f1f86392012-04-03 13:51:58184 chrome::kFileSystemScheme,
[email protected]12ea22a2009-11-19 07:17:23185 chrome::kFtpScheme,
186 chrome::kHttpScheme,
187 chrome::kHttpsScheme,
[email protected]885c0e92012-11-13 20:27:42188 extensions::kExtensionScheme,
[email protected]12ea22a2009-11-19 07:17:23189 };
190
191 for (size_t i = 0; i < arraysize(kValidUrlSchemes); ++i) {
192 if (url.SchemeIs(kValidUrlSchemes[i]))
193 return true;
194 }
195
196 return false;
197}
198
[email protected]be3df2b2010-06-25 21:39:07199#if defined(TOOLKIT_VIEWS)
[email protected]38789d82010-11-17 06:03:44200void GetIconsInfo(const WebApplicationInfo& app_info,
[email protected]eabfdae92009-12-11 06:13:51201 IconInfoList* icons) {
202 DCHECK(icons);
203
204 icons->clear();
205 for (size_t i = 0; i < app_info.icons.size(); ++i) {
206 // We only take square shaped icons (i.e. width == height).
207 if (app_info.icons[i].width == app_info.icons[i].height) {
208 icons->push_back(app_info.icons[i]);
209 }
210 }
211
212 std::sort(icons->begin(), icons->end(), &IconPrecedes);
213}
[email protected]be3df2b2010-06-25 21:39:07214#endif
[email protected]eabfdae92009-12-11 06:13:51215
[email protected]a13283cc2012-04-05 00:21:22216#if defined(TOOLKIT_GTK)
[email protected]a0b60cfd2011-04-06 18:02:41217std::string GetWMClassFromAppName(std::string app_name) {
218 file_util::ReplaceIllegalCharactersInPath(&app_name, '_');
219 TrimString(app_name, "_", &app_name);
220 return app_name;
221}
222#endif
223
[email protected]f847e6082011-03-24 00:08:26224} // namespace web_app