web_app.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// 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 7#include "base/bind.h" 8#include "base/bind_helpers.h" 9#include "base/file_util.h" 10#include "base/i18n/file_util_icu.h" 11#include "base/strings/string_util.h" 12#include "base/strings/utf_string_conversions.h" 13#include "base/threading/thread.h" 14#include "chrome/common/chrome_constants.h" 15#include "chrome/common/chrome_version_info.h" 16#include "chrome/common/extensions/extension.h" 17#include "chrome/common/extensions/manifest_handlers/app_launch_info.h" 18#include "chrome/common/url_constants.h" 19#include "content/public/browser/browser_thread.h" 20#include "extensions/common/constants.h" 21#include "grit/chromium_strings.h" 22#include "ui/base/l10n/l10n_util.h" 23 24using content::BrowserThread; 25 26namespace { 27 28#if defined(TOOLKIT_VIEWS) 29// Predicator for sorting images from largest to smallest. 30bool IconPrecedes(const WebApplicationInfo::IconInfo& left, 31 const WebApplicationInfo::IconInfo& right) { 32 return left.width < right.width; 33} 34#endif 35 36void DeleteShortcutsOnFileThread( 37 const ShellIntegration::ShortcutInfo& shortcut_info) { 38 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 39 40 base::FilePath shortcut_data_dir = web_app::GetWebAppDataDirectory( 41 shortcut_info.profile_path, shortcut_info.extension_id, GURL()); 42 return web_app::internals::DeletePlatformShortcuts( 43 shortcut_data_dir, shortcut_info); 44} 45 46void UpdateShortcutsOnFileThread( 47 const string16& old_app_title, 48 const ShellIntegration::ShortcutInfo& shortcut_info) { 49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 50 51 base::FilePath shortcut_data_dir = web_app::GetWebAppDataDirectory( 52 shortcut_info.profile_path, shortcut_info.extension_id, GURL()); 53 return web_app::internals::UpdatePlatformShortcuts( 54 shortcut_data_dir, old_app_title, shortcut_info); 55} 56 57} // namespace 58 59namespace web_app { 60 61// The following string is used to build the directory name for 62// shortcuts to chrome applications (the kind which are installed 63// from a CRX). Application shortcuts to URLs use the {host}_{path} 64// for the name of this directory. Hosts can't include an underscore. 65// By starting this string with an underscore, we ensure that there 66// are no naming conflicts. 67static const char* kCrxAppPrefix = "_crx_"; 68 69namespace internals { 70 71base::FilePath GetSanitizedFileName(const string16& name) { 72#if defined(OS_WIN) 73 string16 file_name = name; 74#else 75 std::string file_name = UTF16ToUTF8(name); 76#endif 77 file_util::ReplaceIllegalCharactersInPath(&file_name, '_'); 78 return base::FilePath(file_name); 79} 80 81} // namespace internals 82 83base::FilePath GetWebAppDataDirectory(const base::FilePath& profile_path, 84 const std::string& extension_id, 85 const GURL& url) { 86 DCHECK(!profile_path.empty()); 87 base::FilePath app_data_dir(profile_path.Append(chrome::kWebAppDirname)); 88 89 if (!extension_id.empty()) { 90 return app_data_dir.AppendASCII( 91 GenerateApplicationNameFromExtensionId(extension_id)); 92 } 93 94 std::string host(url.host()); 95 std::string scheme(url.has_scheme() ? url.scheme() : "http"); 96 std::string port(url.has_port() ? url.port() : "80"); 97 std::string scheme_port(scheme + "_" + port); 98 99#if defined(OS_WIN) 100 base::FilePath::StringType host_path(UTF8ToUTF16(host)); 101 base::FilePath::StringType scheme_port_path(UTF8ToUTF16(scheme_port)); 102#elif defined(OS_POSIX) 103 base::FilePath::StringType host_path(host); 104 base::FilePath::StringType scheme_port_path(scheme_port); 105#endif 106 107 return app_data_dir.Append(host_path).Append(scheme_port_path); 108} 109 110base::FilePath GetWebAppDataDirectory(const base::FilePath& profile_path, 111 const extensions::Extension& extension) { 112 return GetWebAppDataDirectory( 113 profile_path, 114 extension.id(), 115 GURL(extensions::AppLaunchInfo::GetLaunchWebURL(&extension))); 116} 117 118std::string GenerateApplicationNameFromInfo( 119 const ShellIntegration::ShortcutInfo& shortcut_info) { 120 if (!shortcut_info.extension_id.empty()) { 121 return web_app::GenerateApplicationNameFromExtensionId( 122 shortcut_info.extension_id); 123 } else { 124 return web_app::GenerateApplicationNameFromURL( 125 shortcut_info.url); 126 } 127} 128 129std::string GenerateApplicationNameFromURL(const GURL& url) { 130 std::string t; 131 t.append(url.host()); 132 t.append("_"); 133 t.append(url.path()); 134 return t; 135} 136 137std::string GenerateApplicationNameFromExtensionId(const std::string& id) { 138 std::string t(web_app::kCrxAppPrefix); 139 t.append(id); 140 return t; 141} 142 143std::string GetExtensionIdFromApplicationName(const std::string& app_name) { 144 std::string prefix(kCrxAppPrefix); 145 if (app_name.substr(0, prefix.length()) != prefix) 146 return std::string(); 147 return app_name.substr(prefix.length()); 148} 149 150void CreateShortcuts( 151 const ShellIntegration::ShortcutInfo& shortcut_info, 152 const ShellIntegration::ShortcutLocations& creation_locations, 153 ShortcutCreationPolicy creation_policy) { 154 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 155 156 BrowserThread::PostTask( 157 BrowserThread::FILE, 158 FROM_HERE, 159 base::Bind(base::IgnoreResult(&CreateShortcutsOnFileThread), 160 shortcut_info, creation_locations, creation_policy)); 161} 162 163void DeleteAllShortcuts(const ShellIntegration::ShortcutInfo& shortcut_info) { 164 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 165 166 BrowserThread::PostTask( 167 BrowserThread::FILE, 168 FROM_HERE, 169 base::Bind(&DeleteShortcutsOnFileThread, shortcut_info)); 170} 171 172void UpdateAllShortcuts(const string16& old_app_title, 173 const ShellIntegration::ShortcutInfo& shortcut_info) { 174 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 175 176 BrowserThread::PostTask( 177 BrowserThread::FILE, 178 FROM_HERE, 179 base::Bind(&UpdateShortcutsOnFileThread, old_app_title, shortcut_info)); 180} 181 182bool CreateShortcutsOnFileThread( 183 const ShellIntegration::ShortcutInfo& shortcut_info, 184 const ShellIntegration::ShortcutLocations& creation_locations, 185 ShortcutCreationPolicy creation_policy) { 186 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 187 188 base::FilePath shortcut_data_dir = GetWebAppDataDirectory( 189 shortcut_info.profile_path, shortcut_info.extension_id, 190 shortcut_info.url); 191 return internals::CreatePlatformShortcuts(shortcut_data_dir, shortcut_info, 192 creation_locations, 193 creation_policy); 194} 195 196bool IsValidUrl(const GURL& url) { 197 static const char* const kValidUrlSchemes[] = { 198 chrome::kFileScheme, 199 chrome::kFileSystemScheme, 200 chrome::kFtpScheme, 201 chrome::kHttpScheme, 202 chrome::kHttpsScheme, 203 extensions::kExtensionScheme, 204 }; 205 206 for (size_t i = 0; i < arraysize(kValidUrlSchemes); ++i) { 207 if (url.SchemeIs(kValidUrlSchemes[i])) 208 return true; 209 } 210 211 return false; 212} 213 214#if defined(TOOLKIT_VIEWS) 215void GetIconsInfo(const WebApplicationInfo& app_info, 216 IconInfoList* icons) { 217 DCHECK(icons); 218 219 icons->clear(); 220 for (size_t i = 0; i < app_info.icons.size(); ++i) { 221 // We only take square shaped icons (i.e. width == height). 222 if (app_info.icons[i].width == app_info.icons[i].height) { 223 icons->push_back(app_info.icons[i]); 224 } 225 } 226 227 std::sort(icons->begin(), icons->end(), &IconPrecedes); 228} 229#endif 230 231#if defined(TOOLKIT_GTK) 232std::string GetWMClassFromAppName(std::string app_name) { 233 file_util::ReplaceIllegalCharactersInPath(&app_name, '_'); 234 TrimString(app_name, "_", &app_name); 235 return app_name; 236} 237#endif 238 239string16 GetAppShortcutsSubdirName() { 240 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); 241 if (channel == chrome::VersionInfo::CHANNEL_CANARY) 242 return l10n_util::GetStringUTF16(IDS_APP_SHORTCUTS_SUBDIR_NAME_CANARY); 243 return l10n_util::GetStringUTF16(IDS_APP_SHORTCUTS_SUBDIR_NAME); 244} 245 246} // namespace web_app 247