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 <objbase.h> // For CoInitialize(). 6 7 #include "base/base_paths.h" 8 #include "base/file_util.h" 9 #include "base/location.h" 10 #include "base/message_loop/message_loop.h" 11 #include "base/path_service.h" 12 #include "base/strings/string16.h" 13 #include "base/test/scoped_path_override.h" 14 #include "base/test/test_shortcut_win.h" 15 #include "base/win/shortcut.h" 16 #include "chrome/browser/profiles/profile.h" 17 #include "chrome/browser/profiles/profile_manager.h" 18 #include "chrome/browser/profiles/profile_shortcut_manager.h" 19 #include "chrome/browser/profiles/profile_shortcut_manager_win.h" 20 #include "chrome/browser/shell_integration.h" 21 #include "chrome/installer/util/browser_distribution.h" 22 #include "chrome/installer/util/product.h" 23 #include "chrome/installer/util/shell_util.h" 24 #include "chrome/test/base/testing_browser_process.h" 25 #include "chrome/test/base/testing_profile.h" 26 #include "chrome/test/base/testing_profile_manager.h" 27 #include "content/public/test/test_browser_thread.h" 28 #include "grit/chromium_strings.h" 29 #include "testing/gtest/include/gtest/gtest.h" 30 #include "ui/base/l10n/l10n_util.h" 31 32 using content::BrowserThread; 33 34 class ProfileShortcutManagerTest : public testing::Test { 35 protected: 36 ProfileShortcutManagerTest() 37 : ui_thread_(BrowserThread::UI, &message_loop_), 38 file_thread_(BrowserThread::FILE, &message_loop_), 39 profile_info_cache_(NULL), 40 fake_user_desktop_(base::DIR_USER_DESKTOP), 41 fake_system_desktop_(base::DIR_COMMON_DESKTOP) { 42 } 43 44 virtual void SetUp() OVERRIDE { 45 CoInitialize(NULL); 46 47 TestingBrowserProcess* browser_process = 48 TestingBrowserProcess::GetGlobal(); 49 profile_manager_.reset(new TestingProfileManager(browser_process)); 50 ASSERT_TRUE(profile_manager_->SetUp()); 51 profile_info_cache_ = profile_manager_->profile_info_cache(); 52 profile_shortcut_manager_.reset( 53 ProfileShortcutManager::Create(profile_manager_->profile_manager())); 54 profile_1_name_ = L"My profile"; 55 profile_1_path_ = CreateProfileDirectory(profile_1_name_); 56 profile_2_name_ = L"My profile 2"; 57 profile_2_path_ = CreateProfileDirectory(profile_2_name_); 58 profile_3_name_ = L"My profile 3"; 59 profile_3_path_ = CreateProfileDirectory(profile_3_name_); 60 } 61 62 virtual void TearDown() OVERRIDE { 63 message_loop_.RunUntilIdle(); 64 65 // Delete all profiles and ensure their shortcuts got removed. 66 const int num_profiles = profile_info_cache_->GetNumberOfProfiles(); 67 for (int i = 0; i < num_profiles; ++i) { 68 const base::FilePath profile_path = 69 profile_info_cache_->GetPathOfProfileAtIndex(0); 70 string16 profile_name = profile_info_cache_->GetNameOfProfileAtIndex(0); 71 profile_info_cache_->DeleteProfileFromCache(profile_path); 72 RunPendingTasks(); 73 ASSERT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_name)); 74 // The icon file is not deleted until the profile directory is deleted. 75 const base::FilePath icon_path = 76 profiles::internal::GetProfileIconPath(profile_path); 77 ASSERT_TRUE(base::PathExists(icon_path)); 78 } 79 } 80 81 base::FilePath CreateProfileDirectory(const string16& profile_name) { 82 const base::FilePath profile_path = 83 profile_info_cache_->GetUserDataDir().Append(profile_name); 84 file_util::CreateDirectory(profile_path); 85 return profile_path; 86 } 87 88 void RunPendingTasks() { 89 base::MessageLoop::current()->PostTask(FROM_HERE, 90 base::MessageLoop::QuitClosure()); 91 base::MessageLoop::current()->Run(); 92 } 93 94 void SetupDefaultProfileShortcut(const tracked_objects::Location& location) { 95 ASSERT_EQ(0, profile_info_cache_->GetNumberOfProfiles()) 96 << location.ToString(); 97 ASSERT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_1_name_)) 98 << location.ToString(); 99 profile_info_cache_->AddProfileToCache(profile_1_path_, profile_1_name_, 100 string16(), 0, std::string()); 101 // Also create a non-badged shortcut for Chrome, which is conveniently done 102 // by |CreateProfileShortcut()| since there is only one profile. 103 profile_shortcut_manager_->CreateProfileShortcut(profile_1_path_); 104 RunPendingTasks(); 105 // Verify that there's now a shortcut with no profile information. 106 ValidateNonProfileShortcut(location); 107 } 108 109 void SetupAndCreateTwoShortcuts(const tracked_objects::Location& location) { 110 SetupDefaultProfileShortcut(location); 111 CreateProfileWithShortcut(location, profile_2_name_, profile_2_path_); 112 ValidateProfileShortcut(location, profile_1_name_, profile_1_path_); 113 } 114 115 // Returns the default shortcut path for this profile. 116 base::FilePath GetDefaultShortcutPathForProfile( 117 const string16& profile_name) { 118 return GetUserShortcutsDirectory().Append( 119 profiles::internal::GetShortcutFilenameForProfile(profile_name, 120 GetDistribution())); 121 } 122 123 // Returns true if the shortcut for this profile exists. 124 bool ProfileShortcutExistsAtDefaultPath(const string16& profile_name) { 125 return base::PathExists( 126 GetDefaultShortcutPathForProfile(profile_name)); 127 } 128 129 // Calls base::win::ValidateShortcut() with expected properties for the 130 // shortcut at |shortcut_path| for the profile at |profile_path|. 131 void ValidateProfileShortcutAtPath(const tracked_objects::Location& location, 132 const base::FilePath& shortcut_path, 133 const base::FilePath& profile_path) { 134 EXPECT_TRUE(base::PathExists(shortcut_path)) << location.ToString(); 135 136 // Ensure that the corresponding icon exists. 137 const base::FilePath icon_path = 138 profiles::internal::GetProfileIconPath(profile_path); 139 EXPECT_TRUE(base::PathExists(icon_path)) << location.ToString(); 140 141 base::win::ShortcutProperties expected_properties; 142 expected_properties.set_app_id( 143 ShellIntegration::GetChromiumModelIdForProfile(profile_path)); 144 expected_properties.set_target(GetExePath()); 145 expected_properties.set_description(GetDistribution()->GetAppDescription()); 146 expected_properties.set_dual_mode(false); 147 expected_properties.set_arguments( 148 profiles::internal::CreateProfileShortcutFlags(profile_path)); 149 expected_properties.set_icon(icon_path, 0); 150 base::win::ValidateShortcut(shortcut_path, expected_properties); 151 } 152 153 // Calls base::win::ValidateShortcut() with expected properties for 154 // |profile_name|'s shortcut. 155 void ValidateProfileShortcut(const tracked_objects::Location& location, 156 const string16& profile_name, 157 const base::FilePath& profile_path) { 158 ValidateProfileShortcutAtPath( 159 location, GetDefaultShortcutPathForProfile(profile_name), profile_path); 160 } 161 162 void ValidateNonProfileShortcutAtPath( 163 const tracked_objects::Location& location, 164 const base::FilePath& shortcut_path) { 165 EXPECT_TRUE(base::PathExists(shortcut_path)) << location.ToString(); 166 167 base::win::ShortcutProperties expected_properties; 168 expected_properties.set_target(GetExePath()); 169 expected_properties.set_arguments(string16()); 170 expected_properties.set_icon(GetExePath(), 0); 171 expected_properties.set_description(GetDistribution()->GetAppDescription()); 172 expected_properties.set_dual_mode(false); 173 base::win::ValidateShortcut(shortcut_path, expected_properties); 174 } 175 176 void ValidateNonProfileShortcut(const tracked_objects::Location& location) { 177 const base::FilePath shortcut_path = 178 GetDefaultShortcutPathForProfile(string16()); 179 ValidateNonProfileShortcutAtPath(location, shortcut_path); 180 } 181 182 void CreateProfileWithShortcut(const tracked_objects::Location& location, 183 const string16& profile_name, 184 const base::FilePath& profile_path) { 185 ASSERT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_name)) 186 << location.ToString(); 187 profile_info_cache_->AddProfileToCache(profile_path, profile_name, 188 string16(), 0, std::string()); 189 profile_shortcut_manager_->CreateProfileShortcut(profile_path); 190 RunPendingTasks(); 191 ValidateProfileShortcut(location, profile_name, profile_path); 192 } 193 194 // Creates a regular (non-profile) desktop shortcut with the given name and 195 // returns its path. Fails the test if an error occurs. 196 base::FilePath CreateRegularShortcutWithName( 197 const tracked_objects::Location& location, 198 const string16& shortcut_name) { 199 const base::FilePath shortcut_path = 200 GetUserShortcutsDirectory().Append(shortcut_name + installer::kLnkExt); 201 EXPECT_FALSE(base::PathExists(shortcut_path)) << location.ToString(); 202 203 installer::Product product(GetDistribution()); 204 ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER); 205 product.AddDefaultShortcutProperties(GetExePath(), &properties); 206 properties.set_shortcut_name(shortcut_name); 207 EXPECT_TRUE(ShellUtil::CreateOrUpdateShortcut( 208 ShellUtil::SHORTCUT_LOCATION_DESKTOP, GetDistribution(), properties, 209 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)) << location.ToString(); 210 EXPECT_TRUE(base::PathExists(shortcut_path)) << location.ToString(); 211 212 return shortcut_path; 213 } 214 215 base::FilePath CreateRegularSystemLevelShortcut( 216 const tracked_objects::Location& location) { 217 BrowserDistribution* distribution = GetDistribution(); 218 installer::Product product(distribution); 219 ShellUtil::ShortcutProperties properties(ShellUtil::SYSTEM_LEVEL); 220 product.AddDefaultShortcutProperties(GetExePath(), &properties); 221 EXPECT_TRUE(ShellUtil::CreateOrUpdateShortcut( 222 ShellUtil::SHORTCUT_LOCATION_DESKTOP, distribution, properties, 223 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)) << location.ToString(); 224 const base::FilePath system_level_shortcut_path = 225 GetSystemShortcutsDirectory().Append( 226 distribution->GetAppShortCutName() + installer::kLnkExt); 227 EXPECT_TRUE(base::PathExists(system_level_shortcut_path)) 228 << location.ToString(); 229 return system_level_shortcut_path; 230 } 231 232 void RenameProfile(const tracked_objects::Location& location, 233 const base::FilePath& profile_path, 234 const string16& new_profile_name) { 235 const size_t profile_index = 236 profile_info_cache_->GetIndexOfProfileWithPath(profile_2_path_); 237 ASSERT_NE(std::string::npos, profile_index); 238 ASSERT_NE(profile_info_cache_->GetNameOfProfileAtIndex(profile_index), 239 new_profile_name); 240 profile_info_cache_->SetNameOfProfileAtIndex(profile_index, 241 new_profile_name); 242 RunPendingTasks(); 243 } 244 245 BrowserDistribution* GetDistribution() { 246 return BrowserDistribution::GetDistribution(); 247 } 248 249 base::FilePath GetExePath() { 250 base::FilePath exe_path; 251 EXPECT_TRUE(PathService::Get(base::FILE_EXE, &exe_path)); 252 return exe_path; 253 } 254 255 base::FilePath GetUserShortcutsDirectory() { 256 base::FilePath user_shortcuts_directory; 257 EXPECT_TRUE(ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP, 258 GetDistribution(), 259 ShellUtil::CURRENT_USER, 260 &user_shortcuts_directory)); 261 return user_shortcuts_directory; 262 } 263 264 base::FilePath GetSystemShortcutsDirectory() { 265 base::FilePath system_shortcuts_directory; 266 EXPECT_TRUE(ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP, 267 GetDistribution(), 268 ShellUtil::SYSTEM_LEVEL, 269 &system_shortcuts_directory)); 270 return system_shortcuts_directory; 271 } 272 273 base::MessageLoopForUI message_loop_; 274 content::TestBrowserThread ui_thread_; 275 content::TestBrowserThread file_thread_; 276 scoped_ptr<TestingProfileManager> profile_manager_; 277 scoped_ptr<ProfileShortcutManager> profile_shortcut_manager_; 278 ProfileInfoCache* profile_info_cache_; 279 base::ScopedPathOverride fake_user_desktop_; 280 base::ScopedPathOverride fake_system_desktop_; 281 string16 profile_1_name_; 282 base::FilePath profile_1_path_; 283 string16 profile_2_name_; 284 base::FilePath profile_2_path_; 285 string16 profile_3_name_; 286 base::FilePath profile_3_path_; 287 }; 288 289 TEST_F(ProfileShortcutManagerTest, ShortcutFilename) { 290 const string16 kProfileName = L"Harry"; 291 BrowserDistribution* distribution = GetDistribution(); 292 const string16 expected_name = kProfileName + L" - " + 293 l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME) + installer::kLnkExt; 294 EXPECT_EQ(expected_name, 295 profiles::internal::GetShortcutFilenameForProfile(kProfileName, 296 distribution)); 297 } 298 299 TEST_F(ProfileShortcutManagerTest, ShortcutLongFilenameIsTrimmed) { 300 const string16 kLongProfileName = L"Harry Harry Harry Harry Harry Harry Harry" 301 L"Harry Harry Harry Harry Harry Harry Harry Harry Harry Harry Harry" 302 L"Harry Harry Harry Harry Harry Harry Harry Harry Harry Harry Harry"; 303 const string16 file_name = 304 profiles::internal::GetShortcutFilenameForProfile(kLongProfileName, 305 GetDistribution()); 306 EXPECT_LT(file_name.size(), kLongProfileName.size()); 307 } 308 309 TEST_F(ProfileShortcutManagerTest, ShortcutFilenameStripsReservedCharacters) { 310 const string16 kProfileName = L"<Harry/>"; 311 const string16 kSanitizedProfileName = L"Harry"; 312 BrowserDistribution* distribution = GetDistribution(); 313 const string16 expected_name = kSanitizedProfileName + L" - " + 314 distribution->GetAppShortCutName() + installer::kLnkExt; 315 EXPECT_EQ(expected_name, 316 profiles::internal::GetShortcutFilenameForProfile(kProfileName, 317 distribution)); 318 } 319 320 TEST_F(ProfileShortcutManagerTest, UnbadgedShortcutFilename) { 321 BrowserDistribution* distribution = GetDistribution(); 322 EXPECT_EQ(distribution->GetAppShortCutName() + installer::kLnkExt, 323 profiles::internal::GetShortcutFilenameForProfile(string16(), 324 distribution)); 325 } 326 327 TEST_F(ProfileShortcutManagerTest, ShortcutFlags) { 328 const string16 kProfileName = L"MyProfileX"; 329 const base::FilePath profile_path = 330 profile_info_cache_->GetUserDataDir().Append(kProfileName); 331 EXPECT_EQ(L"--profile-directory=\"" + kProfileName + L"\"", 332 profiles::internal::CreateProfileShortcutFlags(profile_path)); 333 } 334 335 TEST_F(ProfileShortcutManagerTest, DesktopShortcutsCreate) { 336 SetupDefaultProfileShortcut(FROM_HERE); 337 // Validation is done by |ValidateProfileShortcutAtPath()| which is called 338 // by |CreateProfileWithShortcut()|. 339 CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_); 340 } 341 342 TEST_F(ProfileShortcutManagerTest, DesktopShortcutsUpdate) { 343 SetupDefaultProfileShortcut(FROM_HERE); 344 CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_); 345 346 // Cause an update in ProfileShortcutManager by modifying the profile info 347 // cache. 348 const string16 new_profile_2_name = L"New Profile Name"; 349 RenameProfile(FROM_HERE, profile_2_path_, new_profile_2_name); 350 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_)); 351 ValidateProfileShortcut(FROM_HERE, new_profile_2_name, profile_2_path_); 352 } 353 354 TEST_F(ProfileShortcutManagerTest, CreateSecondProfileBadgesFirstShortcut) { 355 SetupDefaultProfileShortcut(FROM_HERE); 356 // Assert that a shortcut without a profile name exists. 357 ASSERT_TRUE(ProfileShortcutExistsAtDefaultPath(string16())); 358 359 // Create a second profile without a shortcut. 360 profile_info_cache_->AddProfileToCache(profile_2_path_, profile_2_name_, 361 string16(), 0, std::string()); 362 RunPendingTasks(); 363 364 // Ensure that the second profile doesn't have a shortcut and that the first 365 // profile's shortcut got renamed and badged. 366 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_)); 367 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(string16())); 368 ValidateProfileShortcut(FROM_HERE, profile_1_name_, profile_1_path_); 369 } 370 371 TEST_F(ProfileShortcutManagerTest, DesktopShortcutsDeleteSecondToLast) { 372 SetupAndCreateTwoShortcuts(FROM_HERE); 373 374 // Delete one shortcut. 375 profile_info_cache_->DeleteProfileFromCache(profile_2_path_); 376 RunPendingTasks(); 377 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_)); 378 379 // Verify that the profile name has been removed from the remaining shortcut. 380 ValidateNonProfileShortcut(FROM_HERE); 381 // Verify that an additional shortcut, with the default profile's name does 382 // not exist. 383 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_1_name_)); 384 } 385 386 TEST_F(ProfileShortcutManagerTest, DeleteSecondToLastProfileWithoutShortcut) { 387 SetupAndCreateTwoShortcuts(FROM_HERE); 388 389 const base::FilePath profile_1_shortcut_path = 390 GetDefaultShortcutPathForProfile(profile_1_name_); 391 const base::FilePath profile_2_shortcut_path = 392 GetDefaultShortcutPathForProfile(profile_2_name_); 393 394 // Delete the shortcut for the first profile, but keep the one for the 2nd. 395 ASSERT_TRUE(base::DeleteFile(profile_1_shortcut_path, false)); 396 ASSERT_FALSE(base::PathExists(profile_1_shortcut_path)); 397 ASSERT_TRUE(base::PathExists(profile_2_shortcut_path)); 398 399 // Delete the profile that doesn't have a shortcut. 400 profile_info_cache_->DeleteProfileFromCache(profile_1_path_); 401 RunPendingTasks(); 402 403 // Verify that the remaining shortcut does not have a profile name. 404 ValidateNonProfileShortcut(FROM_HERE); 405 // Verify that shortcuts with profile names do not exist. 406 EXPECT_FALSE(base::PathExists(profile_1_shortcut_path)); 407 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path)); 408 } 409 410 TEST_F(ProfileShortcutManagerTest, DeleteSecondToLastProfileWithShortcut) { 411 SetupAndCreateTwoShortcuts(FROM_HERE); 412 413 const base::FilePath profile_1_shortcut_path = 414 GetDefaultShortcutPathForProfile(profile_1_name_); 415 const base::FilePath profile_2_shortcut_path = 416 GetDefaultShortcutPathForProfile(profile_2_name_); 417 418 // Delete the shortcut for the first profile, but keep the one for the 2nd. 419 ASSERT_TRUE(base::DeleteFile(profile_1_shortcut_path, false)); 420 ASSERT_FALSE(base::PathExists(profile_1_shortcut_path)); 421 ASSERT_TRUE(base::PathExists(profile_2_shortcut_path)); 422 423 // Delete the profile that has a shortcut. 424 profile_info_cache_->DeleteProfileFromCache(profile_2_path_); 425 RunPendingTasks(); 426 427 // Verify that the remaining shortcut does not have a profile name. 428 ValidateNonProfileShortcut(FROM_HERE); 429 // Verify that shortcuts with profile names do not exist. 430 EXPECT_FALSE(base::PathExists(profile_1_shortcut_path)); 431 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path)); 432 } 433 434 TEST_F(ProfileShortcutManagerTest, DeleteOnlyProfileWithShortcuts) { 435 SetupAndCreateTwoShortcuts(FROM_HERE); 436 CreateProfileWithShortcut(FROM_HERE, profile_3_name_, profile_3_path_); 437 438 const base::FilePath non_profile_shortcut_path = 439 GetDefaultShortcutPathForProfile(string16()); 440 const base::FilePath profile_1_shortcut_path = 441 GetDefaultShortcutPathForProfile(profile_1_name_); 442 const base::FilePath profile_2_shortcut_path = 443 GetDefaultShortcutPathForProfile(profile_2_name_); 444 const base::FilePath profile_3_shortcut_path = 445 GetDefaultShortcutPathForProfile(profile_3_name_); 446 447 // Delete shortcuts for the first two profiles. 448 ASSERT_TRUE(base::DeleteFile(profile_1_shortcut_path, false)); 449 ASSERT_TRUE(base::DeleteFile(profile_2_shortcut_path, false)); 450 451 // Only the shortcut to the third profile should exist. 452 ASSERT_FALSE(base::PathExists(profile_1_shortcut_path)); 453 ASSERT_FALSE(base::PathExists(profile_2_shortcut_path)); 454 ASSERT_FALSE(base::PathExists(non_profile_shortcut_path)); 455 ASSERT_TRUE(base::PathExists(profile_3_shortcut_path)); 456 457 // Delete the third profile and check that its shortcut is gone and no 458 // shortcuts have been re-created. 459 profile_info_cache_->DeleteProfileFromCache(profile_3_path_); 460 RunPendingTasks(); 461 ASSERT_FALSE(base::PathExists(profile_1_shortcut_path)); 462 ASSERT_FALSE(base::PathExists(profile_2_shortcut_path)); 463 ASSERT_FALSE(base::PathExists(profile_3_shortcut_path)); 464 ASSERT_FALSE(base::PathExists(non_profile_shortcut_path)); 465 } 466 467 TEST_F(ProfileShortcutManagerTest, DesktopShortcutsCreateSecond) { 468 SetupAndCreateTwoShortcuts(FROM_HERE); 469 470 // Delete one shortcut. 471 profile_info_cache_->DeleteProfileFromCache(profile_2_path_); 472 RunPendingTasks(); 473 474 // Verify that a default shortcut exists (no profile name/avatar). 475 ValidateNonProfileShortcut(FROM_HERE); 476 // Verify that an additional shortcut, with the first profile's name does 477 // not exist. 478 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_1_name_)); 479 480 // Create a second profile and shortcut. 481 CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_); 482 483 // Verify that the original shortcut received the profile's name. 484 ValidateProfileShortcut(FROM_HERE, profile_1_name_, profile_1_path_); 485 // Verify that a default shortcut no longer exists. 486 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(string16())); 487 } 488 489 TEST_F(ProfileShortcutManagerTest, RenamedDesktopShortcuts) { 490 SetupAndCreateTwoShortcuts(FROM_HERE); 491 492 const base::FilePath profile_2_shortcut_path_1 = 493 GetDefaultShortcutPathForProfile(profile_2_name_); 494 const base::FilePath profile_2_shortcut_path_2 = 495 GetUserShortcutsDirectory().Append(L"MyChrome.lnk"); 496 ASSERT_TRUE(base::Move(profile_2_shortcut_path_1, 497 profile_2_shortcut_path_2)); 498 499 // Ensure that a new shortcut does not get made if the old one was renamed. 500 profile_shortcut_manager_->CreateProfileShortcut(profile_2_path_); 501 RunPendingTasks(); 502 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_)); 503 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2, 504 profile_2_path_); 505 506 // Delete the renamed shortcut and try to create it again, which should work. 507 ASSERT_TRUE(base::DeleteFile(profile_2_shortcut_path_2, false)); 508 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path_2)); 509 profile_shortcut_manager_->CreateProfileShortcut(profile_2_path_); 510 RunPendingTasks(); 511 ValidateProfileShortcut(FROM_HERE, profile_2_name_, profile_2_path_); 512 } 513 514 TEST_F(ProfileShortcutManagerTest, RenamedDesktopShortcutsGetDeleted) { 515 SetupAndCreateTwoShortcuts(FROM_HERE); 516 517 const base::FilePath profile_2_shortcut_path_1 = 518 GetDefaultShortcutPathForProfile(profile_2_name_); 519 const base::FilePath profile_2_shortcut_path_2 = 520 GetUserShortcutsDirectory().Append(L"MyChrome.lnk"); 521 // Make a copy of the shortcut. 522 ASSERT_TRUE(base::CopyFile(profile_2_shortcut_path_1, 523 profile_2_shortcut_path_2)); 524 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_1, 525 profile_2_path_); 526 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2, 527 profile_2_path_); 528 529 // Also, copy the shortcut for the first user and ensure it gets preserved. 530 const base::FilePath preserved_profile_1_shortcut_path = 531 GetUserShortcutsDirectory().Append(L"Preserved.lnk"); 532 ASSERT_TRUE(base::CopyFile( 533 GetDefaultShortcutPathForProfile(profile_1_name_), 534 preserved_profile_1_shortcut_path)); 535 EXPECT_TRUE(base::PathExists(preserved_profile_1_shortcut_path)); 536 537 // Delete the profile and ensure both shortcuts were also deleted. 538 profile_info_cache_->DeleteProfileFromCache(profile_2_path_); 539 RunPendingTasks(); 540 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path_1)); 541 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path_2)); 542 ValidateNonProfileShortcutAtPath(FROM_HERE, 543 preserved_profile_1_shortcut_path); 544 } 545 546 TEST_F(ProfileShortcutManagerTest, RenamedDesktopShortcutsAfterProfileRename) { 547 SetupAndCreateTwoShortcuts(FROM_HERE); 548 549 const base::FilePath profile_2_shortcut_path_1 = 550 GetDefaultShortcutPathForProfile(profile_2_name_); 551 const base::FilePath profile_2_shortcut_path_2 = 552 GetUserShortcutsDirectory().Append(L"MyChrome.lnk"); 553 // Make a copy of the shortcut. 554 ASSERT_TRUE(base::CopyFile(profile_2_shortcut_path_1, 555 profile_2_shortcut_path_2)); 556 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_1, 557 profile_2_path_); 558 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2, 559 profile_2_path_); 560 561 // Now, rename the profile. 562 const string16 new_profile_2_name = L"New profile"; 563 RenameProfile(FROM_HERE, profile_2_path_, new_profile_2_name); 564 565 // The original shortcut should be renamed but the copied shortcut should 566 // keep its name. 567 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path_1)); 568 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2, 569 profile_2_path_); 570 ValidateProfileShortcut(FROM_HERE, new_profile_2_name, profile_2_path_); 571 } 572 573 TEST_F(ProfileShortcutManagerTest, UpdateShortcutWithNoFlags) { 574 SetupDefaultProfileShortcut(FROM_HERE); 575 576 // Delete the shortcut that got created for this profile and instead make 577 // a new one without any command-line flags. 578 ASSERT_TRUE(base::DeleteFile(GetDefaultShortcutPathForProfile(string16()), 579 false)); 580 const base::FilePath regular_shortcut_path = 581 CreateRegularShortcutWithName(FROM_HERE, 582 GetDistribution()->GetAppShortCutName()); 583 584 // Add another profile and check that the shortcut was replaced with 585 // a badged shortcut with the right command line for the profile 586 CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_); 587 EXPECT_FALSE(base::PathExists(regular_shortcut_path)); 588 ValidateProfileShortcut(FROM_HERE, profile_1_name_, profile_1_path_); 589 } 590 591 TEST_F(ProfileShortcutManagerTest, UpdateTwoShortcutsWithNoFlags) { 592 SetupDefaultProfileShortcut(FROM_HERE); 593 594 // Delete the shortcut that got created for this profile and instead make 595 // two new ones without any command-line flags. 596 ASSERT_TRUE(base::DeleteFile(GetDefaultShortcutPathForProfile(string16()), 597 false)); 598 const base::FilePath regular_shortcut_path = 599 CreateRegularShortcutWithName(FROM_HERE, 600 GetDistribution()->GetAppShortCutName()); 601 const base::FilePath customized_regular_shortcut_path = 602 CreateRegularShortcutWithName(FROM_HERE, L"MyChrome"); 603 604 // Add another profile and check that one shortcut was renamed and that the 605 // other shortcut was updated but kept the same name. 606 CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_); 607 EXPECT_FALSE(base::PathExists(regular_shortcut_path)); 608 ValidateProfileShortcutAtPath(FROM_HERE, customized_regular_shortcut_path, 609 profile_1_path_); 610 ValidateProfileShortcut(FROM_HERE, profile_1_name_, profile_1_path_); 611 } 612 613 TEST_F(ProfileShortcutManagerTest, RemoveProfileShortcuts) { 614 SetupAndCreateTwoShortcuts(FROM_HERE); 615 CreateProfileWithShortcut(FROM_HERE, profile_3_name_, profile_3_path_); 616 617 const base::FilePath profile_1_shortcut_path_1 = 618 GetDefaultShortcutPathForProfile(profile_1_name_); 619 const base::FilePath profile_2_shortcut_path_1 = 620 GetDefaultShortcutPathForProfile(profile_2_name_); 621 622 // Make copies of the shortcuts for both profiles. 623 const base::FilePath profile_1_shortcut_path_2 = 624 GetUserShortcutsDirectory().Append(L"Copied1.lnk"); 625 const base::FilePath profile_2_shortcut_path_2 = 626 GetUserShortcutsDirectory().Append(L"Copied2.lnk"); 627 ASSERT_TRUE(base::CopyFile(profile_1_shortcut_path_1, 628 profile_1_shortcut_path_2)); 629 ASSERT_TRUE(base::CopyFile(profile_2_shortcut_path_1, 630 profile_2_shortcut_path_2)); 631 ValidateProfileShortcutAtPath(FROM_HERE, profile_1_shortcut_path_2, 632 profile_1_path_); 633 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2, 634 profile_2_path_); 635 636 // Delete shortcuts for profile 1 and ensure that they got deleted while the 637 // shortcuts for profile 2 were kept. 638 profile_shortcut_manager_->RemoveProfileShortcuts(profile_1_path_); 639 RunPendingTasks(); 640 EXPECT_FALSE(base::PathExists(profile_1_shortcut_path_1)); 641 EXPECT_FALSE(base::PathExists(profile_1_shortcut_path_2)); 642 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_1, 643 profile_2_path_); 644 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2, 645 profile_2_path_); 646 } 647 648 TEST_F(ProfileShortcutManagerTest, HasProfileShortcuts) { 649 SetupAndCreateTwoShortcuts(FROM_HERE); 650 651 struct HasShortcutsResult { 652 bool has_shortcuts; 653 void set_has_shortcuts(bool value) { has_shortcuts = value; } 654 } result = { false }; 655 656 const base::Callback<void(bool)> callback = 657 base::Bind(&HasShortcutsResult::set_has_shortcuts, 658 base::Unretained(&result)); 659 660 // Profile 2 should have a shortcut initially. 661 profile_shortcut_manager_->HasProfileShortcuts(profile_2_path_, callback); 662 RunPendingTasks(); 663 EXPECT_TRUE(result.has_shortcuts); 664 665 // Delete the shortcut and check that the function returns false. 666 const base::FilePath profile_2_shortcut_path = 667 GetDefaultShortcutPathForProfile(profile_2_name_); 668 ASSERT_TRUE(base::DeleteFile(profile_2_shortcut_path, false)); 669 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path)); 670 profile_shortcut_manager_->HasProfileShortcuts(profile_2_path_, callback); 671 RunPendingTasks(); 672 EXPECT_FALSE(result.has_shortcuts); 673 } 674 675 TEST_F(ProfileShortcutManagerTest, ProfileShortcutsWithSystemLevelShortcut) { 676 const base::FilePath system_level_shortcut_path = 677 CreateRegularSystemLevelShortcut(FROM_HERE); 678 679 // Create the initial profile. 680 profile_info_cache_->AddProfileToCache(profile_1_path_, profile_1_name_, 681 string16(), 0, std::string()); 682 RunPendingTasks(); 683 ASSERT_EQ(1U, profile_info_cache_->GetNumberOfProfiles()); 684 685 // Ensure system-level continues to exist and user-level was not created. 686 EXPECT_TRUE(base::PathExists(system_level_shortcut_path)); 687 EXPECT_FALSE(base::PathExists( 688 GetDefaultShortcutPathForProfile(string16()))); 689 690 // Create another profile with a shortcut and ensure both profiles receive 691 // user-level profile shortcuts and the system-level one still exists. 692 CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_); 693 ValidateProfileShortcut(FROM_HERE, profile_1_name_, profile_1_path_); 694 ValidateProfileShortcut(FROM_HERE, profile_2_name_, profile_2_path_); 695 EXPECT_TRUE(base::PathExists(system_level_shortcut_path)); 696 697 // Create a third profile without a shortcut and ensure it doesn't get one. 698 profile_info_cache_->AddProfileToCache(profile_3_path_, profile_3_name_, 699 string16(), 0, std::string()); 700 RunPendingTasks(); 701 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_3_name_)); 702 703 // Ensure that changing the avatar icon and the name does not result in a 704 // shortcut being created. 705 profile_info_cache_->SetAvatarIconOfProfileAtIndex( 706 profile_info_cache_->GetIndexOfProfileWithPath(profile_3_path_), 3); 707 RunPendingTasks(); 708 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_3_name_)); 709 710 const string16 new_profile_3_name = L"New Name 3"; 711 profile_info_cache_->SetNameOfProfileAtIndex( 712 profile_info_cache_->GetIndexOfProfileWithPath(profile_3_path_), 713 new_profile_3_name); 714 RunPendingTasks(); 715 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_3_name_)); 716 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(new_profile_3_name)); 717 718 // Rename the second profile and ensure its shortcut got renamed. 719 const string16 new_profile_2_name = L"New Name 2"; 720 profile_info_cache_->SetNameOfProfileAtIndex( 721 profile_info_cache_->GetIndexOfProfileWithPath(profile_2_path_), 722 new_profile_2_name); 723 RunPendingTasks(); 724 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_)); 725 ValidateProfileShortcut(FROM_HERE, new_profile_2_name, profile_2_path_); 726 } 727 728 TEST_F(ProfileShortcutManagerTest, 729 DeleteSecondToLastProfileWithSystemLevelShortcut) { 730 SetupAndCreateTwoShortcuts(FROM_HERE); 731 732 const base::FilePath system_level_shortcut_path = 733 CreateRegularSystemLevelShortcut(FROM_HERE); 734 735 // Delete a profile and verify that only the system-level shortcut still 736 // exists. 737 profile_info_cache_->DeleteProfileFromCache(profile_1_path_); 738 RunPendingTasks(); 739 740 EXPECT_TRUE(base::PathExists(system_level_shortcut_path)); 741 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(string16())); 742 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_1_name_)); 743 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_)); 744 } 745 746 TEST_F(ProfileShortcutManagerTest, 747 DeleteSecondToLastProfileWithShortcutWhenSystemLevelShortcutExists) { 748 SetupAndCreateTwoShortcuts(FROM_HERE); 749 750 const base::FilePath profile_1_shortcut_path = 751 GetDefaultShortcutPathForProfile(profile_1_name_); 752 const base::FilePath profile_2_shortcut_path = 753 GetDefaultShortcutPathForProfile(profile_2_name_); 754 755 // Delete the shortcut for the first profile, but keep the one for the 2nd. 756 ASSERT_TRUE(base::DeleteFile(profile_1_shortcut_path, false)); 757 ASSERT_FALSE(base::PathExists(profile_1_shortcut_path)); 758 ASSERT_TRUE(base::PathExists(profile_2_shortcut_path)); 759 760 const base::FilePath system_level_shortcut_path = 761 CreateRegularSystemLevelShortcut(FROM_HERE); 762 763 // Delete the profile that has a shortcut, which will exercise the non-profile 764 // shortcut creation path in |DeleteDesktopShortcuts()|, which is 765 // not covered by the |DeleteSecondToLastProfileWithSystemLevelShortcut| test. 766 profile_info_cache_->DeleteProfileFromCache(profile_2_path_); 767 RunPendingTasks(); 768 769 // Verify that only the system-level shortcut still exists. 770 EXPECT_TRUE(base::PathExists(system_level_shortcut_path)); 771 EXPECT_FALSE(base::PathExists( 772 GetDefaultShortcutPathForProfile(string16()))); 773 EXPECT_FALSE(base::PathExists(profile_1_shortcut_path)); 774 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path)); 775 } 776 777 TEST_F(ProfileShortcutManagerTest, CreateProfileIcon) { 778 SetupDefaultProfileShortcut(FROM_HERE); 779 780 const base::FilePath icon_path = 781 profiles::internal::GetProfileIconPath(profile_1_path_); 782 783 EXPECT_TRUE(base::PathExists(icon_path)); 784 EXPECT_TRUE(base::DeleteFile(icon_path, false)); 785 EXPECT_FALSE(base::PathExists(icon_path)); 786 787 profile_shortcut_manager_->CreateOrUpdateProfileIcon(profile_1_path_, 788 base::Closure()); 789 RunPendingTasks(); 790 EXPECT_TRUE(base::PathExists(icon_path)); 791 } 792 793 TEST_F(ProfileShortcutManagerTest, UnbadgeProfileIconOnDeletion) { 794 SetupDefaultProfileShortcut(FROM_HERE); 795 const base::FilePath icon_path_1 = 796 profiles::internal::GetProfileIconPath(profile_1_path_); 797 const base::FilePath icon_path_2 = 798 profiles::internal::GetProfileIconPath(profile_2_path_); 799 800 // Default profile has unbadged icon to start. 801 std::string unbadged_icon_1; 802 EXPECT_TRUE(file_util::ReadFileToString(icon_path_1, &unbadged_icon_1)); 803 804 // Creating a new profile adds a badge to both the new profile icon and the 805 // default profile icon. Since they use the same icon index, the icon files 806 // should be the same. 807 CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_); 808 809 std::string badged_icon_1; 810 EXPECT_TRUE(file_util::ReadFileToString(icon_path_1, &badged_icon_1)); 811 std::string badged_icon_2; 812 EXPECT_TRUE(file_util::ReadFileToString(icon_path_2, &badged_icon_2)); 813 814 EXPECT_NE(badged_icon_1, unbadged_icon_1); 815 EXPECT_EQ(badged_icon_1, badged_icon_2); 816 817 // Deleting the default profile will unbadge the new profile's icon and should 818 // result in an icon that is identical to the unbadged default profile icon. 819 profile_info_cache_->DeleteProfileFromCache(profile_1_path_); 820 RunPendingTasks(); 821 822 std::string unbadged_icon_2; 823 EXPECT_TRUE(file_util::ReadFileToString(icon_path_2, &unbadged_icon_2)); 824 EXPECT_EQ(unbadged_icon_1, unbadged_icon_2); 825 } 826 827 TEST_F(ProfileShortcutManagerTest, ProfileIconOnAvatarChange) { 828 SetupAndCreateTwoShortcuts(FROM_HERE); 829 const base::FilePath icon_path_1 = 830 profiles::internal::GetProfileIconPath(profile_1_path_); 831 const base::FilePath icon_path_2 = 832 profiles::internal::GetProfileIconPath(profile_2_path_); 833 const size_t profile_index_1 = 834 profile_info_cache_->GetIndexOfProfileWithPath(profile_1_path_); 835 836 std::string badged_icon_1; 837 EXPECT_TRUE(file_util::ReadFileToString(icon_path_1, &badged_icon_1)); 838 std::string badged_icon_2; 839 EXPECT_TRUE(file_util::ReadFileToString(icon_path_2, &badged_icon_2)); 840 841 // Profile 1 and 2 are created with the same icon. 842 EXPECT_EQ(badged_icon_1, badged_icon_2); 843 844 // Change profile 1's icon. 845 profile_info_cache_->SetAvatarIconOfProfileAtIndex(profile_index_1, 1); 846 RunPendingTasks(); 847 848 std::string new_badged_icon_1; 849 EXPECT_TRUE(file_util::ReadFileToString(icon_path_1, &new_badged_icon_1)); 850 EXPECT_NE(new_badged_icon_1, badged_icon_1); 851 852 // Ensure the new icon is not the unbadged icon. 853 profile_info_cache_->DeleteProfileFromCache(profile_2_path_); 854 RunPendingTasks(); 855 856 std::string unbadged_icon_1; 857 EXPECT_TRUE(file_util::ReadFileToString(icon_path_1, &unbadged_icon_1)); 858 EXPECT_NE(unbadged_icon_1, new_badged_icon_1); 859 860 // Ensure the icon doesn't change on avatar change without 2 profiles. 861 profile_info_cache_->SetAvatarIconOfProfileAtIndex(profile_index_1, 1); 862 RunPendingTasks(); 863 864 std::string unbadged_icon_1_a; 865 EXPECT_TRUE(file_util::ReadFileToString(icon_path_1, &unbadged_icon_1_a)); 866 EXPECT_EQ(unbadged_icon_1, unbadged_icon_1_a); 867 } 868