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