1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/web_applications/web_app.h" 6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 7c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <shlobj.h> 9c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // defined(OS_WIN) 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/command_line.h" 12c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/file_util.h" 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/i18n/file_util_icu.h" 14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/md5.h" 15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/path_service.h" 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/string_util.h" 173f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/threading/thread.h" 18c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "base/utf_string_conversions.h" 19731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/win/windows_version.h" 20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/download/download_util.h" 21c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_constants.h" 22c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/chrome_paths.h" 23c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/url_constants.h" 24dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/browser_thread.h" 25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_LINUX) 273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/environment.h" 28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // defined(OS_LINUX) 29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 30c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/gfx/icon_util.h" 32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // defined(OS_WIN) 33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochnamespace { 35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 36c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 37c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochconst FilePath::CharType kIconChecksumFileExt[] = FILE_PATH_LITERAL(".ico.md5"); 38c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 39c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns true if |ch| is in visible ASCII range and not one of 40c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// "/ \ : * ? " < > | ; ,". 41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool IsValidFilePathChar(char16 c) { 42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (c < 32) 43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 45c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch switch (c) { 46c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case '/': 47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case '\\': 48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case ':': 49c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case '*': 50c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case '?': 51c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case '"': 52c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case '<': 53c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case '>': 54c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case '|': 55c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case ';': 56c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case ',': 57c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 58c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 59c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 60c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 61c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 62c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 63c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // defined(OS_WIN) 64c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 65c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns relative directory of given web app url. 6672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenFilePath GetWebAppDir(const ShellIntegration::ShortcutInfo& info) { 6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen if (!info.extension_id.empty()) { 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string app_name = 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen web_app::GenerateApplicationNameFromExtensionId(info.extension_id); 7072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#if defined(OS_WIN) 7172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return FilePath(UTF8ToWide(app_name)); 7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#elif defined(OS_POSIX) 7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return FilePath(app_name); 7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#endif 7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } else { 7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FilePath::StringType host; 7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen FilePath::StringType scheme_port; 78c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_WIN) 8072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen host = UTF8ToWide(info.url.host()); 8172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scheme_port = (info.url.has_scheme() ? UTF8ToWide(info.url.scheme()) 8272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen : L"http") + FILE_PATH_LITERAL("_") + 8372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen (info.url.has_port() ? UTF8ToWide(info.url.port()) : L"80"); 84c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(OS_POSIX) 8572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen host = info.url.host(); 8672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scheme_port = info.url.scheme() + FILE_PATH_LITERAL("_") + info.url.port(); 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 88c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return FilePath(host).Append(scheme_port); 9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen } 91c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 92c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 933345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(TOOLKIT_VIEWS) 94c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Predicator for sorting images from largest to smallest. 954a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochbool IconPrecedes(const WebApplicationInfo::IconInfo& left, 964a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdoch const WebApplicationInfo::IconInfo& right) { 97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return left.width < right.width; 98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 993345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#endif 100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 1013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#if defined(OS_WIN) 102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Calculates image checksum using MD5. 103c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid GetImageCheckSum(const SkBitmap& image, MD5Digest* digest) { 104c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(digest); 105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SkAutoLockPixels image_lock(image); 107c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MD5Sum(image.getPixels(), image.getSize(), digest); 108c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 109c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 110c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Saves |image| as an |icon_file| with the checksum. 111c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool SaveIconWithCheckSum(const FilePath& icon_file, const SkBitmap& image) { 1123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!IconUtil::CreateIconFileFromSkBitmap(image, icon_file)) 113c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 114c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 115c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MD5Digest digest; 116c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetImageCheckSum(image, &digest); 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 118c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath cheksum_file(icon_file.ReplaceExtension(kIconChecksumFileExt)); 119c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return file_util::WriteFile(cheksum_file, 120c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<const char*>(&digest), 121c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sizeof(digest)) == sizeof(digest); 122c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns true if |icon_file| is missing or different from |image|. 125c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool ShouldUpdateIcon(const FilePath& icon_file, const SkBitmap& image) { 126c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath checksum_file(icon_file.ReplaceExtension(kIconChecksumFileExt)); 127c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 128c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returns true if icon_file or checksum file is missing. 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!file_util::PathExists(icon_file) || 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !file_util::PathExists(checksum_file)) 131c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 132c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 133c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MD5Digest persisted_image_checksum; 134c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (sizeof(persisted_image_checksum) != file_util::ReadFile(checksum_file, 135c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch reinterpret_cast<char*>(&persisted_image_checksum), 136c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sizeof(persisted_image_checksum))) 137c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 138c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 139c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MD5Digest downloaded_image_checksum; 140c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch GetImageCheckSum(image, &downloaded_image_checksum); 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Update icon if checksums are not equal. 143c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return memcmp(&persisted_image_checksum, &downloaded_image_checksum, 144c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch sizeof(MD5Digest)) != 0; 145c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 146c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 147c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif // defined(OS_WIN) 148c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 149c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Represents a task that creates web application shortcut. This runs on 150c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// file thread and schedules the callback (if any) on the calling thread 151c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// when finished (either success or failure). 152c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass CreateShortcutTask : public Task { 153c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 154c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CreateShortcutTask(const FilePath& profile_path, 155c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ShellIntegration::ShortcutInfo& shortcut_info, 156c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_app::CreateShortcutCallback* callback); 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 158c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 159c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch class CreateShortcutCallbackTask : public Task { 160c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public: 161c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CreateShortcutCallbackTask(web_app::CreateShortcutCallback* callback, 162c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool success) 163c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch : callback_(callback), 164c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch success_(success) { 165c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 166c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 167c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Overridden from Task: 168c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void Run() { 169c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch callback_->Run(success_); 170c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 171c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 172c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private: 173c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_app::CreateShortcutCallback* callback_; 174c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool success_; 175c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 176c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Overridden from Task: 178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch virtual void Run(); 179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Returns true if shortcut is created successfully. 181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool CreateShortcut(); 182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Path to store persisted data for web app. 184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath web_app_path_; 185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Out copy of profile path. 187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath profile_path_; 188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 189c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Our copy of short cut data. 190c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ShellIntegration::ShortcutInfo shortcut_info_; 191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Callback when task is finished. 193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_app::CreateShortcutCallback* callback_; 194c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch MessageLoop* message_loop_; 195c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 196c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DISALLOW_COPY_AND_ASSIGN(CreateShortcutTask); 197c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}; 198c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 199c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochCreateShortcutTask::CreateShortcutTask( 200c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const FilePath& profile_path, 201c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ShellIntegration::ShortcutInfo& shortcut_info, 202c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch web_app::CreateShortcutCallback* callback) 203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : web_app_path_(web_app::internals::GetWebAppDataDirectory( 20472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen web_app::GetDataDir(profile_path), 20572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen shortcut_info)), 206c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch profile_path_(profile_path), 207c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch shortcut_info_(shortcut_info), 208c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch callback_(callback), 209c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch message_loop_(MessageLoop::current()) { 210c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(message_loop_ != NULL); 211c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 212c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 213c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CreateShortcutTask::Run() { 214c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool success = CreateShortcut(); 215c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 216c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (callback_ != NULL) 217c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch message_loop_->PostTask(FROM_HERE, 218c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new CreateShortcutCallbackTask(callback_, success)); 219c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 220c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool CreateShortcutTask::CreateShortcut() { 222731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 223c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 224c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(OS_LINUX) 2253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick scoped_ptr<base::Environment> env(base::Environment::Create()); 226c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 227c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string shortcut_template; 2283345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!ShellIntegration::GetDesktopShortcutTemplate(env.get(), 229c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &shortcut_template)) { 230c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 231c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 232c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ShellIntegration::CreateDesktopShortcut(shortcut_info_, shortcut_template); 233c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; // assuming always success. 234c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#elif defined(OS_WIN) 235c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Shortcut paths under which to create shortcuts. 236c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<FilePath> shortcut_paths; 237c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 238c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Locations to add to shortcut_paths. 239c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch struct { 240c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const bool& use_this_location; 241c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int location_id; 242c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const wchar_t* sub_dir; 243c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } locations[] = { 244c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch { 245c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch shortcut_info_.create_on_desktop, 246c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chrome::DIR_USER_DESKTOP, 247c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NULL 248c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }, { 249c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch shortcut_info_.create_in_applications_menu, 250c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::DIR_START_MENU, 251c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NULL 252c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }, { 253c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch shortcut_info_.create_in_quick_launch_bar, 254c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // For Win7, create_in_quick_launch_bar means pinning to taskbar. Use 255c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // base::PATH_START as a flag for this case. 256731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick (base::win::GetVersion() >= base::win::VERSION_WIN7) ? 257c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::PATH_START : base::DIR_APP_DATA, 258731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick (base::win::GetVersion() >= base::win::VERSION_WIN7) ? 259c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NULL : L"Microsoft\\Internet Explorer\\Quick Launch" 260c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 261c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 262c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 263c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Populate shortcut_paths. 264c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (int i = 0; i < arraysize(locations); ++i) { 265c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (locations[i].use_this_location) { 266c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath path; 267c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 268c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Skip the Win7 case. 269c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (locations[i].location_id == base::PATH_START) 270c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 271c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 272c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!PathService::Get(locations[i].location_id, &path)) { 273c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 274c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 275c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 276c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 277c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (locations[i].sub_dir != NULL) 278c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch path = path.Append(locations[i].sub_dir); 279c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 280c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch shortcut_paths.push_back(path); 281c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 282c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 283c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 284c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool pin_to_taskbar = 285c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch shortcut_info_.create_in_quick_launch_bar && 286731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick (base::win::GetVersion() >= base::win::VERSION_WIN7); 287c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 288c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // For Win7's pinning support, any shortcut could be used. So we only create 289c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // the shortcut file when there is no shortcut file will be created. That is, 290c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // user only selects "Pin to taskbar". 291c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (pin_to_taskbar && shortcut_paths.empty()) { 292c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Creates the shortcut in web_app_path_ in this case. 293c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch shortcut_paths.push_back(web_app_path_); 294c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 295c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 296c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (shortcut_paths.empty()) { 297c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 298c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 299c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 300c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 301c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Ensure web_app_path_ exists. 302c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!file_util::PathExists(web_app_path_) && 303c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !file_util::CreateDirectory(web_app_path_)) { 304c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 305c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 306c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 307c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 308c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Generates file name to use with persisted ico and shortcut file. 309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FilePath file_name = 310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen web_app::internals::GetSanitizedFileName(shortcut_info_.title); 311c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 312c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Creates an ico file to use with shortcut. 313c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath icon_file = web_app_path_.Append(file_name).ReplaceExtension( 314c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FILE_PATH_LITERAL(".ico")); 315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!web_app::internals::CheckAndSaveIcon(icon_file, 316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen shortcut_info_.favicon)) { 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 318c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 319c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath chrome_exe; 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Working directory. 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath chrome_folder = chrome_exe.DirName(); 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 330ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CommandLine cmd_line = 331ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ShellIntegration::CommandLineArgsForLauncher(shortcut_info_.url, 332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen shortcut_info_.extension_id); 333ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // TODO(evan): we rely on the fact that command_line_string() is 334ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // properly quoted for a Windows command line. The method on 335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // CommandLine should probably be renamed to better reflect that 336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // fact. 337ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::wstring wide_switches(cmd_line.command_line_string()); 338c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 339c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Sanitize description 340c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (shortcut_info_.description.length() >= MAX_PATH) 341c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch shortcut_info_.description.resize(MAX_PATH - 1); 342c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 343c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Generates app id from web app url and profile path. 344ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::string app_name = 345ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen web_app::GenerateApplicationNameFromInfo(shortcut_info_); 346c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::wstring app_id = ShellIntegration::GetAppId( 34772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen UTF8ToWide(app_name), profile_path_); 348c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 349c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath shortcut_to_pin; 350c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 351c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch bool success = true; 352c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < shortcut_paths.size(); ++i) { 353c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch FilePath shortcut_file = shortcut_paths[i].Append(file_name). 354c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ReplaceExtension(FILE_PATH_LITERAL(".lnk")); 355c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 356c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int unique_number = download_util::GetUniquePathNumber(shortcut_file); 357c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (unique_number == -1) { 358c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch success = false; 359c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch continue; 360c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else if (unique_number > 0) { 361c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch download_util::AppendNumberToPath(&shortcut_file, unique_number); 362c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 363c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 364c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch success &= file_util::CreateShortcutLink(chrome_exe.value().c_str(), 365c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch shortcut_file.value().c_str(), 366c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chrome_folder.value().c_str(), 367ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen wide_switches.c_str(), 368c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch shortcut_info_.description.c_str(), 369c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch icon_file.value().c_str(), 370c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 0, 371c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch app_id.c_str()); 372c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 373c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Any shortcut would work for the pinning. We use the first one. 374c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (success && pin_to_taskbar && shortcut_to_pin.empty()) 375c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch shortcut_to_pin = shortcut_file; 376c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 377c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 378c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (success && pin_to_taskbar) { 379c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!shortcut_to_pin.empty()) { 380c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch success &= file_util::TaskbarPinShortcutLink( 381c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch shortcut_to_pin.value().c_str()); 382c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 383c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTREACHED(); 384c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch success = false; 385c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 386c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 387c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 388c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return success; 389c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#else 390c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch NOTIMPLEMENTED(); 391c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 392c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 393c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 394c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 395ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} // namespace 396c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 397ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace web_app { 398c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 399ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// The following string is used to build the directory name for 400ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// shortcuts to chrome applications (the kind which are installed 401ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// from a CRX). Application shortcuts to URLs use the {host}_{path} 402ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// for the name of this directory. Hosts can't include an underscore. 403ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// By starting this string with an underscore, we ensure that there 404ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// are no naming conflicts. 405ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstatic const char* kCrxAppPrefix = "_crx_"; 406c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 407ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace internals { 408c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 409ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_WIN) 410ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Returns sanitized name that could be used as a file name 411ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenFilePath GetSanitizedFileName(const string16& name) { 412ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen string16 file_name; 413c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 414ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < name.length(); ++i) { 415ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen char16 c = name[i]; 416ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!IsValidFilePathChar(c)) 417ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen c = '_'; 418c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 419ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen file_name += c; 420c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 421c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 422ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return FilePath(file_name); 423c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 424c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 425ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Saves |image| to |icon_file| if the file is outdated and refresh shell's 426ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// icon cache to ensure correct icon is displayed. Returns true if icon_file 427ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// is up to date or successfully updated. 428ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool CheckAndSaveIcon(const FilePath& icon_file, const SkBitmap& image) { 429ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (ShouldUpdateIcon(icon_file, image)) { 430ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (SaveIconWithCheckSum(icon_file, image)) { 431ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Refresh shell's icon cache. This call is quite disruptive as user would 432ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // see explorer rebuilding the icon cache. It would be great that we find 433ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // a better way to achieve this. 434ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT, 435ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NULL, NULL); 436ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 437ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 440c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 441ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return true; 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 443ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif // OS_WIN 444c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 445ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Returns data directory for given web app url 446ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenFilePath GetWebAppDataDirectory(const FilePath& root_dir, 447ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const ShellIntegration::ShortcutInfo& info) { 448ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return root_dir.Append(GetWebAppDir(info)); 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 451ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} // namespace internals 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 453ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstd::string GenerateApplicationNameFromInfo( 454ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const ShellIntegration::ShortcutInfo& shortcut_info) { 455ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!shortcut_info.extension_id.empty()) { 456ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return web_app::GenerateApplicationNameFromExtensionId( 457ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen shortcut_info.extension_id); 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } else { 459ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return web_app::GenerateApplicationNameFromURL( 460ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen shortcut_info.url); 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 4643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrickstd::string GenerateApplicationNameFromURL(const GURL& url) { 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::string t; 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch t.append(url.host()); 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch t.append("_"); 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch t.append(url.path()); 4693345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return t; 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 47272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstd::string GenerateApplicationNameFromExtensionId(const std::string& id) { 47372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen std::string t(web_app::kCrxAppPrefix); 47472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen t.append(id); 47572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen return t; 47672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen} 47772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochvoid CreateShortcut( 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const FilePath& data_dir, 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch const ShellIntegration::ShortcutInfo& shortcut_info, 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CreateShortcutCallback* callback) { 482731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new CreateShortcutTask(data_dir, shortcut_info, callback)); 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool IsValidUrl(const GURL& url) { 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch static const char* const kValidUrlSchemes[] = { 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chrome::kFileScheme, 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chrome::kFtpScheme, 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chrome::kHttpScheme, 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chrome::kHttpsScheme, 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch chrome::kExtensionScheme, 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch }; 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < arraysize(kValidUrlSchemes); ++i) { 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (url.SchemeIs(kValidUrlSchemes[i])) 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return true; 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return false; 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochFilePath GetDataDir(const FilePath& profile_path) { 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return profile_path.Append(chrome::kWebAppDirname); 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#if defined(TOOLKIT_VIEWS) 5084a5e2dc747d50c653511c68ccb2cfbfb740bd5a7Ben Murdochvoid GetIconsInfo(const WebApplicationInfo& app_info, 509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch IconInfoList* icons) { 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(icons); 511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch icons->clear(); 513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch for (size_t i = 0; i < app_info.icons.size(); ++i) { 514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We only take square shaped icons (i.e. width == height). 515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (app_info.icons[i].width == app_info.icons[i].height) { 516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch icons->push_back(app_info.icons[i]); 517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 518c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::sort(icons->begin(), icons->end(), &IconPrecedes); 521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#endif 523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 524ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(TOOLKIT_USES_GTK) 525ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstd::string GetWMClassFromAppName(std::string app_name) { 526ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen file_util::ReplaceIllegalCharactersInPath(&app_name, '_'); 527ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TrimString(app_name, "_", &app_name); 528ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return app_name; 529c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 530ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif 531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 532ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} // namespace web_app 533