1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/ui/app_list/app_list_service_impl.h"
6
7#include "base/prefs/pref_service.h"
8#include "chrome/browser/browser_process.h"
9#include "chrome/browser/profiles/profile_manager.h"
10#include "chrome/browser/ui/app_list/app_list_view_delegate.h"
11#include "chrome/browser/ui/app_list/test/chrome_app_list_test_support.h"
12#include "chrome/browser/ui/browser.h"
13#include "chrome/common/pref_names.h"
14#include "chrome/test/base/in_process_browser_test.h"
15
16namespace test {
17
18// Test API to access private members of AppListServiceImpl.
19class AppListServiceImplTestApi {
20 public:
21  explicit AppListServiceImplTestApi(AppListServiceImpl* impl) : impl_(impl) {}
22
23  ProfileLoader* profile_loader() { return impl_->profile_loader_.get(); }
24  AppListViewDelegate* view_delegate() { return impl_->view_delegate_.get(); }
25
26 private:
27  AppListServiceImpl* impl_;
28
29  DISALLOW_COPY_AND_ASSIGN(AppListServiceImplTestApi);
30};
31
32}  // namespace test
33
34// Browser Test for AppListServiceImpl that runs on all platforms supporting
35// app_list.
36class AppListServiceImplBrowserTest : public InProcessBrowserTest {
37 public:
38  AppListServiceImplBrowserTest() {}
39
40  // Overridden from InProcessBrowserTest:
41  virtual void SetUpOnMainThread() OVERRIDE {
42    service_ = test::GetAppListServiceImpl();
43    test_api_.reset(new test::AppListServiceImplTestApi(service_));
44  }
45
46 protected:
47  AppListServiceImpl* service_;
48  scoped_ptr<test::AppListServiceImplTestApi> test_api_;
49
50 private:
51  DISALLOW_COPY_AND_ASSIGN(AppListServiceImplBrowserTest);
52};
53
54// Test that showing a loaded profile for the first time is lazy and
55// synchronous. Then tests that showing a second loaded profile without
56// dismissing correctly switches profiles.
57IN_PROC_BROWSER_TEST_F(AppListServiceImplBrowserTest, ShowLoadedProfiles) {
58  PrefService* local_state = g_browser_process->local_state();
59  EXPECT_FALSE(local_state->HasPrefPath(prefs::kAppListProfile));
60
61  // When never shown, profile path should match the last used profile.
62  base::FilePath user_data_dir =
63      g_browser_process->profile_manager()->user_data_dir();
64  EXPECT_EQ(service_->GetProfilePath(user_data_dir),
65            browser()->profile()->GetPath());
66
67  // Just requesting the profile path shouldn't set it.
68  EXPECT_FALSE(local_state->HasPrefPath(prefs::kAppListProfile));
69
70  // Loading the Profile* should be lazy, except on ChromeOS where it is bound
71  // to ChromeLauncherController, which always has a profile.
72#if defined(OS_CHROMEOS)
73  EXPECT_TRUE(service_->GetCurrentAppListProfile());
74#else
75  EXPECT_FALSE(service_->GetCurrentAppListProfile());
76#endif
77
78  // Showing the app list for an unspecified profile, uses the loaded profile.
79  service_->Show();
80
81  // Load should be synchronous.
82  EXPECT_FALSE(test_api_->profile_loader()->IsAnyProfileLoading());
83  EXPECT_EQ(service_->GetCurrentAppListProfile(), browser()->profile());
84
85#if defined(OS_CHROMEOS)
86  // ChromeOS doesn't record the app list profile pref, and doesn't do profile
87  // switching.
88  EXPECT_FALSE(local_state->HasPrefPath(prefs::kAppListProfile));
89
90#else
91  // Preference should be updated automatically.
92  EXPECT_TRUE(local_state->HasPrefPath(prefs::kAppListProfile));
93  EXPECT_EQ(local_state->GetString(prefs::kAppListProfile),
94            browser()->profile()->GetPath().BaseName().MaybeAsASCII());
95
96  // Show for a second, pre-loaded profile without dismissing. Don't try this on
97  // ChromeOS because it does not support profile switching the app list.
98  Profile* profile2 = test::CreateSecondProfileAsync();
99  service_->ShowForProfile(profile2);
100
101  // Current profile and saved path should update synchronously.
102  EXPECT_FALSE(test_api_->profile_loader()->IsAnyProfileLoading());
103  EXPECT_EQ(profile2->GetPath(), service_->GetProfilePath(user_data_dir));
104  EXPECT_EQ(profile2, service_->GetCurrentAppListProfile());
105#endif
106}
107
108// Tests that the AppListViewDelegate is created lazily.
109IN_PROC_BROWSER_TEST_F(AppListServiceImplBrowserTest, CreatedLazily) {
110  EXPECT_FALSE(test_api_->view_delegate());
111  service_->ShowForProfile(browser()->profile());
112  EXPECT_TRUE(test_api_->view_delegate());
113}
114
115// Tests that deleting a profile properly clears the app list view delegate, but
116// doesn't destroy it. Disabled on ChromeOS, since profiles can't be deleted
117// this way (the second profile isn't signed in, so the test fails when creating
118// UserCloudPolicyManagerChromeOS).
119#if defined(OS_CHROMEOS)
120#define MAYBE_DeletingProfileUpdatesViewDelegate \
121    DISABLED_DeletingProfileUpdatesViewDelegate
122#else
123#define MAYBE_DeletingProfileUpdatesViewDelegate \
124    DeletingProfileUpdatesViewDelegate
125#endif
126IN_PROC_BROWSER_TEST_F(AppListServiceImplBrowserTest,
127                       MAYBE_DeletingProfileUpdatesViewDelegate) {
128  Profile* second_profile = test::CreateSecondProfileAsync();
129  service_->ShowForProfile(second_profile);
130  AppListViewDelegate* view_delegate = test_api_->view_delegate();
131
132  EXPECT_TRUE(view_delegate);
133  EXPECT_EQ(view_delegate->profile(), second_profile);
134
135  ProfileManager* profile_manager = g_browser_process->profile_manager();
136
137  // Delete the profile being used by the app list.
138  profile_manager->ScheduleProfileForDeletion(second_profile->GetPath(),
139                                              ProfileManager::CreateCallback());
140
141  // View delegate doesn't change when changing profiles.
142  EXPECT_EQ(view_delegate, test_api_->view_delegate());
143
144  // But the profile gets cleared until shown again.
145  EXPECT_FALSE(view_delegate->profile());
146  service_->ShowForProfile(browser()->profile());
147
148  EXPECT_EQ(view_delegate, test_api_->view_delegate());
149  EXPECT_EQ(view_delegate->profile(), browser()->profile());
150}
151