diff options
author | benwells@chromium.org <benwells@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-10 12:50:11 +0000 |
---|---|---|
committer | benwells@chromium.org <benwells@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-08-10 12:50:11 +0000 |
commit | c002e757a3ce8027631cd2f22e5ec0f9b1322b14 (patch) | |
tree | 3f20648c028edf46c9ed9115af838276ae5a8cd0 | |
parent | 44cd60e5d3cc1005ac02792cae967af33052a996 (diff) | |
download | chromium_src-c002e757a3ce8027631cd2f22e5ec0f9b1322b14.zip chromium_src-c002e757a3ce8027631cd2f22e5ec0f9b1322b14.tar.gz chromium_src-c002e757a3ce8027631cd2f22e5ec0f9b1322b14.tar.bz2 |
Remove packaged app Windows shortcuts when app is uninstalled.
BUG=130456
TEST=Check app shortcuts are removed when the app is uninstalled. Test extension uninstallation in general.
Review URL: https://chromiumcodereview.appspot.com/10837034
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@151021 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | base/file_util.h | 14 | ||||
-rw-r--r-- | base/file_util_unittest.cc | 10 | ||||
-rw-r--r-- | base/file_util_win.cc | 63 | ||||
-rw-r--r-- | chrome/browser/extensions/app_shortcut_manager.cc | 44 | ||||
-rw-r--r-- | chrome/browser/extensions/app_shortcut_manager.h | 1 | ||||
-rw-r--r-- | chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.cc | 2 | ||||
-rw-r--r-- | chrome/browser/ui/views/create_application_shortcut_view.cc | 2 | ||||
-rw-r--r-- | chrome/browser/ui/web_applications/web_app_ui.cc | 2 | ||||
-rw-r--r-- | chrome/browser/web_applications/web_app.cc | 34 | ||||
-rw-r--r-- | chrome/browser/web_applications/web_app.h | 37 | ||||
-rw-r--r-- | chrome/browser/web_applications/web_app_android.cc | 8 | ||||
-rw-r--r-- | chrome/browser/web_applications/web_app_linux.cc | 11 | ||||
-rw-r--r-- | chrome/browser/web_applications/web_app_mac.mm | 8 | ||||
-rw-r--r-- | chrome/browser/web_applications/web_app_win.cc | 155 | ||||
-rw-r--r-- | net/url_request/url_request_file_job.cc | 2 | ||||
-rw-r--r-- | ui/base/dialogs/select_file_dialog_win.cc | 2 |
16 files changed, 252 insertions, 143 deletions
diff --git a/base/file_util.h b/base/file_util.h index fb6f624..a868112 100644 --- a/base/file_util.h +++ b/base/file_util.h @@ -235,10 +235,16 @@ enum ShortcutOptions { }; // Resolve Windows shortcut (.LNK file) -// This methods tries to resolve a shortcut .LNK file. If the |path| is valid -// returns true and puts the target into the |path|, otherwise returns -// false leaving the path as it is. -BASE_EXPORT bool ResolveShortcut(FilePath* path); +// This methods tries to resolve a shortcut .LNK file. The path of the shortcut +// to resolve is in |shortcut_path|. If |target_path| is not NULL, the target +// will be resolved and placed in |target_path|. If |args| is not NULL, the +// arguments will be retrieved and placed in |args|. The function returns true +// if all requested fields are are found successfully. +// Callers can safely use the same variable for both |shortcut_path| and +// |target_path|. +BASE_EXPORT bool ResolveShortcut(const FilePath& shortcut_path, + FilePath* target_path, + string16* args); // Creates (or updates) a Windows shortcut (.LNK file) // This method creates (or updates) a shortcut link using the information given. diff --git a/base/file_util_unittest.cc b/base/file_util_unittest.cc index 25e2f40..b471f88 100644 --- a/base/file_util_unittest.cc +++ b/base/file_util_unittest.cc @@ -1617,6 +1617,8 @@ TEST_F(FileUtilTest, ResolveShortcutTest) { EXPECT_TRUE(SUCCEEDED(result)); result = shell->SetDescription(L"ResolveShortcutTest"); EXPECT_TRUE(SUCCEEDED(result)); + result = shell->SetArguments(L"--args"); + EXPECT_TRUE(SUCCEEDED(result)); result = persist->Save(link_file.value().c_str(), TRUE); EXPECT_TRUE(SUCCEEDED(result)); if (persist) @@ -1625,8 +1627,10 @@ TEST_F(FileUtilTest, ResolveShortcutTest) { shell->Release(); bool is_solved; - is_solved = file_util::ResolveShortcut(&link_file); + std::wstring args; + is_solved = file_util::ResolveShortcut(link_file, &link_file, &args); EXPECT_TRUE(is_solved); + EXPECT_EQ(L"--args", args); std::wstring contents; contents = ReadTextFile(link_file); EXPECT_EQ(L"This is the target.", contents); @@ -1649,8 +1653,8 @@ TEST_F(FileUtilTest, CreateShortcutTest) { target_file.value().c_str(), link_file.value().c_str(), NULL, NULL, NULL, NULL, 0, NULL, file_util::SHORTCUT_CREATE_ALWAYS)); - FilePath resolved_name = link_file; - EXPECT_TRUE(file_util::ResolveShortcut(&resolved_name)); + FilePath resolved_name; + EXPECT_TRUE(file_util::ResolveShortcut(link_file, &resolved_name, NULL)); std::wstring read_contents = ReadTextFile(resolved_name); EXPECT_EQ(file_contents, read_contents); diff --git a/base/file_util_win.cc b/base/file_util_win.cc index bf9dd9c..6602121 100644 --- a/base/file_util_win.cc +++ b/base/file_util_win.cc @@ -332,38 +332,53 @@ bool GetFileCreationLocalTime(const std::wstring& filename, return GetFileCreationLocalTimeFromHandle(file_handle.Get(), creation_time); } -bool ResolveShortcut(FilePath* path) { +bool ResolveShortcut(const FilePath& shortcut_path, + FilePath* target_path, + string16* args) { base::ThreadRestrictions::AssertIOAllowed(); HRESULT result; base::win::ScopedComPtr<IShellLink> i_shell_link; - bool is_resolved = false; - // Get pointer to the IShellLink interface + // Get pointer to the IShellLink interface. result = i_shell_link.CreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER); - if (SUCCEEDED(result)) { - base::win::ScopedComPtr<IPersistFile> persist; - // Query IShellLink for the IPersistFile interface - result = persist.QueryFrom(i_shell_link); - if (SUCCEEDED(result)) { - WCHAR temp_path[MAX_PATH]; - // Load the shell link - result = persist->Load(path->value().c_str(), STGM_READ); - if (SUCCEEDED(result)) { - // Try to find the target of a shortcut - result = i_shell_link->Resolve(0, SLR_NO_UI); - if (SUCCEEDED(result)) { - result = i_shell_link->GetPath(temp_path, MAX_PATH, - NULL, SLGP_UNCPRIORITY); - *path = FilePath(temp_path); - is_resolved = true; - } - } - } + if (FAILED(result)) + return false; + + base::win::ScopedComPtr<IPersistFile> persist; + // Query IShellLink for the IPersistFile interface. + result = persist.QueryFrom(i_shell_link); + if (FAILED(result)) + return false; + + // Load the shell link. + result = persist->Load(shortcut_path.value().c_str(), STGM_READ); + if (FAILED(result)) + return false; + + WCHAR temp[MAX_PATH]; + if (target_path) { + // Try to find the target of a shortcut. + result = i_shell_link->Resolve(0, SLR_NO_UI); + if (FAILED(result)) + return false; + + result = i_shell_link->GetPath(temp, MAX_PATH, NULL, SLGP_UNCPRIORITY); + if (FAILED(result)) + return false; + + *target_path = FilePath(temp); } - return is_resolved; + if (args) { + result = i_shell_link->GetArguments(temp, MAX_PATH); + if (FAILED(result)) + return false; + + *args = string16(temp); + } + return true; } bool CreateOrUpdateShortcutLink(const wchar_t *source, @@ -389,7 +404,7 @@ bool CreateOrUpdateShortcutLink(const wchar_t *source, base::win::ScopedComPtr<IShellLink> i_shell_link; base::win::ScopedComPtr<IPersistFile> i_persist_file; - // Get pointer to the IShellLink interface + // Get pointer to the IShellLink interface. if (FAILED(i_shell_link.CreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER)) || FAILED(i_persist_file.QueryFrom(i_shell_link))) { diff --git a/chrome/browser/extensions/app_shortcut_manager.cc b/chrome/browser/extensions/app_shortcut_manager.cc index cdf2ce2..6d8fc81 100644 --- a/chrome/browser/extensions/app_shortcut_manager.cc +++ b/chrome/browser/extensions/app_shortcut_manager.cc @@ -29,6 +29,23 @@ const int kDesiredSizes[] = {16, 32, 128, 256, 512}; #else const int kDesiredSizes[] = {32}; #endif + +ShellIntegration::ShortcutInfo ShortcutInfoForExtensionAndProfile( + const Extension* extension, Profile* profile) { + ShellIntegration::ShortcutInfo shortcut_info; + shortcut_info.extension_id = extension->id(); + shortcut_info.url = GURL(extension->launch_web_url()); + shortcut_info.title = UTF8ToUTF16(extension->name()); + shortcut_info.description = UTF8ToUTF16(extension->description()); + shortcut_info.extension_path = extension->path(); + shortcut_info.is_platform_app = extension->is_platform_app(); + shortcut_info.create_in_applications_menu = true; + shortcut_info.create_in_quick_launch_bar = true; + shortcut_info.create_on_desktop = true; + shortcut_info.profile_path = profile->GetPath(); + return shortcut_info; +} + } // namespace AppShortcutManager::AppShortcutManager(Profile* profile) @@ -57,7 +74,7 @@ void AppShortcutManager::OnImageLoaded(const gfx::Image& image, shortcut_info_.favicon = image; } - web_app::CreateShortcut(profile_->GetPath(), shortcut_info_); + web_app::CreateShortcuts(shortcut_info_); } void AppShortcutManager::Observe(int type, @@ -76,10 +93,10 @@ void AppShortcutManager::Observe(int type, break; } case chrome::NOTIFICATION_EXTENSION_UNINSTALLED: { - std::string extension_id = - content::Details<const Extension>(details).ptr()->id(); + const Extension* extension = content::Details<const Extension>( + details).ptr(); if (!disable_shortcut_creation_for_tests) - web_app::DeleteAllShortcuts(profile_->GetPath(), extension_id); + DeleteApplicationShortcuts(extension); break; } default: @@ -95,17 +112,7 @@ void AppShortcutManager::SetShortcutCreationDisabledForTesting(bool disabled) { void AppShortcutManager::InstallApplicationShortcuts( const Extension* extension) { - shortcut_info_.extension_id = extension->id(); - shortcut_info_.url = GURL(extension->launch_web_url()); - shortcut_info_.title = UTF8ToUTF16(extension->name()); - shortcut_info_.description = UTF8ToUTF16(extension->description()); - shortcut_info_.extension_path = extension->path(); - shortcut_info_.is_platform_app = extension->is_platform_app(); - shortcut_info_.create_in_applications_menu = true; - shortcut_info_.create_in_quick_launch_bar = true; - shortcut_info_.create_on_desktop = true; - shortcut_info_.profile_path = profile_->GetPath(); - + shortcut_info_ = ShortcutInfoForExtensionAndProfile(extension, profile_); std::vector<ImageLoadingTracker::ImageInfo> info_list; for (size_t i = 0; i < arraysize(kDesiredSizes); ++i) { int size = kDesiredSizes[i]; @@ -139,3 +146,10 @@ void AppShortcutManager::InstallApplicationShortcuts( // immediately. tracker_.LoadImages(extension, info_list, ImageLoadingTracker::DONT_CACHE); } + +void AppShortcutManager::DeleteApplicationShortcuts( + const Extension* extension) { + ShellIntegration::ShortcutInfo delete_info = + ShortcutInfoForExtensionAndProfile(extension, profile_); + web_app::DeleteAllShortcuts(delete_info); +} diff --git a/chrome/browser/extensions/app_shortcut_manager.h b/chrome/browser/extensions/app_shortcut_manager.h index 6eb344a..1b0a94d 100644 --- a/chrome/browser/extensions/app_shortcut_manager.h +++ b/chrome/browser/extensions/app_shortcut_manager.h @@ -36,6 +36,7 @@ class AppShortcutManager : public ImageLoadingTracker::Observer, private: // Install the shortcuts for an application. void InstallApplicationShortcuts(const extensions::Extension* extension); + void DeleteApplicationShortcuts(const extensions::Extension* extension); content::NotificationRegistrar registrar_; Profile* profile_; diff --git a/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.cc b/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.cc index d126711..63db89f 100644 --- a/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.cc +++ b/chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.cc @@ -370,7 +370,7 @@ void CreateChromeApplicationShortcutsDialogGtk::CreateDesktopShortcut( const ShellIntegration::ShortcutInfo& shortcut_info) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); - if (web_app::CreateShortcutOnFileThread(profile_path_, shortcut_info)) { + if (web_app::CreateShortcutsOnFileThread(shortcut_info)) { Release(); } else { BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, diff --git a/chrome/browser/ui/views/create_application_shortcut_view.cc b/chrome/browser/ui/views/create_application_shortcut_view.cc index 9671807..90d1c33 100644 --- a/chrome/browser/ui/views/create_application_shortcut_view.cc +++ b/chrome/browser/ui/views/create_application_shortcut_view.cc @@ -381,7 +381,7 @@ bool CreateApplicationShortcutView::Accept() { shortcut_info_.create_in_quick_launch_bar = false; #endif - web_app::CreateShortcut(profile_->GetPath(), shortcut_info_); + web_app::CreateShortcuts(shortcut_info_); return true; } diff --git a/chrome/browser/ui/web_applications/web_app_ui.cc b/chrome/browser/ui/web_applications/web_app_ui.cc index 861a01e..85285d3 100644 --- a/chrome/browser/ui/web_applications/web_app_ui.cc +++ b/chrome/browser/ui/web_applications/web_app_ui.cc @@ -315,6 +315,8 @@ void GetShortcutInfoForTab(TabContents* tab_contents, info->description = app_info.description; info->favicon = gfx::Image(tab_contents->favicon_tab_helper()->GetFavicon()); + + info->profile_path = tab_contents->profile()->GetPath(); } void UpdateShortcutForTabContents(TabContents* tab_contents) { diff --git a/chrome/browser/web_applications/web_app.cc b/chrome/browser/web_applications/web_app.cc index c2b2a34..e7558e5 100644 --- a/chrome/browser/web_applications/web_app.cc +++ b/chrome/browser/web_applications/web_app.cc @@ -28,6 +28,16 @@ bool IconPrecedes(const WebApplicationInfo::IconInfo& left, } #endif +void DeleteShortcutsOnFileThread( + const ShellIntegration::ShortcutInfo& shortcut_info) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); + + FilePath shortcut_data_dir = web_app::GetWebAppDataDirectory( + shortcut_info.profile_path, shortcut_info.extension_id, GURL()); + return web_app::internals::DeletePlatformShortcuts( + shortcut_data_dir, shortcut_info); +} + } // namespace namespace web_app { @@ -57,6 +67,7 @@ FilePath GetSanitizedFileName(const string16& name) { FilePath GetWebAppDataDirectory(const FilePath& profile_path, const std::string& extension_id, const GURL& url) { + DCHECK(!profile_path.empty()); FilePath app_data_dir(profile_path.Append(chrome::kWebAppDirname)); if (!extension_id.empty()) { @@ -118,38 +129,33 @@ std::string GetExtensionIdFromApplicationName(const std::string& app_name) { return app_name.substr(prefix.length()); } -void CreateShortcut( - const FilePath& profile_path, - const ShellIntegration::ShortcutInfo& shortcut_info) { +void CreateShortcuts(const ShellIntegration::ShortcutInfo& shortcut_info) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, - base::Bind(base::IgnoreResult(&CreateShortcutOnFileThread), - profile_path, shortcut_info)); + base::Bind(base::IgnoreResult(&CreateShortcutsOnFileThread), + shortcut_info)); } -void DeleteAllShortcuts(const FilePath& profile_path, - const std::string& extension_id) { +void DeleteAllShortcuts(const ShellIntegration::ShortcutInfo& shortcut_info) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); BrowserThread::PostTask( BrowserThread::FILE, FROM_HERE, - base::Bind(&internals::DeletePlatformShortcuts, profile_path, - extension_id)); + base::Bind(&DeleteShortcutsOnFileThread, shortcut_info)); } -bool CreateShortcutOnFileThread( - const FilePath& profile_path, +bool CreateShortcutsOnFileThread( const ShellIntegration::ShortcutInfo& shortcut_info) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); FilePath shortcut_data_dir = GetWebAppDataDirectory( - profile_path, shortcut_info.extension_id, shortcut_info.url); - return internals::CreatePlatformShortcut( - shortcut_data_dir, profile_path, shortcut_info); + shortcut_info.profile_path, shortcut_info.extension_id, + shortcut_info.url); + return internals::CreatePlatformShortcuts(shortcut_data_dir, shortcut_info); } bool IsValidUrl(const GURL& url) { diff --git a/chrome/browser/web_applications/web_app.h b/chrome/browser/web_applications/web_app.h index 256e09b..2322504 100644 --- a/chrome/browser/web_applications/web_app.h +++ b/chrome/browser/web_applications/web_app.h @@ -46,24 +46,18 @@ std::string GenerateApplicationNameFromExtensionId(const std::string& id); // Extracts the extension id from the app name. std::string GetExtensionIdFromApplicationName(const std::string& app_name); -// Creates a shortcut for web application based on given shortcut data. -// |profile_path| is the path of the creating profile. |shortcut_info) -// contains information about the shortcut to create. -void CreateShortcut( - const FilePath& profile_path, - const ShellIntegration::ShortcutInfo& shortcut_info); +// Creates shortcuts for web application based on given shortcut data. +// |shortcut_info| contains information about the shortcut to create. +void CreateShortcuts(const ShellIntegration::ShortcutInfo& shortcut_info); -// Delete all the shortcuts that have been created for the extension with -// |extension_id| in the profile with |profile_path|. -void DeleteAllShortcuts(const FilePath& profile_path, - const std::string& extension_id); +// Delete all the shortcuts that have been created for the given +// |shortcut_data| in the profile with |profile_path|. +void DeleteAllShortcuts(const ShellIntegration::ShortcutInfo& shortcut_info); // Creates a shortcut. Must be called on the file thread. This is used to -// implement CreateShortcut() above, and can also be used directly from the -// file thread. |profile_path| is the path of the creating profile. -// |shortcut_info| constains info about the shortcut to create. -bool CreateShortcutOnFileThread( - const FilePath& profile_path, +// implement CreateShortcuts() above, and can also be used directly from the +// file thread. |shortcut_info| contains info about the shortcut to create. +bool CreateShortcutsOnFileThread( const ShellIntegration::ShortcutInfo& shortcut_info); // Returns true if given url is a valid web app url. @@ -91,21 +85,20 @@ bool CheckAndSaveIcon(const FilePath& icon_file, const SkBitmap& image); #endif // Implemented for each platform, does the platform specific parts of creating -// shortcuts. Used internally by CreateShortcutOnFileThread. +// shortcuts. Used internally by CreateShortcutsOnFileThread. // |shortcut_data_path| is where to store any resources created for the // shortcut, and is also used as the UserDataDir for platform app shortcuts. -// |profile_path| is the path of the creating profile. |shortcut_info| -// contains info about the shortcut to create. -bool CreatePlatformShortcut( +// |shortcut_info| contains info about the shortcut to create. +bool CreatePlatformShortcuts( const FilePath& shortcut_data_path, - const FilePath& profile_path, const ShellIntegration::ShortcutInfo& shortcut_info); // Delete all the shortcuts we have added for this extension. This is the // platform specific implementation of the DeleteAllShortcuts function, and // is executed on the FILE thread.. -void DeletePlatformShortcuts(const FilePath& profile_path, - const std::string& extension_id); +void DeletePlatformShortcuts( + const FilePath& shortcut_data_path, + const ShellIntegration::ShortcutInfo& shortcut_info); // Sanitizes |name| and returns a version of it that is safe to use as an // on-disk file name . diff --git a/chrome/browser/web_applications/web_app_android.cc b/chrome/browser/web_applications/web_app_android.cc index 0163868..b5f00cf 100644 --- a/chrome/browser/web_applications/web_app_android.cc +++ b/chrome/browser/web_applications/web_app_android.cc @@ -7,15 +7,15 @@ namespace web_app { namespace internals { -bool CreatePlatformShortcut( +bool CreatePlatformShortcuts( const FilePath& web_app_path, - const FilePath& profile_path, const ShellIntegration::ShortcutInfo& shortcut_info) { return true; } -void DeletePlatformShortcuts(const FilePath& profile_path, - const std::string& extension_id) {} +void DeletePlatformShortcuts( + const FilePath& web_app_path, + const ShellIntegration::ShortcutInfo& shortcut_info) {} } // namespace internals } // namespace web_app diff --git a/chrome/browser/web_applications/web_app_linux.cc b/chrome/browser/web_applications/web_app_linux.cc index 56d02fbf..c66968d 100644 --- a/chrome/browser/web_applications/web_app_linux.cc +++ b/chrome/browser/web_applications/web_app_linux.cc @@ -12,9 +12,8 @@ namespace web_app { namespace internals { -bool CreatePlatformShortcut( +bool CreatePlatformShortcuts( const FilePath& web_app_path, - const FilePath& profile_path, const ShellIntegration::ShortcutInfo& shortcut_info) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); @@ -29,9 +28,11 @@ bool CreatePlatformShortcut( shortcut_info, shortcut_template); } -void DeletePlatformShortcuts(const FilePath& profile_path, - const std::string& extension_id) { - ShellIntegrationLinux::DeleteDesktopShortcuts(profile_path, extension_id); +void DeletePlatformShortcuts( + const FilePath& web_app_path, + const ShellIntegration::ShortcutInfo& shortcut_info) { + ShellIntegrationLinux::DeleteDesktopShortcuts(shortcut_info.profile_path, + shortcut_info.extension_id); } } // namespace internals diff --git a/chrome/browser/web_applications/web_app_mac.mm b/chrome/browser/web_applications/web_app_mac.mm index 90c0abb..2246926 100644 --- a/chrome/browser/web_applications/web_app_mac.mm +++ b/chrome/browser/web_applications/web_app_mac.mm @@ -251,9 +251,8 @@ void WebAppShortcutCreator::RevealGeneratedBundleInFinder( namespace web_app { namespace internals { -bool CreatePlatformShortcut( +bool CreatePlatformShortcuts( const FilePath& web_app_path, - const FilePath& profile_path, const ShellIntegration::ShortcutInfo& shortcut_info) { DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); string16 bundle_id = UTF8ToUTF16(base::mac::BaseBundleID()); @@ -262,8 +261,9 @@ bool CreatePlatformShortcut( return shortcut_creator.CreateShortcut(); } -void DeletePlatformShortcuts(const FilePath& profile_path, - const std::string& extension_id) { +void DeletePlatformShortcuts( + const FilePath& web_app_path, + const ShellIntegration::ShortcutInfo& shortcut_info) { // TODO(benwells): Implement this when shortcuts / weblings are enabled on // mac. } diff --git a/chrome/browser/web_applications/web_app_win.cc b/chrome/browser/web_applications/web_app_win.cc index f5d85bd..8bf3b8f 100644 --- a/chrome/browser/web_applications/web_app_win.cc +++ b/chrome/browser/web_applications/web_app_win.cc @@ -15,6 +15,7 @@ #include "base/utf_string_conversions.h" #include "base/win/windows_version.h" #include "chrome/common/chrome_paths.h" +#include "chrome/common/chrome_switches.h" #include "content/public/browser/browser_thread.h" #include "ui/gfx/icon_util.h" @@ -67,37 +68,8 @@ bool ShouldUpdateIcon(const FilePath& icon_file, const SkBitmap& image) { sizeof(base::MD5Digest)) != 0; } -} // namespace - -namespace web_app { - -namespace internals { - -// Saves |image| to |icon_file| if the file is outdated and refresh shell's -// icon cache to ensure correct icon is displayed. Returns true if icon_file -// is up to date or successfully updated. -bool CheckAndSaveIcon(const FilePath& icon_file, const SkBitmap& image) { - if (ShouldUpdateIcon(icon_file, image)) { - if (SaveIconWithCheckSum(icon_file, image)) { - // Refresh shell's icon cache. This call is quite disruptive as user would - // see explorer rebuilding the icon cache. It would be great that we find - // a better way to achieve this. - SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT, - NULL, NULL); - } else { - return false; - } - } - - return true; -} - -bool CreatePlatformShortcut( - const FilePath& web_app_path, - const FilePath& profile_path, - const ShellIntegration::ShortcutInfo& shortcut_info) { - DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); - +std::vector<FilePath> GetShortcutPaths( + ShellIntegration::ShortcutInfo shortcut_info) { // Shortcut paths under which to create shortcuts. std::vector<FilePath> shortcut_paths; @@ -136,7 +108,7 @@ bool CreatePlatformShortcut( continue; if (!PathService::Get(locations[i].location_id, &path)) { - return false; + continue; } if (locations[i].sub_dir != NULL) @@ -146,9 +118,82 @@ bool CreatePlatformShortcut( } } - bool pin_to_taskbar = - shortcut_info.create_in_quick_launch_bar && - (base::win::GetVersion() >= base::win::VERSION_WIN7); + return shortcut_paths; +} + +bool ShortcutIsForProfile(const FilePath& shortcut_file_name, + const FilePath& profile_path) { + string16 cmd_line_string; + if (file_util::ResolveShortcut(shortcut_file_name, NULL, &cmd_line_string)) { + cmd_line_string = L"program " + cmd_line_string; + CommandLine shortcut_cmd_line = CommandLine::FromString(cmd_line_string); + return shortcut_cmd_line.HasSwitch(switches::kProfileDirectory) && + shortcut_cmd_line.GetSwitchValuePath(switches::kProfileDirectory) == + profile_path.BaseName(); + } + + return false; +} + +std::vector<FilePath> MatchingShortcutsForProfileAndExtension( + const FilePath& shortcut_path, + const FilePath& profile_path, + const string16& shortcut_name) { + std::vector<FilePath> shortcut_paths; + FilePath base_path = shortcut_path. + Append(web_app::internals::GetSanitizedFileName(shortcut_name)). + ReplaceExtension(FILE_PATH_LITERAL(".lnk")); + + const int fileNamesToCheck = 10; + for (int i = 0; i < fileNamesToCheck; ++i) { + FilePath shortcut_file = base_path; + if (i) { + shortcut_file = shortcut_file.InsertBeforeExtensionASCII( + StringPrintf(" (%d)", i)); + } + if (file_util::PathExists(shortcut_file) && + ShortcutIsForProfile(shortcut_file, profile_path)) { + shortcut_paths.push_back(shortcut_file); + } + } + return shortcut_paths; +} + +} // namespace + +namespace web_app { + +namespace internals { + +// Saves |image| to |icon_file| if the file is outdated and refresh shell's +// icon cache to ensure correct icon is displayed. Returns true if icon_file +// is up to date or successfully updated. +bool CheckAndSaveIcon(const FilePath& icon_file, const SkBitmap& image) { + if (ShouldUpdateIcon(icon_file, image)) { + if (SaveIconWithCheckSum(icon_file, image)) { + // Refresh shell's icon cache. This call is quite disruptive as user would + // see explorer rebuilding the icon cache. It would be great that we find + // a better way to achieve this. + SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST | SHCNF_FLUSHNOWAIT, + NULL, NULL); + } else { + return false; + } + } + + return true; +} + +bool CreatePlatformShortcuts( + const FilePath& web_app_path, + const ShellIntegration::ShortcutInfo& shortcut_info) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); + + // Shortcut paths under which to create shortcuts. + std::vector<FilePath> shortcut_paths = GetShortcutPaths(shortcut_info); + + bool pin_to_taskbar = shortcut_info.create_in_quick_launch_bar && + (base::win::GetVersion() >= base::win::VERSION_WIN7); // For Win7's pinning support, any shortcut could be used. So we only create // the shortcut file when there is no shortcut file will be created. That is, @@ -158,9 +203,8 @@ bool CreatePlatformShortcut( shortcut_paths.push_back(web_app_path); } - if (shortcut_paths.empty()) { + if (shortcut_paths.empty()) return false; - } // Ensure web_app_path exists if (!file_util::PathExists(web_app_path) && @@ -181,9 +225,8 @@ bool CreatePlatformShortcut( } FilePath chrome_exe; - if (!PathService::Get(base::FILE_EXE, &chrome_exe)) { + if (!PathService::Get(base::FILE_EXE, &chrome_exe)) return false; - } // Working directory. FilePath chrome_folder = chrome_exe.DirName(); @@ -208,10 +251,9 @@ bool CreatePlatformShortcut( std::string app_name = web_app::GenerateApplicationNameFromInfo(shortcut_info); string16 app_id = ShellIntegration::GetAppModelIdForProfile( - UTF8ToUTF16(app_name), profile_path); + UTF8ToUTF16(app_name), shortcut_info.profile_path); FilePath shortcut_to_pin; - bool success = true; for (size_t i = 0; i < shortcut_paths.size(); ++i) { FilePath shortcut_file = shortcut_paths[i].Append(file_name). @@ -255,9 +297,34 @@ bool CreatePlatformShortcut( return success; } -void DeletePlatformShortcuts(const FilePath& profile_path, - const std::string& extension_id) { - // TODO(benwells): Implement this. +void DeletePlatformShortcuts( + const FilePath& web_app_path, + const ShellIntegration::ShortcutInfo& shortcut_info) { + DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE)); + + // Get all possible locations for shortcuts. + ShellIntegration::ShortcutInfo all_shortcuts_info = shortcut_info; + all_shortcuts_info.create_in_applications_menu = true; + all_shortcuts_info.create_in_quick_launch_bar = true; + all_shortcuts_info.create_on_desktop = true; + std::vector<FilePath> shortcut_locations = GetShortcutPaths( + all_shortcuts_info); + if (base::win::GetVersion() >= base::win::VERSION_WIN7) + shortcut_locations.push_back(web_app_path); + + for (std::vector<FilePath>::const_iterator i = shortcut_locations.begin(); + i != shortcut_locations.end(); ++i) { + std::vector<FilePath> shortcut_files = + MatchingShortcutsForProfileAndExtension(*i, shortcut_info.profile_path, + shortcut_info.title); + for (std::vector<FilePath>::const_iterator j = shortcut_files.begin(); + j != shortcut_files.end(); ++j) { + // Any shortcut could have been pinned, either by chrome or the user, so + // they are all unpinned. + file_util::TaskbarUnpinShortcutLink(j->value().c_str()); + file_util::Delete(*j, false); + } + } } } // namespace internals diff --git a/net/url_request/url_request_file_job.cc b/net/url_request/url_request_file_job.cc index ce0cc8b..f18ad8f 100644 --- a/net/url_request/url_request_file_job.cc +++ b/net/url_request/url_request_file_job.cc @@ -200,7 +200,7 @@ bool URLRequestFileJob::IsRedirectResponse(GURL* location, FilePath new_path = file_path_; bool resolved; - resolved = file_util::ResolveShortcut(&new_path); + resolved = file_util::ResolveShortcut(new_path, &new_path, NULL); // If shortcut is not resolved succesfully, do not redirect. if (!resolved) diff --git a/ui/base/dialogs/select_file_dialog_win.cc b/ui/base/dialogs/select_file_dialog_win.cc index 3a69991..1b88f34 100644 --- a/ui/base/dialogs/select_file_dialog_win.cc +++ b/ui/base/dialogs/select_file_dialog_win.cc @@ -686,7 +686,7 @@ bool SelectFileDialogImpl::RunSelectFolderDialog(const std::wstring& title, // According to MSDN, win2000 will not resolve shortcuts, so we do it // ourself. - file_util::ResolveShortcut(path); + file_util::ResolveShortcut(*path, path, NULL); } CoTaskMemFree(list); } |