diff options
-rw-r--r-- | base/win/shortcut.cc | 32 | ||||
-rw-r--r-- | base/win/shortcut.h | 2 | ||||
-rw-r--r-- | base/win/shortcut_unittest.cc | 27 | ||||
-rw-r--r-- | chrome/installer/util/shell_util.h | 2 | ||||
-rw-r--r-- | chrome/installer/util/shell_util_unittest.cc | 2 |
5 files changed, 51 insertions, 14 deletions
diff --git a/base/win/shortcut.cc b/base/win/shortcut.cc index 912bdb5..eb7a72c 100644 --- a/base/win/shortcut.cc +++ b/base/win/shortcut.cc @@ -55,6 +55,11 @@ bool CreateOrUpdateShortcutLink(const FilePath& shortcut_path, bool shortcut_existed = file_util::PathExists(shortcut_path); + // Interfaces to the old shortcut when replacing an existing shortcut. + ScopedComPtr<IShellLink> old_i_shell_link; + ScopedComPtr<IPersistFile> old_i_persist_file; + + // Interfaces to the shortcut being created/updated. ScopedComPtr<IShellLink> i_shell_link; ScopedComPtr<IPersistFile> i_persist_file; switch (operation) { @@ -66,13 +71,13 @@ bool CreateOrUpdateShortcutLink(const FilePath& shortcut_path, &i_persist_file); break; case SHORTCUT_REPLACE_EXISTING: - InitializeShortcutInterfaces(shortcut_path.value().c_str(), &i_shell_link, - &i_persist_file); + InitializeShortcutInterfaces(shortcut_path.value().c_str(), + &old_i_shell_link, &old_i_persist_file); // Confirm |shortcut_path| exists and is a shortcut by verifying - // |i_persist_file| was successfully initialized in the call above. If so, - // re-initialize the interfaces to begin writing a new shortcut (to + // |old_i_persist_file| was successfully initialized in the call above. If + // so, initialize the interfaces to begin writing a new shortcut (to // overwrite the current one if successful). - if (i_persist_file.get()) + if (old_i_persist_file.get()) InitializeShortcutInterfaces(NULL, &i_shell_link, &i_persist_file); break; default: @@ -94,9 +99,15 @@ bool CreateOrUpdateShortcutLink(const FilePath& shortcut_path, return false; } - if ((properties.options & ShortcutProperties::PROPERTIES_ARGUMENTS) && - FAILED(i_shell_link->SetArguments(properties.arguments.c_str()))) { - return false; + if (properties.options & ShortcutProperties::PROPERTIES_ARGUMENTS) { + if (FAILED(i_shell_link->SetArguments(properties.arguments.c_str()))) + return false; + } else if (old_i_persist_file.get()) { + wchar_t current_arguments[MAX_PATH] = {0}; + if (SUCCEEDED(old_i_shell_link->GetArguments(current_arguments, + MAX_PATH))) { + i_shell_link->SetArguments(current_arguments); + } } if ((properties.options & ShortcutProperties::PROPERTIES_DESCRIPTION) && @@ -132,6 +143,11 @@ bool CreateOrUpdateShortcutLink(const FilePath& shortcut_path, } } + // Release the interfaces to the old shortcut to make sure it doesn't prevent + // overwriting it if needed. + old_i_persist_file.Release(); + old_i_shell_link.Release(); + HRESULT result = i_persist_file->Save(shortcut_path.value().c_str(), TRUE); // Release the interfaces in case the SHChangeNotify call below depends on diff --git a/base/win/shortcut.h b/base/win/shortcut.h index c1e7d5c..52ac1a7 100644 --- a/base/win/shortcut.h +++ b/base/win/shortcut.h @@ -18,6 +18,8 @@ enum ShortcutOperation { // Create a new shortcut (overwriting if necessary). SHORTCUT_CREATE_ALWAYS = 0, // Overwrite an existing shortcut (fails if the shortcut doesn't exist). + // If the arguments are not specified on the new shortcut, keep the old + // shortcut's arguments. SHORTCUT_REPLACE_EXISTING, // Update specified properties only on an existing shortcut. SHORTCUT_UPDATE_EXISTING, diff --git a/base/win/shortcut_unittest.cc b/base/win/shortcut_unittest.cc index 26b22be..70cc852 100644 --- a/base/win/shortcut_unittest.cc +++ b/base/win/shortcut_unittest.cc @@ -212,7 +212,7 @@ TEST_F(ShortcutTest, FailUpdateShortcutThatDoesNotExist) { ASSERT_FALSE(file_util::PathExists(link_file_)); } -TEST_F(ShortcutTest, TruncateShortcutAllProperties) { +TEST_F(ShortcutTest, ReplaceShortcutAllProperties) { ASSERT_TRUE(base::win::CreateOrUpdateShortcutLink( link_file_, link_properties_, base::win::SHORTCUT_CREATE_ALWAYS)); @@ -222,29 +222,46 @@ TEST_F(ShortcutTest, TruncateShortcutAllProperties) { base::win::ValidateShortcut(link_file_, link_properties_2_); } -TEST_F(ShortcutTest, TruncateShortcutSomeProperties) { +TEST_F(ShortcutTest, ReplaceShortcutSomeProperties) { ASSERT_TRUE(base::win::CreateOrUpdateShortcutLink( link_file_, link_properties_, base::win::SHORTCUT_CREATE_ALWAYS)); base::win::ShortcutProperties new_properties; new_properties.set_target(link_properties_2_.target); + new_properties.set_arguments(link_properties_2_.arguments); new_properties.set_description(link_properties_2_.description); ASSERT_TRUE(base::win::CreateOrUpdateShortcutLink( link_file_, new_properties, base::win::SHORTCUT_REPLACE_EXISTING)); // Expect only properties in |new_properties| to be set, all other properties // should have been overwritten. - base::win::ShortcutProperties expected_properties = new_properties; + base::win::ShortcutProperties expected_properties(new_properties); expected_properties.set_working_dir(FilePath()); - expected_properties.set_arguments(string16()); expected_properties.set_icon(FilePath(), 0); expected_properties.set_app_id(string16()); expected_properties.set_dual_mode(false); base::win::ValidateShortcut(link_file_, expected_properties); } -TEST_F(ShortcutTest, FailTruncateShortcutThatDoesNotExist) { +TEST_F(ShortcutTest, FailReplaceShortcutThatDoesNotExist) { ASSERT_FALSE(base::win::CreateOrUpdateShortcutLink( link_file_, link_properties_, base::win::SHORTCUT_REPLACE_EXISTING)); ASSERT_FALSE(file_util::PathExists(link_file_)); } + +// Test that the old arguments remain on the replaced shortcut when not +// otherwise specified. +TEST_F(ShortcutTest, ReplaceShortcutKeepOldArguments) { + ASSERT_TRUE(base::win::CreateOrUpdateShortcutLink( + link_file_, link_properties_, base::win::SHORTCUT_CREATE_ALWAYS)); + + // Do not explicitly set the arguments. + link_properties_2_.options &= + ~base::win::ShortcutProperties::PROPERTIES_ARGUMENTS; + ASSERT_TRUE(base::win::CreateOrUpdateShortcutLink( + link_file_, link_properties_2_, base::win::SHORTCUT_REPLACE_EXISTING)); + + base::win::ShortcutProperties expected_properties(link_properties_2_); + expected_properties.set_arguments(link_properties_.arguments); + base::win::ValidateShortcut(link_file_, expected_properties); +} diff --git a/chrome/installer/util/shell_util.h b/chrome/installer/util/shell_util.h index 746102f..98439c3 100644 --- a/chrome/installer/util/shell_util.h +++ b/chrome/installer/util/shell_util.h @@ -53,6 +53,8 @@ class ShellUtil { // present. SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL, // Overwrite an existing shortcut (fail if the shortcut doesn't exist). + // If the arguments are not specified on the new shortcut, keep the old + // shortcut's arguments. SHELL_SHORTCUT_REPLACE_EXISTING, // Update specified properties only on an existing shortcut. SHELL_SHORTCUT_UPDATE_EXISTING, diff --git a/chrome/installer/util/shell_util_unittest.cc b/chrome/installer/util/shell_util_unittest.cc index fa6b8b9..dd52fcf 100644 --- a/chrome/installer/util/shell_util_unittest.cc +++ b/chrome/installer/util/shell_util_unittest.cc @@ -229,6 +229,7 @@ TEST_F(ShellUtilShortcutTest, ReplaceSystemLevelQuickLaunchShortcut) { ShellUtil::ShortcutProperties new_properties(ShellUtil::SYSTEM_LEVEL); product_->AddDefaultShortcutProperties(chrome_exe_, &new_properties); new_properties.set_description(L"New description"); + new_properties.set_arguments(L"--new-arguments"); ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, dist_, new_properties, @@ -238,7 +239,6 @@ TEST_F(ShellUtilShortcutTest, ReplaceSystemLevelQuickLaunchShortcut) { // properties that don't have a default value to be set back to their default // (as validated in ValidateChromeShortcut()) or unset if they don't . ShellUtil::ShortcutProperties expected_properties(new_properties); - expected_properties.set_arguments(string16()); expected_properties.set_dual_mode(false); ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, dist_, |