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.
5 #include <objbase.h> // For CoInitialize().
7 #include "base/base_paths.h"
8 #include "base/files/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/grit/chromium_strings.h"
22 #include "chrome/installer/util/browser_distribution.h"
23 #include "chrome/installer/util/product.h"
24 #include "chrome/installer/util/shell_util.h"
25 #include "chrome/test/base/testing_browser_process.h"
26 #include "chrome/test/base/testing_profile.h"
27 #include "chrome/test/base/testing_profile_manager.h"
28 #include "content/public/test/test_browser_thread.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "ui/base/l10n/l10n_util.h"
32 using content::BrowserThread
;
34 class ProfileShortcutManagerTest
: public testing::Test
{
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
) {
44 void SetUp() override
{
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_
);
62 void TearDown() override
{
63 message_loop_
.RunUntilIdle();
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 base::string16 profile_name
=
71 profile_info_cache_
->GetNameOfProfileAtIndex(0);
72 profile_info_cache_
->DeleteProfileFromCache(profile_path
);
74 ASSERT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_name
));
75 // The icon file is not deleted until the profile directory is deleted.
76 const base::FilePath icon_path
=
77 profiles::internal::GetProfileIconPath(profile_path
);
78 ASSERT_TRUE(base::PathExists(icon_path
));
82 base::FilePath
CreateProfileDirectory(const base::string16
& profile_name
) {
83 const base::FilePath profile_path
=
84 profile_info_cache_
->GetUserDataDir().Append(profile_name
);
85 base::CreateDirectory(profile_path
);
89 void RunPendingTasks() {
90 base::MessageLoop::current()->PostTask(FROM_HERE
,
91 base::MessageLoop::QuitClosure());
92 base::MessageLoop::current()->Run();
95 void SetupDefaultProfileShortcut(const tracked_objects::Location
& location
) {
96 ASSERT_EQ(0, profile_info_cache_
->GetNumberOfProfiles())
97 << location
.ToString();
98 ASSERT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_1_name_
))
99 << location
.ToString();
100 profile_info_cache_
->AddProfileToCache(profile_1_path_
, profile_1_name_
,
101 std::string(), base::string16(), 0,
103 // Also create a non-badged shortcut for Chrome, which is conveniently done
104 // by |CreateProfileShortcut()| since there is only one profile.
105 profile_shortcut_manager_
->CreateProfileShortcut(profile_1_path_
);
107 // Verify that there's now a shortcut with no profile information.
108 ValidateNonProfileShortcut(location
);
111 void SetupAndCreateTwoShortcuts(const tracked_objects::Location
& location
) {
112 SetupDefaultProfileShortcut(location
);
113 CreateProfileWithShortcut(location
, profile_2_name_
, profile_2_path_
);
114 ValidateProfileShortcut(location
, profile_1_name_
, profile_1_path_
);
117 // Returns the default shortcut path for this profile.
118 base::FilePath
GetDefaultShortcutPathForProfile(
119 const base::string16
& profile_name
) {
120 return GetUserShortcutsDirectory().Append(
121 profiles::internal::GetShortcutFilenameForProfile(profile_name
,
125 // Returns true if the shortcut for this profile exists.
126 bool ProfileShortcutExistsAtDefaultPath(const base::string16
& profile_name
) {
127 return base::PathExists(
128 GetDefaultShortcutPathForProfile(profile_name
));
131 // Calls base::win::ValidateShortcut() with expected properties for the
132 // shortcut at |shortcut_path| for the profile at |profile_path|.
133 void ValidateProfileShortcutAtPath(const tracked_objects::Location
& location
,
134 const base::FilePath
& shortcut_path
,
135 const base::FilePath
& profile_path
) {
136 EXPECT_TRUE(base::PathExists(shortcut_path
)) << location
.ToString();
138 // Ensure that the corresponding icon exists.
139 const base::FilePath icon_path
=
140 profiles::internal::GetProfileIconPath(profile_path
);
141 EXPECT_TRUE(base::PathExists(icon_path
)) << location
.ToString();
143 base::win::ShortcutProperties expected_properties
;
144 expected_properties
.set_app_id(
145 ShellIntegration::GetChromiumModelIdForProfile(profile_path
));
146 expected_properties
.set_target(GetExePath());
147 expected_properties
.set_description(GetDistribution()->GetAppDescription());
148 expected_properties
.set_dual_mode(false);
149 expected_properties
.set_arguments(
150 profiles::internal::CreateProfileShortcutFlags(profile_path
));
151 expected_properties
.set_icon(icon_path
, 0);
152 base::win::ValidateShortcut(shortcut_path
, expected_properties
);
155 // Calls base::win::ValidateShortcut() with expected properties for
156 // |profile_name|'s shortcut.
157 void ValidateProfileShortcut(const tracked_objects::Location
& location
,
158 const base::string16
& profile_name
,
159 const base::FilePath
& profile_path
) {
160 ValidateProfileShortcutAtPath(
161 location
, GetDefaultShortcutPathForProfile(profile_name
), profile_path
);
164 void ValidateNonProfileShortcutAtPath(
165 const tracked_objects::Location
& location
,
166 const base::FilePath
& shortcut_path
) {
167 EXPECT_TRUE(base::PathExists(shortcut_path
)) << location
.ToString();
169 base::win::ShortcutProperties expected_properties
;
170 expected_properties
.set_target(GetExePath());
171 expected_properties
.set_arguments(base::string16());
172 expected_properties
.set_icon(GetExePath(), 0);
173 expected_properties
.set_description(GetDistribution()->GetAppDescription());
174 expected_properties
.set_dual_mode(false);
175 base::win::ValidateShortcut(shortcut_path
, expected_properties
);
178 void ValidateNonProfileShortcut(const tracked_objects::Location
& location
) {
179 const base::FilePath shortcut_path
=
180 GetDefaultShortcutPathForProfile(base::string16());
181 ValidateNonProfileShortcutAtPath(location
, shortcut_path
);
184 void CreateProfileWithShortcut(const tracked_objects::Location
& location
,
185 const base::string16
& profile_name
,
186 const base::FilePath
& profile_path
) {
187 ASSERT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_name
))
188 << location
.ToString();
189 profile_info_cache_
->AddProfileToCache(profile_path
, profile_name
,
190 std::string(), base::string16(), 0,
192 profile_shortcut_manager_
->CreateProfileShortcut(profile_path
);
194 ValidateProfileShortcut(location
, profile_name
, profile_path
);
197 // Creates a regular (non-profile) desktop shortcut with the given name and
198 // returns its path. Fails the test if an error occurs.
199 base::FilePath
CreateRegularShortcutWithName(
200 const tracked_objects::Location
& location
,
201 const base::string16
& shortcut_name
) {
202 const base::FilePath shortcut_path
=
203 GetUserShortcutsDirectory().Append(shortcut_name
+ installer::kLnkExt
);
204 EXPECT_FALSE(base::PathExists(shortcut_path
)) << location
.ToString();
206 installer::Product
product(GetDistribution());
207 ShellUtil::ShortcutProperties
properties(ShellUtil::CURRENT_USER
);
208 product
.AddDefaultShortcutProperties(GetExePath(), &properties
);
209 properties
.set_shortcut_name(shortcut_name
);
210 EXPECT_TRUE(ShellUtil::CreateOrUpdateShortcut(
211 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, GetDistribution(), properties
,
212 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
)) << location
.ToString();
213 EXPECT_TRUE(base::PathExists(shortcut_path
)) << location
.ToString();
215 return shortcut_path
;
218 base::FilePath
CreateRegularSystemLevelShortcut(
219 const tracked_objects::Location
& location
) {
220 BrowserDistribution
* distribution
= GetDistribution();
221 installer::Product
product(distribution
);
222 ShellUtil::ShortcutProperties
properties(ShellUtil::SYSTEM_LEVEL
);
223 product
.AddDefaultShortcutProperties(GetExePath(), &properties
);
224 EXPECT_TRUE(ShellUtil::CreateOrUpdateShortcut(
225 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, distribution
, properties
,
226 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
)) << location
.ToString();
227 const base::FilePath system_level_shortcut_path
=
228 GetSystemShortcutsDirectory().Append(
230 GetShortcutName(BrowserDistribution::SHORTCUT_CHROME
) +
232 EXPECT_TRUE(base::PathExists(system_level_shortcut_path
))
233 << location
.ToString();
234 return system_level_shortcut_path
;
237 void RenameProfile(const tracked_objects::Location
& location
,
238 const base::FilePath
& profile_path
,
239 const base::string16
& new_profile_name
) {
240 const size_t profile_index
=
241 profile_info_cache_
->GetIndexOfProfileWithPath(profile_2_path_
);
242 ASSERT_NE(std::string::npos
, profile_index
);
243 ASSERT_NE(profile_info_cache_
->GetNameOfProfileAtIndex(profile_index
),
245 profile_info_cache_
->SetNameOfProfileAtIndex(profile_index
,
250 BrowserDistribution
* GetDistribution() {
251 return BrowserDistribution::GetDistribution();
254 base::FilePath
GetExePath() {
255 base::FilePath exe_path
;
256 EXPECT_TRUE(PathService::Get(base::FILE_EXE
, &exe_path
));
260 base::FilePath
GetUserShortcutsDirectory() {
261 base::FilePath user_shortcuts_directory
;
262 EXPECT_TRUE(ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP
,
264 ShellUtil::CURRENT_USER
,
265 &user_shortcuts_directory
));
266 return user_shortcuts_directory
;
269 base::FilePath
GetSystemShortcutsDirectory() {
270 base::FilePath system_shortcuts_directory
;
271 EXPECT_TRUE(ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP
,
273 ShellUtil::SYSTEM_LEVEL
,
274 &system_shortcuts_directory
));
275 return system_shortcuts_directory
;
278 base::MessageLoopForUI message_loop_
;
279 content::TestBrowserThread ui_thread_
;
280 content::TestBrowserThread file_thread_
;
281 scoped_ptr
<TestingProfileManager
> profile_manager_
;
282 scoped_ptr
<ProfileShortcutManager
> profile_shortcut_manager_
;
283 ProfileInfoCache
* profile_info_cache_
;
284 base::ScopedPathOverride fake_user_desktop_
;
285 base::ScopedPathOverride fake_system_desktop_
;
286 base::string16 profile_1_name_
;
287 base::FilePath profile_1_path_
;
288 base::string16 profile_2_name_
;
289 base::FilePath profile_2_path_
;
290 base::string16 profile_3_name_
;
291 base::FilePath profile_3_path_
;
294 TEST_F(ProfileShortcutManagerTest
, ShortcutFilename
) {
295 const base::string16 kProfileName
= L
"Harry";
296 BrowserDistribution
* distribution
= GetDistribution();
297 const base::string16 expected_name
= kProfileName
+ L
" - " +
298 l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME
) + installer::kLnkExt
;
299 EXPECT_EQ(expected_name
,
300 profiles::internal::GetShortcutFilenameForProfile(kProfileName
,
304 TEST_F(ProfileShortcutManagerTest
, ShortcutLongFilenameIsTrimmed
) {
305 const base::string16 kLongProfileName
=
306 L
"Harry Harry Harry Harry Harry Harry Harry"
307 L
"Harry Harry Harry Harry Harry Harry Harry Harry Harry Harry Harry"
308 L
"Harry Harry Harry Harry Harry Harry Harry Harry Harry Harry Harry";
309 const base::string16 file_name
=
310 profiles::internal::GetShortcutFilenameForProfile(kLongProfileName
,
312 EXPECT_LT(file_name
.size(), kLongProfileName
.size());
315 TEST_F(ProfileShortcutManagerTest
, ShortcutFilenameStripsReservedCharacters
) {
316 const base::string16 kProfileName
= L
"<Harry/>";
317 const base::string16 kSanitizedProfileName
= L
"Harry";
318 BrowserDistribution
* distribution
= GetDistribution();
319 const base::string16 expected_name
= kSanitizedProfileName
+ L
" - " +
320 l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME
) + installer::kLnkExt
;
321 EXPECT_EQ(expected_name
,
322 profiles::internal::GetShortcutFilenameForProfile(kProfileName
,
326 TEST_F(ProfileShortcutManagerTest
, UnbadgedShortcutFilename
) {
327 BrowserDistribution
* distribution
= GetDistribution();
329 distribution
->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME
) +
331 profiles::internal::GetShortcutFilenameForProfile(base::string16(),
335 TEST_F(ProfileShortcutManagerTest
, ShortcutFlags
) {
336 const base::string16 kProfileName
= L
"MyProfileX";
337 const base::FilePath profile_path
=
338 profile_info_cache_
->GetUserDataDir().Append(kProfileName
);
339 EXPECT_EQ(L
"--profile-directory=\"" + kProfileName
+ L
"\"",
340 profiles::internal::CreateProfileShortcutFlags(profile_path
));
343 TEST_F(ProfileShortcutManagerTest
, DesktopShortcutsCreate
) {
344 SetupDefaultProfileShortcut(FROM_HERE
);
345 // Validation is done by |ValidateProfileShortcutAtPath()| which is called
346 // by |CreateProfileWithShortcut()|.
347 CreateProfileWithShortcut(FROM_HERE
, profile_2_name_
, profile_2_path_
);
350 TEST_F(ProfileShortcutManagerTest
, DesktopShortcutsUpdate
) {
351 SetupDefaultProfileShortcut(FROM_HERE
);
352 CreateProfileWithShortcut(FROM_HERE
, profile_2_name_
, profile_2_path_
);
354 // Cause an update in ProfileShortcutManager by modifying the profile info
356 const base::string16 new_profile_2_name
= L
"New Profile Name";
357 RenameProfile(FROM_HERE
, profile_2_path_
, new_profile_2_name
);
358 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_
));
359 ValidateProfileShortcut(FROM_HERE
, new_profile_2_name
, profile_2_path_
);
362 TEST_F(ProfileShortcutManagerTest
, CreateSecondProfileBadgesFirstShortcut
) {
363 SetupDefaultProfileShortcut(FROM_HERE
);
364 // Assert that a shortcut without a profile name exists.
365 ASSERT_TRUE(ProfileShortcutExistsAtDefaultPath(base::string16()));
367 // Create a second profile without a shortcut.
368 profile_info_cache_
->AddProfileToCache(profile_2_path_
, profile_2_name_
,
369 std::string(), base::string16(), 0,
373 // Ensure that the second profile doesn't have a shortcut and that the first
374 // profile's shortcut got renamed and badged.
375 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_
));
376 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(base::string16()));
377 ValidateProfileShortcut(FROM_HERE
, profile_1_name_
, profile_1_path_
);
380 TEST_F(ProfileShortcutManagerTest
, DesktopShortcutsDeleteSecondToLast
) {
381 SetupAndCreateTwoShortcuts(FROM_HERE
);
383 // Delete one shortcut.
384 profile_info_cache_
->DeleteProfileFromCache(profile_2_path_
);
386 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_
));
388 // Verify that the profile name has been removed from the remaining shortcut.
389 ValidateNonProfileShortcut(FROM_HERE
);
390 // Verify that an additional shortcut, with the default profile's name does
392 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_1_name_
));
395 TEST_F(ProfileShortcutManagerTest
, DeleteSecondToLastProfileWithoutShortcut
) {
396 SetupAndCreateTwoShortcuts(FROM_HERE
);
398 const base::FilePath profile_1_shortcut_path
=
399 GetDefaultShortcutPathForProfile(profile_1_name_
);
400 const base::FilePath profile_2_shortcut_path
=
401 GetDefaultShortcutPathForProfile(profile_2_name_
);
403 // Delete the shortcut for the first profile, but keep the one for the 2nd.
404 ASSERT_TRUE(base::DeleteFile(profile_1_shortcut_path
, false));
405 ASSERT_FALSE(base::PathExists(profile_1_shortcut_path
));
406 ASSERT_TRUE(base::PathExists(profile_2_shortcut_path
));
408 // Delete the profile that doesn't have a shortcut.
409 profile_info_cache_
->DeleteProfileFromCache(profile_1_path_
);
412 // Verify that the remaining shortcut does not have a profile name.
413 ValidateNonProfileShortcut(FROM_HERE
);
414 // Verify that shortcuts with profile names do not exist.
415 EXPECT_FALSE(base::PathExists(profile_1_shortcut_path
));
416 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path
));
419 TEST_F(ProfileShortcutManagerTest
, DeleteSecondToLastProfileWithShortcut
) {
420 SetupAndCreateTwoShortcuts(FROM_HERE
);
422 const base::FilePath profile_1_shortcut_path
=
423 GetDefaultShortcutPathForProfile(profile_1_name_
);
424 const base::FilePath profile_2_shortcut_path
=
425 GetDefaultShortcutPathForProfile(profile_2_name_
);
427 // Delete the shortcut for the first profile, but keep the one for the 2nd.
428 ASSERT_TRUE(base::DeleteFile(profile_1_shortcut_path
, false));
429 ASSERT_FALSE(base::PathExists(profile_1_shortcut_path
));
430 ASSERT_TRUE(base::PathExists(profile_2_shortcut_path
));
432 // Delete the profile that has a shortcut.
433 profile_info_cache_
->DeleteProfileFromCache(profile_2_path_
);
436 // Verify that the remaining shortcut does not have a profile name.
437 ValidateNonProfileShortcut(FROM_HERE
);
438 // Verify that shortcuts with profile names do not exist.
439 EXPECT_FALSE(base::PathExists(profile_1_shortcut_path
));
440 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path
));
443 TEST_F(ProfileShortcutManagerTest
, DeleteOnlyProfileWithShortcuts
) {
444 SetupAndCreateTwoShortcuts(FROM_HERE
);
445 CreateProfileWithShortcut(FROM_HERE
, profile_3_name_
, profile_3_path_
);
447 const base::FilePath non_profile_shortcut_path
=
448 GetDefaultShortcutPathForProfile(base::string16());
449 const base::FilePath profile_1_shortcut_path
=
450 GetDefaultShortcutPathForProfile(profile_1_name_
);
451 const base::FilePath profile_2_shortcut_path
=
452 GetDefaultShortcutPathForProfile(profile_2_name_
);
453 const base::FilePath profile_3_shortcut_path
=
454 GetDefaultShortcutPathForProfile(profile_3_name_
);
456 // Delete shortcuts for the first two profiles.
457 ASSERT_TRUE(base::DeleteFile(profile_1_shortcut_path
, false));
458 ASSERT_TRUE(base::DeleteFile(profile_2_shortcut_path
, false));
460 // Only the shortcut to the third profile should exist.
461 ASSERT_FALSE(base::PathExists(profile_1_shortcut_path
));
462 ASSERT_FALSE(base::PathExists(profile_2_shortcut_path
));
463 ASSERT_FALSE(base::PathExists(non_profile_shortcut_path
));
464 ASSERT_TRUE(base::PathExists(profile_3_shortcut_path
));
466 // Delete the third profile and check that its shortcut is gone and no
467 // shortcuts have been re-created.
468 profile_info_cache_
->DeleteProfileFromCache(profile_3_path_
);
470 ASSERT_FALSE(base::PathExists(profile_1_shortcut_path
));
471 ASSERT_FALSE(base::PathExists(profile_2_shortcut_path
));
472 ASSERT_FALSE(base::PathExists(profile_3_shortcut_path
));
473 ASSERT_FALSE(base::PathExists(non_profile_shortcut_path
));
476 TEST_F(ProfileShortcutManagerTest
, DesktopShortcutsCreateSecond
) {
477 SetupAndCreateTwoShortcuts(FROM_HERE
);
479 // Delete one shortcut.
480 profile_info_cache_
->DeleteProfileFromCache(profile_2_path_
);
483 // Verify that a default shortcut exists (no profile name/avatar).
484 ValidateNonProfileShortcut(FROM_HERE
);
485 // Verify that an additional shortcut, with the first profile's name does
487 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_1_name_
));
489 // Create a second profile and shortcut.
490 CreateProfileWithShortcut(FROM_HERE
, profile_2_name_
, profile_2_path_
);
492 // Verify that the original shortcut received the profile's name.
493 ValidateProfileShortcut(FROM_HERE
, profile_1_name_
, profile_1_path_
);
494 // Verify that a default shortcut no longer exists.
495 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(base::string16()));
498 TEST_F(ProfileShortcutManagerTest
, RenamedDesktopShortcuts
) {
499 SetupAndCreateTwoShortcuts(FROM_HERE
);
501 const base::FilePath profile_2_shortcut_path_1
=
502 GetDefaultShortcutPathForProfile(profile_2_name_
);
503 const base::FilePath profile_2_shortcut_path_2
=
504 GetUserShortcutsDirectory().Append(L
"MyChrome.lnk");
505 ASSERT_TRUE(base::Move(profile_2_shortcut_path_1
,
506 profile_2_shortcut_path_2
));
508 // Ensure that a new shortcut does not get made if the old one was renamed.
509 profile_shortcut_manager_
->CreateProfileShortcut(profile_2_path_
);
511 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_
));
512 ValidateProfileShortcutAtPath(FROM_HERE
, profile_2_shortcut_path_2
,
515 // Delete the renamed shortcut and try to create it again, which should work.
516 ASSERT_TRUE(base::DeleteFile(profile_2_shortcut_path_2
, false));
517 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path_2
));
518 profile_shortcut_manager_
->CreateProfileShortcut(profile_2_path_
);
520 ValidateProfileShortcut(FROM_HERE
, profile_2_name_
, profile_2_path_
);
523 TEST_F(ProfileShortcutManagerTest
, RenamedDesktopShortcutsGetDeleted
) {
524 SetupAndCreateTwoShortcuts(FROM_HERE
);
526 const base::FilePath profile_2_shortcut_path_1
=
527 GetDefaultShortcutPathForProfile(profile_2_name_
);
528 const base::FilePath profile_2_shortcut_path_2
=
529 GetUserShortcutsDirectory().Append(L
"MyChrome.lnk");
530 // Make a copy of the shortcut.
531 ASSERT_TRUE(base::CopyFile(profile_2_shortcut_path_1
,
532 profile_2_shortcut_path_2
));
533 ValidateProfileShortcutAtPath(FROM_HERE
, profile_2_shortcut_path_1
,
535 ValidateProfileShortcutAtPath(FROM_HERE
, profile_2_shortcut_path_2
,
538 // Also, copy the shortcut for the first user and ensure it gets preserved.
539 const base::FilePath preserved_profile_1_shortcut_path
=
540 GetUserShortcutsDirectory().Append(L
"Preserved.lnk");
541 ASSERT_TRUE(base::CopyFile(
542 GetDefaultShortcutPathForProfile(profile_1_name_
),
543 preserved_profile_1_shortcut_path
));
544 EXPECT_TRUE(base::PathExists(preserved_profile_1_shortcut_path
));
546 // Delete the profile and ensure both shortcuts were also deleted.
547 profile_info_cache_
->DeleteProfileFromCache(profile_2_path_
);
549 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path_1
));
550 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path_2
));
551 ValidateNonProfileShortcutAtPath(FROM_HERE
,
552 preserved_profile_1_shortcut_path
);
555 TEST_F(ProfileShortcutManagerTest
, RenamedDesktopShortcutsAfterProfileRename
) {
556 SetupAndCreateTwoShortcuts(FROM_HERE
);
558 const base::FilePath profile_2_shortcut_path_1
=
559 GetDefaultShortcutPathForProfile(profile_2_name_
);
560 const base::FilePath profile_2_shortcut_path_2
=
561 GetUserShortcutsDirectory().Append(L
"MyChrome.lnk");
562 // Make a copy of the shortcut.
563 ASSERT_TRUE(base::CopyFile(profile_2_shortcut_path_1
,
564 profile_2_shortcut_path_2
));
565 ValidateProfileShortcutAtPath(FROM_HERE
, profile_2_shortcut_path_1
,
567 ValidateProfileShortcutAtPath(FROM_HERE
, profile_2_shortcut_path_2
,
570 // Now, rename the profile.
571 const base::string16 new_profile_2_name
= L
"New profile";
572 RenameProfile(FROM_HERE
, profile_2_path_
, new_profile_2_name
);
574 // The original shortcut should be renamed but the copied shortcut should
576 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path_1
));
577 ValidateProfileShortcutAtPath(FROM_HERE
, profile_2_shortcut_path_2
,
579 ValidateProfileShortcut(FROM_HERE
, new_profile_2_name
, profile_2_path_
);
582 TEST_F(ProfileShortcutManagerTest
, UpdateShortcutWithNoFlags
) {
583 SetupDefaultProfileShortcut(FROM_HERE
);
585 // Delete the shortcut that got created for this profile and instead make
586 // a new one without any command-line flags.
587 ASSERT_TRUE(base::DeleteFile(
588 GetDefaultShortcutPathForProfile(base::string16()), false));
589 const base::FilePath regular_shortcut_path
=
590 CreateRegularShortcutWithName(FROM_HERE
,
591 GetDistribution()->GetShortcutName(
592 BrowserDistribution::SHORTCUT_CHROME
));
594 // Add another profile and check that the shortcut was replaced with
595 // a badged shortcut with the right command line for the profile
596 CreateProfileWithShortcut(FROM_HERE
, profile_2_name_
, profile_2_path_
);
597 EXPECT_FALSE(base::PathExists(regular_shortcut_path
));
598 ValidateProfileShortcut(FROM_HERE
, profile_1_name_
, profile_1_path_
);
601 TEST_F(ProfileShortcutManagerTest
, UpdateTwoShortcutsWithNoFlags
) {
602 SetupDefaultProfileShortcut(FROM_HERE
);
604 // Delete the shortcut that got created for this profile and instead make
605 // two new ones without any command-line flags.
606 ASSERT_TRUE(base::DeleteFile(
607 GetDefaultShortcutPathForProfile(base::string16()), false));
608 const base::FilePath regular_shortcut_path
=
609 CreateRegularShortcutWithName(FROM_HERE
,
610 GetDistribution()->GetShortcutName(
611 BrowserDistribution::SHORTCUT_CHROME
));
612 const base::FilePath customized_regular_shortcut_path
=
613 CreateRegularShortcutWithName(FROM_HERE
, L
"MyChrome");
615 // Add another profile and check that one shortcut was renamed and that the
616 // other shortcut was updated but kept the same name.
617 CreateProfileWithShortcut(FROM_HERE
, profile_2_name_
, profile_2_path_
);
618 EXPECT_FALSE(base::PathExists(regular_shortcut_path
));
619 ValidateProfileShortcutAtPath(FROM_HERE
, customized_regular_shortcut_path
,
621 ValidateProfileShortcut(FROM_HERE
, profile_1_name_
, profile_1_path_
);
624 TEST_F(ProfileShortcutManagerTest
, RemoveProfileShortcuts
) {
625 SetupAndCreateTwoShortcuts(FROM_HERE
);
626 CreateProfileWithShortcut(FROM_HERE
, profile_3_name_
, profile_3_path_
);
628 const base::FilePath profile_1_shortcut_path_1
=
629 GetDefaultShortcutPathForProfile(profile_1_name_
);
630 const base::FilePath profile_2_shortcut_path_1
=
631 GetDefaultShortcutPathForProfile(profile_2_name_
);
633 // Make copies of the shortcuts for both profiles.
634 const base::FilePath profile_1_shortcut_path_2
=
635 GetUserShortcutsDirectory().Append(L
"Copied1.lnk");
636 const base::FilePath profile_2_shortcut_path_2
=
637 GetUserShortcutsDirectory().Append(L
"Copied2.lnk");
638 ASSERT_TRUE(base::CopyFile(profile_1_shortcut_path_1
,
639 profile_1_shortcut_path_2
));
640 ASSERT_TRUE(base::CopyFile(profile_2_shortcut_path_1
,
641 profile_2_shortcut_path_2
));
642 ValidateProfileShortcutAtPath(FROM_HERE
, profile_1_shortcut_path_2
,
644 ValidateProfileShortcutAtPath(FROM_HERE
, profile_2_shortcut_path_2
,
647 // Delete shortcuts for profile 1 and ensure that they got deleted while the
648 // shortcuts for profile 2 were kept.
649 profile_shortcut_manager_
->RemoveProfileShortcuts(profile_1_path_
);
651 EXPECT_FALSE(base::PathExists(profile_1_shortcut_path_1
));
652 EXPECT_FALSE(base::PathExists(profile_1_shortcut_path_2
));
653 ValidateProfileShortcutAtPath(FROM_HERE
, profile_2_shortcut_path_1
,
655 ValidateProfileShortcutAtPath(FROM_HERE
, profile_2_shortcut_path_2
,
659 TEST_F(ProfileShortcutManagerTest
, HasProfileShortcuts
) {
660 SetupAndCreateTwoShortcuts(FROM_HERE
);
662 struct HasShortcutsResult
{
664 void set_has_shortcuts(bool value
) { has_shortcuts
= value
; }
665 } result
= { false };
667 const base::Callback
<void(bool)> callback
=
668 base::Bind(&HasShortcutsResult::set_has_shortcuts
,
669 base::Unretained(&result
));
671 // Profile 2 should have a shortcut initially.
672 profile_shortcut_manager_
->HasProfileShortcuts(profile_2_path_
, callback
);
674 EXPECT_TRUE(result
.has_shortcuts
);
676 // Delete the shortcut and check that the function returns false.
677 const base::FilePath profile_2_shortcut_path
=
678 GetDefaultShortcutPathForProfile(profile_2_name_
);
679 ASSERT_TRUE(base::DeleteFile(profile_2_shortcut_path
, false));
680 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path
));
681 profile_shortcut_manager_
->HasProfileShortcuts(profile_2_path_
, callback
);
683 EXPECT_FALSE(result
.has_shortcuts
);
686 TEST_F(ProfileShortcutManagerTest
, ProfileShortcutsWithSystemLevelShortcut
) {
687 const base::FilePath system_level_shortcut_path
=
688 CreateRegularSystemLevelShortcut(FROM_HERE
);
690 // Create the initial profile.
691 profile_info_cache_
->AddProfileToCache(profile_1_path_
, profile_1_name_
,
692 std::string(), base::string16(), 0,
695 ASSERT_EQ(1U, profile_info_cache_
->GetNumberOfProfiles());
697 // Ensure system-level continues to exist and user-level was not created.
698 EXPECT_TRUE(base::PathExists(system_level_shortcut_path
));
699 EXPECT_FALSE(base::PathExists(
700 GetDefaultShortcutPathForProfile(base::string16())));
702 // Create another profile with a shortcut and ensure both profiles receive
703 // user-level profile shortcuts and the system-level one still exists.
704 CreateProfileWithShortcut(FROM_HERE
, profile_2_name_
, profile_2_path_
);
705 ValidateProfileShortcut(FROM_HERE
, profile_1_name_
, profile_1_path_
);
706 ValidateProfileShortcut(FROM_HERE
, profile_2_name_
, profile_2_path_
);
707 EXPECT_TRUE(base::PathExists(system_level_shortcut_path
));
709 // Create a third profile without a shortcut and ensure it doesn't get one.
710 profile_info_cache_
->AddProfileToCache(profile_3_path_
, profile_3_name_
,
711 std::string(), base::string16(), 0,
714 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_3_name_
));
716 // Ensure that changing the avatar icon and the name does not result in a
717 // shortcut being created.
718 profile_info_cache_
->SetAvatarIconOfProfileAtIndex(
719 profile_info_cache_
->GetIndexOfProfileWithPath(profile_3_path_
), 3);
721 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_3_name_
));
723 const base::string16 new_profile_3_name
= L
"New Name 3";
724 profile_info_cache_
->SetNameOfProfileAtIndex(
725 profile_info_cache_
->GetIndexOfProfileWithPath(profile_3_path_
),
728 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_3_name_
));
729 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(new_profile_3_name
));
731 // Rename the second profile and ensure its shortcut got renamed.
732 const base::string16 new_profile_2_name
= L
"New Name 2";
733 profile_info_cache_
->SetNameOfProfileAtIndex(
734 profile_info_cache_
->GetIndexOfProfileWithPath(profile_2_path_
),
737 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_
));
738 ValidateProfileShortcut(FROM_HERE
, new_profile_2_name
, profile_2_path_
);
741 TEST_F(ProfileShortcutManagerTest
,
742 DeleteSecondToLastProfileWithSystemLevelShortcut
) {
743 SetupAndCreateTwoShortcuts(FROM_HERE
);
745 const base::FilePath system_level_shortcut_path
=
746 CreateRegularSystemLevelShortcut(FROM_HERE
);
748 // Delete a profile and verify that only the system-level shortcut still
750 profile_info_cache_
->DeleteProfileFromCache(profile_1_path_
);
753 EXPECT_TRUE(base::PathExists(system_level_shortcut_path
));
754 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(base::string16()));
755 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_1_name_
));
756 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_
));
759 TEST_F(ProfileShortcutManagerTest
,
760 DeleteSecondToLastProfileWithShortcutWhenSystemLevelShortcutExists
) {
761 SetupAndCreateTwoShortcuts(FROM_HERE
);
763 const base::FilePath profile_1_shortcut_path
=
764 GetDefaultShortcutPathForProfile(profile_1_name_
);
765 const base::FilePath profile_2_shortcut_path
=
766 GetDefaultShortcutPathForProfile(profile_2_name_
);
768 // Delete the shortcut for the first profile, but keep the one for the 2nd.
769 ASSERT_TRUE(base::DeleteFile(profile_1_shortcut_path
, false));
770 ASSERT_FALSE(base::PathExists(profile_1_shortcut_path
));
771 ASSERT_TRUE(base::PathExists(profile_2_shortcut_path
));
773 const base::FilePath system_level_shortcut_path
=
774 CreateRegularSystemLevelShortcut(FROM_HERE
);
776 // Delete the profile that has a shortcut, which will exercise the non-profile
777 // shortcut creation path in |DeleteDesktopShortcuts()|, which is
778 // not covered by the |DeleteSecondToLastProfileWithSystemLevelShortcut| test.
779 profile_info_cache_
->DeleteProfileFromCache(profile_2_path_
);
782 // Verify that only the system-level shortcut still exists.
783 EXPECT_TRUE(base::PathExists(system_level_shortcut_path
));
784 EXPECT_FALSE(base::PathExists(
785 GetDefaultShortcutPathForProfile(base::string16())));
786 EXPECT_FALSE(base::PathExists(profile_1_shortcut_path
));
787 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path
));
790 TEST_F(ProfileShortcutManagerTest
, CreateProfileIcon
) {
791 SetupDefaultProfileShortcut(FROM_HERE
);
793 const base::FilePath icon_path
=
794 profiles::internal::GetProfileIconPath(profile_1_path_
);
796 EXPECT_TRUE(base::PathExists(icon_path
));
797 EXPECT_TRUE(base::DeleteFile(icon_path
, false));
798 EXPECT_FALSE(base::PathExists(icon_path
));
800 profile_shortcut_manager_
->CreateOrUpdateProfileIcon(profile_1_path_
);
802 EXPECT_TRUE(base::PathExists(icon_path
));
805 TEST_F(ProfileShortcutManagerTest
, UnbadgeProfileIconOnDeletion
) {
806 SetupDefaultProfileShortcut(FROM_HERE
);
807 const base::FilePath icon_path_1
=
808 profiles::internal::GetProfileIconPath(profile_1_path_
);
809 const base::FilePath icon_path_2
=
810 profiles::internal::GetProfileIconPath(profile_2_path_
);
812 // Default profile has unbadged icon to start.
813 std::string unbadged_icon_1
;
814 EXPECT_TRUE(base::ReadFileToString(icon_path_1
, &unbadged_icon_1
));
816 // Creating a new profile adds a badge to both the new profile icon and the
817 // default profile icon. Since they use the same icon index, the icon files
818 // should be the same.
819 CreateProfileWithShortcut(FROM_HERE
, profile_2_name_
, profile_2_path_
);
821 std::string badged_icon_1
;
822 EXPECT_TRUE(base::ReadFileToString(icon_path_1
, &badged_icon_1
));
823 std::string badged_icon_2
;
824 EXPECT_TRUE(base::ReadFileToString(icon_path_2
, &badged_icon_2
));
826 EXPECT_NE(badged_icon_1
, unbadged_icon_1
);
827 EXPECT_EQ(badged_icon_1
, badged_icon_2
);
829 // Deleting the default profile will unbadge the new profile's icon and should
830 // result in an icon that is identical to the unbadged default profile icon.
831 profile_info_cache_
->DeleteProfileFromCache(profile_1_path_
);
834 std::string unbadged_icon_2
;
835 EXPECT_TRUE(base::ReadFileToString(icon_path_2
, &unbadged_icon_2
));
836 EXPECT_EQ(unbadged_icon_1
, unbadged_icon_2
);
839 TEST_F(ProfileShortcutManagerTest
, ProfileIconOnAvatarChange
) {
840 SetupAndCreateTwoShortcuts(FROM_HERE
);
841 const base::FilePath icon_path_1
=
842 profiles::internal::GetProfileIconPath(profile_1_path_
);
843 const base::FilePath icon_path_2
=
844 profiles::internal::GetProfileIconPath(profile_2_path_
);
845 const size_t profile_index_1
=
846 profile_info_cache_
->GetIndexOfProfileWithPath(profile_1_path_
);
848 std::string badged_icon_1
;
849 EXPECT_TRUE(base::ReadFileToString(icon_path_1
, &badged_icon_1
));
850 std::string badged_icon_2
;
851 EXPECT_TRUE(base::ReadFileToString(icon_path_2
, &badged_icon_2
));
853 // Profile 1 and 2 are created with the same icon.
854 EXPECT_EQ(badged_icon_1
, badged_icon_2
);
856 // Change profile 1's icon.
857 profile_info_cache_
->SetAvatarIconOfProfileAtIndex(profile_index_1
, 1);
860 std::string new_badged_icon_1
;
861 EXPECT_TRUE(base::ReadFileToString(icon_path_1
, &new_badged_icon_1
));
862 EXPECT_NE(new_badged_icon_1
, badged_icon_1
);
864 // Ensure the new icon is not the unbadged icon.
865 profile_info_cache_
->DeleteProfileFromCache(profile_2_path_
);
868 std::string unbadged_icon_1
;
869 EXPECT_TRUE(base::ReadFileToString(icon_path_1
, &unbadged_icon_1
));
870 EXPECT_NE(unbadged_icon_1
, new_badged_icon_1
);
872 // Ensure the icon doesn't change on avatar change without 2 profiles.
873 profile_info_cache_
->SetAvatarIconOfProfileAtIndex(profile_index_1
, 1);
876 std::string unbadged_icon_1_a
;
877 EXPECT_TRUE(base::ReadFileToString(icon_path_1
, &unbadged_icon_1_a
));
878 EXPECT_EQ(unbadged_icon_1
, unbadged_icon_1_a
);