summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbenwells@chromium.org <benwells@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-10 12:50:11 +0000
committerbenwells@chromium.org <benwells@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-10 12:50:11 +0000
commitc002e757a3ce8027631cd2f22e5ec0f9b1322b14 (patch)
tree3f20648c028edf46c9ed9115af838276ae5a8cd0
parent44cd60e5d3cc1005ac02792cae967af33052a996 (diff)
downloadchromium_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.h14
-rw-r--r--base/file_util_unittest.cc10
-rw-r--r--base/file_util_win.cc63
-rw-r--r--chrome/browser/extensions/app_shortcut_manager.cc44
-rw-r--r--chrome/browser/extensions/app_shortcut_manager.h1
-rw-r--r--chrome/browser/ui/gtk/create_application_shortcuts_dialog_gtk.cc2
-rw-r--r--chrome/browser/ui/views/create_application_shortcut_view.cc2
-rw-r--r--chrome/browser/ui/web_applications/web_app_ui.cc2
-rw-r--r--chrome/browser/web_applications/web_app.cc34
-rw-r--r--chrome/browser/web_applications/web_app.h37
-rw-r--r--chrome/browser/web_applications/web_app_android.cc8
-rw-r--r--chrome/browser/web_applications/web_app_linux.cc11
-rw-r--r--chrome/browser/web_applications/web_app_mac.mm8
-rw-r--r--chrome/browser/web_applications/web_app_win.cc155
-rw-r--r--net/url_request/url_request_file_job.cc2
-rw-r--r--ui/base/dialogs/select_file_dialog_win.cc2
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);
}