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 "chrome/installer/util/shell_util.h" 6 7 #include <vector> 8 9 #include "base/base_paths.h" 10 #include "base/base_paths_win.h" 11 #include "base/files/file_enumerator.h" 12 #include "base/files/file_util.h" 13 #include "base/files/scoped_temp_dir.h" 14 #include "base/md5.h" 15 #include "base/memory/scoped_ptr.h" 16 #include "base/strings/string16.h" 17 #include "base/strings/string_util.h" 18 #include "base/synchronization/cancellation_flag.h" 19 #include "base/test/scoped_path_override.h" 20 #include "base/test/test_shortcut_win.h" 21 #include "base/win/shortcut.h" 22 #include "base/win/windows_version.h" 23 #include "chrome/installer/util/browser_distribution.h" 24 #include "chrome/installer/util/product.h" 25 #include "chrome/installer/util/util_constants.h" 26 #include "testing/gtest/include/gtest/gtest.h" 27 28 namespace { 29 30 const wchar_t kManganeseExe[] = L"manganese.exe"; 31 const wchar_t kIronExe[] = L"iron.exe"; 32 const wchar_t kOtherIco[] = L"other.ico"; 33 34 // TODO(huangs): Separate this into generic shortcut tests and Chrome-specific 35 // tests. Specifically, we should not overly rely on getting shortcut properties 36 // from product_->AddDefaultShortcutProperties(). 37 class ShellUtilShortcutTest : public testing::Test { 38 protected: 39 ShellUtilShortcutTest() : test_properties_(ShellUtil::CURRENT_USER) {} 40 41 virtual void SetUp() OVERRIDE { 42 dist_ = BrowserDistribution::GetDistribution(); 43 ASSERT_TRUE(dist_ != NULL); 44 product_.reset(new installer::Product(dist_)); 45 46 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 47 chrome_exe_ = temp_dir_.path().Append(installer::kChromeExe); 48 EXPECT_EQ(0, base::WriteFile(chrome_exe_, "", 0)); 49 50 manganese_exe_ = temp_dir_.path().Append(kManganeseExe); 51 EXPECT_EQ(0, base::WriteFile(manganese_exe_, "", 0)); 52 53 iron_exe_ = temp_dir_.path().Append(kIronExe); 54 EXPECT_EQ(0, base::WriteFile(iron_exe_, "", 0)); 55 56 other_ico_ = temp_dir_.path().Append(kOtherIco); 57 EXPECT_EQ(0, base::WriteFile(other_ico_, "", 0)); 58 59 ASSERT_TRUE(fake_user_desktop_.CreateUniqueTempDir()); 60 ASSERT_TRUE(fake_common_desktop_.CreateUniqueTempDir()); 61 ASSERT_TRUE(fake_user_quick_launch_.CreateUniqueTempDir()); 62 ASSERT_TRUE(fake_default_user_quick_launch_.CreateUniqueTempDir()); 63 ASSERT_TRUE(fake_start_menu_.CreateUniqueTempDir()); 64 ASSERT_TRUE(fake_common_start_menu_.CreateUniqueTempDir()); 65 user_desktop_override_.reset( 66 new base::ScopedPathOverride(base::DIR_USER_DESKTOP, 67 fake_user_desktop_.path())); 68 common_desktop_override_.reset( 69 new base::ScopedPathOverride(base::DIR_COMMON_DESKTOP, 70 fake_common_desktop_.path())); 71 user_quick_launch_override_.reset( 72 new base::ScopedPathOverride(base::DIR_USER_QUICK_LAUNCH, 73 fake_user_quick_launch_.path())); 74 start_menu_override_.reset( 75 new base::ScopedPathOverride(base::DIR_START_MENU, 76 fake_start_menu_.path())); 77 common_start_menu_override_.reset( 78 new base::ScopedPathOverride(base::DIR_COMMON_START_MENU, 79 fake_common_start_menu_.path())); 80 81 base::FilePath icon_path; 82 base::CreateTemporaryFileInDir(temp_dir_.path(), &icon_path); 83 test_properties_.set_target(chrome_exe_); 84 test_properties_.set_arguments(L"--test --chrome"); 85 test_properties_.set_description(L"Makes polar bears dance."); 86 test_properties_.set_icon(icon_path, 7); 87 test_properties_.set_app_id(L"Polar.Bear"); 88 test_properties_.set_dual_mode(true); 89 } 90 91 // Returns the expected path of a test shortcut. Returns an empty FilePath on 92 // failure. 93 base::FilePath GetExpectedShortcutPath( 94 ShellUtil::ShortcutLocation location, 95 BrowserDistribution* dist, 96 const ShellUtil::ShortcutProperties& properties) { 97 base::FilePath expected_path; 98 switch (location) { 99 case ShellUtil::SHORTCUT_LOCATION_DESKTOP: 100 expected_path = (properties.level == ShellUtil::CURRENT_USER) ? 101 fake_user_desktop_.path() : fake_common_desktop_.path(); 102 break; 103 case ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH: 104 expected_path = fake_user_quick_launch_.path(); 105 break; 106 case ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR: 107 expected_path = (properties.level == ShellUtil::CURRENT_USER) ? 108 fake_start_menu_.path() : fake_common_start_menu_.path(); 109 expected_path = expected_path.Append( 110 dist_->GetStartMenuShortcutSubfolder( 111 BrowserDistribution::SUBFOLDER_CHROME)); 112 break; 113 default: 114 ADD_FAILURE() << "Unknown location"; 115 return base::FilePath(); 116 } 117 118 base::string16 shortcut_name = properties.has_shortcut_name() ? 119 properties.shortcut_name : 120 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME); 121 shortcut_name.append(installer::kLnkExt); 122 return expected_path.Append(shortcut_name); 123 } 124 125 // Validates that the shortcut at |location| matches |properties| (and 126 // implicit default properties) for |dist|. 127 // Note: This method doesn't verify the |pin_to_taskbar| property as it 128 // implies real (non-mocked) state which is flaky to test. 129 void ValidateChromeShortcut( 130 ShellUtil::ShortcutLocation location, 131 BrowserDistribution* dist, 132 const ShellUtil::ShortcutProperties& properties) { 133 base::FilePath expected_path( 134 GetExpectedShortcutPath(location, dist, properties)); 135 136 base::win::ShortcutProperties expected_properties; 137 if (properties.has_target()) { 138 expected_properties.set_target(properties.target); 139 expected_properties.set_working_dir(properties.target.DirName()); 140 } else { 141 expected_properties.set_target(chrome_exe_); 142 expected_properties.set_working_dir(chrome_exe_.DirName()); 143 } 144 145 if (properties.has_arguments()) 146 expected_properties.set_arguments(properties.arguments); 147 else 148 expected_properties.set_arguments(base::string16()); 149 150 if (properties.has_description()) 151 expected_properties.set_description(properties.description); 152 else 153 expected_properties.set_description(dist->GetAppDescription()); 154 155 if (properties.has_icon()) { 156 expected_properties.set_icon(properties.icon, properties.icon_index); 157 } else { 158 int icon_index = dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME); 159 expected_properties.set_icon(chrome_exe_, icon_index); 160 } 161 162 if (properties.has_app_id()) { 163 expected_properties.set_app_id(properties.app_id); 164 } else { 165 // Tests are always seen as user-level installs in ShellUtil. 166 expected_properties.set_app_id(ShellUtil::GetBrowserModelId(dist, true)); 167 } 168 169 if (properties.has_dual_mode()) 170 expected_properties.set_dual_mode(properties.dual_mode); 171 else 172 expected_properties.set_dual_mode(false); 173 174 base::win::ValidateShortcut(expected_path, expected_properties); 175 } 176 177 BrowserDistribution* dist_; 178 scoped_ptr<installer::Product> product_; 179 180 // A ShellUtil::ShortcutProperties object with common properties set already. 181 ShellUtil::ShortcutProperties test_properties_; 182 183 base::ScopedTempDir temp_dir_; 184 base::ScopedTempDir fake_user_desktop_; 185 base::ScopedTempDir fake_common_desktop_; 186 base::ScopedTempDir fake_user_quick_launch_; 187 base::ScopedTempDir fake_default_user_quick_launch_; 188 base::ScopedTempDir fake_start_menu_; 189 base::ScopedTempDir fake_common_start_menu_; 190 scoped_ptr<base::ScopedPathOverride> user_desktop_override_; 191 scoped_ptr<base::ScopedPathOverride> common_desktop_override_; 192 scoped_ptr<base::ScopedPathOverride> user_quick_launch_override_; 193 scoped_ptr<base::ScopedPathOverride> start_menu_override_; 194 scoped_ptr<base::ScopedPathOverride> common_start_menu_override_; 195 196 base::FilePath chrome_exe_; 197 base::FilePath manganese_exe_; 198 base::FilePath iron_exe_; 199 base::FilePath other_ico_; 200 }; 201 202 } // namespace 203 204 TEST_F(ShellUtilShortcutTest, GetShortcutPath) { 205 base::FilePath path; 206 207 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 208 ShellUtil::CURRENT_USER, &path); 209 EXPECT_EQ(fake_user_desktop_.path(), path); 210 211 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 212 ShellUtil::SYSTEM_LEVEL, &path); 213 EXPECT_EQ(fake_common_desktop_.path(), path); 214 215 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, dist_, 216 ShellUtil::CURRENT_USER, &path); 217 EXPECT_EQ(fake_user_quick_launch_.path(), path); 218 219 base::string16 start_menu_subfolder = 220 dist_->GetStartMenuShortcutSubfolder( 221 BrowserDistribution::SUBFOLDER_CHROME); 222 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, 223 dist_, ShellUtil::CURRENT_USER, &path); 224 EXPECT_EQ(fake_start_menu_.path().Append(start_menu_subfolder), 225 path); 226 227 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, 228 dist_, ShellUtil::SYSTEM_LEVEL, &path); 229 EXPECT_EQ(fake_common_start_menu_.path().Append(start_menu_subfolder), 230 path); 231 } 232 233 TEST_F(ShellUtilShortcutTest, CreateChromeExeShortcutWithDefaultProperties) { 234 ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER); 235 product_->AddDefaultShortcutProperties(chrome_exe_, &properties); 236 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 237 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, properties, 238 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 239 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 240 properties); 241 } 242 243 TEST_F(ShellUtilShortcutTest, CreateStartMenuShortcutWithAllProperties) { 244 test_properties_.set_shortcut_name(L"Bobo le shortcut"); 245 test_properties_.level = ShellUtil::SYSTEM_LEVEL; 246 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 247 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, 248 dist_, test_properties_, 249 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 250 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, 251 dist_, test_properties_); 252 } 253 254 TEST_F(ShellUtilShortcutTest, ReplaceSystemLevelDesktopShortcut) { 255 test_properties_.level = ShellUtil::SYSTEM_LEVEL; 256 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 257 ShellUtil::SHORTCUT_LOCATION_DESKTOP, 258 dist_, test_properties_, 259 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 260 261 ShellUtil::ShortcutProperties new_properties(ShellUtil::SYSTEM_LEVEL); 262 product_->AddDefaultShortcutProperties(chrome_exe_, &new_properties); 263 new_properties.set_description(L"New description"); 264 new_properties.set_arguments(L"--new-arguments"); 265 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 266 ShellUtil::SHORTCUT_LOCATION_DESKTOP, 267 dist_, new_properties, 268 ShellUtil::SHELL_SHORTCUT_REPLACE_EXISTING)); 269 270 // Expect the properties set in |new_properties| to be set as above and 271 // properties that don't have a default value to be set back to their default 272 // (as validated in ValidateChromeShortcut()) or unset if they don't . 273 ShellUtil::ShortcutProperties expected_properties(new_properties); 274 expected_properties.set_dual_mode(false); 275 276 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 277 expected_properties); 278 } 279 280 TEST_F(ShellUtilShortcutTest, UpdateQuickLaunchShortcutArguments) { 281 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 282 ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, 283 dist_, test_properties_, 284 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 285 286 // Only changing one property, don't need all the defaults. 287 ShellUtil::ShortcutProperties updated_properties(ShellUtil::CURRENT_USER); 288 updated_properties.set_arguments(L"--updated --arguments"); 289 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 290 ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, 291 dist_, updated_properties, 292 ShellUtil::SHELL_SHORTCUT_UPDATE_EXISTING)); 293 294 // Expect the properties set in |updated_properties| to be set as above and 295 // all other properties to remain unchanged. 296 ShellUtil::ShortcutProperties expected_properties(test_properties_); 297 expected_properties.set_arguments(updated_properties.arguments); 298 299 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, dist_, 300 expected_properties); 301 } 302 303 TEST_F(ShellUtilShortcutTest, UpdateAddDualModeToStartMenuShortcut) { 304 ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER); 305 product_->AddDefaultShortcutProperties(chrome_exe_, &properties); 306 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 307 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, dist_, 308 properties, ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 309 310 ShellUtil::ShortcutProperties added_properties(ShellUtil::CURRENT_USER); 311 added_properties.set_dual_mode(true); 312 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 313 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, dist_, 314 added_properties, ShellUtil::SHELL_SHORTCUT_UPDATE_EXISTING)); 315 316 ShellUtil::ShortcutProperties expected_properties(properties); 317 expected_properties.set_dual_mode(true); 318 319 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, 320 dist_, expected_properties); 321 } 322 323 TEST_F(ShellUtilShortcutTest, CreateIfNoSystemLevel) { 324 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 325 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 326 ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL)); 327 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 328 test_properties_); 329 } 330 331 TEST_F(ShellUtilShortcutTest, CreateIfNoSystemLevelWithSystemLevelPresent) { 332 base::string16 shortcut_name( 333 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) + 334 installer::kLnkExt); 335 336 test_properties_.level = ShellUtil::SYSTEM_LEVEL; 337 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 338 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 339 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 340 ASSERT_TRUE(base::PathExists( 341 fake_common_desktop_.path().Append(shortcut_name))); 342 343 test_properties_.level = ShellUtil::CURRENT_USER; 344 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 345 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 346 ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL)); 347 ASSERT_FALSE(base::PathExists( 348 fake_user_desktop_.path().Append(shortcut_name))); 349 } 350 351 TEST_F(ShellUtilShortcutTest, CreateIfNoSystemLevelStartMenu) { 352 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 353 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, 354 dist_, test_properties_, 355 ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL)); 356 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, 357 dist_, test_properties_); 358 } 359 360 TEST_F(ShellUtilShortcutTest, CreateAlwaysUserWithSystemLevelPresent) { 361 base::string16 shortcut_name( 362 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) + 363 installer::kLnkExt); 364 365 test_properties_.level = ShellUtil::SYSTEM_LEVEL; 366 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 367 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 368 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 369 ASSERT_TRUE(base::PathExists( 370 fake_common_desktop_.path().Append(shortcut_name))); 371 372 test_properties_.level = ShellUtil::CURRENT_USER; 373 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 374 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 375 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 376 ASSERT_TRUE(base::PathExists( 377 fake_user_desktop_.path().Append(shortcut_name))); 378 } 379 380 TEST_F(ShellUtilShortcutTest, RemoveChromeShortcut) { 381 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 382 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 383 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 384 base::FilePath shortcut_path = GetExpectedShortcutPath( 385 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_); 386 ASSERT_TRUE(base::PathExists(shortcut_path)); 387 388 ASSERT_TRUE(ShellUtil::RemoveShortcuts( 389 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER, 390 chrome_exe_)); 391 ASSERT_FALSE(base::PathExists(shortcut_path)); 392 ASSERT_TRUE(base::PathExists(shortcut_path.DirName())); 393 } 394 395 TEST_F(ShellUtilShortcutTest, RemoveSystemLevelChromeShortcut) { 396 test_properties_.level = ShellUtil::SYSTEM_LEVEL; 397 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 398 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 399 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 400 base::FilePath shortcut_path = GetExpectedShortcutPath( 401 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_); 402 ASSERT_TRUE(base::PathExists(shortcut_path)); 403 404 ASSERT_TRUE(ShellUtil::RemoveShortcuts( 405 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::SYSTEM_LEVEL, 406 chrome_exe_)); 407 ASSERT_FALSE(base::PathExists(shortcut_path)); 408 ASSERT_TRUE(base::PathExists(shortcut_path.DirName())); 409 } 410 411 TEST_F(ShellUtilShortcutTest, RemoveMultipleChromeShortcuts) { 412 // Shortcut 1: targets "chrome.exe"; no arguments. 413 test_properties_.set_shortcut_name(L"Chrome 1"); 414 test_properties_.set_arguments(L""); 415 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 416 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 417 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 418 base::FilePath shortcut1_path = GetExpectedShortcutPath( 419 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_); 420 ASSERT_TRUE(base::PathExists(shortcut1_path)); 421 422 // Shortcut 2: targets "chrome.exe"; has arguments; icon set to "other.ico". 423 test_properties_.set_shortcut_name(L"Chrome 2"); 424 test_properties_.set_arguments(L"--profile-directory=\"Profile 2\""); 425 test_properties_.set_icon(other_ico_, 0); 426 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 427 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 428 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 429 base::FilePath shortcut2_path = GetExpectedShortcutPath( 430 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_); 431 ASSERT_TRUE(base::PathExists(shortcut2_path)); 432 433 // Shortcut 3: targets "iron.exe"; has arguments; icon set to "chrome.exe". 434 test_properties_.set_shortcut_name(L"Iron 3"); 435 test_properties_.set_target(iron_exe_); 436 test_properties_.set_icon(chrome_exe_, 3); 437 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 438 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 439 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 440 base::FilePath shortcut3_path = GetExpectedShortcutPath( 441 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_); 442 ASSERT_TRUE(base::PathExists(shortcut3_path)); 443 444 // Remove shortcuts that target "chrome.exe". 445 ASSERT_TRUE(ShellUtil::RemoveShortcuts( 446 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER, 447 chrome_exe_)); 448 ASSERT_FALSE(base::PathExists(shortcut1_path)); 449 ASSERT_FALSE(base::PathExists(shortcut2_path)); 450 ASSERT_TRUE(base::PathExists(shortcut3_path)); 451 ASSERT_TRUE(base::PathExists(shortcut1_path.DirName())); 452 } 453 454 TEST_F(ShellUtilShortcutTest, RetargetShortcutsWithArgs) { 455 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 456 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 457 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 458 ASSERT_TRUE(base::PathExists(GetExpectedShortcutPath( 459 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_))); 460 461 base::FilePath new_exe = manganese_exe_; 462 // Relies on the fact that |test_properties_| has non-empty arguments. 463 ASSERT_TRUE(ShellUtil::RetargetShortcutsWithArgs( 464 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER, 465 chrome_exe_, new_exe)); 466 467 ShellUtil::ShortcutProperties expected_properties(test_properties_); 468 expected_properties.set_target(new_exe); 469 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 470 expected_properties); 471 } 472 473 TEST_F(ShellUtilShortcutTest, RetargetSystemLevelChromeShortcutsWithArgs) { 474 test_properties_.level = ShellUtil::SYSTEM_LEVEL; 475 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 476 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 477 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 478 ASSERT_TRUE(base::PathExists(GetExpectedShortcutPath( 479 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_))); 480 481 base::FilePath new_exe = manganese_exe_; 482 // Relies on the fact that |test_properties_| has non-empty arguments. 483 ASSERT_TRUE(ShellUtil::RetargetShortcutsWithArgs( 484 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::SYSTEM_LEVEL, 485 chrome_exe_, new_exe)); 486 487 ShellUtil::ShortcutProperties expected_properties(test_properties_); 488 expected_properties.set_target(new_exe); 489 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 490 expected_properties); 491 } 492 493 TEST_F(ShellUtilShortcutTest, RetargetChromeShortcutsWithArgsEmpty) { 494 // Shortcut 1: targets "chrome.exe"; no arguments. 495 test_properties_.set_shortcut_name(L"Chrome 1"); 496 test_properties_.set_arguments(L""); 497 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 498 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 499 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 500 ASSERT_TRUE(base::PathExists(GetExpectedShortcutPath( 501 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_))); 502 ShellUtil::ShortcutProperties expected_properties1(test_properties_); 503 504 // Shortcut 2: targets "chrome.exe"; has arguments. 505 test_properties_.set_shortcut_name(L"Chrome 2"); 506 test_properties_.set_arguments(L"--profile-directory=\"Profile 2\""); 507 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 508 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 509 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 510 ASSERT_TRUE(base::PathExists(GetExpectedShortcutPath( 511 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_))); 512 ShellUtil::ShortcutProperties expected_properties2(test_properties_); 513 514 // Retarget shortcuts: replace "chrome.exe" with "manganese.exe". Only 515 // shortcuts with non-empty arguments (i.e., shortcut 2) gets updated. 516 base::FilePath new_exe = manganese_exe_; 517 ASSERT_TRUE(ShellUtil::RetargetShortcutsWithArgs( 518 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER, 519 chrome_exe_, new_exe)); 520 521 // Verify shortcut 1: no change. 522 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 523 expected_properties1); 524 525 // Verify shortcut 2: target => "manganese.exe". 526 expected_properties2.set_target(new_exe); 527 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 528 expected_properties2); 529 } 530 531 TEST_F(ShellUtilShortcutTest, RetargetChromeShortcutsWithArgsIcon) { 532 const int kTestIconIndex1 = 3; 533 const int kTestIconIndex2 = 5; 534 const int kTestIconIndex3 = 8; 535 536 // Shortcut 1: targets "chrome.exe"; icon same as target. 537 test_properties_.set_shortcut_name(L"Chrome 1"); 538 test_properties_.set_icon(test_properties_.target, kTestIconIndex1); 539 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 540 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 541 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 542 ASSERT_TRUE(base::PathExists(GetExpectedShortcutPath( 543 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_))); 544 ShellUtil::ShortcutProperties expected_properties1(test_properties_); 545 546 // Shortcut 2: targets "chrome.exe"; icon set to "other.ico". 547 test_properties_.set_shortcut_name(L"Chrome 2"); 548 test_properties_.set_icon(other_ico_, kTestIconIndex2); 549 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 550 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 551 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 552 ASSERT_TRUE(base::PathExists(GetExpectedShortcutPath( 553 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_))); 554 ShellUtil::ShortcutProperties expected_properties2(test_properties_); 555 556 // Shortcut 3: targets "iron.exe"; icon set to "chrome.exe". 557 test_properties_.set_target(iron_exe_); 558 test_properties_.set_shortcut_name(L"Iron 3"); 559 test_properties_.set_icon(chrome_exe_, kTestIconIndex3); 560 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 561 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 562 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 563 ASSERT_TRUE(base::PathExists(GetExpectedShortcutPath( 564 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_))); 565 ShellUtil::ShortcutProperties expected_properties3(test_properties_); 566 567 // Retarget shortcuts: replace "chrome.exe" with "manganese.exe". 568 // Relies on the fact that |test_properties_| has non-empty arguments. 569 base::FilePath new_exe = manganese_exe_; 570 ASSERT_TRUE(ShellUtil::RetargetShortcutsWithArgs( 571 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER, 572 chrome_exe_, new_exe)); 573 574 // Verify shortcut 1: target & icon => "manganese.exe", kept same icon index. 575 expected_properties1.set_target(new_exe); 576 expected_properties1.set_icon(new_exe, kTestIconIndex1); 577 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 578 expected_properties1); 579 580 // Verify shortcut 2: target => "manganese.exe", kept icon. 581 expected_properties2.set_target(new_exe); 582 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 583 expected_properties2); 584 585 // Verify shortcut 3: no change, since target doesn't match. 586 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 587 expected_properties3); 588 } 589 590 TEST_F(ShellUtilShortcutTest, ClearShortcutArguments) { 591 // Shortcut 1: targets "chrome.exe"; no arguments. 592 test_properties_.set_shortcut_name(L"Chrome 1"); 593 test_properties_.set_arguments(L""); 594 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 595 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 596 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 597 base::FilePath shortcut1_path = GetExpectedShortcutPath( 598 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_); 599 ASSERT_TRUE(base::PathExists(shortcut1_path)); 600 ShellUtil::ShortcutProperties expected_properties1(test_properties_); 601 602 // Shortcut 2: targets "chrome.exe"; has 1 whitelisted argument. 603 test_properties_.set_shortcut_name(L"Chrome 2"); 604 test_properties_.set_arguments(L"--profile-directory=\"Profile 2\""); 605 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 606 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 607 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 608 base::FilePath shortcut2_path = GetExpectedShortcutPath( 609 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_); 610 ASSERT_TRUE(base::PathExists(shortcut2_path)); 611 ShellUtil::ShortcutProperties expected_properties2(test_properties_); 612 613 // Shortcut 3: targets "chrome.exe"; has an unknown argument. 614 test_properties_.set_shortcut_name(L"Chrome 3"); 615 test_properties_.set_arguments(L"foo.com"); 616 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 617 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 618 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 619 base::FilePath shortcut3_path = GetExpectedShortcutPath( 620 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_); 621 ASSERT_TRUE(base::PathExists(shortcut3_path)); 622 ShellUtil::ShortcutProperties expected_properties3(test_properties_); 623 624 // Shortcut 4: targets "chrome.exe"; has both unknown and known arguments. 625 test_properties_.set_shortcut_name(L"Chrome 4"); 626 test_properties_.set_arguments(L"foo.com --show-app-list"); 627 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 628 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 629 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 630 base::FilePath shortcut4_path = GetExpectedShortcutPath( 631 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_); 632 ASSERT_TRUE(base::PathExists(shortcut4_path)); 633 ShellUtil::ShortcutProperties expected_properties4(test_properties_); 634 635 // List the shortcuts. 636 std::vector<std::pair<base::FilePath, base::string16> > shortcuts; 637 EXPECT_TRUE(ShellUtil::ShortcutListMaybeRemoveUnknownArgs( 638 ShellUtil::SHORTCUT_LOCATION_DESKTOP, 639 dist_, 640 ShellUtil::CURRENT_USER, 641 chrome_exe_, 642 false, 643 NULL, 644 &shortcuts)); 645 ASSERT_EQ(2u, shortcuts.size()); 646 std::pair<base::FilePath, base::string16> shortcut3 = 647 shortcuts[0].first == shortcut3_path ? shortcuts[0] : shortcuts[1]; 648 std::pair<base::FilePath, base::string16> shortcut4 = 649 shortcuts[0].first == shortcut4_path ? shortcuts[0] : shortcuts[1]; 650 EXPECT_EQ(shortcut3_path, shortcut3.first); 651 EXPECT_EQ(L"foo.com", shortcut3.second); 652 EXPECT_EQ(shortcut4_path, shortcut4.first); 653 EXPECT_EQ(L"foo.com --show-app-list", shortcut4.second); 654 655 // Clear shortcuts. 656 shortcuts.clear(); 657 EXPECT_TRUE(ShellUtil::ShortcutListMaybeRemoveUnknownArgs( 658 ShellUtil::SHORTCUT_LOCATION_DESKTOP, 659 dist_, 660 ShellUtil::CURRENT_USER, 661 chrome_exe_, 662 true, 663 NULL, 664 &shortcuts)); 665 ASSERT_EQ(2u, shortcuts.size()); 666 shortcut3 = shortcuts[0].first == shortcut3_path ? shortcuts[0] : 667 shortcuts[1]; 668 shortcut4 = shortcuts[0].first == shortcut4_path ? shortcuts[0] : 669 shortcuts[1]; 670 EXPECT_EQ(shortcut3_path, shortcut3.first); 671 EXPECT_EQ(L"foo.com", shortcut3.second); 672 EXPECT_EQ(shortcut4_path, shortcut4.first); 673 EXPECT_EQ(L"foo.com --show-app-list", shortcut4.second); 674 675 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 676 expected_properties1); 677 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 678 expected_properties2); 679 expected_properties3.set_arguments(base::string16()); 680 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 681 expected_properties3); 682 expected_properties4.set_arguments(L"--show-app-list"); 683 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 684 expected_properties4); 685 } 686 687 TEST_F(ShellUtilShortcutTest, CreateMultipleStartMenuShortcutsAndRemoveFolder) { 688 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 689 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, 690 dist_, test_properties_, 691 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 692 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 693 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR, 694 dist_, test_properties_, 695 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 696 test_properties_.set_shortcut_name(L"A second shortcut"); 697 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 698 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, 699 dist_, test_properties_, 700 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 701 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 702 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR, 703 dist_, test_properties_, 704 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 705 706 base::FilePath chrome_shortcut_folder( 707 fake_start_menu_.path().Append( 708 dist_->GetStartMenuShortcutSubfolder( 709 BrowserDistribution::SUBFOLDER_CHROME))); 710 base::FilePath chrome_apps_shortcut_folder( 711 fake_start_menu_.path().Append( 712 dist_->GetStartMenuShortcutSubfolder( 713 BrowserDistribution::SUBFOLDER_APPS))); 714 715 base::FileEnumerator chrome_file_counter(chrome_shortcut_folder, false, 716 base::FileEnumerator::FILES); 717 int count = 0; 718 while (!chrome_file_counter.Next().empty()) 719 ++count; 720 EXPECT_EQ(2, count); 721 722 base::FileEnumerator chrome_apps_file_counter(chrome_apps_shortcut_folder, 723 false, 724 base::FileEnumerator::FILES); 725 count = 0; 726 while (!chrome_apps_file_counter.Next().empty()) 727 ++count; 728 EXPECT_EQ(2, count); 729 730 ASSERT_TRUE(base::PathExists(chrome_shortcut_folder)); 731 ASSERT_TRUE(ShellUtil::RemoveShortcuts( 732 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, dist_, 733 ShellUtil::CURRENT_USER, chrome_exe_)); 734 ASSERT_FALSE(base::PathExists(chrome_shortcut_folder)); 735 736 ASSERT_TRUE(base::PathExists(chrome_apps_shortcut_folder)); 737 ASSERT_TRUE(ShellUtil::RemoveShortcuts( 738 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR, dist_, 739 ShellUtil::CURRENT_USER, chrome_exe_)); 740 ASSERT_FALSE(base::PathExists(chrome_apps_shortcut_folder)); 741 } 742 743 TEST_F(ShellUtilShortcutTest, 744 DeleteStartMenuRootShortcutWithoutRemovingFolder) { 745 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 746 ShellUtil::SHORTCUT_LOCATION_START_MENU_ROOT, 747 dist_, test_properties_, 748 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 749 750 base::string16 shortcut_name( 751 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) + 752 installer::kLnkExt); 753 base::FilePath shortcut_path( 754 fake_start_menu_.path().Append(shortcut_name)); 755 756 ASSERT_TRUE(base::PathExists(fake_start_menu_.path())); 757 ASSERT_TRUE(base::PathExists(shortcut_path)); 758 ASSERT_TRUE(ShellUtil::RemoveShortcuts( 759 ShellUtil::SHORTCUT_LOCATION_START_MENU_ROOT, dist_, 760 ShellUtil::CURRENT_USER, chrome_exe_)); 761 // The shortcut should be removed but the "Start Menu" root directory should 762 // remain. 763 ASSERT_TRUE(base::PathExists(fake_start_menu_.path())); 764 ASSERT_FALSE(base::PathExists(shortcut_path)); 765 } 766 767 TEST_F(ShellUtilShortcutTest, DontRemoveChromeShortcutIfPointsToAnotherChrome) { 768 base::ScopedTempDir other_exe_dir; 769 ASSERT_TRUE(other_exe_dir.CreateUniqueTempDir()); 770 base::FilePath other_chrome_exe = 771 other_exe_dir.path().Append(installer::kChromeExe); 772 EXPECT_EQ(0, base::WriteFile(other_chrome_exe, "", 0)); 773 774 test_properties_.set_target(other_chrome_exe); 775 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 776 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 777 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 778 779 base::string16 shortcut_name( 780 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) + 781 installer::kLnkExt); 782 base::FilePath shortcut_path(fake_user_desktop_.path().Append(shortcut_name)); 783 ASSERT_TRUE(base::PathExists(shortcut_path)); 784 785 // The shortcut shouldn't be removed as it was installed pointing to 786 // |other_chrome_exe| and RemoveChromeShortcut() is being told that the 787 // removed shortcut should point to |chrome_exe_|. 788 ASSERT_TRUE(ShellUtil::RemoveShortcuts( 789 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER, 790 chrome_exe_)); 791 ASSERT_TRUE(base::PathExists(shortcut_path)); 792 ASSERT_TRUE(base::PathExists(shortcut_path.DirName())); 793 } 794 795 TEST(ShellUtilTest, BuildAppModelIdBasic) { 796 std::vector<base::string16> components; 797 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 798 const base::string16 base_app_id(dist->GetBaseAppId()); 799 components.push_back(base_app_id); 800 ASSERT_EQ(base_app_id, ShellUtil::BuildAppModelId(components)); 801 } 802 803 TEST(ShellUtilTest, BuildAppModelIdManySmall) { 804 std::vector<base::string16> components; 805 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 806 const base::string16 suffixed_app_id(dist->GetBaseAppId().append(L".gab")); 807 components.push_back(suffixed_app_id); 808 components.push_back(L"Default"); 809 components.push_back(L"Test"); 810 ASSERT_EQ(suffixed_app_id + L".Default.Test", 811 ShellUtil::BuildAppModelId(components)); 812 } 813 814 TEST(ShellUtilTest, BuildAppModelIdLongUsernameNormalProfile) { 815 std::vector<base::string16> components; 816 const base::string16 long_appname( 817 L"Chrome.a_user_who_has_a_crazy_long_name_with_some_weird@symbols_in_it_" 818 L"that_goes_over_64_characters"); 819 components.push_back(long_appname); 820 components.push_back(L"Default"); 821 ASSERT_EQ(L"Chrome.a_user_wer_64_characters.Default", 822 ShellUtil::BuildAppModelId(components)); 823 } 824 825 TEST(ShellUtilTest, BuildAppModelIdLongEverything) { 826 std::vector<base::string16> components; 827 const base::string16 long_appname(L"Chrome.a_user_who_has_a_crazy_long_name_" 828 L"with_some_weird@symbols_in_" 829 L"it_" L"that_goes_over_64_characters"); 830 components.push_back(long_appname); 831 components.push_back( 832 L"A_crazy_profile_name_not_even_sure_whether_that_is_possible"); 833 const base::string16 constructed_app_id( 834 ShellUtil::BuildAppModelId(components)); 835 ASSERT_LE(constructed_app_id.length(), installer::kMaxAppModelIdLength); 836 ASSERT_EQ(L"Chrome.a_user_wer_64_characters.A_crazy_profilethat_is_possible", 837 constructed_app_id); 838 } 839 840 TEST(ShellUtilTest, GetUserSpecificRegistrySuffix) { 841 base::string16 suffix; 842 ASSERT_TRUE(ShellUtil::GetUserSpecificRegistrySuffix(&suffix)); 843 ASSERT_TRUE(StartsWith(suffix, L".", true)); 844 ASSERT_EQ(27, suffix.length()); 845 ASSERT_TRUE(base::ContainsOnlyChars(suffix.substr(1), 846 L"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567")); 847 } 848 849 TEST(ShellUtilTest, GetOldUserSpecificRegistrySuffix) { 850 base::string16 suffix; 851 ASSERT_TRUE(ShellUtil::GetOldUserSpecificRegistrySuffix(&suffix)); 852 ASSERT_TRUE(StartsWith(suffix, L".", true)); 853 854 wchar_t user_name[256]; 855 DWORD size = arraysize(user_name); 856 ASSERT_NE(0, ::GetUserName(user_name, &size)); 857 ASSERT_GE(size, 1U); 858 ASSERT_STREQ(user_name, suffix.substr(1).c_str()); 859 } 860 861 TEST(ShellUtilTest, ByteArrayToBase32) { 862 // Tests from http://tools.ietf.org/html/rfc4648#section-10. 863 const unsigned char test_array[] = { 'f', 'o', 'o', 'b', 'a', 'r' }; 864 865 const base::string16 expected[] = { L"", L"MY", L"MZXQ", L"MZXW6", L"MZXW6YQ", 866 L"MZXW6YTB", L"MZXW6YTBOI"}; 867 868 // Run the tests, with one more letter in the input every pass. 869 for (int i = 0; i < arraysize(expected); ++i) { 870 ASSERT_EQ(expected[i], 871 ShellUtil::ByteArrayToBase32(test_array, i)); 872 } 873 } 874