Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / profiles / profile_shortcut_manager_unittest_win.cc
blobe8e1275b1a7fb063a8811350f0b5c75e1671fad3
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 {
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) {
44 virtual void SetUp() OVERRIDE {
45 CoInitialize(NULL);
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 base::string16 profile_name =
71 profile_info_cache_->GetNameOfProfileAtIndex(0);
72 profile_info_cache_->DeleteProfileFromCache(profile_path);
73 RunPendingTasks();
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);
86 return 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 base::string16(), 0, std::string());
102 // Also create a non-badged shortcut for Chrome, which is conveniently done
103 // by |CreateProfileShortcut()| since there is only one profile.
104 profile_shortcut_manager_->CreateProfileShortcut(profile_1_path_);
105 RunPendingTasks();
106 // Verify that there's now a shortcut with no profile information.
107 ValidateNonProfileShortcut(location);
110 void SetupAndCreateTwoShortcuts(const tracked_objects::Location& location) {
111 SetupDefaultProfileShortcut(location);
112 CreateProfileWithShortcut(location, profile_2_name_, profile_2_path_);
113 ValidateProfileShortcut(location, profile_1_name_, profile_1_path_);
116 // Returns the default shortcut path for this profile.
117 base::FilePath GetDefaultShortcutPathForProfile(
118 const base::string16& profile_name) {
119 return GetUserShortcutsDirectory().Append(
120 profiles::internal::GetShortcutFilenameForProfile(profile_name,
121 GetDistribution()));
124 // Returns true if the shortcut for this profile exists.
125 bool ProfileShortcutExistsAtDefaultPath(const base::string16& profile_name) {
126 return base::PathExists(
127 GetDefaultShortcutPathForProfile(profile_name));
130 // Calls base::win::ValidateShortcut() with expected properties for the
131 // shortcut at |shortcut_path| for the profile at |profile_path|.
132 void ValidateProfileShortcutAtPath(const tracked_objects::Location& location,
133 const base::FilePath& shortcut_path,
134 const base::FilePath& profile_path) {
135 EXPECT_TRUE(base::PathExists(shortcut_path)) << location.ToString();
137 // Ensure that the corresponding icon exists.
138 const base::FilePath icon_path =
139 profiles::internal::GetProfileIconPath(profile_path);
140 EXPECT_TRUE(base::PathExists(icon_path)) << location.ToString();
142 base::win::ShortcutProperties expected_properties;
143 expected_properties.set_app_id(
144 ShellIntegration::GetChromiumModelIdForProfile(profile_path));
145 expected_properties.set_target(GetExePath());
146 expected_properties.set_description(GetDistribution()->GetAppDescription());
147 expected_properties.set_dual_mode(false);
148 expected_properties.set_arguments(
149 profiles::internal::CreateProfileShortcutFlags(profile_path));
150 expected_properties.set_icon(icon_path, 0);
151 base::win::ValidateShortcut(shortcut_path, expected_properties);
154 // Calls base::win::ValidateShortcut() with expected properties for
155 // |profile_name|'s shortcut.
156 void ValidateProfileShortcut(const tracked_objects::Location& location,
157 const base::string16& profile_name,
158 const base::FilePath& profile_path) {
159 ValidateProfileShortcutAtPath(
160 location, GetDefaultShortcutPathForProfile(profile_name), profile_path);
163 void ValidateNonProfileShortcutAtPath(
164 const tracked_objects::Location& location,
165 const base::FilePath& shortcut_path) {
166 EXPECT_TRUE(base::PathExists(shortcut_path)) << location.ToString();
168 base::win::ShortcutProperties expected_properties;
169 expected_properties.set_target(GetExePath());
170 expected_properties.set_arguments(base::string16());
171 expected_properties.set_icon(GetExePath(), 0);
172 expected_properties.set_description(GetDistribution()->GetAppDescription());
173 expected_properties.set_dual_mode(false);
174 base::win::ValidateShortcut(shortcut_path, expected_properties);
177 void ValidateNonProfileShortcut(const tracked_objects::Location& location) {
178 const base::FilePath shortcut_path =
179 GetDefaultShortcutPathForProfile(base::string16());
180 ValidateNonProfileShortcutAtPath(location, shortcut_path);
183 void CreateProfileWithShortcut(const tracked_objects::Location& location,
184 const base::string16& profile_name,
185 const base::FilePath& profile_path) {
186 ASSERT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_name))
187 << location.ToString();
188 profile_info_cache_->AddProfileToCache(profile_path, profile_name,
189 base::string16(), 0, std::string());
190 profile_shortcut_manager_->CreateProfileShortcut(profile_path);
191 RunPendingTasks();
192 ValidateProfileShortcut(location, profile_name, profile_path);
195 // Creates a regular (non-profile) desktop shortcut with the given name and
196 // returns its path. Fails the test if an error occurs.
197 base::FilePath CreateRegularShortcutWithName(
198 const tracked_objects::Location& location,
199 const base::string16& shortcut_name) {
200 const base::FilePath shortcut_path =
201 GetUserShortcutsDirectory().Append(shortcut_name + installer::kLnkExt);
202 EXPECT_FALSE(base::PathExists(shortcut_path)) << location.ToString();
204 installer::Product product(GetDistribution());
205 ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER);
206 product.AddDefaultShortcutProperties(GetExePath(), &properties);
207 properties.set_shortcut_name(shortcut_name);
208 EXPECT_TRUE(ShellUtil::CreateOrUpdateShortcut(
209 ShellUtil::SHORTCUT_LOCATION_DESKTOP, GetDistribution(), properties,
210 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)) << location.ToString();
211 EXPECT_TRUE(base::PathExists(shortcut_path)) << location.ToString();
213 return shortcut_path;
216 base::FilePath CreateRegularSystemLevelShortcut(
217 const tracked_objects::Location& location) {
218 BrowserDistribution* distribution = GetDistribution();
219 installer::Product product(distribution);
220 ShellUtil::ShortcutProperties properties(ShellUtil::SYSTEM_LEVEL);
221 product.AddDefaultShortcutProperties(GetExePath(), &properties);
222 EXPECT_TRUE(ShellUtil::CreateOrUpdateShortcut(
223 ShellUtil::SHORTCUT_LOCATION_DESKTOP, distribution, properties,
224 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS)) << location.ToString();
225 const base::FilePath system_level_shortcut_path =
226 GetSystemShortcutsDirectory().Append(
227 distribution->
228 GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) +
229 installer::kLnkExt);
230 EXPECT_TRUE(base::PathExists(system_level_shortcut_path))
231 << location.ToString();
232 return system_level_shortcut_path;
235 void RenameProfile(const tracked_objects::Location& location,
236 const base::FilePath& profile_path,
237 const base::string16& new_profile_name) {
238 const size_t profile_index =
239 profile_info_cache_->GetIndexOfProfileWithPath(profile_2_path_);
240 ASSERT_NE(std::string::npos, profile_index);
241 ASSERT_NE(profile_info_cache_->GetNameOfProfileAtIndex(profile_index),
242 new_profile_name);
243 profile_info_cache_->SetNameOfProfileAtIndex(profile_index,
244 new_profile_name);
245 RunPendingTasks();
248 BrowserDistribution* GetDistribution() {
249 return BrowserDistribution::GetDistribution();
252 base::FilePath GetExePath() {
253 base::FilePath exe_path;
254 EXPECT_TRUE(PathService::Get(base::FILE_EXE, &exe_path));
255 return exe_path;
258 base::FilePath GetUserShortcutsDirectory() {
259 base::FilePath user_shortcuts_directory;
260 EXPECT_TRUE(ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP,
261 GetDistribution(),
262 ShellUtil::CURRENT_USER,
263 &user_shortcuts_directory));
264 return user_shortcuts_directory;
267 base::FilePath GetSystemShortcutsDirectory() {
268 base::FilePath system_shortcuts_directory;
269 EXPECT_TRUE(ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP,
270 GetDistribution(),
271 ShellUtil::SYSTEM_LEVEL,
272 &system_shortcuts_directory));
273 return system_shortcuts_directory;
276 base::MessageLoopForUI message_loop_;
277 content::TestBrowserThread ui_thread_;
278 content::TestBrowserThread file_thread_;
279 scoped_ptr<TestingProfileManager> profile_manager_;
280 scoped_ptr<ProfileShortcutManager> profile_shortcut_manager_;
281 ProfileInfoCache* profile_info_cache_;
282 base::ScopedPathOverride fake_user_desktop_;
283 base::ScopedPathOverride fake_system_desktop_;
284 base::string16 profile_1_name_;
285 base::FilePath profile_1_path_;
286 base::string16 profile_2_name_;
287 base::FilePath profile_2_path_;
288 base::string16 profile_3_name_;
289 base::FilePath profile_3_path_;
292 TEST_F(ProfileShortcutManagerTest, ShortcutFilename) {
293 const base::string16 kProfileName = L"Harry";
294 BrowserDistribution* distribution = GetDistribution();
295 const base::string16 expected_name = kProfileName + L" - " +
296 l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME) + installer::kLnkExt;
297 EXPECT_EQ(expected_name,
298 profiles::internal::GetShortcutFilenameForProfile(kProfileName,
299 distribution));
302 TEST_F(ProfileShortcutManagerTest, ShortcutLongFilenameIsTrimmed) {
303 const base::string16 kLongProfileName =
304 L"Harry Harry Harry Harry Harry Harry Harry"
305 L"Harry Harry Harry Harry Harry Harry Harry Harry Harry Harry Harry"
306 L"Harry Harry Harry Harry Harry Harry Harry Harry Harry Harry Harry";
307 const base::string16 file_name =
308 profiles::internal::GetShortcutFilenameForProfile(kLongProfileName,
309 GetDistribution());
310 EXPECT_LT(file_name.size(), kLongProfileName.size());
313 TEST_F(ProfileShortcutManagerTest, ShortcutFilenameStripsReservedCharacters) {
314 const base::string16 kProfileName = L"<Harry/>";
315 const base::string16 kSanitizedProfileName = L"Harry";
316 BrowserDistribution* distribution = GetDistribution();
317 const base::string16 expected_name = kSanitizedProfileName + L" - " +
318 l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME) + installer::kLnkExt;
319 EXPECT_EQ(expected_name,
320 profiles::internal::GetShortcutFilenameForProfile(kProfileName,
321 distribution));
324 TEST_F(ProfileShortcutManagerTest, UnbadgedShortcutFilename) {
325 BrowserDistribution* distribution = GetDistribution();
326 EXPECT_EQ(
327 distribution->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) +
328 installer::kLnkExt,
329 profiles::internal::GetShortcutFilenameForProfile(base::string16(),
330 distribution));
333 TEST_F(ProfileShortcutManagerTest, ShortcutFlags) {
334 const base::string16 kProfileName = L"MyProfileX";
335 const base::FilePath profile_path =
336 profile_info_cache_->GetUserDataDir().Append(kProfileName);
337 EXPECT_EQ(L"--profile-directory=\"" + kProfileName + L"\"",
338 profiles::internal::CreateProfileShortcutFlags(profile_path));
341 TEST_F(ProfileShortcutManagerTest, DesktopShortcutsCreate) {
342 SetupDefaultProfileShortcut(FROM_HERE);
343 // Validation is done by |ValidateProfileShortcutAtPath()| which is called
344 // by |CreateProfileWithShortcut()|.
345 CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_);
348 TEST_F(ProfileShortcutManagerTest, DesktopShortcutsUpdate) {
349 SetupDefaultProfileShortcut(FROM_HERE);
350 CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_);
352 // Cause an update in ProfileShortcutManager by modifying the profile info
353 // cache.
354 const base::string16 new_profile_2_name = L"New Profile Name";
355 RenameProfile(FROM_HERE, profile_2_path_, new_profile_2_name);
356 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_));
357 ValidateProfileShortcut(FROM_HERE, new_profile_2_name, profile_2_path_);
360 TEST_F(ProfileShortcutManagerTest, CreateSecondProfileBadgesFirstShortcut) {
361 SetupDefaultProfileShortcut(FROM_HERE);
362 // Assert that a shortcut without a profile name exists.
363 ASSERT_TRUE(ProfileShortcutExistsAtDefaultPath(base::string16()));
365 // Create a second profile without a shortcut.
366 profile_info_cache_->AddProfileToCache(profile_2_path_, profile_2_name_,
367 base::string16(), 0, std::string());
368 RunPendingTasks();
370 // Ensure that the second profile doesn't have a shortcut and that the first
371 // profile's shortcut got renamed and badged.
372 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_));
373 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(base::string16()));
374 ValidateProfileShortcut(FROM_HERE, profile_1_name_, profile_1_path_);
377 TEST_F(ProfileShortcutManagerTest, DesktopShortcutsDeleteSecondToLast) {
378 SetupAndCreateTwoShortcuts(FROM_HERE);
380 // Delete one shortcut.
381 profile_info_cache_->DeleteProfileFromCache(profile_2_path_);
382 RunPendingTasks();
383 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_));
385 // Verify that the profile name has been removed from the remaining shortcut.
386 ValidateNonProfileShortcut(FROM_HERE);
387 // Verify that an additional shortcut, with the default profile's name does
388 // not exist.
389 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_1_name_));
392 TEST_F(ProfileShortcutManagerTest, DeleteSecondToLastProfileWithoutShortcut) {
393 SetupAndCreateTwoShortcuts(FROM_HERE);
395 const base::FilePath profile_1_shortcut_path =
396 GetDefaultShortcutPathForProfile(profile_1_name_);
397 const base::FilePath profile_2_shortcut_path =
398 GetDefaultShortcutPathForProfile(profile_2_name_);
400 // Delete the shortcut for the first profile, but keep the one for the 2nd.
401 ASSERT_TRUE(base::DeleteFile(profile_1_shortcut_path, false));
402 ASSERT_FALSE(base::PathExists(profile_1_shortcut_path));
403 ASSERT_TRUE(base::PathExists(profile_2_shortcut_path));
405 // Delete the profile that doesn't have a shortcut.
406 profile_info_cache_->DeleteProfileFromCache(profile_1_path_);
407 RunPendingTasks();
409 // Verify that the remaining shortcut does not have a profile name.
410 ValidateNonProfileShortcut(FROM_HERE);
411 // Verify that shortcuts with profile names do not exist.
412 EXPECT_FALSE(base::PathExists(profile_1_shortcut_path));
413 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path));
416 TEST_F(ProfileShortcutManagerTest, DeleteSecondToLastProfileWithShortcut) {
417 SetupAndCreateTwoShortcuts(FROM_HERE);
419 const base::FilePath profile_1_shortcut_path =
420 GetDefaultShortcutPathForProfile(profile_1_name_);
421 const base::FilePath profile_2_shortcut_path =
422 GetDefaultShortcutPathForProfile(profile_2_name_);
424 // Delete the shortcut for the first profile, but keep the one for the 2nd.
425 ASSERT_TRUE(base::DeleteFile(profile_1_shortcut_path, false));
426 ASSERT_FALSE(base::PathExists(profile_1_shortcut_path));
427 ASSERT_TRUE(base::PathExists(profile_2_shortcut_path));
429 // Delete the profile that has a shortcut.
430 profile_info_cache_->DeleteProfileFromCache(profile_2_path_);
431 RunPendingTasks();
433 // Verify that the remaining shortcut does not have a profile name.
434 ValidateNonProfileShortcut(FROM_HERE);
435 // Verify that shortcuts with profile names do not exist.
436 EXPECT_FALSE(base::PathExists(profile_1_shortcut_path));
437 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path));
440 TEST_F(ProfileShortcutManagerTest, DeleteOnlyProfileWithShortcuts) {
441 SetupAndCreateTwoShortcuts(FROM_HERE);
442 CreateProfileWithShortcut(FROM_HERE, profile_3_name_, profile_3_path_);
444 const base::FilePath non_profile_shortcut_path =
445 GetDefaultShortcutPathForProfile(base::string16());
446 const base::FilePath profile_1_shortcut_path =
447 GetDefaultShortcutPathForProfile(profile_1_name_);
448 const base::FilePath profile_2_shortcut_path =
449 GetDefaultShortcutPathForProfile(profile_2_name_);
450 const base::FilePath profile_3_shortcut_path =
451 GetDefaultShortcutPathForProfile(profile_3_name_);
453 // Delete shortcuts for the first two profiles.
454 ASSERT_TRUE(base::DeleteFile(profile_1_shortcut_path, false));
455 ASSERT_TRUE(base::DeleteFile(profile_2_shortcut_path, false));
457 // Only the shortcut to the third profile should exist.
458 ASSERT_FALSE(base::PathExists(profile_1_shortcut_path));
459 ASSERT_FALSE(base::PathExists(profile_2_shortcut_path));
460 ASSERT_FALSE(base::PathExists(non_profile_shortcut_path));
461 ASSERT_TRUE(base::PathExists(profile_3_shortcut_path));
463 // Delete the third profile and check that its shortcut is gone and no
464 // shortcuts have been re-created.
465 profile_info_cache_->DeleteProfileFromCache(profile_3_path_);
466 RunPendingTasks();
467 ASSERT_FALSE(base::PathExists(profile_1_shortcut_path));
468 ASSERT_FALSE(base::PathExists(profile_2_shortcut_path));
469 ASSERT_FALSE(base::PathExists(profile_3_shortcut_path));
470 ASSERT_FALSE(base::PathExists(non_profile_shortcut_path));
473 TEST_F(ProfileShortcutManagerTest, DesktopShortcutsCreateSecond) {
474 SetupAndCreateTwoShortcuts(FROM_HERE);
476 // Delete one shortcut.
477 profile_info_cache_->DeleteProfileFromCache(profile_2_path_);
478 RunPendingTasks();
480 // Verify that a default shortcut exists (no profile name/avatar).
481 ValidateNonProfileShortcut(FROM_HERE);
482 // Verify that an additional shortcut, with the first profile's name does
483 // not exist.
484 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_1_name_));
486 // Create a second profile and shortcut.
487 CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_);
489 // Verify that the original shortcut received the profile's name.
490 ValidateProfileShortcut(FROM_HERE, profile_1_name_, profile_1_path_);
491 // Verify that a default shortcut no longer exists.
492 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(base::string16()));
495 TEST_F(ProfileShortcutManagerTest, RenamedDesktopShortcuts) {
496 SetupAndCreateTwoShortcuts(FROM_HERE);
498 const base::FilePath profile_2_shortcut_path_1 =
499 GetDefaultShortcutPathForProfile(profile_2_name_);
500 const base::FilePath profile_2_shortcut_path_2 =
501 GetUserShortcutsDirectory().Append(L"MyChrome.lnk");
502 ASSERT_TRUE(base::Move(profile_2_shortcut_path_1,
503 profile_2_shortcut_path_2));
505 // Ensure that a new shortcut does not get made if the old one was renamed.
506 profile_shortcut_manager_->CreateProfileShortcut(profile_2_path_);
507 RunPendingTasks();
508 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_));
509 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
510 profile_2_path_);
512 // Delete the renamed shortcut and try to create it again, which should work.
513 ASSERT_TRUE(base::DeleteFile(profile_2_shortcut_path_2, false));
514 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path_2));
515 profile_shortcut_manager_->CreateProfileShortcut(profile_2_path_);
516 RunPendingTasks();
517 ValidateProfileShortcut(FROM_HERE, profile_2_name_, profile_2_path_);
520 TEST_F(ProfileShortcutManagerTest, RenamedDesktopShortcutsGetDeleted) {
521 SetupAndCreateTwoShortcuts(FROM_HERE);
523 const base::FilePath profile_2_shortcut_path_1 =
524 GetDefaultShortcutPathForProfile(profile_2_name_);
525 const base::FilePath profile_2_shortcut_path_2 =
526 GetUserShortcutsDirectory().Append(L"MyChrome.lnk");
527 // Make a copy of the shortcut.
528 ASSERT_TRUE(base::CopyFile(profile_2_shortcut_path_1,
529 profile_2_shortcut_path_2));
530 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_1,
531 profile_2_path_);
532 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
533 profile_2_path_);
535 // Also, copy the shortcut for the first user and ensure it gets preserved.
536 const base::FilePath preserved_profile_1_shortcut_path =
537 GetUserShortcutsDirectory().Append(L"Preserved.lnk");
538 ASSERT_TRUE(base::CopyFile(
539 GetDefaultShortcutPathForProfile(profile_1_name_),
540 preserved_profile_1_shortcut_path));
541 EXPECT_TRUE(base::PathExists(preserved_profile_1_shortcut_path));
543 // Delete the profile and ensure both shortcuts were also deleted.
544 profile_info_cache_->DeleteProfileFromCache(profile_2_path_);
545 RunPendingTasks();
546 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path_1));
547 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path_2));
548 ValidateNonProfileShortcutAtPath(FROM_HERE,
549 preserved_profile_1_shortcut_path);
552 TEST_F(ProfileShortcutManagerTest, RenamedDesktopShortcutsAfterProfileRename) {
553 SetupAndCreateTwoShortcuts(FROM_HERE);
555 const base::FilePath profile_2_shortcut_path_1 =
556 GetDefaultShortcutPathForProfile(profile_2_name_);
557 const base::FilePath profile_2_shortcut_path_2 =
558 GetUserShortcutsDirectory().Append(L"MyChrome.lnk");
559 // Make a copy of the shortcut.
560 ASSERT_TRUE(base::CopyFile(profile_2_shortcut_path_1,
561 profile_2_shortcut_path_2));
562 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_1,
563 profile_2_path_);
564 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
565 profile_2_path_);
567 // Now, rename the profile.
568 const base::string16 new_profile_2_name = L"New profile";
569 RenameProfile(FROM_HERE, profile_2_path_, new_profile_2_name);
571 // The original shortcut should be renamed but the copied shortcut should
572 // keep its name.
573 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path_1));
574 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
575 profile_2_path_);
576 ValidateProfileShortcut(FROM_HERE, new_profile_2_name, profile_2_path_);
579 TEST_F(ProfileShortcutManagerTest, UpdateShortcutWithNoFlags) {
580 SetupDefaultProfileShortcut(FROM_HERE);
582 // Delete the shortcut that got created for this profile and instead make
583 // a new one without any command-line flags.
584 ASSERT_TRUE(base::DeleteFile(
585 GetDefaultShortcutPathForProfile(base::string16()), false));
586 const base::FilePath regular_shortcut_path =
587 CreateRegularShortcutWithName(FROM_HERE,
588 GetDistribution()->GetShortcutName(
589 BrowserDistribution::SHORTCUT_CHROME));
591 // Add another profile and check that the shortcut was replaced with
592 // a badged shortcut with the right command line for the profile
593 CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_);
594 EXPECT_FALSE(base::PathExists(regular_shortcut_path));
595 ValidateProfileShortcut(FROM_HERE, profile_1_name_, profile_1_path_);
598 TEST_F(ProfileShortcutManagerTest, UpdateTwoShortcutsWithNoFlags) {
599 SetupDefaultProfileShortcut(FROM_HERE);
601 // Delete the shortcut that got created for this profile and instead make
602 // two new ones without any command-line flags.
603 ASSERT_TRUE(base::DeleteFile(
604 GetDefaultShortcutPathForProfile(base::string16()), false));
605 const base::FilePath regular_shortcut_path =
606 CreateRegularShortcutWithName(FROM_HERE,
607 GetDistribution()->GetShortcutName(
608 BrowserDistribution::SHORTCUT_CHROME));
609 const base::FilePath customized_regular_shortcut_path =
610 CreateRegularShortcutWithName(FROM_HERE, L"MyChrome");
612 // Add another profile and check that one shortcut was renamed and that the
613 // other shortcut was updated but kept the same name.
614 CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_);
615 EXPECT_FALSE(base::PathExists(regular_shortcut_path));
616 ValidateProfileShortcutAtPath(FROM_HERE, customized_regular_shortcut_path,
617 profile_1_path_);
618 ValidateProfileShortcut(FROM_HERE, profile_1_name_, profile_1_path_);
621 TEST_F(ProfileShortcutManagerTest, RemoveProfileShortcuts) {
622 SetupAndCreateTwoShortcuts(FROM_HERE);
623 CreateProfileWithShortcut(FROM_HERE, profile_3_name_, profile_3_path_);
625 const base::FilePath profile_1_shortcut_path_1 =
626 GetDefaultShortcutPathForProfile(profile_1_name_);
627 const base::FilePath profile_2_shortcut_path_1 =
628 GetDefaultShortcutPathForProfile(profile_2_name_);
630 // Make copies of the shortcuts for both profiles.
631 const base::FilePath profile_1_shortcut_path_2 =
632 GetUserShortcutsDirectory().Append(L"Copied1.lnk");
633 const base::FilePath profile_2_shortcut_path_2 =
634 GetUserShortcutsDirectory().Append(L"Copied2.lnk");
635 ASSERT_TRUE(base::CopyFile(profile_1_shortcut_path_1,
636 profile_1_shortcut_path_2));
637 ASSERT_TRUE(base::CopyFile(profile_2_shortcut_path_1,
638 profile_2_shortcut_path_2));
639 ValidateProfileShortcutAtPath(FROM_HERE, profile_1_shortcut_path_2,
640 profile_1_path_);
641 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
642 profile_2_path_);
644 // Delete shortcuts for profile 1 and ensure that they got deleted while the
645 // shortcuts for profile 2 were kept.
646 profile_shortcut_manager_->RemoveProfileShortcuts(profile_1_path_);
647 RunPendingTasks();
648 EXPECT_FALSE(base::PathExists(profile_1_shortcut_path_1));
649 EXPECT_FALSE(base::PathExists(profile_1_shortcut_path_2));
650 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_1,
651 profile_2_path_);
652 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
653 profile_2_path_);
656 TEST_F(ProfileShortcutManagerTest, HasProfileShortcuts) {
657 SetupAndCreateTwoShortcuts(FROM_HERE);
659 struct HasShortcutsResult {
660 bool has_shortcuts;
661 void set_has_shortcuts(bool value) { has_shortcuts = value; }
662 } result = { false };
664 const base::Callback<void(bool)> callback =
665 base::Bind(&HasShortcutsResult::set_has_shortcuts,
666 base::Unretained(&result));
668 // Profile 2 should have a shortcut initially.
669 profile_shortcut_manager_->HasProfileShortcuts(profile_2_path_, callback);
670 RunPendingTasks();
671 EXPECT_TRUE(result.has_shortcuts);
673 // Delete the shortcut and check that the function returns false.
674 const base::FilePath profile_2_shortcut_path =
675 GetDefaultShortcutPathForProfile(profile_2_name_);
676 ASSERT_TRUE(base::DeleteFile(profile_2_shortcut_path, false));
677 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path));
678 profile_shortcut_manager_->HasProfileShortcuts(profile_2_path_, callback);
679 RunPendingTasks();
680 EXPECT_FALSE(result.has_shortcuts);
683 TEST_F(ProfileShortcutManagerTest, ProfileShortcutsWithSystemLevelShortcut) {
684 const base::FilePath system_level_shortcut_path =
685 CreateRegularSystemLevelShortcut(FROM_HERE);
687 // Create the initial profile.
688 profile_info_cache_->AddProfileToCache(profile_1_path_, profile_1_name_,
689 base::string16(), 0, std::string());
690 RunPendingTasks();
691 ASSERT_EQ(1U, profile_info_cache_->GetNumberOfProfiles());
693 // Ensure system-level continues to exist and user-level was not created.
694 EXPECT_TRUE(base::PathExists(system_level_shortcut_path));
695 EXPECT_FALSE(base::PathExists(
696 GetDefaultShortcutPathForProfile(base::string16())));
698 // Create another profile with a shortcut and ensure both profiles receive
699 // user-level profile shortcuts and the system-level one still exists.
700 CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_);
701 ValidateProfileShortcut(FROM_HERE, profile_1_name_, profile_1_path_);
702 ValidateProfileShortcut(FROM_HERE, profile_2_name_, profile_2_path_);
703 EXPECT_TRUE(base::PathExists(system_level_shortcut_path));
705 // Create a third profile without a shortcut and ensure it doesn't get one.
706 profile_info_cache_->AddProfileToCache(profile_3_path_, profile_3_name_,
707 base::string16(), 0, std::string());
708 RunPendingTasks();
709 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_3_name_));
711 // Ensure that changing the avatar icon and the name does not result in a
712 // shortcut being created.
713 profile_info_cache_->SetAvatarIconOfProfileAtIndex(
714 profile_info_cache_->GetIndexOfProfileWithPath(profile_3_path_), 3);
715 RunPendingTasks();
716 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_3_name_));
718 const base::string16 new_profile_3_name = L"New Name 3";
719 profile_info_cache_->SetNameOfProfileAtIndex(
720 profile_info_cache_->GetIndexOfProfileWithPath(profile_3_path_),
721 new_profile_3_name);
722 RunPendingTasks();
723 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_3_name_));
724 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(new_profile_3_name));
726 // Rename the second profile and ensure its shortcut got renamed.
727 const base::string16 new_profile_2_name = L"New Name 2";
728 profile_info_cache_->SetNameOfProfileAtIndex(
729 profile_info_cache_->GetIndexOfProfileWithPath(profile_2_path_),
730 new_profile_2_name);
731 RunPendingTasks();
732 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_));
733 ValidateProfileShortcut(FROM_HERE, new_profile_2_name, profile_2_path_);
736 TEST_F(ProfileShortcutManagerTest,
737 DeleteSecondToLastProfileWithSystemLevelShortcut) {
738 SetupAndCreateTwoShortcuts(FROM_HERE);
740 const base::FilePath system_level_shortcut_path =
741 CreateRegularSystemLevelShortcut(FROM_HERE);
743 // Delete a profile and verify that only the system-level shortcut still
744 // exists.
745 profile_info_cache_->DeleteProfileFromCache(profile_1_path_);
746 RunPendingTasks();
748 EXPECT_TRUE(base::PathExists(system_level_shortcut_path));
749 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(base::string16()));
750 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_1_name_));
751 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_));
754 TEST_F(ProfileShortcutManagerTest,
755 DeleteSecondToLastProfileWithShortcutWhenSystemLevelShortcutExists) {
756 SetupAndCreateTwoShortcuts(FROM_HERE);
758 const base::FilePath profile_1_shortcut_path =
759 GetDefaultShortcutPathForProfile(profile_1_name_);
760 const base::FilePath profile_2_shortcut_path =
761 GetDefaultShortcutPathForProfile(profile_2_name_);
763 // Delete the shortcut for the first profile, but keep the one for the 2nd.
764 ASSERT_TRUE(base::DeleteFile(profile_1_shortcut_path, false));
765 ASSERT_FALSE(base::PathExists(profile_1_shortcut_path));
766 ASSERT_TRUE(base::PathExists(profile_2_shortcut_path));
768 const base::FilePath system_level_shortcut_path =
769 CreateRegularSystemLevelShortcut(FROM_HERE);
771 // Delete the profile that has a shortcut, which will exercise the non-profile
772 // shortcut creation path in |DeleteDesktopShortcuts()|, which is
773 // not covered by the |DeleteSecondToLastProfileWithSystemLevelShortcut| test.
774 profile_info_cache_->DeleteProfileFromCache(profile_2_path_);
775 RunPendingTasks();
777 // Verify that only the system-level shortcut still exists.
778 EXPECT_TRUE(base::PathExists(system_level_shortcut_path));
779 EXPECT_FALSE(base::PathExists(
780 GetDefaultShortcutPathForProfile(base::string16())));
781 EXPECT_FALSE(base::PathExists(profile_1_shortcut_path));
782 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path));
785 TEST_F(ProfileShortcutManagerTest, CreateProfileIcon) {
786 SetupDefaultProfileShortcut(FROM_HERE);
788 const base::FilePath icon_path =
789 profiles::internal::GetProfileIconPath(profile_1_path_);
791 EXPECT_TRUE(base::PathExists(icon_path));
792 EXPECT_TRUE(base::DeleteFile(icon_path, false));
793 EXPECT_FALSE(base::PathExists(icon_path));
795 profile_shortcut_manager_->CreateOrUpdateProfileIcon(profile_1_path_);
796 RunPendingTasks();
797 EXPECT_TRUE(base::PathExists(icon_path));
800 TEST_F(ProfileShortcutManagerTest, UnbadgeProfileIconOnDeletion) {
801 SetupDefaultProfileShortcut(FROM_HERE);
802 const base::FilePath icon_path_1 =
803 profiles::internal::GetProfileIconPath(profile_1_path_);
804 const base::FilePath icon_path_2 =
805 profiles::internal::GetProfileIconPath(profile_2_path_);
807 // Default profile has unbadged icon to start.
808 std::string unbadged_icon_1;
809 EXPECT_TRUE(base::ReadFileToString(icon_path_1, &unbadged_icon_1));
811 // Creating a new profile adds a badge to both the new profile icon and the
812 // default profile icon. Since they use the same icon index, the icon files
813 // should be the same.
814 CreateProfileWithShortcut(FROM_HERE, profile_2_name_, profile_2_path_);
816 std::string badged_icon_1;
817 EXPECT_TRUE(base::ReadFileToString(icon_path_1, &badged_icon_1));
818 std::string badged_icon_2;
819 EXPECT_TRUE(base::ReadFileToString(icon_path_2, &badged_icon_2));
821 EXPECT_NE(badged_icon_1, unbadged_icon_1);
822 EXPECT_EQ(badged_icon_1, badged_icon_2);
824 // Deleting the default profile will unbadge the new profile's icon and should
825 // result in an icon that is identical to the unbadged default profile icon.
826 profile_info_cache_->DeleteProfileFromCache(profile_1_path_);
827 RunPendingTasks();
829 std::string unbadged_icon_2;
830 EXPECT_TRUE(base::ReadFileToString(icon_path_2, &unbadged_icon_2));
831 EXPECT_EQ(unbadged_icon_1, unbadged_icon_2);
834 TEST_F(ProfileShortcutManagerTest, ProfileIconOnAvatarChange) {
835 SetupAndCreateTwoShortcuts(FROM_HERE);
836 const base::FilePath icon_path_1 =
837 profiles::internal::GetProfileIconPath(profile_1_path_);
838 const base::FilePath icon_path_2 =
839 profiles::internal::GetProfileIconPath(profile_2_path_);
840 const size_t profile_index_1 =
841 profile_info_cache_->GetIndexOfProfileWithPath(profile_1_path_);
843 std::string badged_icon_1;
844 EXPECT_TRUE(base::ReadFileToString(icon_path_1, &badged_icon_1));
845 std::string badged_icon_2;
846 EXPECT_TRUE(base::ReadFileToString(icon_path_2, &badged_icon_2));
848 // Profile 1 and 2 are created with the same icon.
849 EXPECT_EQ(badged_icon_1, badged_icon_2);
851 // Change profile 1's icon.
852 profile_info_cache_->SetAvatarIconOfProfileAtIndex(profile_index_1, 1);
853 RunPendingTasks();
855 std::string new_badged_icon_1;
856 EXPECT_TRUE(base::ReadFileToString(icon_path_1, &new_badged_icon_1));
857 EXPECT_NE(new_badged_icon_1, badged_icon_1);
859 // Ensure the new icon is not the unbadged icon.
860 profile_info_cache_->DeleteProfileFromCache(profile_2_path_);
861 RunPendingTasks();
863 std::string unbadged_icon_1;
864 EXPECT_TRUE(base::ReadFileToString(icon_path_1, &unbadged_icon_1));
865 EXPECT_NE(unbadged_icon_1, new_badged_icon_1);
867 // Ensure the icon doesn't change on avatar change without 2 profiles.
868 profile_info_cache_->SetAvatarIconOfProfileAtIndex(profile_index_1, 1);
869 RunPendingTasks();
871 std::string unbadged_icon_1_a;
872 EXPECT_TRUE(base::ReadFileToString(icon_path_1, &unbadged_icon_1_a));
873 EXPECT_EQ(unbadged_icon_1, unbadged_icon_1_a);