shell_util_unittest.cc revision d0247b1b59f9c528cb6df88b4f2b9afaf80d181e
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/file_util.h" 12#include "base/files/file_enumerator.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/test/scoped_path_override.h" 19#include "base/test/test_shortcut_win.h" 20#include "base/win/shortcut.h" 21#include "base/win/windows_version.h" 22#include "chrome/installer/util/browser_distribution.h" 23#include "chrome/installer/util/product.h" 24#include "chrome/installer/util/util_constants.h" 25#include "testing/gtest/include/gtest/gtest.h" 26 27namespace { 28 29const wchar_t kManganeseExe[] = L"manganese.exe"; 30 31// TODO(huangs): Separate this into generic shortcut tests and Chrome-specific 32// tests. Specifically, we should not overly rely on getting shortcut properties 33// from product_->AddDefaultShortcutProperties(). 34class ShellUtilShortcutTest : public testing::Test { 35 protected: 36 ShellUtilShortcutTest() : test_properties_(ShellUtil::CURRENT_USER) {} 37 38 virtual void SetUp() OVERRIDE { 39 dist_ = BrowserDistribution::GetDistribution(); 40 ASSERT_TRUE(dist_ != NULL); 41 product_.reset(new installer::Product(dist_)); 42 43 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 44 chrome_exe_ = temp_dir_.path().Append(installer::kChromeExe); 45 EXPECT_EQ(0, file_util::WriteFile(chrome_exe_, "", 0)); 46 47 manganese_exe_ = temp_dir_.path().Append(kManganeseExe); 48 EXPECT_EQ(0, file_util::WriteFile(manganese_exe_, "", 0)); 49 50 ASSERT_TRUE(fake_user_desktop_.CreateUniqueTempDir()); 51 ASSERT_TRUE(fake_common_desktop_.CreateUniqueTempDir()); 52 ASSERT_TRUE(fake_user_quick_launch_.CreateUniqueTempDir()); 53 ASSERT_TRUE(fake_default_user_quick_launch_.CreateUniqueTempDir()); 54 ASSERT_TRUE(fake_start_menu_.CreateUniqueTempDir()); 55 ASSERT_TRUE(fake_common_start_menu_.CreateUniqueTempDir()); 56 user_desktop_override_.reset( 57 new base::ScopedPathOverride(base::DIR_USER_DESKTOP, 58 fake_user_desktop_.path())); 59 common_desktop_override_.reset( 60 new base::ScopedPathOverride(base::DIR_COMMON_DESKTOP, 61 fake_common_desktop_.path())); 62 user_quick_launch_override_.reset( 63 new base::ScopedPathOverride(base::DIR_USER_QUICK_LAUNCH, 64 fake_user_quick_launch_.path())); 65 default_user_quick_launch_override_.reset( 66 new base::ScopedPathOverride(base::DIR_DEFAULT_USER_QUICK_LAUNCH, 67 fake_default_user_quick_launch_.path())); 68 start_menu_override_.reset( 69 new base::ScopedPathOverride(base::DIR_START_MENU, 70 fake_start_menu_.path())); 71 common_start_menu_override_.reset( 72 new base::ScopedPathOverride(base::DIR_COMMON_START_MENU, 73 fake_common_start_menu_.path())); 74 75 base::FilePath icon_path; 76 file_util::CreateTemporaryFileInDir(temp_dir_.path(), &icon_path); 77 test_properties_.set_target(chrome_exe_); 78 test_properties_.set_arguments(L"--test --chrome"); 79 test_properties_.set_description(L"Makes polar bears dance."); 80 test_properties_.set_icon(icon_path, 0); 81 test_properties_.set_app_id(L"Polar.Bear"); 82 test_properties_.set_dual_mode(true); 83 } 84 85 // Validates that the shortcut at |location| matches |properties| (and 86 // implicit default properties) for |dist|. 87 // Note: This method doesn't verify the |pin_to_taskbar| property as it 88 // implies real (non-mocked) state which is flaky to test. 89 void ValidateChromeShortcut( 90 ShellUtil::ShortcutLocation location, 91 BrowserDistribution* dist, 92 const ShellUtil::ShortcutProperties& properties) { 93 base::FilePath expected_path; 94 switch (location) { 95 case ShellUtil::SHORTCUT_LOCATION_DESKTOP: 96 expected_path = (properties.level == ShellUtil::CURRENT_USER) ? 97 fake_user_desktop_.path() : fake_common_desktop_.path(); 98 break; 99 case ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH: 100 expected_path = (properties.level == ShellUtil::CURRENT_USER) ? 101 fake_user_quick_launch_.path() : 102 fake_default_user_quick_launch_.path(); 103 break; 104 case ShellUtil::SHORTCUT_LOCATION_START_MENU: 105 expected_path = (properties.level == ShellUtil::CURRENT_USER) ? 106 fake_start_menu_.path() : fake_common_start_menu_.path(); 107 expected_path = expected_path.Append( 108 dist_->GetStartMenuShortcutSubfolder( 109 BrowserDistribution::SUBFOLDER_CHROME)); 110 break; 111 default: 112 ADD_FAILURE() << "Unknown location"; 113 return; 114 } 115 116 string16 shortcut_name; 117 if (properties.has_shortcut_name()) { 118 shortcut_name = properties.shortcut_name; 119 } else { 120 shortcut_name = 121 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME); 122 } 123 shortcut_name.append(installer::kLnkExt); 124 expected_path = expected_path.Append(shortcut_name); 125 126 base::win::ShortcutProperties expected_properties; 127 if (properties.has_target()) { 128 expected_properties.set_target(properties.target); 129 expected_properties.set_working_dir(properties.target.DirName()); 130 } else { 131 expected_properties.set_target(chrome_exe_); 132 expected_properties.set_working_dir(chrome_exe_.DirName()); 133 } 134 135 if (properties.has_arguments()) 136 expected_properties.set_arguments(properties.arguments); 137 else 138 expected_properties.set_arguments(string16()); 139 140 if (properties.has_description()) 141 expected_properties.set_description(properties.description); 142 else 143 expected_properties.set_description(dist->GetAppDescription()); 144 145 if (properties.has_icon()) { 146 expected_properties.set_icon(properties.icon, 0); 147 } else { 148 int icon_index = dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME); 149 expected_properties.set_icon(chrome_exe_, icon_index); 150 } 151 152 if (properties.has_app_id()) { 153 expected_properties.set_app_id(properties.app_id); 154 } else { 155 // Tests are always seen as user-level installs in ShellUtil. 156 expected_properties.set_app_id(ShellUtil::GetBrowserModelId(dist, true)); 157 } 158 159 if (properties.has_dual_mode()) 160 expected_properties.set_dual_mode(properties.dual_mode); 161 else 162 expected_properties.set_dual_mode(false); 163 164 base::win::ValidateShortcut(expected_path, expected_properties); 165 } 166 167 BrowserDistribution* dist_; 168 scoped_ptr<installer::Product> product_; 169 170 // A ShellUtil::ShortcutProperties object with common properties set already. 171 ShellUtil::ShortcutProperties test_properties_; 172 173 base::ScopedTempDir temp_dir_; 174 base::ScopedTempDir fake_user_desktop_; 175 base::ScopedTempDir fake_common_desktop_; 176 base::ScopedTempDir fake_user_quick_launch_; 177 base::ScopedTempDir fake_default_user_quick_launch_; 178 base::ScopedTempDir fake_start_menu_; 179 base::ScopedTempDir fake_common_start_menu_; 180 scoped_ptr<base::ScopedPathOverride> user_desktop_override_; 181 scoped_ptr<base::ScopedPathOverride> common_desktop_override_; 182 scoped_ptr<base::ScopedPathOverride> user_quick_launch_override_; 183 scoped_ptr<base::ScopedPathOverride> default_user_quick_launch_override_; 184 scoped_ptr<base::ScopedPathOverride> start_menu_override_; 185 scoped_ptr<base::ScopedPathOverride> common_start_menu_override_; 186 187 base::FilePath chrome_exe_; 188 base::FilePath manganese_exe_; 189}; 190 191} // namespace 192 193TEST_F(ShellUtilShortcutTest, GetShortcutPath) { 194 base::FilePath path; 195 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 196 ShellUtil::CURRENT_USER, &path); 197 EXPECT_EQ(fake_user_desktop_.path(), path); 198 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 199 ShellUtil::SYSTEM_LEVEL, &path); 200 EXPECT_EQ(fake_common_desktop_.path(), path); 201 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, dist_, 202 ShellUtil::CURRENT_USER, &path); 203 EXPECT_EQ(fake_user_quick_launch_.path(), path); 204 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, dist_, 205 ShellUtil::SYSTEM_LEVEL, &path); 206 EXPECT_EQ(fake_default_user_quick_launch_.path(), path); 207 string16 start_menu_subfolder = 208 dist_->GetStartMenuShortcutSubfolder( 209 BrowserDistribution::SUBFOLDER_CHROME); 210 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_START_MENU, dist_, 211 ShellUtil::CURRENT_USER, &path); 212 EXPECT_EQ(fake_start_menu_.path().Append(start_menu_subfolder), 213 path); 214 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_START_MENU, dist_, 215 ShellUtil::SYSTEM_LEVEL, &path); 216 EXPECT_EQ(fake_common_start_menu_.path().Append(start_menu_subfolder), 217 path); 218} 219 220TEST_F(ShellUtilShortcutTest, CreateChromeExeShortcutWithDefaultProperties) { 221 ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER); 222 product_->AddDefaultShortcutProperties(chrome_exe_, &properties); 223 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 224 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, properties, 225 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 226 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 227 properties); 228} 229 230TEST_F(ShellUtilShortcutTest, CreateStartMenuShortcutWithAllProperties) { 231 test_properties_.set_shortcut_name(L"Bobo le shortcut"); 232 test_properties_.level = ShellUtil::SYSTEM_LEVEL; 233 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 234 ShellUtil::SHORTCUT_LOCATION_START_MENU, 235 dist_, test_properties_, 236 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 237 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_START_MENU, dist_, 238 test_properties_); 239} 240 241TEST_F(ShellUtilShortcutTest, ReplaceSystemLevelQuickLaunchShortcut) { 242 test_properties_.level = ShellUtil::SYSTEM_LEVEL; 243 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 244 ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, 245 dist_, test_properties_, 246 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 247 248 ShellUtil::ShortcutProperties new_properties(ShellUtil::SYSTEM_LEVEL); 249 product_->AddDefaultShortcutProperties(chrome_exe_, &new_properties); 250 new_properties.set_description(L"New description"); 251 new_properties.set_arguments(L"--new-arguments"); 252 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 253 ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, 254 dist_, new_properties, 255 ShellUtil::SHELL_SHORTCUT_REPLACE_EXISTING)); 256 257 // Expect the properties set in |new_properties| to be set as above and 258 // properties that don't have a default value to be set back to their default 259 // (as validated in ValidateChromeShortcut()) or unset if they don't . 260 ShellUtil::ShortcutProperties expected_properties(new_properties); 261 expected_properties.set_dual_mode(false); 262 263 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, dist_, 264 expected_properties); 265} 266 267TEST_F(ShellUtilShortcutTest, UpdateQuickLaunchShortcutArguments) { 268 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 269 ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, 270 dist_, test_properties_, 271 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 272 273 // Only changing one property, don't need all the defaults. 274 ShellUtil::ShortcutProperties updated_properties(ShellUtil::CURRENT_USER); 275 updated_properties.set_arguments(L"--updated --arguments"); 276 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 277 ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, 278 dist_, updated_properties, 279 ShellUtil::SHELL_SHORTCUT_UPDATE_EXISTING)); 280 281 // Expect the properties set in |updated_properties| to be set as above and 282 // all other properties to remain unchanged. 283 ShellUtil::ShortcutProperties expected_properties(test_properties_); 284 expected_properties.set_arguments(updated_properties.arguments); 285 286 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, dist_, 287 expected_properties); 288} 289 290TEST_F(ShellUtilShortcutTest, UpdateAddDualModeToStartMenuShortcut) { 291 ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER); 292 product_->AddDefaultShortcutProperties(chrome_exe_, &properties); 293 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 294 ShellUtil::SHORTCUT_LOCATION_START_MENU, dist_, properties, 295 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 296 297 ShellUtil::ShortcutProperties added_properties(ShellUtil::CURRENT_USER); 298 added_properties.set_dual_mode(true); 299 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 300 ShellUtil::SHORTCUT_LOCATION_START_MENU, dist_, 301 added_properties, ShellUtil::SHELL_SHORTCUT_UPDATE_EXISTING)); 302 303 ShellUtil::ShortcutProperties expected_properties(properties); 304 expected_properties.set_dual_mode(true); 305 306 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_START_MENU, dist_, 307 expected_properties); 308} 309 310TEST_F(ShellUtilShortcutTest, CreateIfNoSystemLevel) { 311 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 312 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 313 ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL)); 314 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 315 test_properties_); 316} 317 318TEST_F(ShellUtilShortcutTest, CreateIfNoSystemLevelWithSystemLevelPresent) { 319 string16 shortcut_name( 320 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) + 321 installer::kLnkExt); 322 323 test_properties_.level = ShellUtil::SYSTEM_LEVEL; 324 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 325 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 326 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 327 ASSERT_TRUE(base::PathExists( 328 fake_common_desktop_.path().Append(shortcut_name))); 329 330 test_properties_.level = ShellUtil::CURRENT_USER; 331 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 332 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 333 ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL)); 334 ASSERT_FALSE(base::PathExists( 335 fake_user_desktop_.path().Append(shortcut_name))); 336} 337 338TEST_F(ShellUtilShortcutTest, CreateIfNoSystemLevelStartMenu) { 339 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 340 ShellUtil::SHORTCUT_LOCATION_START_MENU, 341 dist_, test_properties_, 342 ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL)); 343 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_START_MENU, dist_, 344 test_properties_); 345} 346 347TEST_F(ShellUtilShortcutTest, CreateAlwaysUserWithSystemLevelPresent) { 348 string16 shortcut_name( 349 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) + 350 installer::kLnkExt); 351 352 test_properties_.level = ShellUtil::SYSTEM_LEVEL; 353 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 354 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 355 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 356 ASSERT_TRUE(base::PathExists( 357 fake_common_desktop_.path().Append(shortcut_name))); 358 359 test_properties_.level = ShellUtil::CURRENT_USER; 360 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 361 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 362 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 363 ASSERT_TRUE(base::PathExists( 364 fake_user_desktop_.path().Append(shortcut_name))); 365} 366 367TEST_F(ShellUtilShortcutTest, RemoveChromeShortcut) { 368 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 369 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 370 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 371 372 string16 shortcut_name( 373 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) + 374 installer::kLnkExt); 375 base::FilePath shortcut_path(fake_user_desktop_.path().Append(shortcut_name)); 376 ASSERT_TRUE(base::PathExists(shortcut_path)); 377 378 ASSERT_TRUE(ShellUtil::RemoveShortcuts( 379 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER, 380 chrome_exe_)); 381 ASSERT_FALSE(base::PathExists(shortcut_path)); 382 ASSERT_TRUE(base::PathExists(shortcut_path.DirName())); 383} 384 385TEST_F(ShellUtilShortcutTest, RemoveSystemLevelChromeShortcut) { 386 test_properties_.level = ShellUtil::SYSTEM_LEVEL; 387 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 388 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 389 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 390 391 string16 shortcut_name( 392 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) + 393 installer::kLnkExt); 394 base::FilePath shortcut_path( 395 fake_common_desktop_.path().Append(shortcut_name)); 396 ASSERT_TRUE(base::PathExists(shortcut_path)); 397 398 ASSERT_TRUE(ShellUtil::RemoveShortcuts( 399 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::SYSTEM_LEVEL, 400 chrome_exe_)); 401 ASSERT_FALSE(base::PathExists(shortcut_path)); 402 ASSERT_TRUE(base::PathExists(shortcut_path.DirName())); 403} 404 405TEST_F(ShellUtilShortcutTest, RemoveMultipleChromeShortcuts) { 406 const wchar_t kShortcutName1[] = L"Chrome 1"; 407 const wchar_t kShortcutName2[] = L"Chrome 2"; 408 409 test_properties_.set_shortcut_name(kShortcutName1); 410 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 411 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 412 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 413 string16 shortcut1_name( 414 string16(kShortcutName1).append(installer::kLnkExt)); 415 base::FilePath shortcut1_path( 416 fake_user_desktop_.path().Append(shortcut1_name)); 417 ASSERT_TRUE(base::PathExists(shortcut1_path)); 418 419 test_properties_.set_shortcut_name(kShortcutName2); 420 test_properties_.set_arguments(L"--profile-directory=\"Profile 2\""); 421 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 422 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 423 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 424 string16 shortcut2_name(string16(kShortcutName2).append(installer::kLnkExt)); 425 base::FilePath shortcut2_path( 426 fake_user_desktop_.path().Append(shortcut2_name)); 427 ASSERT_TRUE(base::PathExists(shortcut2_path)); 428 429 ASSERT_TRUE(ShellUtil::RemoveShortcuts( 430 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER, 431 chrome_exe_)); 432 ASSERT_FALSE(base::PathExists(shortcut1_path)); 433 ASSERT_FALSE(base::PathExists(shortcut2_path)); 434 ASSERT_TRUE(base::PathExists(shortcut1_path.DirName())); 435} 436 437TEST_F(ShellUtilShortcutTest, UpdateChromeShortcutsWithArgs) { 438 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 439 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 440 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 441 442 string16 shortcut_name( 443 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) + 444 installer::kLnkExt); 445 base::FilePath shortcut_path(fake_user_desktop_.path().Append(shortcut_name)); 446 ASSERT_TRUE(base::PathExists(shortcut_path)); 447 448 base::FilePath new_exe = temp_dir_.path().Append(kManganeseExe); 449 ShellUtil::ShortcutProperties updated_properties(ShellUtil::CURRENT_USER); 450 updated_properties.set_target(new_exe); 451 // |updated_properties| has arguments. 452 ASSERT_TRUE(ShellUtil::UpdateShortcutsWithArgs( 453 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER, 454 chrome_exe_, updated_properties)); 455 456 ShellUtil::ShortcutProperties expected_properties(test_properties_); 457 expected_properties.set_target(new_exe); 458 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 459 expected_properties); 460} 461 462TEST_F(ShellUtilShortcutTest, UpdateSystemLevelChromeShortcutsWithArgs) { 463 test_properties_.level = ShellUtil::SYSTEM_LEVEL; 464 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 465 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 466 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 467 468 string16 shortcut_name( 469 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) + 470 installer::kLnkExt); 471 base::FilePath shortcut_path( 472 fake_common_desktop_.path().Append(shortcut_name)); 473 ASSERT_TRUE(base::PathExists(shortcut_path)); 474 475 base::FilePath new_exe = temp_dir_.path().Append(kManganeseExe); 476 ShellUtil::ShortcutProperties updated_properties(ShellUtil::CURRENT_USER); 477 updated_properties.set_target(new_exe); 478 // |updated_properties| has arguments. 479 ASSERT_TRUE(ShellUtil::UpdateShortcutsWithArgs( 480 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::SYSTEM_LEVEL, 481 chrome_exe_, updated_properties)); 482 483 ShellUtil::ShortcutProperties expected_properties(test_properties_); 484 expected_properties.set_target(new_exe); 485 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 486 expected_properties); 487} 488 489TEST_F(ShellUtilShortcutTest, UpdateMultipleChromeShortcutsWithArgs) { 490 const wchar_t kShortcutName1[] = L"Chrome 1"; 491 const wchar_t kShortcutName2[] = L"Chrome 2"; 492 493 // Setup shortcut 1, which has empty arguments. 494 test_properties_.set_shortcut_name(kShortcutName1); 495 test_properties_.set_arguments(L""); 496 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 497 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 498 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 499 string16 shortcut1_name(string16(kShortcutName1).append(installer::kLnkExt)); 500 base::FilePath shortcut1_path( 501 fake_user_desktop_.path().Append(shortcut1_name)); 502 ShellUtil::ShortcutProperties expected_properties1(test_properties_); 503 504 // Setup shortcut 2, which has non-empty arguments. 505 string16 shortcut2_args = L"--profile-directory=\"Profile 2\""; 506 test_properties_.set_shortcut_name(kShortcutName2); 507 test_properties_.set_arguments(shortcut2_args); 508 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 509 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 510 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 511 string16 shortcut2_name(string16(kShortcutName2).append(installer::kLnkExt)); 512 base::FilePath shortcut2_path( 513 fake_user_desktop_.path().Append(shortcut2_name)); 514 ASSERT_TRUE(base::PathExists(shortcut2_path)); 515 ShellUtil::ShortcutProperties expected_properties2(test_properties_); 516 517 // Update shortcuts: target "manganese.exe" instead of "chrome.exe". 518 base::FilePath new_exe = temp_dir_.path().Append(kManganeseExe); 519 ShellUtil::ShortcutProperties updated_properties(ShellUtil::CURRENT_USER); 520 updated_properties.set_target(new_exe); 521 522 // Only changing shrotcuts that have non-empty arguments, i.e., shortcut 2. 523 ASSERT_TRUE(ShellUtil::UpdateShortcutsWithArgs( 524 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER, 525 chrome_exe_, updated_properties)); 526 // Verify shortcut 1. 527 // |expected_properties1| was unchanged and still targets "chrome.exe", since 528 // it has empty target, yet we passed |require_args| = true. 529 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 530 expected_properties1); 531 // Verify shortcut 2. 532 expected_properties2.set_target(new_exe); 533 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, 534 expected_properties2); 535} 536 537TEST_F(ShellUtilShortcutTest, CreateMultipleStartMenuShortcutsAndRemoveFolder) { 538 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 539 ShellUtil::SHORTCUT_LOCATION_START_MENU, 540 dist_, test_properties_, 541 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 542 test_properties_.set_shortcut_name(L"A second shortcut"); 543 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 544 ShellUtil::SHORTCUT_LOCATION_START_MENU, 545 dist_, test_properties_, 546 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 547 548 base::FilePath shortcut_folder( 549 fake_start_menu_.path().Append( 550 dist_->GetStartMenuShortcutSubfolder( 551 BrowserDistribution::SUBFOLDER_CHROME))); 552 base::FileEnumerator file_counter(shortcut_folder, false, 553 base::FileEnumerator::FILES); 554 int count = 0; 555 while (!file_counter.Next().empty()) 556 ++count; 557 EXPECT_EQ(2, count); 558 559 ASSERT_TRUE(base::PathExists(shortcut_folder)); 560 ASSERT_TRUE(ShellUtil::RemoveShortcuts( 561 ShellUtil::SHORTCUT_LOCATION_START_MENU, dist_, ShellUtil::CURRENT_USER, 562 chrome_exe_)); 563 ASSERT_FALSE(base::PathExists(shortcut_folder)); 564} 565 566TEST_F(ShellUtilShortcutTest, DontRemoveChromeShortcutIfPointsToAnotherChrome) { 567 base::ScopedTempDir other_exe_dir; 568 ASSERT_TRUE(other_exe_dir.CreateUniqueTempDir()); 569 base::FilePath other_chrome_exe = 570 other_exe_dir.path().Append(installer::kChromeExe); 571 EXPECT_EQ(0, file_util::WriteFile(other_chrome_exe, "", 0)); 572 573 test_properties_.set_target(other_chrome_exe); 574 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 575 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 576 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 577 578 string16 shortcut_name( 579 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) + 580 installer::kLnkExt); 581 base::FilePath shortcut_path(fake_user_desktop_.path().Append(shortcut_name)); 582 ASSERT_TRUE(base::PathExists(shortcut_path)); 583 584 // The shortcut shouldn't be removed as it was installed pointing to 585 // |other_chrome_exe| and RemoveChromeShortcut() is being told that the 586 // removed shortcut should point to |chrome_exe_|. 587 ASSERT_TRUE(ShellUtil::RemoveShortcuts( 588 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER, 589 chrome_exe_)); 590 ASSERT_TRUE(base::PathExists(shortcut_path)); 591 ASSERT_TRUE(base::PathExists(shortcut_path.DirName())); 592} 593 594TEST(ShellUtilTest, BuildAppModelIdBasic) { 595 std::vector<string16> components; 596 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 597 const string16 base_app_id(dist->GetBaseAppId()); 598 components.push_back(base_app_id); 599 ASSERT_EQ(base_app_id, ShellUtil::BuildAppModelId(components)); 600} 601 602TEST(ShellUtilTest, BuildAppModelIdManySmall) { 603 std::vector<string16> components; 604 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 605 const string16 suffixed_app_id(dist->GetBaseAppId().append(L".gab")); 606 components.push_back(suffixed_app_id); 607 components.push_back(L"Default"); 608 components.push_back(L"Test"); 609 ASSERT_EQ(suffixed_app_id + L".Default.Test", 610 ShellUtil::BuildAppModelId(components)); 611} 612 613TEST(ShellUtilTest, BuildAppModelIdLongUsernameNormalProfile) { 614 std::vector<string16> components; 615 const string16 long_appname( 616 L"Chrome.a_user_who_has_a_crazy_long_name_with_some_weird@symbols_in_it_" 617 L"that_goes_over_64_characters"); 618 components.push_back(long_appname); 619 components.push_back(L"Default"); 620 ASSERT_EQ(L"Chrome.a_user_wer_64_characters.Default", 621 ShellUtil::BuildAppModelId(components)); 622} 623 624TEST(ShellUtilTest, BuildAppModelIdLongEverything) { 625 std::vector<string16> components; 626 const string16 long_appname( 627 L"Chrome.a_user_who_has_a_crazy_long_name_with_some_weird@symbols_in_it_" 628 L"that_goes_over_64_characters"); 629 components.push_back(long_appname); 630 components.push_back( 631 L"A_crazy_profile_name_not_even_sure_whether_that_is_possible"); 632 const string16 constructed_app_id(ShellUtil::BuildAppModelId(components)); 633 ASSERT_LE(constructed_app_id.length(), installer::kMaxAppModelIdLength); 634 ASSERT_EQ(L"Chrome.a_user_wer_64_characters.A_crazy_profilethat_is_possible", 635 constructed_app_id); 636} 637 638TEST(ShellUtilTest, GetUserSpecificRegistrySuffix) { 639 string16 suffix; 640 ASSERT_TRUE(ShellUtil::GetUserSpecificRegistrySuffix(&suffix)); 641 ASSERT_TRUE(StartsWith(suffix, L".", true)); 642 ASSERT_EQ(27, suffix.length()); 643 ASSERT_TRUE(ContainsOnlyChars(suffix.substr(1), 644 L"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567")); 645} 646 647TEST(ShellUtilTest, GetOldUserSpecificRegistrySuffix) { 648 string16 suffix; 649 ASSERT_TRUE(ShellUtil::GetOldUserSpecificRegistrySuffix(&suffix)); 650 ASSERT_TRUE(StartsWith(suffix, L".", true)); 651 652 wchar_t user_name[256]; 653 DWORD size = arraysize(user_name); 654 ASSERT_NE(0, ::GetUserName(user_name, &size)); 655 ASSERT_GE(size, 1U); 656 ASSERT_STREQ(user_name, suffix.substr(1).c_str()); 657} 658 659TEST(ShellUtilTest, ByteArrayToBase32) { 660 // Tests from http://tools.ietf.org/html/rfc4648#section-10. 661 const unsigned char test_array[] = { 'f', 'o', 'o', 'b', 'a', 'r' }; 662 663 const string16 expected[] = { L"", L"MY", L"MZXQ", L"MZXW6", L"MZXW6YQ", 664 L"MZXW6YTB", L"MZXW6YTBOI"}; 665 666 // Run the tests, with one more letter in the input every pass. 667 for (int i = 0; i < arraysize(expected); ++i) { 668 ASSERT_EQ(expected[i], 669 ShellUtil::ByteArrayToBase32(test_array, i)); 670 } 671} 672