| Index: chrome/browser/profiles/profile_shortcut_manager_win.cc
|
| ===================================================================
|
| --- chrome/browser/profiles/profile_shortcut_manager_win.cc (revision 178353)
|
| +++ chrome/browser/profiles/profile_shortcut_manager_win.cc (working copy)
|
| @@ -8,6 +8,7 @@
|
| #include <vector>
|
|
|
| #include "base/bind.h"
|
| +#include "base/command_line.h"
|
| #include "base/file_util.h"
|
| #include "base/path_service.h"
|
| #include "base/string16.h"
|
| @@ -20,6 +21,8 @@
|
| #include "chrome/browser/profiles/profile_info_cache_observer.h"
|
| #include "chrome/browser/profiles/profile_info_util.h"
|
| #include "chrome/browser/profiles/profile_manager.h"
|
| +#include "chrome/common/chrome_paths.h"
|
| +#include "chrome/common/chrome_paths_internal.h"
|
| #include "chrome/common/chrome_switches.h"
|
| #include "chrome/installer/util/browser_distribution.h"
|
| #include "chrome/installer/util/product.h"
|
| @@ -144,6 +147,13 @@
|
| return path;
|
| }
|
|
|
| +// Tests whether the given paths are equal. Compares the Windows long paths
|
| +// because one of the paths may be in short (elided) form, which is a case that
|
| +// is not handled by FilePath's == operator.
|
| +bool FilePathsEqual(const FilePath& path1, const FilePath& path2) {
|
| + return ConvertToLongPath(path1) == ConvertToLongPath(path2);
|
| +}
|
| +
|
| // Returns true if the file at |path| is a Chrome shortcut and returns its
|
| // command line in output parameter |command_line|.
|
| bool IsChromeShortcut(const FilePath& path,
|
| @@ -157,35 +167,73 @@
|
| FilePath target_path;
|
| if (!base::win::ResolveShortcut(path, &target_path, command_line))
|
| return false;
|
| - // One of the paths may be in short (elided) form. Compare long paths to
|
| - // ensure these are still properly matched.
|
| - return ConvertToLongPath(target_path) == ConvertToLongPath(chrome_exe);
|
| +
|
| + return FilePathsEqual(target_path, chrome_exe);
|
| }
|
|
|
| -// 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.
|
| +// Returns true if either |command_line| has no specified user data dir and
|
| +// |custom_user_data_dir| is false or if it has a user data dir that matches
|
| +// |user_data_dir|.
|
| +bool CommandLineMatchesUserDataDir(const CommandLine& command_line,
|
| + const FilePath& user_data_dir,
|
| + bool custom_user_data_dir) {
|
| + const FilePath switch_value =
|
| + command_line.GetSwitchValuePath(switches::kUserDataDir);
|
| + if (switch_value.empty() && !custom_user_data_dir)
|
| + return true;
|
| + return FilePathsEqual(switch_value, user_data_dir);
|
| +}
|
| +
|
| +// Populates |paths| with the file paths of Chrome desktop shortcuts that match
|
| +// the specified |command_line| in terms of user data dir and profile directory.
|
| +// If |include_nonprofile_shortcuts| is true, Chrome desktop shortcuts without
|
| +// profile command lines will also be included.
|
| void ListDesktopShortcutsWithCommandLine(const FilePath& chrome_exe,
|
| - const string16& command_line,
|
| - bool include_empty_command_lines,
|
| + const CommandLine& command_line,
|
| + bool include_nonprofile_shortcuts,
|
| std::vector<FilePath>* paths) {
|
| FilePath user_shortcuts_directory;
|
| if (!GetDesktopShortcutsDirectories(&user_shortcuts_directory, NULL))
|
| return;
|
|
|
| + // Get the wanted profile path and user data dir from |command_line|.
|
| + const string16& wanted_profile_path =
|
| + command_line.GetSwitchValueNative(switches::kProfileDirectory);
|
| + FilePath wanted_user_data_dir =
|
| + command_line.GetSwitchValuePath(switches::kUserDataDir);
|
| + bool custom_user_data_dir = true;
|
| + // If the command line doesn't have a user data dir specified, that means
|
| + // it is not a custom user data dir, so match shortcuts that either don't
|
| + // have it specified, or which have it equal to the current user data dir.
|
| + if (wanted_user_data_dir.empty()) {
|
| + if (!PathService::Get(chrome::DIR_USER_DATA, &wanted_user_data_dir)) {
|
| + NOTREACHED();
|
| + return;
|
| + }
|
| + custom_user_data_dir = false;
|
| + }
|
| +
|
| file_util::FileEnumerator enumerator(user_shortcuts_directory, false,
|
| file_util::FileEnumerator::FILES);
|
| for (FilePath path = enumerator.Next(); !path.empty();
|
| path = enumerator.Next()) {
|
| - string16 shortcut_command_line;
|
| - if (!IsChromeShortcut(path, chrome_exe, &shortcut_command_line))
|
| + string16 shortcut_command_line_args;
|
| + if (!IsChromeShortcut(path, chrome_exe, &shortcut_command_line_args))
|
| 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) != string16::npos)) {
|
| + const CommandLine shortcut_command_line =
|
| + CommandLine::FromString(chrome_exe.value() + L" " +
|
| + shortcut_command_line_args);
|
| + if (!CommandLineMatchesUserDataDir(shortcut_command_line,
|
| + wanted_user_data_dir,
|
| + custom_user_data_dir)) {
|
| + continue;
|
| + }
|
| +
|
| + const string16 shortcut_profile_path =
|
| + shortcut_command_line.GetSwitchValueNative(switches::kProfileDirectory);
|
| + if ((shortcut_profile_path.empty() && include_nonprofile_shortcuts) ||
|
| + (shortcut_profile_path == wanted_profile_path)) {
|
| paths->push_back(path);
|
| }
|
| }
|
| @@ -272,8 +320,9 @@
|
| installer::Product product(distribution);
|
| product.AddDefaultShortcutProperties(chrome_exe, &properties);
|
|
|
| - const string16 command_line =
|
| - profiles::internal::CreateProfileShortcutFlags(profile_path);
|
| + const CommandLine command_line =
|
| + profiles::internal::CreateCommandLineForProfileShortcut(chrome_exe,
|
| + 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,
|
| @@ -283,11 +332,14 @@
|
| CreateChromeDesktopShortcutIconForProfile(profile_path, avatar_image);
|
| if (!shortcut_icon.empty())
|
| properties.set_icon(shortcut_icon, 0);
|
| - properties.set_arguments(command_line);
|
| + properties.set_arguments(command_line.GetArgumentsString());
|
| } else {
|
| - // Set the arguments explicitly to the empty string to ensure that
|
| - // |ShellUtil::CreateOrUpdateShortcut| updates that part of the shortcut.
|
| - properties.set_arguments(string16());
|
| + // Set the arguments explicitly (possibly including a custom user data dir)
|
| + // to ensure that |ShellUtil::CreateOrUpdateShortcut| updates that part of
|
| + // the shortcut.
|
| + const CommandLine command_line =
|
| + profiles::internal::CreateCommandLineForNonProfileShortcut(chrome_exe);
|
| + properties.set_arguments(command_line.GetArgumentsString());
|
| }
|
|
|
| ShellUtil::ShortcutOperation operation =
|
| @@ -346,8 +398,9 @@
|
| return;
|
| }
|
|
|
| - const string16 command_line =
|
| - profiles::internal::CreateProfileShortcutFlags(profile_path);
|
| + const CommandLine command_line =
|
| + profiles::internal::CreateCommandLineForProfileShortcut(chrome_exe,
|
| + profile_path);
|
| std::vector<FilePath> shortcuts;
|
| ListDesktopShortcutsWithCommandLine(chrome_exe, command_line, false,
|
| &shortcuts);
|
| @@ -381,6 +434,9 @@
|
| properties.set_shortcut_name(
|
| profiles::internal::GetShortcutFilenameForProfile(string16(),
|
| distribution));
|
| + const CommandLine command_line =
|
| + profiles::internal::CreateCommandLineForNonProfileShortcut(chrome_exe);
|
| + properties.set_arguments(command_line.GetArgumentsString());
|
| ShellUtil::CreateOrUpdateShortcut(
|
| ShellUtil::SHORTCUT_LOCATION_DESKTOP, distribution, properties,
|
| ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL);
|
| @@ -398,8 +454,9 @@
|
| return false;
|
| }
|
|
|
| - const string16 command_line =
|
| - profiles::internal::CreateProfileShortcutFlags(profile_path);
|
| + const CommandLine command_line =
|
| + profiles::internal::CreateCommandLineForProfileShortcut(chrome_exe,
|
| + profile_path);
|
| std::vector<FilePath> shortcuts;
|
| ListDesktopShortcutsWithCommandLine(chrome_exe, command_line, false,
|
| &shortcuts);
|
| @@ -446,12 +503,41 @@
|
| return shortcut_name + installer::kLnkExt;
|
| }
|
|
|
| -string16 CreateProfileShortcutFlags(const FilePath& profile_path) {
|
| - return base::StringPrintf(L"--%ls=\"%ls\"",
|
| - ASCIIToUTF16(switches::kProfileDirectory).c_str(),
|
| - profile_path.BaseName().value().c_str());
|
| +FilePath GetCustomUserDataDirectory() {
|
| + FilePath user_data_dir;
|
| + if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) {
|
| + NOTREACHED();
|
| + return FilePath();
|
| + }
|
| +
|
| + FilePath default_user_data_dir;
|
| + if (!chrome::GetDefaultUserDataDirectory(&default_user_data_dir)) {
|
| + NOTREACHED();
|
| + return FilePath();
|
| + }
|
| +
|
| + if (FilePathsEqual(user_data_dir, default_user_data_dir))
|
| + return FilePath();
|
| +
|
| + return user_data_dir;
|
| }
|
|
|
| +CommandLine CreateCommandLineForNonProfileShortcut(const FilePath& chrome_exe) {
|
| + CommandLine command_line(chrome_exe);
|
| + const FilePath custom_user_data_dir = GetCustomUserDataDirectory();
|
| + if (!custom_user_data_dir.empty())
|
| + command_line.AppendSwitchPath(switches::kUserDataDir, custom_user_data_dir);
|
| + return command_line;
|
| +}
|
| +
|
| +CommandLine CreateCommandLineForProfileShortcut(const FilePath& chrome_exe,
|
| + const FilePath& profile_path) {
|
| + CommandLine command_line = CreateCommandLineForNonProfileShortcut(chrome_exe);
|
| + command_line.AppendSwitchPath(switches::kProfileDirectory,
|
| + profile_path.BaseName());
|
| + return command_line;
|
| +}
|
| +
|
| } // namespace internal
|
| } // namespace profiles
|
|
|
|
|