web_app.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
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/chrome_constants.h" 15#include "chrome/common/extensions/extension.h" 16#include "chrome/common/url_constants.h" 17#include "content/public/browser/browser_thread.h" 18#include "extensions/common/constants.h" 19 20using content::BrowserThread; 21 22namespace { 23 24#if defined(TOOLKIT_VIEWS) 25// Predicator for sorting images from largest to smallest. 26bool IconPrecedes(const WebApplicationInfo::IconInfo& left, 27 const WebApplicationInfo::IconInfo& right) { 28 return left.width < right.width; 29} 30#endif 31 32void DeleteShortcutsOnFileThread( 33 const ShellIntegration::ShortcutInfo& shortcut_info) { 34 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 35 36 base::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 42void UpdateShortcutsOnFileThread( 43 const ShellIntegration::ShortcutInfo& shortcut_info) { 44 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 45 46 base::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 52} // namespace 53 54namespace web_app { 55 56// 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 64namespace internals { 65 66base::FilePath 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 base::FilePath(file_name); 74} 75 76} // namespace internals 77 78base::FilePath GetWebAppDataDirectory(const base::FilePath& profile_path, 79 const std::string& extension_id, 80 const GURL& url) { 81 DCHECK(!profile_path.empty()); 82 base::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 base::FilePath::StringType host_path(UTF8ToUTF16(host)); 96 base::FilePath::StringType scheme_port_path(UTF8ToUTF16(scheme_port)); 97#elif defined(OS_POSIX) 98 base::FilePath::StringType host_path(host); 99 base::FilePath::StringType scheme_port_path(scheme_port); 100#endif 101 102 return app_data_dir.Append(host_path).Append(scheme_port_path); 103} 104 105base::FilePath GetWebAppDataDirectory(const base::FilePath& profile_path, 106 const extensions::Extension& extension) { 107 return GetWebAppDataDirectory( 108 profile_path, extension.id(), GURL(extension.launch_web_url())); 109} 110 111std::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 122std::string GenerateApplicationNameFromURL(const GURL& url) { 123 std::string t; 124 t.append(url.host()); 125 t.append("_"); 126 t.append(url.path()); 127 return t; 128} 129 130std::string GenerateApplicationNameFromExtensionId(const std::string& id) { 131 std::string t(web_app::kCrxAppPrefix); 132 t.append(id); 133 return t; 134} 135 136std::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 143void CreateShortcuts( 144 const ShellIntegration::ShortcutInfo& shortcut_info, 145 const ShellIntegration::ShortcutLocations& creation_locations) { 146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 147 148 BrowserThread::PostTask( 149 BrowserThread::FILE, 150 FROM_HERE, 151 base::Bind(base::IgnoreResult(&CreateShortcutsOnFileThread), 152 shortcut_info, creation_locations)); 153} 154 155void DeleteAllShortcuts(const ShellIntegration::ShortcutInfo& shortcut_info) { 156 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 157 158 BrowserThread::PostTask( 159 BrowserThread::FILE, 160 FROM_HERE, 161 base::Bind(&DeleteShortcutsOnFileThread, shortcut_info)); 162} 163 164void UpdateAllShortcuts(const ShellIntegration::ShortcutInfo& shortcut_info) { 165 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 166 167 BrowserThread::PostTask( 168 BrowserThread::FILE, 169 FROM_HERE, 170 base::Bind(&UpdateShortcutsOnFileThread, shortcut_info)); 171} 172 173bool CreateShortcutsOnFileThread( 174 const ShellIntegration::ShortcutInfo& shortcut_info, 175 const ShellIntegration::ShortcutLocations& creation_locations) { 176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 177 178 base::FilePath shortcut_data_dir = GetWebAppDataDirectory( 179 shortcut_info.profile_path, shortcut_info.extension_id, 180 shortcut_info.url); 181 return internals::CreatePlatformShortcuts(shortcut_data_dir, shortcut_info, 182 creation_locations); 183} 184 185bool IsValidUrl(const GURL& url) { 186 static const char* const kValidUrlSchemes[] = { 187 chrome::kFileScheme, 188 chrome::kFileSystemScheme, 189 chrome::kFtpScheme, 190 chrome::kHttpScheme, 191 chrome::kHttpsScheme, 192 extensions::kExtensionScheme, 193 }; 194 195 for (size_t i = 0; i < arraysize(kValidUrlSchemes); ++i) { 196 if (url.SchemeIs(kValidUrlSchemes[i])) 197 return true; 198 } 199 200 return false; 201} 202 203#if defined(TOOLKIT_VIEWS) 204void GetIconsInfo(const WebApplicationInfo& app_info, 205 IconInfoList* icons) { 206 DCHECK(icons); 207 208 icons->clear(); 209 for (size_t i = 0; i < app_info.icons.size(); ++i) { 210 // We only take square shaped icons (i.e. width == height). 211 if (app_info.icons[i].width == app_info.icons[i].height) { 212 icons->push_back(app_info.icons[i]); 213 } 214 } 215 216 std::sort(icons->begin(), icons->end(), &IconPrecedes); 217} 218#endif 219 220#if defined(TOOLKIT_GTK) 221std::string GetWMClassFromAppName(std::string app_name) { 222 file_util::ReplaceIllegalCharactersInPath(&app_name, '_'); 223 TrimString(app_name, "_", &app_name); 224 return app_name; 225} 226#endif 227 228} // namespace web_app 229