Home | History | Annotate | Download | only in profiles
      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