1// Copyright (c) 2011 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 "base/command_line.h"
6#include "base/memory/scoped_ptr.h"
7#include "base/strings/utf_string_conversions.h"
8#include "chrome/browser/background/background_mode_manager.h"
9#include "chrome/browser/lifetime/application_lifetime.h"
10#include "chrome/browser/profiles/profile_info_cache.h"
11#include "chrome/common/chrome_switches.h"
12#include "chrome/test/base/testing_browser_process.h"
13#include "chrome/test/base/testing_profile.h"
14#include "chrome/test/base/testing_profile_manager.h"
15#include "testing/gtest/include/gtest/gtest.h"
16#include "ui/gfx/image/image.h"
17#include "ui/gfx/image/image_unittest_util.h"
18
19class BackgroundModeManagerTest : public testing::Test {
20 public:
21  BackgroundModeManagerTest()
22      : profile_manager_(TestingBrowserProcess::GetGlobal()) {}
23  virtual ~BackgroundModeManagerTest() {}
24  virtual void SetUp() {
25    command_line_.reset(new CommandLine(CommandLine::NO_PROGRAM));
26    ASSERT_TRUE(profile_manager_.SetUp());
27  }
28  scoped_ptr<CommandLine> command_line_;
29  TestingProfileManager profile_manager_;
30};
31
32class TestBackgroundModeManager : public BackgroundModeManager {
33 public:
34  TestBackgroundModeManager(
35      CommandLine* command_line, ProfileInfoCache* cache, bool enabled)
36      : BackgroundModeManager(command_line, cache),
37        enabled_(enabled),
38        app_count_(0),
39        profile_app_count_(0),
40        have_status_tray_(false),
41        launch_on_startup_(false) {}
42  virtual void EnableLaunchOnStartup(bool launch) OVERRIDE {
43    launch_on_startup_ = launch;
44  }
45  virtual void CreateStatusTrayIcon() OVERRIDE { have_status_tray_ = true; }
46  virtual void RemoveStatusTrayIcon() OVERRIDE { have_status_tray_ = false; }
47  virtual int GetBackgroundAppCount() const OVERRIDE { return app_count_; }
48  virtual int GetBackgroundAppCountForProfile(
49      Profile* const profile) const OVERRIDE {
50    return profile_app_count_;
51  }
52  virtual bool IsBackgroundModePrefEnabled() const OVERRIDE { return enabled_; }
53  void SetBackgroundAppCount(int count) { app_count_ = count; }
54  void SetBackgroundAppCountForProfile(int count) {
55    profile_app_count_ = count;
56  }
57  void SetEnabled(bool enabled) {
58    enabled_ = enabled;
59    OnBackgroundModeEnabledPrefChanged();
60  }
61  bool HaveStatusTray() const { return have_status_tray_; }
62  bool IsLaunchOnStartup() const { return launch_on_startup_; }
63 private:
64  bool enabled_;
65  int app_count_;
66  int profile_app_count_;
67
68  // Flags to track whether we are launching on startup/have a status tray.
69  bool have_status_tray_;
70  bool launch_on_startup_;
71};
72
73static void AssertBackgroundModeActive(
74    const TestBackgroundModeManager& manager) {
75  EXPECT_TRUE(chrome::WillKeepAlive());
76  EXPECT_TRUE(manager.HaveStatusTray());
77  EXPECT_TRUE(manager.IsLaunchOnStartup());
78}
79
80static void AssertBackgroundModeInactive(
81    const TestBackgroundModeManager& manager) {
82  EXPECT_FALSE(chrome::WillKeepAlive());
83  EXPECT_FALSE(manager.HaveStatusTray());
84  EXPECT_FALSE(manager.IsLaunchOnStartup());
85}
86
87TEST_F(BackgroundModeManagerTest, BackgroundAppLoadUnload) {
88  TestingProfile* profile = profile_manager_.CreateTestingProfile("p1");
89  TestBackgroundModeManager manager(
90      command_line_.get(), profile_manager_.profile_info_cache(), true);
91  manager.RegisterProfile(profile);
92  EXPECT_FALSE(chrome::WillKeepAlive());
93
94  // Mimic app load.
95  manager.OnBackgroundAppInstalled(NULL);
96  manager.SetBackgroundAppCount(1);
97  manager.OnApplicationListChanged(profile);
98  AssertBackgroundModeActive(manager);
99
100  // Mimic app unload.
101  manager.SetBackgroundAppCount(0);
102  manager.OnApplicationListChanged(profile);
103  AssertBackgroundModeInactive(manager);
104}
105
106// App installs while background mode is disabled should do nothing.
107TEST_F(BackgroundModeManagerTest, BackgroundAppInstallUninstallWhileDisabled) {
108  TestingProfile* profile = profile_manager_.CreateTestingProfile("p1");
109  TestBackgroundModeManager manager(
110      command_line_.get(), profile_manager_.profile_info_cache(), true);
111  manager.RegisterProfile(profile);
112  // Turn off background mode.
113  manager.SetEnabled(false);
114  manager.DisableBackgroundMode();
115  AssertBackgroundModeInactive(manager);
116
117  // Status tray icons will not be created, launch on startup status will not
118  // be modified.
119  manager.OnBackgroundAppInstalled(NULL);
120  manager.SetBackgroundAppCount(1);
121  manager.OnApplicationListChanged(profile);
122  AssertBackgroundModeInactive(manager);
123
124  manager.SetBackgroundAppCount(0);
125  manager.OnApplicationListChanged(profile);
126  AssertBackgroundModeInactive(manager);
127
128  // Re-enable background mode.
129  manager.SetEnabled(true);
130  manager.EnableBackgroundMode();
131  AssertBackgroundModeInactive(manager);
132}
133
134
135// App installs while disabled should do nothing until background mode is
136// enabled..
137TEST_F(BackgroundModeManagerTest, EnableAfterBackgroundAppInstall) {
138  TestingProfile* profile = profile_manager_.CreateTestingProfile("p1");
139  TestBackgroundModeManager manager(
140      command_line_.get(), profile_manager_.profile_info_cache(), true);
141  manager.RegisterProfile(profile);
142
143  // Install app, should show status tray icon.
144  manager.OnBackgroundAppInstalled(NULL);
145  // OnBackgroundAppInstalled does not actually add an app to the
146  // BackgroundApplicationListModel which would result in another
147  // call to CreateStatusTray.
148  manager.SetBackgroundAppCount(1);
149  manager.OnApplicationListChanged(profile);
150  AssertBackgroundModeActive(manager);
151
152  // Turn off background mode - should hide status tray icon.
153  manager.SetEnabled(false);
154  manager.DisableBackgroundMode();
155  AssertBackgroundModeInactive(manager);
156
157  // Turn back on background mode - again, no status tray icon
158  // will show up since we didn't actually add anything to the list.
159  manager.SetEnabled(true);
160  manager.EnableBackgroundMode();
161  AssertBackgroundModeActive(manager);
162
163  // Uninstall app, should hide status tray icon again.
164  manager.SetBackgroundAppCount(0);
165  manager.OnApplicationListChanged(profile);
166  AssertBackgroundModeInactive(manager);
167}
168
169TEST_F(BackgroundModeManagerTest, MultiProfile) {
170  TestingProfile* profile1 = profile_manager_.CreateTestingProfile("p1");
171  TestingProfile* profile2 = profile_manager_.CreateTestingProfile("p2");
172  TestBackgroundModeManager manager(
173      command_line_.get(), profile_manager_.profile_info_cache(), true);
174  manager.RegisterProfile(profile1);
175  manager.RegisterProfile(profile2);
176  EXPECT_FALSE(chrome::WillKeepAlive());
177
178  // Install app, should show status tray icon.
179  manager.OnBackgroundAppInstalled(NULL);
180  manager.SetBackgroundAppCount(1);
181  manager.OnApplicationListChanged(profile1);
182  AssertBackgroundModeActive(manager);
183
184  // Install app for other profile, hsould show other status tray icon.
185  manager.OnBackgroundAppInstalled(NULL);
186  manager.SetBackgroundAppCount(2);
187  manager.OnApplicationListChanged(profile2);
188  AssertBackgroundModeActive(manager);
189
190  // Should hide both status tray icons.
191  manager.SetEnabled(false);
192  manager.DisableBackgroundMode();
193  AssertBackgroundModeInactive(manager);
194
195  // Turn back on background mode - should show both status tray icons.
196  manager.SetEnabled(true);
197  manager.EnableBackgroundMode();
198  AssertBackgroundModeActive(manager);
199
200  manager.SetBackgroundAppCount(1);
201  manager.OnApplicationListChanged(profile2);
202  // There is still one background app alive
203  AssertBackgroundModeActive(manager);
204
205  manager.SetBackgroundAppCount(0);
206  manager.OnApplicationListChanged(profile1);
207  AssertBackgroundModeInactive(manager);
208}
209
210TEST_F(BackgroundModeManagerTest, ProfileInfoCacheStorage) {
211  TestingProfile* profile1 = profile_manager_.CreateTestingProfile("p1");
212  TestingProfile* profile2 = profile_manager_.CreateTestingProfile("p2");
213  TestBackgroundModeManager manager(
214      command_line_.get(), profile_manager_.profile_info_cache(), true);
215  manager.RegisterProfile(profile1);
216  manager.RegisterProfile(profile2);
217  EXPECT_FALSE(chrome::WillKeepAlive());
218
219  ProfileInfoCache* cache = profile_manager_.profile_info_cache();
220  EXPECT_EQ(2u, cache->GetNumberOfProfiles());
221
222  EXPECT_FALSE(cache->GetBackgroundStatusOfProfileAtIndex(0));
223  EXPECT_FALSE(cache->GetBackgroundStatusOfProfileAtIndex(1));
224
225  // Install app, should show status tray icon.
226  manager.OnBackgroundAppInstalled(NULL);
227  manager.SetBackgroundAppCount(1);
228  manager.SetBackgroundAppCountForProfile(1);
229  manager.OnApplicationListChanged(profile1);
230
231  // Install app for other profile.
232  manager.OnBackgroundAppInstalled(NULL);
233  manager.SetBackgroundAppCount(1);
234  manager.SetBackgroundAppCountForProfile(1);
235  manager.OnApplicationListChanged(profile2);
236
237  EXPECT_TRUE(cache->GetBackgroundStatusOfProfileAtIndex(0));
238  EXPECT_TRUE(cache->GetBackgroundStatusOfProfileAtIndex(1));
239
240  manager.SetBackgroundAppCountForProfile(0);
241  manager.OnApplicationListChanged(profile1);
242
243  size_t p1_index = cache->GetIndexOfProfileWithPath(profile1->GetPath());
244  EXPECT_FALSE(cache->GetBackgroundStatusOfProfileAtIndex(p1_index));
245
246  manager.SetBackgroundAppCountForProfile(0);
247  manager.OnApplicationListChanged(profile2);
248
249  size_t p2_index = cache->GetIndexOfProfileWithPath(profile1->GetPath());
250  EXPECT_FALSE(cache->GetBackgroundStatusOfProfileAtIndex(p2_index));
251
252  // Even though neither has background status on, there should still be two
253  // profiles in the cache.
254  EXPECT_EQ(2u, cache->GetNumberOfProfiles());
255}
256
257TEST_F(BackgroundModeManagerTest, ProfileInfoCacheObserver) {
258  TestingProfile* profile1 = profile_manager_.CreateTestingProfile("p1");
259  TestBackgroundModeManager manager(
260      command_line_.get(), profile_manager_.profile_info_cache(), true);
261  manager.RegisterProfile(profile1);
262  EXPECT_FALSE(chrome::WillKeepAlive());
263
264  // Install app, should show status tray icon.
265  manager.OnBackgroundAppInstalled(NULL);
266  manager.SetBackgroundAppCount(1);
267  manager.SetBackgroundAppCountForProfile(1);
268  manager.OnApplicationListChanged(profile1);
269
270  manager.OnProfileNameChanged(
271      profile1->GetPath(),
272      manager.GetBackgroundModeData(profile1)->name());
273
274  EXPECT_EQ(UTF8ToUTF16("p1"),
275            manager.GetBackgroundModeData(profile1)->name());
276
277  TestingProfile* profile2 = profile_manager_.CreateTestingProfile("p2");
278  manager.RegisterProfile(profile2);
279  EXPECT_EQ(2, manager.NumberOfBackgroundModeData());
280
281  manager.OnProfileAdded(profile2->GetPath());
282  EXPECT_EQ(UTF8ToUTF16("p2"),
283            manager.GetBackgroundModeData(profile2)->name());
284
285  manager.OnProfileWillBeRemoved(profile2->GetPath());
286  EXPECT_EQ(1, manager.NumberOfBackgroundModeData());
287
288  // Check that the background mode data we think is in the map actually is.
289  EXPECT_EQ(UTF8ToUTF16("p1"),
290            manager.GetBackgroundModeData(profile1)->name());
291}
292
293TEST_F(BackgroundModeManagerTest, DisableBackgroundModeUnderTestFlag) {
294  TestingProfile* profile1 = profile_manager_.CreateTestingProfile("p1");
295  command_line_->AppendSwitch(switches::kKeepAliveForTest);
296  TestBackgroundModeManager manager(
297      command_line_.get(), profile_manager_.profile_info_cache(), true);
298  manager.RegisterProfile(profile1);
299  EXPECT_TRUE(manager.ShouldBeInBackgroundMode());
300  manager.SetEnabled(false);
301  EXPECT_FALSE(manager.ShouldBeInBackgroundMode());
302}
303
304TEST_F(BackgroundModeManagerTest,
305       BackgroundModeDisabledPreventsKeepAliveOnStartup) {
306  TestingProfile* profile1 = profile_manager_.CreateTestingProfile("p1");
307  command_line_->AppendSwitch(switches::kKeepAliveForTest);
308  TestBackgroundModeManager manager(
309      command_line_.get(), profile_manager_.profile_info_cache(), false);
310  manager.RegisterProfile(profile1);
311  EXPECT_FALSE(manager.ShouldBeInBackgroundMode());
312}
313