1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "base/win/shortcut.h" 6 7 #include <string> 8 9 #include "base/file_util.h" 10 #include "base/files/file_path.h" 11 #include "base/files/scoped_temp_dir.h" 12 #include "base/test/test_file_util.h" 13 #include "base/test/test_shortcut_win.h" 14 #include "base/win/scoped_com_initializer.h" 15 #include "testing/gtest/include/gtest/gtest.h" 16 17 namespace base { 18 namespace win { 19 20 namespace { 21 22 static const char kFileContents[] = "This is a target."; 23 static const char kFileContents2[] = "This is another target."; 24 25 class ShortcutTest : public testing::Test { 26 protected: 27 virtual void SetUp() OVERRIDE { 28 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 29 ASSERT_TRUE(temp_dir_2_.CreateUniqueTempDir()); 30 31 link_file_ = temp_dir_.path().Append(L"My Link.lnk"); 32 33 // Shortcut 1's properties 34 { 35 const FilePath target_file(temp_dir_.path().Append(L"Target 1.txt")); 36 file_util::WriteFile(target_file, kFileContents, 37 arraysize(kFileContents)); 38 39 link_properties_.set_target(target_file); 40 link_properties_.set_working_dir(temp_dir_.path()); 41 link_properties_.set_arguments(L"--magic --awesome"); 42 link_properties_.set_description(L"Chrome is awesome."); 43 link_properties_.set_icon(link_properties_.target, 4); 44 link_properties_.set_app_id(L"Chrome"); 45 link_properties_.set_dual_mode(false); 46 } 47 48 // Shortcut 2's properties (all different from properties of shortcut 1). 49 { 50 const FilePath target_file_2(temp_dir_.path().Append(L"Target 2.txt")); 51 file_util::WriteFile(target_file_2, kFileContents2, 52 arraysize(kFileContents2)); 53 54 FilePath icon_path_2; 55 base::CreateTemporaryFileInDir(temp_dir_.path(), &icon_path_2); 56 57 link_properties_2_.set_target(target_file_2); 58 link_properties_2_.set_working_dir(temp_dir_2_.path()); 59 link_properties_2_.set_arguments(L"--super --crazy"); 60 link_properties_2_.set_description(L"The best in the west."); 61 link_properties_2_.set_icon(icon_path_2, 0); 62 link_properties_2_.set_app_id(L"Chrome.UserLevelCrazySuffix"); 63 link_properties_2_.set_dual_mode(true); 64 } 65 } 66 67 ScopedCOMInitializer com_initializer_; 68 ScopedTempDir temp_dir_; 69 ScopedTempDir temp_dir_2_; 70 71 // The link file to be created/updated in the shortcut tests below. 72 FilePath link_file_; 73 74 // Properties for the created shortcut. 75 ShortcutProperties link_properties_; 76 77 // Properties for the updated shortcut. 78 ShortcutProperties link_properties_2_; 79 }; 80 81 } // namespace 82 83 TEST_F(ShortcutTest, CreateAndResolveShortcut) { 84 ShortcutProperties only_target_properties; 85 only_target_properties.set_target(link_properties_.target); 86 87 ASSERT_TRUE(CreateOrUpdateShortcutLink( 88 link_file_, only_target_properties, SHORTCUT_CREATE_ALWAYS)); 89 90 FilePath resolved_name; 91 EXPECT_TRUE(ResolveShortcut(link_file_, &resolved_name, NULL)); 92 93 char read_contents[arraysize(kFileContents)]; 94 base::ReadFile(resolved_name, read_contents, arraysize(read_contents)); 95 EXPECT_STREQ(kFileContents, read_contents); 96 } 97 98 TEST_F(ShortcutTest, ResolveShortcutWithArgs) { 99 ASSERT_TRUE(CreateOrUpdateShortcutLink( 100 link_file_, link_properties_, SHORTCUT_CREATE_ALWAYS)); 101 102 FilePath resolved_name; 103 string16 args; 104 EXPECT_TRUE(ResolveShortcut(link_file_, &resolved_name, &args)); 105 106 char read_contents[arraysize(kFileContents)]; 107 base::ReadFile(resolved_name, read_contents, arraysize(read_contents)); 108 EXPECT_STREQ(kFileContents, read_contents); 109 EXPECT_EQ(link_properties_.arguments, args); 110 } 111 112 TEST_F(ShortcutTest, CreateShortcutWithOnlySomeProperties) { 113 ShortcutProperties target_and_args_properties; 114 target_and_args_properties.set_target(link_properties_.target); 115 target_and_args_properties.set_arguments(link_properties_.arguments); 116 117 ASSERT_TRUE(CreateOrUpdateShortcutLink( 118 link_file_, target_and_args_properties, 119 SHORTCUT_CREATE_ALWAYS)); 120 121 ValidateShortcut(link_file_, target_and_args_properties); 122 } 123 124 TEST_F(ShortcutTest, CreateShortcutVerifyProperties) { 125 ASSERT_TRUE(CreateOrUpdateShortcutLink( 126 link_file_, link_properties_, SHORTCUT_CREATE_ALWAYS)); 127 128 ValidateShortcut(link_file_, link_properties_); 129 } 130 131 TEST_F(ShortcutTest, UpdateShortcutVerifyProperties) { 132 ASSERT_TRUE(CreateOrUpdateShortcutLink( 133 link_file_, link_properties_, SHORTCUT_CREATE_ALWAYS)); 134 135 ASSERT_TRUE(CreateOrUpdateShortcutLink( 136 link_file_, link_properties_2_, SHORTCUT_UPDATE_EXISTING)); 137 138 ValidateShortcut(link_file_, link_properties_2_); 139 } 140 141 TEST_F(ShortcutTest, UpdateShortcutUpdateOnlyTargetAndResolve) { 142 ASSERT_TRUE(CreateOrUpdateShortcutLink( 143 link_file_, link_properties_, SHORTCUT_CREATE_ALWAYS)); 144 145 ShortcutProperties update_only_target_properties; 146 update_only_target_properties.set_target(link_properties_2_.target); 147 148 ASSERT_TRUE(CreateOrUpdateShortcutLink( 149 link_file_, update_only_target_properties, 150 SHORTCUT_UPDATE_EXISTING)); 151 152 ShortcutProperties expected_properties = link_properties_; 153 expected_properties.set_target(link_properties_2_.target); 154 ValidateShortcut(link_file_, expected_properties); 155 156 FilePath resolved_name; 157 EXPECT_TRUE(ResolveShortcut(link_file_, &resolved_name, NULL)); 158 159 char read_contents[arraysize(kFileContents2)]; 160 base::ReadFile(resolved_name, read_contents, arraysize(read_contents)); 161 EXPECT_STREQ(kFileContents2, read_contents); 162 } 163 164 TEST_F(ShortcutTest, UpdateShortcutMakeDualMode) { 165 ASSERT_TRUE(CreateOrUpdateShortcutLink( 166 link_file_, link_properties_, SHORTCUT_CREATE_ALWAYS)); 167 168 ShortcutProperties make_dual_mode_properties; 169 make_dual_mode_properties.set_dual_mode(true); 170 171 ASSERT_TRUE(CreateOrUpdateShortcutLink( 172 link_file_, make_dual_mode_properties, 173 SHORTCUT_UPDATE_EXISTING)); 174 175 ShortcutProperties expected_properties = link_properties_; 176 expected_properties.set_dual_mode(true); 177 ValidateShortcut(link_file_, expected_properties); 178 } 179 180 TEST_F(ShortcutTest, UpdateShortcutRemoveDualMode) { 181 ASSERT_TRUE(CreateOrUpdateShortcutLink( 182 link_file_, link_properties_2_, SHORTCUT_CREATE_ALWAYS)); 183 184 ShortcutProperties remove_dual_mode_properties; 185 remove_dual_mode_properties.set_dual_mode(false); 186 187 ASSERT_TRUE(CreateOrUpdateShortcutLink( 188 link_file_, remove_dual_mode_properties, 189 SHORTCUT_UPDATE_EXISTING)); 190 191 ShortcutProperties expected_properties = link_properties_2_; 192 expected_properties.set_dual_mode(false); 193 ValidateShortcut(link_file_, expected_properties); 194 } 195 196 TEST_F(ShortcutTest, UpdateShortcutClearArguments) { 197 ASSERT_TRUE(CreateOrUpdateShortcutLink( 198 link_file_, link_properties_, SHORTCUT_CREATE_ALWAYS)); 199 200 ShortcutProperties clear_arguments_properties; 201 clear_arguments_properties.set_arguments(string16()); 202 203 ASSERT_TRUE(CreateOrUpdateShortcutLink( 204 link_file_, clear_arguments_properties, 205 SHORTCUT_UPDATE_EXISTING)); 206 207 ShortcutProperties expected_properties = link_properties_; 208 expected_properties.set_arguments(string16()); 209 ValidateShortcut(link_file_, expected_properties); 210 } 211 212 TEST_F(ShortcutTest, FailUpdateShortcutThatDoesNotExist) { 213 ASSERT_FALSE(CreateOrUpdateShortcutLink( 214 link_file_, link_properties_, SHORTCUT_UPDATE_EXISTING)); 215 ASSERT_FALSE(PathExists(link_file_)); 216 } 217 218 TEST_F(ShortcutTest, ReplaceShortcutAllProperties) { 219 ASSERT_TRUE(CreateOrUpdateShortcutLink( 220 link_file_, link_properties_, SHORTCUT_CREATE_ALWAYS)); 221 222 ASSERT_TRUE(CreateOrUpdateShortcutLink( 223 link_file_, link_properties_2_, SHORTCUT_REPLACE_EXISTING)); 224 225 ValidateShortcut(link_file_, link_properties_2_); 226 } 227 228 TEST_F(ShortcutTest, ReplaceShortcutSomeProperties) { 229 ASSERT_TRUE(CreateOrUpdateShortcutLink( 230 link_file_, link_properties_, SHORTCUT_CREATE_ALWAYS)); 231 232 ShortcutProperties new_properties; 233 new_properties.set_target(link_properties_2_.target); 234 new_properties.set_arguments(link_properties_2_.arguments); 235 new_properties.set_description(link_properties_2_.description); 236 ASSERT_TRUE(CreateOrUpdateShortcutLink( 237 link_file_, new_properties, SHORTCUT_REPLACE_EXISTING)); 238 239 // Expect only properties in |new_properties| to be set, all other properties 240 // should have been overwritten. 241 ShortcutProperties expected_properties(new_properties); 242 expected_properties.set_working_dir(FilePath()); 243 expected_properties.set_icon(FilePath(), 0); 244 expected_properties.set_app_id(string16()); 245 expected_properties.set_dual_mode(false); 246 ValidateShortcut(link_file_, expected_properties); 247 } 248 249 TEST_F(ShortcutTest, FailReplaceShortcutThatDoesNotExist) { 250 ASSERT_FALSE(CreateOrUpdateShortcutLink( 251 link_file_, link_properties_, SHORTCUT_REPLACE_EXISTING)); 252 ASSERT_FALSE(PathExists(link_file_)); 253 } 254 255 // Test that the old arguments remain on the replaced shortcut when not 256 // otherwise specified. 257 TEST_F(ShortcutTest, ReplaceShortcutKeepOldArguments) { 258 ASSERT_TRUE(CreateOrUpdateShortcutLink( 259 link_file_, link_properties_, SHORTCUT_CREATE_ALWAYS)); 260 261 // Do not explicitly set the arguments. 262 link_properties_2_.options &= 263 ~ShortcutProperties::PROPERTIES_ARGUMENTS; 264 ASSERT_TRUE(CreateOrUpdateShortcutLink( 265 link_file_, link_properties_2_, SHORTCUT_REPLACE_EXISTING)); 266 267 ShortcutProperties expected_properties(link_properties_2_); 268 expected_properties.set_arguments(link_properties_.arguments); 269 ValidateShortcut(link_file_, expected_properties); 270 } 271 272 } // namespace win 273 } // namespace base 274