Commit c002e757 authored by benwells@chromium.org's avatar benwells@chromium.org

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
parent 44cd60e5
......@@ -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.
......
......@@ -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);
......
......@@ -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)) {
if (FAILED(result))
return false;
base::win::ScopedComPtr<IPersistFile> persist;
// Query IShellLink for the IPersistFile interface
// 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
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 (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;
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))) {
......
......@@ -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);
}
......@@ -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_;
......
......@@ -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,
......
......@@ -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;
}
......
......@@ -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) {
......
......@@ -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) {
......
......@@ -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 .
......
......@@ -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
......@@ -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
......
......@@ -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.
}
......
......@@ -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,8 +118,81 @@ bool CreatePlatformShortcut(
}
}
bool pin_to_taskbar =
shortcut_info.create_in_quick_launch_bar &&
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
......@@ -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
......
......@@ -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)
......
......@@ -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);
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment