Popular sites on the NTP: check that experiment group StartsWith (rather than IS...
[chromium-blink-merge.git] / chrome / browser / profiles / profile_shortcut_manager_unittest_win.cc
blob6a9bfd39987695777eff93be4ca5388fbeb2c63c
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 {
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 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 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 std::string(), base::string16(), 0,
102 std::string());
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_);
106 RunPendingTasks();
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,
122 GetDistribution()));
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,
191 std::string());
192 profile_shortcut_manager_->CreateProfileShortcut(profile_path);
193 RunPendingTasks();
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(
229 distribution->
230 GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) +
231 installer::kLnkExt);
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),
244 new_profile_name);
245 profile_info_cache_->SetNameOfProfileAtIndex(profile_index,
246 new_profile_name);
247 RunPendingTasks();
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));
257 return exe_path;
260 base::FilePath GetUserShortcutsDirectory() {
261 base::FilePath user_shortcuts_directory;
262 EXPECT_TRUE(ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP,
263 GetDistribution(),
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,
272 GetDistribution(),
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,
301 distribution));
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,
311 GetDistribution());
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,
323 distribution));
326 TEST_F(ProfileShortcutManagerTest, UnbadgedShortcutFilename) {
327 BrowserDistribution* distribution = GetDistribution();
328 EXPECT_EQ(
329 distribution->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) +
330 installer::kLnkExt,
331 profiles::internal::GetShortcutFilenameForProfile(base::string16(),
332 distribution));
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
355 // cache.
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,
370 std::string());
371 RunPendingTasks();
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_);
385 RunPendingTasks();
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
391 // not exist.
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_);
410 RunPendingTasks();
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_);
434 RunPendingTasks();
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_);
469 RunPendingTasks();
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_);
481 RunPendingTasks();
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
486 // not exist.
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_);
510 RunPendingTasks();
511 EXPECT_FALSE(ProfileShortcutExistsAtDefaultPath(profile_2_name_));
512 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
513 profile_2_path_);
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_);
519 RunPendingTasks();
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,
534 profile_2_path_);
535 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
536 profile_2_path_);
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_);
548 RunPendingTasks();
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,
566 profile_2_path_);
567 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
568 profile_2_path_);
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
575 // keep its name.
576 EXPECT_FALSE(base::PathExists(profile_2_shortcut_path_1));
577 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
578 profile_2_path_);
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,
620 profile_1_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,
643 profile_1_path_);
644 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
645 profile_2_path_);
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_);
650 RunPendingTasks();
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,
654 profile_2_path_);
655 ValidateProfileShortcutAtPath(FROM_HERE, profile_2_shortcut_path_2,
656 profile_2_path_);
659 TEST_F(ProfileShortcutManagerTest, HasProfileShortcuts) {
660 SetupAndCreateTwoShortcuts(FROM_HERE);
662 struct HasShortcutsResult {
663 bool has_shortcuts;
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);
673 RunPendingTasks();
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);
682 RunPendingTasks();
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,
693 std::string());
694 RunPendingTasks();
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,
712 std::string());
713 RunPendingTasks();
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);
720 RunPendingTasks();
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_),
726 new_profile_3_name);
727 RunPendingTasks();
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_),
735 new_profile_2_name);
736 RunPendingTasks();
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
749 // exists.
750 profile_info_cache_->DeleteProfileFromCache(profile_1_path_);
751 RunPendingTasks();
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_);
780 RunPendingTasks();
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_);
801 RunPendingTasks();
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_);
832 RunPendingTasks();
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);
858 RunPendingTasks();
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_);
866 RunPendingTasks();
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);
874 RunPendingTasks();
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);