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 base::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_CHROME_DIR: 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_CHROME_DIR, 211 dist_, 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_CHROME_DIR, 215 dist_, 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_CHROME_DIR, 235 dist_, test_properties_, 236 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 237 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, 238 dist_, 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_CHROME_DIR, dist_, 295 properties, 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_CHROME_DIR, 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_CHROME_DIR, 307 dist_, 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_CHROME_DIR, 341 dist_, test_properties_, 342 ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL)); 343 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, 344 dist_, 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_CHROME_DIR, 540 dist_, test_properties_, 541 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 542 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 543 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR, 544 dist_, test_properties_, 545 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 546 test_properties_.set_shortcut_name(L"A second shortcut"); 547 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 548 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, 549 dist_, test_properties_, 550 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 551 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 552 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR, 553 dist_, test_properties_, 554 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 555 556 base::FilePath chrome_shortcut_folder( 557 fake_start_menu_.path().Append( 558 dist_->GetStartMenuShortcutSubfolder( 559 BrowserDistribution::SUBFOLDER_CHROME))); 560 base::FilePath chrome_apps_shortcut_folder( 561 fake_start_menu_.path().Append( 562 dist_->GetStartMenuShortcutSubfolder( 563 BrowserDistribution::SUBFOLDER_APPS))); 564 565 base::FileEnumerator chrome_file_counter(chrome_shortcut_folder, false, 566 base::FileEnumerator::FILES); 567 int count = 0; 568 while (!chrome_file_counter.Next().empty()) 569 ++count; 570 EXPECT_EQ(2, count); 571 572 base::FileEnumerator chrome_apps_file_counter(chrome_apps_shortcut_folder, 573 false, 574 base::FileEnumerator::FILES); 575 count = 0; 576 while (!chrome_apps_file_counter.Next().empty()) 577 ++count; 578 EXPECT_EQ(2, count); 579 580 ASSERT_TRUE(base::PathExists(chrome_shortcut_folder)); 581 ASSERT_TRUE(ShellUtil::RemoveShortcuts( 582 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, dist_, 583 ShellUtil::CURRENT_USER, chrome_exe_)); 584 ASSERT_FALSE(base::PathExists(chrome_shortcut_folder)); 585 586 ASSERT_TRUE(base::PathExists(chrome_apps_shortcut_folder)); 587 ASSERT_TRUE(ShellUtil::RemoveShortcuts( 588 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR, dist_, 589 ShellUtil::CURRENT_USER, chrome_exe_)); 590 ASSERT_FALSE(base::PathExists(chrome_apps_shortcut_folder)); 591} 592 593TEST_F(ShellUtilShortcutTest, 594 DeleteStartMenuRootShortcutWithoutRemovingFolder) { 595 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 596 ShellUtil::SHORTCUT_LOCATION_START_MENU_ROOT, 597 dist_, test_properties_, 598 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 599 600 string16 shortcut_name( 601 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) + 602 installer::kLnkExt); 603 base::FilePath shortcut_path( 604 fake_start_menu_.path().Append(shortcut_name)); 605 606 ASSERT_TRUE(base::PathExists(fake_start_menu_.path())); 607 ASSERT_TRUE(base::PathExists(shortcut_path)); 608 ASSERT_TRUE(ShellUtil::RemoveShortcuts( 609 ShellUtil::SHORTCUT_LOCATION_START_MENU_ROOT, dist_, 610 ShellUtil::CURRENT_USER, chrome_exe_)); 611 // The shortcut should be removed but the "Start Menu" root directory should 612 // remain. 613 ASSERT_TRUE(base::PathExists(fake_start_menu_.path())); 614 ASSERT_FALSE(base::PathExists(shortcut_path)); 615} 616 617TEST_F(ShellUtilShortcutTest, DontRemoveChromeShortcutIfPointsToAnotherChrome) { 618 base::ScopedTempDir other_exe_dir; 619 ASSERT_TRUE(other_exe_dir.CreateUniqueTempDir()); 620 base::FilePath other_chrome_exe = 621 other_exe_dir.path().Append(installer::kChromeExe); 622 EXPECT_EQ(0, file_util::WriteFile(other_chrome_exe, "", 0)); 623 624 test_properties_.set_target(other_chrome_exe); 625 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut( 626 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_, 627 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)); 628 629 string16 shortcut_name( 630 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) + 631 installer::kLnkExt); 632 base::FilePath shortcut_path(fake_user_desktop_.path().Append(shortcut_name)); 633 ASSERT_TRUE(base::PathExists(shortcut_path)); 634 635 // The shortcut shouldn't be removed as it was installed pointing to 636 // |other_chrome_exe| and RemoveChromeShortcut() is being told that the 637 // removed shortcut should point to |chrome_exe_|. 638 ASSERT_TRUE(ShellUtil::RemoveShortcuts( 639 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER, 640 chrome_exe_)); 641 ASSERT_TRUE(base::PathExists(shortcut_path)); 642 ASSERT_TRUE(base::PathExists(shortcut_path.DirName())); 643} 644 645TEST(ShellUtilTest, BuildAppModelIdBasic) { 646 std::vector<string16> components; 647 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 648 const string16 base_app_id(dist->GetBaseAppId()); 649 components.push_back(base_app_id); 650 ASSERT_EQ(base_app_id, ShellUtil::BuildAppModelId(components)); 651} 652 653TEST(ShellUtilTest, BuildAppModelIdManySmall) { 654 std::vector<string16> components; 655 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 656 const string16 suffixed_app_id(dist->GetBaseAppId().append(L".gab")); 657 components.push_back(suffixed_app_id); 658 components.push_back(L"Default"); 659 components.push_back(L"Test"); 660 ASSERT_EQ(suffixed_app_id + L".Default.Test", 661 ShellUtil::BuildAppModelId(components)); 662} 663 664TEST(ShellUtilTest, BuildAppModelIdLongUsernameNormalProfile) { 665 std::vector<string16> components; 666 const string16 long_appname( 667 L"Chrome.a_user_who_has_a_crazy_long_name_with_some_weird@symbols_in_it_" 668 L"that_goes_over_64_characters"); 669 components.push_back(long_appname); 670 components.push_back(L"Default"); 671 ASSERT_EQ(L"Chrome.a_user_wer_64_characters.Default", 672 ShellUtil::BuildAppModelId(components)); 673} 674 675TEST(ShellUtilTest, BuildAppModelIdLongEverything) { 676 std::vector<string16> components; 677 const string16 long_appname( 678 L"Chrome.a_user_who_has_a_crazy_long_name_with_some_weird@symbols_in_it_" 679 L"that_goes_over_64_characters"); 680 components.push_back(long_appname); 681 components.push_back( 682 L"A_crazy_profile_name_not_even_sure_whether_that_is_possible"); 683 const string16 constructed_app_id(ShellUtil::BuildAppModelId(components)); 684 ASSERT_LE(constructed_app_id.length(), installer::kMaxAppModelIdLength); 685 ASSERT_EQ(L"Chrome.a_user_wer_64_characters.A_crazy_profilethat_is_possible", 686 constructed_app_id); 687} 688 689TEST(ShellUtilTest, GetUserSpecificRegistrySuffix) { 690 string16 suffix; 691 ASSERT_TRUE(ShellUtil::GetUserSpecificRegistrySuffix(&suffix)); 692 ASSERT_TRUE(StartsWith(suffix, L".", true)); 693 ASSERT_EQ(27, suffix.length()); 694 ASSERT_TRUE(ContainsOnlyChars(suffix.substr(1), 695 L"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567")); 696} 697 698TEST(ShellUtilTest, GetOldUserSpecificRegistrySuffix) { 699 string16 suffix; 700 ASSERT_TRUE(ShellUtil::GetOldUserSpecificRegistrySuffix(&suffix)); 701 ASSERT_TRUE(StartsWith(suffix, L".", true)); 702 703 wchar_t user_name[256]; 704 DWORD size = arraysize(user_name); 705 ASSERT_NE(0, ::GetUserName(user_name, &size)); 706 ASSERT_GE(size, 1U); 707 ASSERT_STREQ(user_name, suffix.substr(1).c_str()); 708} 709 710TEST(ShellUtilTest, ByteArrayToBase32) { 711 // Tests from http://tools.ietf.org/html/rfc4648#section-10. 712 const unsigned char test_array[] = { 'f', 'o', 'o', 'b', 'a', 'r' }; 713 714 const string16 expected[] = { L"", L"MY", L"MZXQ", L"MZXW6", L"MZXW6YQ", 715 L"MZXW6YTB", L"MZXW6YTBOI"}; 716 717 // Run the tests, with one more letter in the input every pass. 718 for (int i = 0; i < arraysize(expected); ++i) { 719 ASSERT_EQ(expected[i], 720 ShellUtil::ByteArrayToBase32(test_array, i)); 721 } 722} 723