- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / profiles / profile_shortcut_manager_unittest_win.cc
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->
227                 GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) +
228                 installer::kLnkExt);
229     EXPECT_TRUE(base::PathExists(system_level_shortcut_path))
230         << location.ToString();
231     return system_level_shortcut_path;
232   }
233
234   void RenameProfile(const tracked_objects::Location& location,
235                      const base::FilePath& profile_path,
236                      const string16& new_profile_name) {
237     const size_t profile_index =
238         profile_info_cache_->GetIndexOfProfileWithPath(profile_2_path_);
239     ASSERT_NE(std::string::npos, profile_index);
240     ASSERT_NE(profile_info_cache_->GetNameOfProfileAtIndex(profile_index),
241               new_profile_name);
242     profile_info_cache_->SetNameOfProfileAtIndex(profile_index,
243                                                  new_profile_name);
244     RunPendingTasks();
245   }
246
247   BrowserDistribution* GetDistribution() {
248     return BrowserDistribution::GetDistribution();
249   }
250
251   base::FilePath GetExePath() {
252     base::FilePath exe_path;
253     EXPECT_TRUE(PathService::Get(base::FILE_EXE, &exe_path));
254     return exe_path;
255   }
256
257   base::FilePath GetUserShortcutsDirectory() {
258     base::FilePath user_shortcuts_directory;
259     EXPECT_TRUE(ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP,
260                                            GetDistribution(),
261                                            ShellUtil::CURRENT_USER,
262                                            &user_shortcuts_directory));
263     return user_shortcuts_directory;
264   }
265
266   base::FilePath GetSystemShortcutsDirectory() {
267     base::FilePath system_shortcuts_directory;
268     EXPECT_TRUE(ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP,
269                                            GetDistribution(),
270                                            ShellUtil::SYSTEM_LEVEL,
271                                            &system_shortcuts_directory));
272     return system_shortcuts_directory;
273   }
274
275   base::MessageLoopForUI message_loop_;
276   content::TestBrowserThread ui_thread_;
277   content::TestBrowserThread file_thread_;
278   scoped_ptr<TestingProfileManager> profile_manager_;
279   scoped_ptr<ProfileShortcutManager> profile_shortcut_manager_;
280   ProfileInfoCache* profile_info_cache_;
281   base::ScopedPathOverride fake_user_desktop_;
282   base::ScopedPathOverride fake_system_desktop_;
283   string16 profile_1_name_;
284   base::FilePath profile_1_path_;
285   string16 profile_2_name_;
286   base::FilePath profile_2_path_;
287   string16 profile_3_name_;
288   base::FilePath profile_3_path_;
289 };
290
291 TEST_F(ProfileShortcutManagerTest, ShortcutFilename) {
292   const string16 kProfileName = L"Harry";
293   BrowserDistribution* distribution = GetDistribution();
294   const string16 expected_name = kProfileName + L" - " +
295       l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME) + installer::kLnkExt;
296   EXPECT_EQ(expected_name,
297             profiles::internal::GetShortcutFilenameForProfile(kProfileName,
298                                                               distribution));
299 }
300
301 TEST_F(ProfileShortcutManagerTest, ShortcutLongFilenameIsTrimmed) {
302   const string16 kLongProfileName = L"Harry Harry Harry Harry Harry Harry Harry"
303       L"Harry Harry Harry Harry Harry Harry Harry Harry Harry Harry Harry"
304       L"Harry Harry Harry Harry Harry Harry Harry Harry Harry Harry Harry";
305   const string16 file_name =
306       profiles::internal::GetShortcutFilenameForProfile(kLongProfileName,
307                                                         GetDistribution());
308   EXPECT_LT(file_name.size(), kLongProfileName.size());
309 }
310
311 TEST_F(ProfileShortcutManagerTest, ShortcutFilenameStripsReservedCharacters) {
312   const string16 kProfileName = L"<Harry/>";
313   const string16 kSanitizedProfileName = L"Harry";
314   BrowserDistribution* distribution = GetDistribution();
315   const string16 expected_name = kSanitizedProfileName + L" - " +
316       l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME) + installer::kLnkExt;
317   EXPECT_EQ(expected_name,
318             profiles::internal::GetShortcutFilenameForProfile(kProfileName,
319                                                               distribution));
320 }
321
322 TEST_F(ProfileShortcutManagerTest, UnbadgedShortcutFilename) {
323   BrowserDistribution* distribution = GetDistribution();
324   EXPECT_EQ(
325       distribution->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) +
326           installer::kLnkExt,
327       profiles::internal::GetShortcutFilenameForProfile(string16(),
328                                                         distribution));
329 }
330
331 TEST_F(ProfileShortcutManagerTest, ShortcutFlags) {
332   const string16 kProfileName = L"MyProfileX";
333   const base::FilePath profile_path =
334       profile_info_cache_->GetUserDataDir().Append(kProfileName);
335   EXPECT_EQ(L"--profile-directory=\"" + kProfileName + L"\"",
336             profiles::internal::CreateProfileShortcutFlags(profile_path));
337 }
338
339 TEST_F(ProfileShortcutManagerTest, DesktopShortcutsCreate) {
340   SetupDefaultProfileShortcut(FROM_HERE);
341   // Validation is done by |ValidateProfileShortcutAtPath()| which is called
342   // by |CreateProfileWithShortcut()|.
343   CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_);
344 }
345
346 TEST_F(ProfileShortcutManagerTest, DesktopShortcutsUpdate) {
347   SetupDefaultProfileShortcut(FROM_HERE);
348   CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_);
349
350   // Cause an update in ProfileShortcutManager by modifying the profile info
351   // cache.
352   const string16 new_profile_2_name = L"New Profile Name";
353   RenameProfile(FROM_HERE, profile_2_path_, new_profile_2_name);
354   EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_));
355   ValidateProfileShortcut(FROM_HERE, new_profile_2_name, profile_2_path_);
356 }
357
358 TEST_F(ProfileShortcutManagerTest, CreateSecondProfileBadgesFirstShortcut) {
359   SetupDefaultProfileShortcut(FROM_HERE);
360   // Assert that a shortcut without a profile name exists.
361   ASSERT_TRUE(ProfileShortcutExistsAtDefaultPath(string16()));
362
363   // Create a second profile without a shortcut.
364   profile_info_cache_->AddProfileToCache(profile_2_path_, profile_2_name_,
365                                          string16(), 0, std::string());
366   RunPendingTasks();
367
368   // Ensure that the second profile doesn't have a shortcut and that the first
369   // profile's shortcut got renamed and badged.
370   EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_));
371   EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(string16()));
372   ValidateProfileShortcut(FROM_HERE, profile_1_name_, profile_1_path_);
373 }
374
375 TEST_F(ProfileShortcutManagerTest, DesktopShortcutsDeleteSecondToLast) {
376   SetupAndCreateTwoShortcuts(FROM_HERE);
377
378   // Delete one shortcut.
379   profile_info_cache_->DeleteProfileFromCache(profile_2_path_);
380   RunPendingTasks();
381   EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_));
382
383   // Verify that the profile name has been removed from the remaining shortcut.
384   ValidateNonProfileShortcut(FROM_HERE);
385   // Verify that an additional shortcut, with the default profile's name does
386   // not exist.
387   EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_1_name_));
388 }
389
390 TEST_F(ProfileShortcutManagerTest, DeleteSecondToLastProfileWithoutShortcut) {
391   SetupAndCreateTwoShortcuts(FROM_HERE);
392
393   const base::FilePath profile_1_shortcut_path =
394       GetDefaultShortcutPathForProfile(profile_1_name_);
395   const base::FilePath profile_2_shortcut_path =
396       GetDefaultShortcutPathForProfile(profile_2_name_);
397
398   // Delete the shortcut for the first profile, but keep the one for the 2nd.
399   ASSERT_TRUE(base::DeleteFile(profile_1_shortcut_path, false));
400   ASSERT_FALSE(base::PathExists(profile_1_shortcut_path));
401   ASSERT_TRUE(base::PathExists(profile_2_shortcut_path));
402
403   // Delete the profile that doesn't have a shortcut.
404   profile_info_cache_->DeleteProfileFromCache(profile_1_path_);
405   RunPendingTasks();
406
407   // Verify that the remaining shortcut does not have a profile name.
408   ValidateNonProfileShortcut(FROM_HERE);
409   // Verify that shortcuts with profile names do not exist.
410   EXPECT_FALSE(base::PathExists(profile_1_shortcut_path));
411   EXPECT_FALSE(base::PathExists(profile_2_shortcut_path));
412 }
413
414 TEST_F(ProfileShortcutManagerTest, DeleteSecondToLastProfileWithShortcut) {
415   SetupAndCreateTwoShortcuts(FROM_HERE);
416
417   const base::FilePath profile_1_shortcut_path =
418       GetDefaultShortcutPathForProfile(profile_1_name_);
419   const base::FilePath profile_2_shortcut_path =
420       GetDefaultShortcutPathForProfile(profile_2_name_);
421
422   // Delete the shortcut for the first profile, but keep the one for the 2nd.
423   ASSERT_TRUE(base::DeleteFile(profile_1_shortcut_path, false));
424   ASSERT_FALSE(base::PathExists(profile_1_shortcut_path));
425   ASSERT_TRUE(base::PathExists(profile_2_shortcut_path));
426
427   // Delete the profile that has a shortcut.
428   profile_info_cache_->DeleteProfileFromCache(profile_2_path_);
429   RunPendingTasks();
430
431   // Verify that the remaining shortcut does not have a profile name.
432   ValidateNonProfileShortcut(FROM_HERE);
433   // Verify that shortcuts with profile names do not exist.
434   EXPECT_FALSE(base::PathExists(profile_1_shortcut_path));
435   EXPECT_FALSE(base::PathExists(profile_2_shortcut_path));
436 }
437
438 TEST_F(ProfileShortcutManagerTest, DeleteOnlyProfileWithShortcuts) {
439   SetupAndCreateTwoShortcuts(FROM_HERE);
440   CreateProfileWithShortcut(FROM_HERE, profile_3_name_, profile_3_path_);
441
442   const base::FilePath non_profile_shortcut_path =
443       GetDefaultShortcutPathForProfile(string16());
444   const base::FilePath profile_1_shortcut_path =
445       GetDefaultShortcutPathForProfile(profile_1_name_);
446   const base::FilePath profile_2_shortcut_path =
447       GetDefaultShortcutPathForProfile(profile_2_name_);
448   const base::FilePath profile_3_shortcut_path =
449       GetDefaultShortcutPathForProfile(profile_3_name_);
450
451   // Delete shortcuts for the first two profiles.
452   ASSERT_TRUE(base::DeleteFile(profile_1_shortcut_path, false));
453   ASSERT_TRUE(base::DeleteFile(profile_2_shortcut_path, false));
454
455   // Only the shortcut to the third profile should exist.
456   ASSERT_FALSE(base::PathExists(profile_1_shortcut_path));
457   ASSERT_FALSE(base::PathExists(profile_2_shortcut_path));
458   ASSERT_FALSE(base::PathExists(non_profile_shortcut_path));
459   ASSERT_TRUE(base::PathExists(profile_3_shortcut_path));
460
461   // Delete the third profile and check that its shortcut is gone and no
462   // shortcuts have been re-created.
463   profile_info_cache_->DeleteProfileFromCache(profile_3_path_);
464   RunPendingTasks();
465   ASSERT_FALSE(base::PathExists(profile_1_shortcut_path));
466   ASSERT_FALSE(base::PathExists(profile_2_shortcut_path));
467   ASSERT_FALSE(base::PathExists(profile_3_shortcut_path));
468   ASSERT_FALSE(base::PathExists(non_profile_shortcut_path));
469 }
470
471 TEST_F(ProfileShortcutManagerTest, DesktopShortcutsCreateSecond) {
472   SetupAndCreateTwoShortcuts(FROM_HERE);
473
474   // Delete one shortcut.
475   profile_info_cache_->DeleteProfileFromCache(profile_2_path_);
476   RunPendingTasks();
477
478   // Verify that a default shortcut exists (no profile name/avatar).
479   ValidateNonProfileShortcut(FROM_HERE);
480   // Verify that an additional shortcut, with the first profile's name does
481   // not exist.
482   EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_1_name_));
483
484   // Create a second profile and shortcut.
485   CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_);
486
487   // Verify that the original shortcut received the profile's name.
488   ValidateProfileShortcut(FROM_HERE, profile_1_name_, profile_1_path_);
489   // Verify that a default shortcut no longer exists.
490   EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(string16()));
491 }
492
493 TEST_F(ProfileShortcutManagerTest, RenamedDesktopShortcuts) {
494   SetupAndCreateTwoShortcuts(FROM_HERE);
495
496   const base::FilePath profile_2_shortcut_path_1 =
497       GetDefaultShortcutPathForProfile(profile_2_name_);
498   const base::FilePath profile_2_shortcut_path_2 =
499       GetUserShortcutsDirectory().Append(L"MyChrome.lnk");
500   ASSERT_TRUE(base::Move(profile_2_shortcut_path_1,
501                               profile_2_shortcut_path_2));
502
503   // Ensure that a new shortcut does not get made if the old one was renamed.
504   profile_shortcut_manager_->CreateProfileShortcut(profile_2_path_);
505   RunPendingTasks();
506   EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_));
507   ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
508                                 profile_2_path_);
509
510   // Delete the renamed shortcut and try to create it again, which should work.
511   ASSERT_TRUE(base::DeleteFile(profile_2_shortcut_path_2, false));
512   EXPECT_FALSE(base::PathExists(profile_2_shortcut_path_2));
513   profile_shortcut_manager_->CreateProfileShortcut(profile_2_path_);
514   RunPendingTasks();
515   ValidateProfileShortcut(FROM_HERE, profile_2_name_, profile_2_path_);
516 }
517
518 TEST_F(ProfileShortcutManagerTest, RenamedDesktopShortcutsGetDeleted) {
519   SetupAndCreateTwoShortcuts(FROM_HERE);
520
521   const base::FilePath profile_2_shortcut_path_1 =
522       GetDefaultShortcutPathForProfile(profile_2_name_);
523   const base::FilePath profile_2_shortcut_path_2 =
524       GetUserShortcutsDirectory().Append(L"MyChrome.lnk");
525   // Make a copy of the shortcut.
526   ASSERT_TRUE(base::CopyFile(profile_2_shortcut_path_1,
527                                   profile_2_shortcut_path_2));
528   ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_1,
529                                 profile_2_path_);
530   ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
531                                 profile_2_path_);
532
533   // Also, copy the shortcut for the first user and ensure it gets preserved.
534   const base::FilePath preserved_profile_1_shortcut_path =
535       GetUserShortcutsDirectory().Append(L"Preserved.lnk");
536   ASSERT_TRUE(base::CopyFile(
537       GetDefaultShortcutPathForProfile(profile_1_name_),
538       preserved_profile_1_shortcut_path));
539   EXPECT_TRUE(base::PathExists(preserved_profile_1_shortcut_path));
540
541   // Delete the profile and ensure both shortcuts were also deleted.
542   profile_info_cache_->DeleteProfileFromCache(profile_2_path_);
543   RunPendingTasks();
544   EXPECT_FALSE(base::PathExists(profile_2_shortcut_path_1));
545   EXPECT_FALSE(base::PathExists(profile_2_shortcut_path_2));
546   ValidateNonProfileShortcutAtPath(FROM_HERE,
547                                    preserved_profile_1_shortcut_path);
548 }
549
550 TEST_F(ProfileShortcutManagerTest, RenamedDesktopShortcutsAfterProfileRename) {
551   SetupAndCreateTwoShortcuts(FROM_HERE);
552
553   const base::FilePath profile_2_shortcut_path_1 =
554       GetDefaultShortcutPathForProfile(profile_2_name_);
555   const base::FilePath profile_2_shortcut_path_2 =
556       GetUserShortcutsDirectory().Append(L"MyChrome.lnk");
557   // Make a copy of the shortcut.
558   ASSERT_TRUE(base::CopyFile(profile_2_shortcut_path_1,
559                                   profile_2_shortcut_path_2));
560   ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_1,
561                                 profile_2_path_);
562   ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
563                                 profile_2_path_);
564
565   // Now, rename the profile.
566   const string16 new_profile_2_name = L"New profile";
567   RenameProfile(FROM_HERE, profile_2_path_, new_profile_2_name);
568
569   // The original shortcut should be renamed but the copied shortcut should
570   // keep its name.
571   EXPECT_FALSE(base::PathExists(profile_2_shortcut_path_1));
572   ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
573                                 profile_2_path_);
574   ValidateProfileShortcut(FROM_HERE, new_profile_2_name, profile_2_path_);
575 }
576
577 TEST_F(ProfileShortcutManagerTest, UpdateShortcutWithNoFlags) {
578   SetupDefaultProfileShortcut(FROM_HERE);
579
580   // Delete the shortcut that got created for this profile and instead make
581   // a new one without any command-line flags.
582   ASSERT_TRUE(base::DeleteFile(GetDefaultShortcutPathForProfile(string16()),
583                                 false));
584   const base::FilePath regular_shortcut_path =
585       CreateRegularShortcutWithName(FROM_HERE,
586                                     GetDistribution()->GetShortcutName(
587                                         BrowserDistribution::SHORTCUT_CHROME));
588
589   // Add another profile and check that the shortcut was replaced with
590   // a badged shortcut with the right command line for the profile
591   CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_);
592   EXPECT_FALSE(base::PathExists(regular_shortcut_path));
593   ValidateProfileShortcut(FROM_HERE, profile_1_name_, profile_1_path_);
594 }
595
596 TEST_F(ProfileShortcutManagerTest, UpdateTwoShortcutsWithNoFlags) {
597   SetupDefaultProfileShortcut(FROM_HERE);
598
599   // Delete the shortcut that got created for this profile and instead make
600   // two new ones without any command-line flags.
601   ASSERT_TRUE(base::DeleteFile(GetDefaultShortcutPathForProfile(string16()),
602                                 false));
603   const base::FilePath regular_shortcut_path =
604       CreateRegularShortcutWithName(FROM_HERE,
605                                     GetDistribution()->GetShortcutName(
606                                         BrowserDistribution::SHORTCUT_CHROME));
607   const base::FilePath customized_regular_shortcut_path =
608       CreateRegularShortcutWithName(FROM_HERE, L"MyChrome");
609
610   // Add another profile and check that one shortcut was renamed and that the
611   // other shortcut was updated but kept the same name.
612   CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_);
613   EXPECT_FALSE(base::PathExists(regular_shortcut_path));
614   ValidateProfileShortcutAtPath(FROM_HERE, customized_regular_shortcut_path,
615                                 profile_1_path_);
616   ValidateProfileShortcut(FROM_HERE, profile_1_name_, profile_1_path_);
617 }
618
619 TEST_F(ProfileShortcutManagerTest, RemoveProfileShortcuts) {
620   SetupAndCreateTwoShortcuts(FROM_HERE);
621   CreateProfileWithShortcut(FROM_HERE, profile_3_name_, profile_3_path_);
622
623   const base::FilePath profile_1_shortcut_path_1 =
624       GetDefaultShortcutPathForProfile(profile_1_name_);
625   const base::FilePath profile_2_shortcut_path_1 =
626       GetDefaultShortcutPathForProfile(profile_2_name_);
627
628   // Make copies of the shortcuts for both profiles.
629   const base::FilePath profile_1_shortcut_path_2 =
630       GetUserShortcutsDirectory().Append(L"Copied1.lnk");
631   const base::FilePath profile_2_shortcut_path_2 =
632       GetUserShortcutsDirectory().Append(L"Copied2.lnk");
633   ASSERT_TRUE(base::CopyFile(profile_1_shortcut_path_1,
634                                   profile_1_shortcut_path_2));
635   ASSERT_TRUE(base::CopyFile(profile_2_shortcut_path_1,
636                                   profile_2_shortcut_path_2));
637   ValidateProfileShortcutAtPath(FROM_HERE, profile_1_shortcut_path_2,
638                                 profile_1_path_);
639   ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
640                                 profile_2_path_);
641
642   // Delete shortcuts for profile 1 and ensure that they got deleted while the
643   // shortcuts for profile 2 were kept.
644   profile_shortcut_manager_->RemoveProfileShortcuts(profile_1_path_);
645   RunPendingTasks();
646   EXPECT_FALSE(base::PathExists(profile_1_shortcut_path_1));
647   EXPECT_FALSE(base::PathExists(profile_1_shortcut_path_2));
648   ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_1,
649                                 profile_2_path_);
650   ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
651                                 profile_2_path_);
652 }
653
654 TEST_F(ProfileShortcutManagerTest, HasProfileShortcuts) {
655   SetupAndCreateTwoShortcuts(FROM_HERE);
656
657   struct HasShortcutsResult {
658     bool has_shortcuts;
659     void set_has_shortcuts(bool value) { has_shortcuts = value; }
660   } result = { false };
661
662   const base::Callback<void(bool)> callback =
663       base::Bind(&HasShortcutsResult::set_has_shortcuts,
664                  base::Unretained(&result));
665
666   // Profile 2 should have a shortcut initially.
667   profile_shortcut_manager_->HasProfileShortcuts(profile_2_path_, callback);
668   RunPendingTasks();
669   EXPECT_TRUE(result.has_shortcuts);
670
671   // Delete the shortcut and check that the function returns false.
672   const base::FilePath profile_2_shortcut_path =
673       GetDefaultShortcutPathForProfile(profile_2_name_);
674   ASSERT_TRUE(base::DeleteFile(profile_2_shortcut_path, false));
675   EXPECT_FALSE(base::PathExists(profile_2_shortcut_path));
676   profile_shortcut_manager_->HasProfileShortcuts(profile_2_path_, callback);
677   RunPendingTasks();
678   EXPECT_FALSE(result.has_shortcuts);
679 }
680
681 TEST_F(ProfileShortcutManagerTest, ProfileShortcutsWithSystemLevelShortcut) {
682   const base::FilePath system_level_shortcut_path =
683       CreateRegularSystemLevelShortcut(FROM_HERE);
684
685   // Create the initial profile.
686   profile_info_cache_->AddProfileToCache(profile_1_path_, profile_1_name_,
687                                          string16(), 0, std::string());
688   RunPendingTasks();
689   ASSERT_EQ(1U, profile_info_cache_->GetNumberOfProfiles());
690
691   // Ensure system-level continues to exist and user-level was not created.
692   EXPECT_TRUE(base::PathExists(system_level_shortcut_path));
693   EXPECT_FALSE(base::PathExists(
694                    GetDefaultShortcutPathForProfile(string16())));
695
696   // Create another profile with a shortcut and ensure both profiles receive
697   // user-level profile shortcuts and the system-level one still exists.
698   CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_);
699   ValidateProfileShortcut(FROM_HERE, profile_1_name_, profile_1_path_);
700   ValidateProfileShortcut(FROM_HERE, profile_2_name_, profile_2_path_);
701   EXPECT_TRUE(base::PathExists(system_level_shortcut_path));
702
703   // Create a third profile without a shortcut and ensure it doesn't get one.
704   profile_info_cache_->AddProfileToCache(profile_3_path_, profile_3_name_,
705                                          string16(), 0, std::string());
706   RunPendingTasks();
707   EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_3_name_));
708
709   // Ensure that changing the avatar icon and the name does not result in a
710   // shortcut being created.
711   profile_info_cache_->SetAvatarIconOfProfileAtIndex(
712       profile_info_cache_->GetIndexOfProfileWithPath(profile_3_path_), 3);
713   RunPendingTasks();
714   EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_3_name_));
715
716   const string16 new_profile_3_name = L"New Name 3";
717   profile_info_cache_->SetNameOfProfileAtIndex(
718       profile_info_cache_->GetIndexOfProfileWithPath(profile_3_path_),
719       new_profile_3_name);
720   RunPendingTasks();
721   EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_3_name_));
722   EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(new_profile_3_name));
723
724   // Rename the second profile and ensure its shortcut got renamed.
725   const string16 new_profile_2_name = L"New Name 2";
726   profile_info_cache_->SetNameOfProfileAtIndex(
727       profile_info_cache_->GetIndexOfProfileWithPath(profile_2_path_),
728       new_profile_2_name);
729   RunPendingTasks();
730   EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_));
731   ValidateProfileShortcut(FROM_HERE, new_profile_2_name, profile_2_path_);
732 }
733
734 TEST_F(ProfileShortcutManagerTest,
735        DeleteSecondToLastProfileWithSystemLevelShortcut) {
736   SetupAndCreateTwoShortcuts(FROM_HERE);
737
738   const base::FilePath system_level_shortcut_path =
739       CreateRegularSystemLevelShortcut(FROM_HERE);
740
741   // Delete a profile and verify that only the system-level shortcut still
742   // exists.
743   profile_info_cache_->DeleteProfileFromCache(profile_1_path_);
744   RunPendingTasks();
745
746   EXPECT_TRUE(base::PathExists(system_level_shortcut_path));
747   EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(string16()));
748   EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_1_name_));
749   EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_));
750 }
751
752 TEST_F(ProfileShortcutManagerTest,
753        DeleteSecondToLastProfileWithShortcutWhenSystemLevelShortcutExists) {
754   SetupAndCreateTwoShortcuts(FROM_HERE);
755
756   const base::FilePath profile_1_shortcut_path =
757       GetDefaultShortcutPathForProfile(profile_1_name_);
758   const base::FilePath profile_2_shortcut_path =
759       GetDefaultShortcutPathForProfile(profile_2_name_);
760
761   // Delete the shortcut for the first profile, but keep the one for the 2nd.
762   ASSERT_TRUE(base::DeleteFile(profile_1_shortcut_path, false));
763   ASSERT_FALSE(base::PathExists(profile_1_shortcut_path));
764   ASSERT_TRUE(base::PathExists(profile_2_shortcut_path));
765
766   const base::FilePath system_level_shortcut_path =
767       CreateRegularSystemLevelShortcut(FROM_HERE);
768
769   // Delete the profile that has a shortcut, which will exercise the non-profile
770   // shortcut creation path in |DeleteDesktopShortcuts()|, which is
771   // not covered by the |DeleteSecondToLastProfileWithSystemLevelShortcut| test.
772   profile_info_cache_->DeleteProfileFromCache(profile_2_path_);
773   RunPendingTasks();
774
775   // Verify that only the system-level shortcut still exists.
776   EXPECT_TRUE(base::PathExists(system_level_shortcut_path));
777   EXPECT_FALSE(base::PathExists(
778                    GetDefaultShortcutPathForProfile(string16())));
779   EXPECT_FALSE(base::PathExists(profile_1_shortcut_path));
780   EXPECT_FALSE(base::PathExists(profile_2_shortcut_path));
781 }
782
783 TEST_F(ProfileShortcutManagerTest, CreateProfileIcon) {
784   SetupDefaultProfileShortcut(FROM_HERE);
785
786   const base::FilePath icon_path =
787       profiles::internal::GetProfileIconPath(profile_1_path_);
788
789   EXPECT_TRUE(base::PathExists(icon_path));
790   EXPECT_TRUE(base::DeleteFile(icon_path, false));
791   EXPECT_FALSE(base::PathExists(icon_path));
792
793   profile_shortcut_manager_->CreateOrUpdateProfileIcon(profile_1_path_);
794   RunPendingTasks();
795   EXPECT_TRUE(base::PathExists(icon_path));
796 }
797
798 TEST_F(ProfileShortcutManagerTest, UnbadgeProfileIconOnDeletion) {
799   SetupDefaultProfileShortcut(FROM_HERE);
800   const base::FilePath icon_path_1 =
801       profiles::internal::GetProfileIconPath(profile_1_path_);
802   const base::FilePath icon_path_2 =
803       profiles::internal::GetProfileIconPath(profile_2_path_);
804
805   // Default profile has unbadged icon to start.
806   std::string unbadged_icon_1;
807   EXPECT_TRUE(base::ReadFileToString(icon_path_1, &unbadged_icon_1));
808
809   // Creating a new profile adds a badge to both the new profile icon and the
810   // default profile icon. Since they use the same icon index, the icon files
811   // should be the same.
812   CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_);
813
814   std::string badged_icon_1;
815   EXPECT_TRUE(base::ReadFileToString(icon_path_1, &badged_icon_1));
816   std::string badged_icon_2;
817   EXPECT_TRUE(base::ReadFileToString(icon_path_2, &badged_icon_2));
818
819   EXPECT_NE(badged_icon_1, unbadged_icon_1);
820   EXPECT_EQ(badged_icon_1, badged_icon_2);
821
822   // Deleting the default profile will unbadge the new profile's icon and should
823   // result in an icon that is identical to the unbadged default profile icon.
824   profile_info_cache_->DeleteProfileFromCache(profile_1_path_);
825   RunPendingTasks();
826
827   std::string unbadged_icon_2;
828   EXPECT_TRUE(base::ReadFileToString(icon_path_2, &unbadged_icon_2));
829   EXPECT_EQ(unbadged_icon_1, unbadged_icon_2);
830 }
831
832 TEST_F(ProfileShortcutManagerTest, ProfileIconOnAvatarChange) {
833   SetupAndCreateTwoShortcuts(FROM_HERE);
834   const base::FilePath icon_path_1 =
835       profiles::internal::GetProfileIconPath(profile_1_path_);
836   const base::FilePath icon_path_2 =
837       profiles::internal::GetProfileIconPath(profile_2_path_);
838   const size_t profile_index_1 =
839       profile_info_cache_->GetIndexOfProfileWithPath(profile_1_path_);
840
841   std::string badged_icon_1;
842   EXPECT_TRUE(base::ReadFileToString(icon_path_1, &badged_icon_1));
843   std::string badged_icon_2;
844   EXPECT_TRUE(base::ReadFileToString(icon_path_2, &badged_icon_2));
845
846   // Profile 1 and 2 are created with the same icon.
847   EXPECT_EQ(badged_icon_1, badged_icon_2);
848
849   // Change profile 1's icon.
850   profile_info_cache_->SetAvatarIconOfProfileAtIndex(profile_index_1, 1);
851   RunPendingTasks();
852
853   std::string new_badged_icon_1;
854   EXPECT_TRUE(base::ReadFileToString(icon_path_1, &new_badged_icon_1));
855   EXPECT_NE(new_badged_icon_1, badged_icon_1);
856
857   // Ensure the new icon is not the unbadged icon.
858   profile_info_cache_->DeleteProfileFromCache(profile_2_path_);
859   RunPendingTasks();
860
861   std::string unbadged_icon_1;
862   EXPECT_TRUE(base::ReadFileToString(icon_path_1, &unbadged_icon_1));
863   EXPECT_NE(unbadged_icon_1, new_badged_icon_1);
864
865   // Ensure the icon doesn't change on avatar change without 2 profiles.
866   profile_info_cache_->SetAvatarIconOfProfileAtIndex(profile_index_1, 1);
867   RunPendingTasks();
868
869   std::string unbadged_icon_1_a;
870   EXPECT_TRUE(base::ReadFileToString(icon_path_1, &unbadged_icon_1_a));
871   EXPECT_EQ(unbadged_icon_1, unbadged_icon_1_a);
872 }