1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Use of this source code is governed by a BSD-style license that can be 3ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// found in the LICENSE file. 4ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 5ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/web_applications/web_app_ui.h" 6ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 7ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/file_util.h" 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/path_service.h" 9ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/task.h" 10ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/win/windows_version.h" 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/extensions/extension_tab_helper.h" 12ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/profiles/profile.h" 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/web_applications/web_app.h" 14ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 15ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/common/chrome_paths.h" 16ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/browser_thread.h" 17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/browser/tab_contents/tab_contents.h" 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_registrar.h" 19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_LINUX) 21ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/environment.h" 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif // defined(OS_LINUX) 23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_WIN) 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_details.h" 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_source.h" 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif // defined(OS_WIN) 28ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 29ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace { 30ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 31ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_WIN) 32ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// UpdateShortcutWorker holds all context data needed for update shortcut. 33ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// It schedules a pre-update check to find all shortcuts that needs to be 34ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// updated. If there are such shortcuts, it schedules icon download and 35ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// update them when icons are downloaded. It observes TAB_CLOSING notification 36ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// and cancels all the work when the underlying tab is closing. 37ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenclass UpdateShortcutWorker : public NotificationObserver { 38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen public: 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen explicit UpdateShortcutWorker(TabContentsWrapper* tab_contents); 40ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 41ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void Run(); 42ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 43ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen private: 44ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Overridden from NotificationObserver: 45ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen virtual void Observe(NotificationType type, 46ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const NotificationSource& source, 47ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const NotificationDetails& details); 48ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 49ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Downloads icon via TabContents. 50ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void DownloadIcon(); 51ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 52ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Callback when icon downloaded. 53ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void OnIconDownloaded(int download_id, bool errored, const SkBitmap& image); 54ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 55ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Checks if shortcuts exists on desktop, start menu and quick launch. 56ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void CheckExistingShortcuts(); 57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 58ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Update shortcut files and icons. 59ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void UpdateShortcuts(); 60ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void UpdateShortcutsOnFileThread(); 61ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 62ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Callback after shortcuts are updated. 63ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void OnShortcutsUpdated(bool); 64ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 65ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Deletes the worker on UI thread where it gets created. 66ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void DeleteMe(); 67ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void DeleteMeOnUIThread(); 68ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NotificationRegistrar registrar_; 70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Underlying TabContentsWrapper whose shortcuts will be updated. 72ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen TabContentsWrapper* tab_contents_; 73ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 74ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Icons info from tab_contents_'s web app data. 75ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen web_app::IconInfoList unprocessed_icons_; 76ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 77ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Cached shortcut data from the tab_contents_. 78ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ShellIntegration::ShortcutInfo shortcut_info_; 79ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 80ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Our copy of profile path. 81ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FilePath profile_path_; 82ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 83ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // File name of shortcut/ico file based on app title. 84ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FilePath file_name_; 85ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 86ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Existing shortcuts. 87ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<FilePath> shortcut_files_; 88ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 89ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DISALLOW_COPY_AND_ASSIGN(UpdateShortcutWorker); 90ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen}; 91ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 92ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenUpdateShortcutWorker::UpdateShortcutWorker(TabContentsWrapper* tab_contents) 93ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen : tab_contents_(tab_contents), 94ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen profile_path_(tab_contents->profile()->GetPath()) { 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen web_app::GetShortcutInfoForTab(tab_contents_, &shortcut_info_); 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen web_app::GetIconsInfo(tab_contents_->extension_tab_helper()->web_app_info(), 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &unprocessed_icons_); 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen file_name_ = web_app::internals::GetSanitizedFileName(shortcut_info_.title); 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen registrar_.Add(this, NotificationType::TAB_CLOSING, 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Source<NavigationController>(&tab_contents_->controller())); 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid UpdateShortcutWorker::Run() { 105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Starting by downloading app icon. 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DownloadIcon(); 107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid UpdateShortcutWorker::Observe(NotificationType type, 110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const NotificationSource& source, 111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const NotificationDetails& details) { 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (type == NotificationType::TAB_CLOSING && 113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Source<NavigationController>(source).ptr() == 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &tab_contents_->controller()) { 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Underlying tab is closing. 116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab_contents_ = NULL; 117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid UpdateShortcutWorker::DownloadIcon() { 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // FetchIcon must run on UI thread because it relies on TabContents 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // to download the icon. 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (tab_contents_ == NULL) { 126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DeleteMe(); // We are done if underlying TabContents is gone. 127ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 128ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 129ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 130ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (unprocessed_icons_.empty()) { 131ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // No app icon. Just use the favicon from TabContents. 132ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UpdateShortcuts(); 133ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 134ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 135ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab_contents_->tab_contents()->favicon_helper().DownloadImage( 137ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen unprocessed_icons_.back().url, 138ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::max(unprocessed_icons_.back().width, 139ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen unprocessed_icons_.back().height), 140ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen history::FAVICON, 141ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NewCallback(this, &UpdateShortcutWorker::OnIconDownloaded)); 142ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen unprocessed_icons_.pop_back(); 143ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 144ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 145ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid UpdateShortcutWorker::OnIconDownloaded(int download_id, 146ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool errored, 147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const SkBitmap& image) { 148ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (tab_contents_ == NULL) { 149ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DeleteMe(); // We are done if underlying TabContents is gone. 150ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 151ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 152ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 153ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!errored && !image.isNull()) { 154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Update icon with download image and update shortcut. 155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen shortcut_info_.favicon = image; 156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab_contents_->extension_tab_helper()->SetAppIcon(image); 157ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UpdateShortcuts(); 158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Try the next icon otherwise. 160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DownloadIcon(); 161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 162ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 163ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 164ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid UpdateShortcutWorker::CheckExistingShortcuts() { 165ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 166ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 167ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Locations to check to shortcut_paths. 168ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen struct { 169ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen bool& use_this_location; 170ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int location_id; 171ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const wchar_t* sub_dir; 172ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } locations[] = { 173ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen { 174ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen shortcut_info_.create_on_desktop, 175ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen chrome::DIR_USER_DESKTOP, 176ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NULL 177ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, { 178ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen shortcut_info_.create_in_applications_menu, 179ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::DIR_START_MENU, 180ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NULL 181ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }, { 182ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen shortcut_info_.create_in_quick_launch_bar, 183ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // For Win7, create_in_quick_launch_bar means pinning to taskbar. 184ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::DIR_APP_DATA, 185ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen (base::win::GetVersion() >= base::win::VERSION_WIN7) ? 186ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen L"Microsoft\\Internet Explorer\\Quick Launch\\User Pinned\\TaskBar" : 187ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen L"Microsoft\\Internet Explorer\\Quick Launch" 188ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 189ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen }; 190ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (int i = 0; i < arraysize(locations); ++i) { 192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen locations[i].use_this_location = false; 193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FilePath path; 195ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!PathService::Get(locations[i].location_id, &path)) { 196ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTREACHED(); 197ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen continue; 198ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 199ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 200ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (locations[i].sub_dir != NULL) 201ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen path = path.Append(locations[i].sub_dir); 202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FilePath shortcut_file = path.Append(file_name_). 204ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ReplaceExtension(FILE_PATH_LITERAL(".lnk")); 205ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (file_util::PathExists(shortcut_file)) { 206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen locations[i].use_this_location = true; 207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen shortcut_files_.push_back(shortcut_file); 208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid UpdateShortcutWorker::UpdateShortcuts() { 213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE, 214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NewRunnableMethod(this, 215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &UpdateShortcutWorker::UpdateShortcutsOnFileThread)); 216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 218ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid UpdateShortcutWorker::UpdateShortcutsOnFileThread() { 219ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 220ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 221ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FilePath web_app_path = web_app::internals::GetWebAppDataDirectory( 222ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen web_app::GetDataDir(profile_path_), shortcut_info_); 223ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 224ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Ensure web_app_path exists. web_app_path could be missing for a legacy 225ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // shortcut created by Gears. 226ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!file_util::PathExists(web_app_path) && 227ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen !file_util::CreateDirectory(web_app_path)) { 228ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NOTREACHED(); 229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return; 230ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 231ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FilePath icon_file = web_app_path.Append(file_name_).ReplaceExtension( 233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FILE_PATH_LITERAL(".ico")); 234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen web_app::internals::CheckAndSaveIcon(icon_file, shortcut_info_.favicon); 235ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 236ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Update existing shortcuts' description, icon and app id. 237ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CheckExistingShortcuts(); 238ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!shortcut_files_.empty()) { 239ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Generates app id from web app url and profile path. 240ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::wstring app_id = ShellIntegration::GetAppId( 241ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UTF8ToWide(web_app::GenerateApplicationNameFromURL(shortcut_info_.url)), 242ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen profile_path_); 243ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 244ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Sanitize description 245ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (shortcut_info_.description.length() >= MAX_PATH) 246ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen shortcut_info_.description.resize(MAX_PATH - 1); 247ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 248ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (size_t i = 0; i < shortcut_files_.size(); ++i) { 249ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen file_util::UpdateShortcutLink(NULL, 250ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen shortcut_files_[i].value().c_str(), 251ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NULL, 252ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NULL, 253ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen shortcut_info_.description.c_str(), 254ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen icon_file.value().c_str(), 255ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 0, 256ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen app_id.c_str()); 257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen OnShortcutsUpdated(true); 261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 263ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid UpdateShortcutWorker::OnShortcutsUpdated(bool) { 264ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DeleteMe(); // We are done. 265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid UpdateShortcutWorker::DeleteMe() { 268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { 269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DeleteMeOnUIThread(); 270ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 271ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, 272ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NewRunnableMethod(this, &UpdateShortcutWorker::DeleteMeOnUIThread)); 273ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 274ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 276ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid UpdateShortcutWorker::DeleteMeOnUIThread() { 277ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 278ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen delete this; 279ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 280ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif // defined(OS_WIN) 281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 282ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} // namespace 283ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 284ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_WIN) 285ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Allows UpdateShortcutWorker without adding refcounting. UpdateShortcutWorker 286ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// manages its own life time and will delete itself when it's done. 287ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenDISABLE_RUNNABLE_METHOD_REFCOUNT(UpdateShortcutWorker); 288ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif // defined(OS_WIN) 289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 290ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsennamespace web_app { 291ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid GetShortcutInfoForTab(TabContentsWrapper* tab_contents_wrapper, 293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ShellIntegration::ShortcutInfo* info) { 294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(info); // Must provide a valid info. 295ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const TabContents* tab_contents = tab_contents_wrapper->tab_contents(); 296ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 297ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const WebApplicationInfo& app_info = 298ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab_contents_wrapper->extension_tab_helper()->web_app_info(); 299ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 300ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen info->url = app_info.app_url.is_empty() ? tab_contents->GetURL() : 301ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen app_info.app_url; 302ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen info->title = app_info.title.empty() ? 303ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen (tab_contents->GetTitle().empty() ? UTF8ToUTF16(info->url.spec()) : 304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen tab_contents->GetTitle()) : 305ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen app_info.title; 306ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen info->description = app_info.description; 307ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen info->favicon = tab_contents->GetFavicon(); 308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 310ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid UpdateShortcutForTabContents(TabContentsWrapper* tab_contents) { 311ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#if defined(OS_WIN) 312ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // UpdateShortcutWorker will delete itself when it's done. 313ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen UpdateShortcutWorker* worker = new UpdateShortcutWorker(tab_contents); 314ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen worker->Run(); 315ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#endif // defined(OS_WIN) 316ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 317ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} // namespace web_app 319