Index: chrome/browser/profiles/profile_shortcut_manager_win.cc |
diff --git a/chrome/browser/profiles/profile_shortcut_manager_win.cc b/chrome/browser/profiles/profile_shortcut_manager_win.cc |
index dcd69f59f97968b2b2f34f4c5af396d6d3c5a48a..0061b4cfcd4938ccc2b9094afd2968fd3708fe0a 100644 |
--- a/chrome/browser/profiles/profile_shortcut_manager_win.cc |
+++ b/chrome/browser/profiles/profile_shortcut_manager_win.cc |
@@ -6,8 +6,6 @@ |
#include <shlobj.h> // For SHChangeNotify(). |
-#include <algorithm> |
-#include <set> |
#include <string> |
#include <vector> |
@@ -291,56 +289,33 @@ |
return ConvertToLongPath(target_path) == ConvertToLongPath(chrome_exe); |
} |
-// A functor checks if |path| is the Chrome desktop shortcut (|chrome_exe|) |
-// that have the specified |command_line|. If |include_empty_command_lines| is |
-// true Chrome desktop shortcuts with empty command lines will also be included. |
-struct ChromeCommandLineFilter { |
- const base::FilePath& chrome_exe; |
- const base::string16& command_line; |
- bool include_empty_command_lines; |
- |
- ChromeCommandLineFilter(const base::FilePath& chrome_exe, |
- const base::string16& command_line, |
- bool include_empty_command_lines) |
- : chrome_exe(chrome_exe), |
- command_line(command_line), |
- include_empty_command_lines(include_empty_command_lines) {} |
- |
- bool operator()(const base::FilePath& path) const { |
+// Populates |paths| with the file paths of Chrome desktop shortcuts that have |
+// the specified |command_line|. If |include_empty_command_lines| is true, |
+// Chrome desktop shortcuts with empty command lines will also be included. |
+void ListDesktopShortcutsWithCommandLine(const base::FilePath& chrome_exe, |
+ const base::string16& command_line, |
+ bool include_empty_command_lines, |
+ std::vector<base::FilePath>* paths) { |
+ base::FilePath user_shortcuts_directory; |
+ if (!GetDesktopShortcutsDirectories(&user_shortcuts_directory, NULL)) |
+ return; |
+ |
+ base::FileEnumerator enumerator(user_shortcuts_directory, false, |
+ base::FileEnumerator::FILES); |
+ for (base::FilePath path = enumerator.Next(); !path.empty(); |
+ path = enumerator.Next()) { |
base::string16 shortcut_command_line; |
if (!IsChromeShortcut(path, chrome_exe, &shortcut_command_line)) |
- return false; |
+ continue; |
// TODO(asvitkine): Change this to build a CommandLine object and ensure all |
// args from |command_line| are present in the shortcut's CommandLine. This |
// will be more robust when |command_line| contains multiple args. |
if ((shortcut_command_line.empty() && include_empty_command_lines) || |
(shortcut_command_line.find(command_line) != base::string16::npos)) { |
- return true; |
+ paths->push_back(path); |
} |
- return false; |
- } |
-}; |
- |
-// Get the file paths of desktop files and folders optionally filtered |
-// by |filter|. |
-std::set<base::FilePath> ListUserDesktopContents( |
- const ChromeCommandLineFilter* filter) { |
- std::set<base::FilePath> result; |
- |
- base::FilePath user_shortcuts_directory; |
- if (!GetDesktopShortcutsDirectories(&user_shortcuts_directory, nullptr)) |
- return result; |
- |
- base::FileEnumerator enumerator( |
- user_shortcuts_directory, false, |
- base::FileEnumerator::FILES | base::FileEnumerator::DIRECTORIES); |
- for (base::FilePath path = enumerator.Next(); !path.empty(); |
- path = enumerator.Next()) { |
- if (!filter || (*filter)(path)) |
- result.insert(path); |
- } |
- return result; |
+ } |
} |
// Renames the given desktop shortcut and informs the shell of this change. |
@@ -360,20 +335,9 @@ |
// Renames an existing Chrome desktop profile shortcut. Must be called on the |
// FILE thread. |
-// |profile_shortcuts| are Chrome desktop shortcuts for the profile (there can |
-// be several). |
-// |desktop_contents| is the collection of all user desktop shortcuts |
-// (not only Chrome). It is used to make an unique shortcut for the |
-// |new_profile_name| among all shortcuts. |
-// This function updates |profile_shortcuts| and |desktop_contents| respectively |
-// when renaming occurs. |
void RenameChromeDesktopShortcutForProfile( |
- const base::string16& old_profile_name, |
- const base::string16& new_profile_name, |
- std::set<base::FilePath>* profile_shortcuts, |
- std::set<base::FilePath>* desktop_contents) { |
- DCHECK(profile_shortcuts); |
- DCHECK(desktop_contents); |
+ const base::string16& old_shortcut_filename, |
+ const base::string16& new_shortcut_filename) { |
DCHECK_CURRENTLY_ON(BrowserThread::FILE); |
base::FilePath user_shortcuts_directory; |
@@ -383,70 +347,32 @@ |
return; |
} |
- BrowserDistribution* distribution = BrowserDistribution::GetDistribution(); |
- |
- // Get a new unique shortcut name. |
- const base::string16 new_shortcut_filename = |
- profiles::internal::GetUniqueShortcutFilenameForProfile( |
- new_profile_name, *desktop_contents, distribution); |
+ const base::FilePath old_shortcut_path = |
+ user_shortcuts_directory.Append(old_shortcut_filename); |
const base::FilePath new_shortcut_path = |
user_shortcuts_directory.Append(new_shortcut_filename); |
- if (!profile_shortcuts->empty()) { |
- // From all profile_shortcuts choose the one with a known (canonical) name. |
- profiles::internal::ShortcutFilenameMatcher matcher(old_profile_name, |
- distribution); |
- auto it = std::find_if(profile_shortcuts->begin(), profile_shortcuts->end(), |
- [&matcher](const base::FilePath& p) { |
- return matcher.IsCanonical(p.BaseName().value()); |
- }); |
- // If all profile_shortcuts were renamed by user, respect it and do not |
- // rename. |
- if (it == profile_shortcuts->end()) |
- return; |
- const base::FilePath old_shortcut_path = *it; |
- |
+ if (base::PathExists(old_shortcut_path)) { |
// Rename the old shortcut unless a system-level shortcut exists at the |
// destination, in which case the old shortcut is simply deleted. |
const base::FilePath possible_new_system_shortcut = |
system_shortcuts_directory.Append(new_shortcut_filename); |
- if (base::PathExists(possible_new_system_shortcut)) { |
- if (base::DeleteFile(old_shortcut_path, false)) { |
- profile_shortcuts->erase(old_shortcut_path); |
- desktop_contents->erase(old_shortcut_path); |
- } else { |
- DLOG(ERROR) << "Could not delete Windows profile desktop shortcut."; |
- } |
- } else { |
- if (RenameDesktopShortcut(old_shortcut_path, new_shortcut_path)) { |
- profile_shortcuts->erase(old_shortcut_path); |
- desktop_contents->erase(old_shortcut_path); |
- profile_shortcuts->insert(new_shortcut_path); |
- desktop_contents->insert(new_shortcut_path); |
- } else { |
- DLOG(ERROR) << "Could not rename Windows profile desktop shortcut."; |
- } |
- } |
+ if (base::PathExists(possible_new_system_shortcut)) |
+ base::DeleteFile(old_shortcut_path, false); |
+ else if (!RenameDesktopShortcut(old_shortcut_path, new_shortcut_path)) |
+ DLOG(ERROR) << "Could not rename Windows profile desktop shortcut."; |
} else { |
- // If the shortcut does not exist, it may have been deleted by the user. |
+ // If the shortcut does not exist, it may have been renamed by the user. In |
+ // that case, its name should not be changed. |
// It's also possible that a system-level shortcut exists instead - this |
// should only be the case for the original Chrome shortcut from an |
// installation. If that's the case, copy that one over - it will get its |
// properties updated by |
// |CreateOrUpdateDesktopShortcutsAndIconForProfile()|. |
- const auto old_shortcut_filename = |
- profiles::internal::GetShortcutFilenameForProfile(old_profile_name, |
- distribution); |
const base::FilePath possible_old_system_shortcut = |
system_shortcuts_directory.Append(old_shortcut_filename); |
- if (base::PathExists(possible_old_system_shortcut)) { |
- if (base::CopyFile(possible_old_system_shortcut, new_shortcut_path)) { |
- profile_shortcuts->insert(new_shortcut_path); |
- desktop_contents->insert(new_shortcut_path); |
- } else { |
- DLOG(ERROR) << "Could not copy Windows profile desktop shortcut."; |
- } |
- } |
+ if (base::PathExists(possible_old_system_shortcut)) |
+ base::CopyFile(possible_old_system_shortcut, new_shortcut_path); |
} |
} |
@@ -502,31 +428,24 @@ |
// the following code may result in NOTREACHED() being hit. |
DCHECK(distribution->CanCreateDesktopShortcuts()); |
- std::set<base::FilePath> desktop_contents = ListUserDesktopContents(nullptr); |
- |
- const base::string16 command_line = |
- profiles::internal::CreateProfileShortcutFlags(params.profile_path); |
- ChromeCommandLineFilter filter( |
- chrome_exe, command_line, |
- params.action == ProfileShortcutManagerWin::UPDATE_NON_PROFILE_SHORTCUTS); |
- |
- std::set<base::FilePath> shortcuts; |
- // Do not call ListUserDesktopContents again (but with filter) to avoid |
- // excess work inside it. Just reuse non-filtered desktop_contents. |
- // We need both of them (desktop_contents and shortcuts) later. |
- std::copy_if(desktop_contents.begin(), desktop_contents.end(), |
- std::inserter(shortcuts, shortcuts.begin()), filter); |
- |
if (params.old_profile_name != params.profile_name) { |
- RenameChromeDesktopShortcutForProfile(params.old_profile_name, |
- params.profile_name, &shortcuts, |
- &desktop_contents); |
+ const base::string16 old_shortcut_filename = |
+ profiles::internal::GetShortcutFilenameForProfile( |
+ params.old_profile_name, |
+ distribution); |
+ const base::string16 new_shortcut_filename = |
+ profiles::internal::GetShortcutFilenameForProfile(params.profile_name, |
+ distribution); |
+ RenameChromeDesktopShortcutForProfile(old_shortcut_filename, |
+ new_shortcut_filename); |
} |
ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER); |
installer::Product product(distribution); |
product.AddDefaultShortcutProperties(chrome_exe, &properties); |
+ const base::string16 command_line = |
+ profiles::internal::CreateProfileShortcutFlags(params.profile_path); |
// Only set the profile-specific properties when |profile_name| is non empty. |
// If it is empty, it means the shortcut being created should be a regular, |
@@ -546,17 +465,22 @@ |
ShellUtil::ShortcutOperation operation = |
ShellUtil::SHELL_SHORTCUT_REPLACE_EXISTING; |
+ std::vector<base::FilePath> shortcuts; |
+ ListDesktopShortcutsWithCommandLine(chrome_exe, command_line, |
+ params.action == ProfileShortcutManagerWin::UPDATE_NON_PROFILE_SHORTCUTS, |
+ &shortcuts); |
if (params.create_mode == ProfileShortcutManagerWin::CREATE_WHEN_NONE_FOUND && |
shortcuts.empty()) { |
const base::string16 shortcut_name = |
- profiles::internal::GetUniqueShortcutFilenameForProfile( |
- params.profile_name, desktop_contents, distribution); |
- shortcuts.insert(base::FilePath(shortcut_name)); |
+ profiles::internal::GetShortcutFilenameForProfile(params.profile_name, |
+ distribution); |
+ shortcuts.push_back(base::FilePath(shortcut_name)); |
operation = ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL; |
} |
- for (const auto& shortcut : shortcuts) { |
- const base::FilePath shortcut_name = shortcut.BaseName().RemoveExtension(); |
+ for (size_t i = 0; i < shortcuts.size(); ++i) { |
+ const base::FilePath shortcut_name = |
+ shortcuts[i].BaseName().RemoveExtension(); |
properties.set_shortcut_name(shortcut_name.value()); |
ShellUtil::CreateOrUpdateShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, |
distribution, properties, operation); |
@@ -597,18 +521,20 @@ |
const base::string16 command_line = |
profiles::internal::CreateProfileShortcutFlags(profile_path); |
- ChromeCommandLineFilter filter(chrome_exe, command_line, false); |
- const std::set<base::FilePath> shortcuts = ListUserDesktopContents(&filter); |
- |
- for (const auto& shortcut : shortcuts) { |
+ std::vector<base::FilePath> shortcuts; |
+ ListDesktopShortcutsWithCommandLine(chrome_exe, command_line, false, |
+ &shortcuts); |
+ |
+ for (size_t i = 0; i < shortcuts.size(); ++i) { |
// Use base::DeleteFile() instead of ShellUtil::RemoveShortcuts(), as the |
// latter causes non-profile taskbar shortcuts to be removed since it |
// doesn't consider the command-line of the shortcuts it deletes. |
// TODO(huangs): Refactor with ShellUtil::RemoveShortcuts(). |
- base::win::UnpinShortcutFromTaskbar(shortcut); |
- base::DeleteFile(shortcut, false); |
+ base::win::UnpinShortcutFromTaskbar(shortcuts[i]); |
+ base::DeleteFile(shortcuts[i], false); |
// Notify the shell that the shortcut was deleted to ensure desktop refresh. |
- SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, shortcut.value().c_str(), nullptr); |
+ SHChangeNotify(SHCNE_DELETE, SHCNF_PATH, shortcuts[i].value().c_str(), |
+ NULL); |
} |
// If |ensure_shortcuts_remain| is true and deleting this profile caused the |
@@ -646,8 +572,10 @@ |
const base::string16 command_line = |
profiles::internal::CreateProfileShortcutFlags(profile_path); |
- ChromeCommandLineFilter filter(chrome_exe, command_line, false); |
- return !ListUserDesktopContents(&filter).empty(); |
+ std::vector<base::FilePath> shortcuts; |
+ ListDesktopShortcutsWithCommandLine(chrome_exe, command_line, false, |
+ &shortcuts); |
+ return !shortcuts.empty(); |
} |
// Replaces any reserved characters with spaces, and trims the resulting string |
@@ -713,60 +641,6 @@ |
distribution->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME)); |
} |
return shortcut_name + installer::kLnkExt; |
-} |
- |
-base::string16 GetUniqueShortcutFilenameForProfile( |
- const base::string16& profile_name, |
- const std::set<base::FilePath>& excludes, |
- BrowserDistribution* distribution) { |
- std::set<base::string16> excludes_names; |
- std::transform(excludes.begin(), excludes.end(), |
- std::inserter(excludes_names, excludes_names.begin()), |
- [](const base::FilePath& e) { return e.BaseName().value(); }); |
- |
- const auto base_name = |
- GetShortcutFilenameForProfile(profile_name, distribution); |
- auto name = base_name; |
- const base::FilePath base_path(base_name); |
- for (int uniquifier = 1; excludes_names.count(name) > 0; ++uniquifier) { |
- const auto suffix = base::StringPrintf(" (%d)", uniquifier); |
- name = base_path.InsertBeforeExtensionASCII(suffix).value(); |
- } |
- return name; |
-} |
- |
-// Corresponds to GetUniqueShortcutFilenameForProfile. |
-ShortcutFilenameMatcher::ShortcutFilenameMatcher( |
- const base::string16& profile_name, |
- BrowserDistribution* distribution) |
- : profile_shortcut_filename_( |
- GetShortcutFilenameForProfile(profile_name, distribution)), |
- lnk_ext_(installer::kLnkExt), |
- profile_shortcut_name_(profile_shortcut_filename_) { |
- DCHECK(profile_shortcut_name_.ends_with(lnk_ext_)); |
- profile_shortcut_name_.remove_suffix(lnk_ext_.size()); |
-} |
- |
-bool ShortcutFilenameMatcher::IsCanonical( |
- const base::string16& filename) const { |
- if (filename == profile_shortcut_filename_) |
- return true; |
- |
- base::StringPiece16 shortcut_suffix(filename); |
- if (!shortcut_suffix.starts_with(profile_shortcut_name_)) |
- return false; |
- shortcut_suffix.remove_prefix(profile_shortcut_name_.size()); |
- |
- if (!shortcut_suffix.ends_with(lnk_ext_)) |
- return false; |
- shortcut_suffix.remove_suffix(lnk_ext_.size()); |
- |
- if (shortcut_suffix.size() < 4 || !shortcut_suffix.starts_with(L" (") || |
- !shortcut_suffix.ends_with(L")")) { |
- return false; |
- } |
- return std::all_of(shortcut_suffix.begin() + 2, shortcut_suffix.end() - 1, |
- iswdigit); |
} |
base::string16 CreateProfileShortcutFlags(const base::FilePath& profile_path) { |