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/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"
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 virtual 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 virtual 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 string16 profile_name = profile_info_cache_->GetNameOfProfileAtIndex(0);
71 profile_info_cache_->DeleteProfileFromCache(profile_path);
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));
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);
88 void RunPendingTasks() {
89 base::MessageLoop::current()->PostTask(FROM_HERE,
90 base::MessageLoop::QuitClosure());
91 base::MessageLoop::current()->Run();
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_);
105 // Verify that there's now a shortcut with no profile information.
106 ValidateNonProfileShortcut(location);
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_);
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,
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));
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();
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();
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);
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);
162 void ValidateNonProfileShortcutAtPath(
163 const tracked_objects::Location& location,
164 const base::FilePath& shortcut_path) {
165 EXPECT_TRUE(base::PathExists(shortcut_path)) << location.ToString();
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);
176 void ValidateNonProfileShortcut(const tracked_objects::Location& location) {
177 const base::FilePath shortcut_path =
178 GetDefaultShortcutPathForProfile(string16());
179 ValidateNonProfileShortcutAtPath(location, shortcut_path);
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);
191 ValidateProfileShortcut(location, profile_name, profile_path);
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();
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();
212 return shortcut_path;
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(
227 GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) +
229 EXPECT_TRUE(base::PathExists(system_level_shortcut_path))
230 << location.ToString();
231 return system_level_shortcut_path;
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),
242 profile_info_cache_->SetNameOfProfileAtIndex(profile_index,
247 BrowserDistribution* GetDistribution() {
248 return BrowserDistribution::GetDistribution();
251 base::FilePath GetExePath() {
252 base::FilePath exe_path;
253 EXPECT_TRUE(PathService::Get(base::FILE_EXE, &exe_path));
257 base::FilePath GetUserShortcutsDirectory() {
258 base::FilePath user_shortcuts_directory;
259 EXPECT_TRUE(ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP,
261 ShellUtil::CURRENT_USER,
262 &user_shortcuts_directory));
263 return user_shortcuts_directory;
266 base::FilePath GetSystemShortcutsDirectory() {
267 base::FilePath system_shortcuts_directory;
268 EXPECT_TRUE(ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP,
270 ShellUtil::SYSTEM_LEVEL,
271 &system_shortcuts_directory));
272 return system_shortcuts_directory;
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_;
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,
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,
308 EXPECT_LT(file_name.size(), kLongProfileName.size());
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,
322 TEST_F(ProfileShortcutManagerTest, UnbadgedShortcutFilename) {
323 BrowserDistribution* distribution = GetDistribution();
325 distribution->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) +
327 profiles::internal::GetShortcutFilenameForProfile(string16(),
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));
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_);
346 TEST_F(ProfileShortcutManagerTest, DesktopShortcutsUpdate) {
347 SetupDefaultProfileShortcut(FROM_HERE);
348 CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_);
350 // Cause an update in ProfileShortcutManager by modifying the profile info
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_);
358 TEST_F(ProfileShortcutManagerTest, CreateSecondProfileBadgesFirstShortcut) {
359 SetupDefaultProfileShortcut(FROM_HERE);
360 // Assert that a shortcut without a profile name exists.
361 ASSERT_TRUE(ProfileShortcutExistsAtDefaultPath(string16()));
363 // Create a second profile without a shortcut.
364 profile_info_cache_->AddProfileToCache(profile_2_path_, profile_2_name_,
365 string16(), 0, std::string());
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_);
375 TEST_F(ProfileShortcutManagerTest, DesktopShortcutsDeleteSecondToLast) {
376 SetupAndCreateTwoShortcuts(FROM_HERE);
378 // Delete one shortcut.
379 profile_info_cache_->DeleteProfileFromCache(profile_2_path_);
381 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_));
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
387 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_1_name_));
390 TEST_F(ProfileShortcutManagerTest, DeleteSecondToLastProfileWithoutShortcut) {
391 SetupAndCreateTwoShortcuts(FROM_HERE);
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_);
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));
403 // Delete the profile that doesn't have a shortcut.
404 profile_info_cache_->DeleteProfileFromCache(profile_1_path_);
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));
414 TEST_F(ProfileShortcutManagerTest, DeleteSecondToLastProfileWithShortcut) {
415 SetupAndCreateTwoShortcuts(FROM_HERE);
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_);
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));
427 // Delete the profile that has a shortcut.
428 profile_info_cache_->DeleteProfileFromCache(profile_2_path_);
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));
438 TEST_F(ProfileShortcutManagerTest, DeleteOnlyProfileWithShortcuts) {
439 SetupAndCreateTwoShortcuts(FROM_HERE);
440 CreateProfileWithShortcut(FROM_HERE, profile_3_name_, profile_3_path_);
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_);
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));
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));
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_);
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));
471 TEST_F(ProfileShortcutManagerTest, DesktopShortcutsCreateSecond) {
472 SetupAndCreateTwoShortcuts(FROM_HERE);
474 // Delete one shortcut.
475 profile_info_cache_->DeleteProfileFromCache(profile_2_path_);
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
482 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_1_name_));
484 // Create a second profile and shortcut.
485 CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_);
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()));
493 TEST_F(ProfileShortcutManagerTest, RenamedDesktopShortcuts) {
494 SetupAndCreateTwoShortcuts(FROM_HERE);
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));
503 // Ensure that a new shortcut does not get made if the old one was renamed.
504 profile_shortcut_manager_->CreateProfileShortcut(profile_2_path_);
506 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_));
507 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
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_);
515 ValidateProfileShortcut(FROM_HERE, profile_2_name_, profile_2_path_);
518 TEST_F(ProfileShortcutManagerTest, RenamedDesktopShortcutsGetDeleted) {
519 SetupAndCreateTwoShortcuts(FROM_HERE);
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,
530 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
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));
541 // Delete the profile and ensure both shortcuts were also deleted.
542 profile_info_cache_->DeleteProfileFromCache(profile_2_path_);
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);
550 TEST_F(ProfileShortcutManagerTest, RenamedDesktopShortcutsAfterProfileRename) {
551 SetupAndCreateTwoShortcuts(FROM_HERE);
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,
562 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
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);
569 // The original shortcut should be renamed but the copied shortcut should
571 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path_1));
572 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
574 ValidateProfileShortcut(FROM_HERE, new_profile_2_name, profile_2_path_);
577 TEST_F(ProfileShortcutManagerTest, UpdateShortcutWithNoFlags) {
578 SetupDefaultProfileShortcut(FROM_HERE);
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()),
584 const base::FilePath regular_shortcut_path =
585 CreateRegularShortcutWithName(FROM_HERE,
586 GetDistribution()->GetShortcutName(
587 BrowserDistribution::SHORTCUT_CHROME));
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_);
596 TEST_F(ProfileShortcutManagerTest, UpdateTwoShortcutsWithNoFlags) {
597 SetupDefaultProfileShortcut(FROM_HERE);
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()),
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");
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,
616 ValidateProfileShortcut(FROM_HERE, profile_1_name_, profile_1_path_);
619 TEST_F(ProfileShortcutManagerTest, RemoveProfileShortcuts) {
620 SetupAndCreateTwoShortcuts(FROM_HERE);
621 CreateProfileWithShortcut(FROM_HERE, profile_3_name_, profile_3_path_);
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_);
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,
639 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
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_);
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,
650 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
654 TEST_F(ProfileShortcutManagerTest, HasProfileShortcuts) {
655 SetupAndCreateTwoShortcuts(FROM_HERE);
657 struct HasShortcutsResult {
659 void set_has_shortcuts(bool value) { has_shortcuts = value; }
660 } result = { false };
662 const base::Callback<void(bool)> callback =
663 base::Bind(&HasShortcutsResult::set_has_shortcuts,
664 base::Unretained(&result));
666 // Profile 2 should have a shortcut initially.
667 profile_shortcut_manager_->HasProfileShortcuts(profile_2_path_, callback);
669 EXPECT_TRUE(result.has_shortcuts);
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);
678 EXPECT_FALSE(result.has_shortcuts);
681 TEST_F(ProfileShortcutManagerTest, ProfileShortcutsWithSystemLevelShortcut) {
682 const base::FilePath system_level_shortcut_path =
683 CreateRegularSystemLevelShortcut(FROM_HERE);
685 // Create the initial profile.
686 profile_info_cache_->AddProfileToCache(profile_1_path_, profile_1_name_,
687 string16(), 0, std::string());
689 ASSERT_EQ(1U, profile_info_cache_->GetNumberOfProfiles());
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())));
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));
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());
707 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_3_name_));
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);
714 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_3_name_));
716 const string16 new_profile_3_name = L"New Name 3";
717 profile_info_cache_->SetNameOfProfileAtIndex(
718 profile_info_cache_->GetIndexOfProfileWithPath(profile_3_path_),
721 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_3_name_));
722 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(new_profile_3_name));
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_),
730 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_));
731 ValidateProfileShortcut(FROM_HERE, new_profile_2_name, profile_2_path_);
734 TEST_F(ProfileShortcutManagerTest,
735 DeleteSecondToLastProfileWithSystemLevelShortcut) {
736 SetupAndCreateTwoShortcuts(FROM_HERE);
738 const base::FilePath system_level_shortcut_path =
739 CreateRegularSystemLevelShortcut(FROM_HERE);
741 // Delete a profile and verify that only the system-level shortcut still
743 profile_info_cache_->DeleteProfileFromCache(profile_1_path_);
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_));
752 TEST_F(ProfileShortcutManagerTest,
753 DeleteSecondToLastProfileWithShortcutWhenSystemLevelShortcutExists) {
754 SetupAndCreateTwoShortcuts(FROM_HERE);
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_);
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));
766 const base::FilePath system_level_shortcut_path =
767 CreateRegularSystemLevelShortcut(FROM_HERE);
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_);
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));
783 TEST_F(ProfileShortcutManagerTest, CreateProfileIcon) {
784 SetupDefaultProfileShortcut(FROM_HERE);
786 const base::FilePath icon_path =
787 profiles::internal::GetProfileIconPath(profile_1_path_);
789 EXPECT_TRUE(base::PathExists(icon_path));
790 EXPECT_TRUE(base::DeleteFile(icon_path, false));
791 EXPECT_FALSE(base::PathExists(icon_path));
793 profile_shortcut_manager_->CreateOrUpdateProfileIcon(profile_1_path_);
795 EXPECT_TRUE(base::PathExists(icon_path));
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_);
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));
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_);
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));
819 EXPECT_NE(badged_icon_1, unbadged_icon_1);
820 EXPECT_EQ(badged_icon_1, badged_icon_2);
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_);
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);
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_);
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));
846 // Profile 1 and 2 are created with the same icon.
847 EXPECT_EQ(badged_icon_1, badged_icon_2);
849 // Change profile 1's icon.
850 profile_info_cache_->SetAvatarIconOfProfileAtIndex(profile_index_1, 1);
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);
857 // Ensure the new icon is not the unbadged icon.
858 profile_info_cache_->DeleteProfileFromCache(profile_2_path_);
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);
865 // Ensure the icon doesn't change on avatar change without 2 profiles.
866 profile_info_cache_->SetAvatarIconOfProfileAtIndex(profile_index_1, 1);
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);