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.
6 #include "base/command_line.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/test/test_simple_task_runner.h"
11 #include "base/thread_task_runner_handle.h"
12 #include "chrome/browser/background/background_mode_manager.h"
13 #include "chrome/browser/browser_shutdown.h"
14 #include "chrome/browser/extensions/extension_function_test_utils.h"
15 #include "chrome/browser/extensions/extension_service.h"
16 #include "chrome/browser/extensions/test_extension_system.h"
17 #include "chrome/browser/lifetime/application_lifetime.h"
18 #include "chrome/browser/profiles/profile_info_cache.h"
19 #include "chrome/browser/status_icons/status_icon_menu_model.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "chrome/test/base/testing_browser_process.h"
22 #include "chrome/test/base/testing_profile.h"
23 #include "chrome/test/base/testing_profile_manager.h"
24 #include "content/public/test/test_browser_thread_bundle.h"
25 #include "extensions/browser/api_test_utils.h"
26 #include "extensions/browser/extension_prefs.h"
27 #include "extensions/browser/extension_system.h"
28 #include "testing/gmock/include/gmock/gmock.h"
29 #include "testing/gtest/include/gtest/gtest.h"
30 #include "ui/gfx/image/image.h"
31 #include "ui/gfx/image/image_unittest_util.h"
32 #include "ui/message_center/message_center.h"
34 #if defined(OS_CHROMEOS)
35 #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
36 #include "chrome/browser/chromeos/settings/cros_settings.h"
37 #include "chrome/browser/chromeos/settings/device_settings_service.h"
41 using testing::AtMost
;
42 using testing::Exactly
;
43 using testing::InSequence
;
45 using testing::StrictMock
;
49 scoped_ptr
<TestingProfileManager
> CreateTestingProfileManager() {
50 scoped_ptr
<TestingProfileManager
> profile_manager(
51 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
52 EXPECT_TRUE(profile_manager
->SetUp());
53 return profile_manager
.Pass();
56 // Helper class that tracks state transitions in BackgroundModeManager and
57 // exposes them via getters (or gmock for EnableLaunchOnStartup).
58 class TestBackgroundModeManager
: public StrictMock
<BackgroundModeManager
> {
60 TestBackgroundModeManager(const base::CommandLine
& command_line
,
61 ProfileInfoCache
* cache
)
62 : StrictMock
<BackgroundModeManager
>(command_line
, cache
),
63 have_status_tray_(false),
64 has_shown_balloon_(false) {
65 ResumeBackgroundMode();
68 MOCK_METHOD1(EnableLaunchOnStartup
, void(bool should_launch
));
70 // TODO: Use strict-mocking rather than keeping state through overrides below.
71 void DisplayAppInstalledNotification(
72 const extensions::Extension
* extension
) override
{
73 has_shown_balloon_
= true;
75 void CreateStatusTrayIcon() override
{ have_status_tray_
= true; }
76 void RemoveStatusTrayIcon() override
{ have_status_tray_
= false; }
78 bool HaveStatusTray() const { return have_status_tray_
; }
79 bool HasShownBalloon() const { return has_shown_balloon_
; }
80 void SetHasShownBalloon(bool value
) { has_shown_balloon_
= value
; }
83 // Flags to track whether we have a status tray/have shown the balloon.
84 bool have_status_tray_
;
85 bool has_shown_balloon_
;
87 DISALLOW_COPY_AND_ASSIGN(TestBackgroundModeManager
);
90 class TestStatusIcon
: public StatusIcon
{
93 void SetImage(const gfx::ImageSkia
& image
) override
{}
94 void SetToolTip(const base::string16
& tool_tip
) override
{}
95 void DisplayBalloon(const gfx::ImageSkia
& icon
,
96 const base::string16
& title
,
97 const base::string16
& contents
) override
{}
98 void UpdatePlatformContextMenu(StatusIconMenuModel
* menu
) override
{}
101 DISALLOW_COPY_AND_ASSIGN(TestStatusIcon
);
104 void AssertBackgroundModeActive(const TestBackgroundModeManager
& manager
) {
105 EXPECT_TRUE(chrome::WillKeepAlive());
106 EXPECT_TRUE(manager
.HaveStatusTray());
109 void AssertBackgroundModeInactive(const TestBackgroundModeManager
& manager
) {
110 EXPECT_FALSE(chrome::WillKeepAlive());
111 EXPECT_FALSE(manager
.HaveStatusTray());
116 // More complex test helper that exposes APIs for fine grained control of
117 // things like the number of background applications. This allows writing
118 // smaller tests that don't have to install/uninstall extensions.
119 class AdvancedTestBackgroundModeManager
: public TestBackgroundModeManager
{
121 AdvancedTestBackgroundModeManager(const base::CommandLine
& command_line
,
122 ProfileInfoCache
* cache
,
124 : TestBackgroundModeManager(command_line
, cache
), enabled_(enabled
) {}
126 int GetBackgroundAppCount() const override
{
128 for (const auto& profile_count_pair
: profile_app_counts_
)
129 app_count
+= profile_count_pair
.second
;
132 int GetBackgroundAppCountForProfile(Profile
* const profile
) const override
{
133 auto it
= profile_app_counts_
.find(profile
);
134 if (it
== profile_app_counts_
.end()) {
140 void SetBackgroundAppCountForProfile(Profile
* profile
, int count
) {
141 profile_app_counts_
[profile
] = count
;
143 void SetEnabled(bool enabled
) {
145 OnBackgroundModeEnabledPrefChanged();
147 bool IsBackgroundModePrefEnabled() const override
{ return enabled_
; }
151 std::map
<Profile
*, int> profile_app_counts_
;
153 DISALLOW_COPY_AND_ASSIGN(AdvancedTestBackgroundModeManager
);
156 class BackgroundModeManagerTest
: public testing::Test
{
158 BackgroundModeManagerTest() {}
159 ~BackgroundModeManagerTest() override
{}
161 void SetUp() override
{
162 command_line_
.reset(new base::CommandLine(base::CommandLine::NO_PROGRAM
));
163 profile_manager_
= CreateTestingProfileManager();
164 profile_
= profile_manager_
->CreateTestingProfile("p1");
165 chrome::DisableShutdownForTesting(true);
168 void TearDown() override
{
169 // Don't allow the browser to be closed because the shutdown procedure will
170 // attempt to access objects that we haven't created (e.g., MessageCenter).
171 browser_shutdown::SetTryingToQuit(true);
172 chrome::DisableShutdownForTesting(false);
173 browser_shutdown::SetTryingToQuit(false);
177 content::TestBrowserThreadBundle thread_bundle_
;
178 scoped_ptr
<base::CommandLine
> command_line_
;
180 scoped_ptr
<TestingProfileManager
> profile_manager_
;
181 // Test profile used by all tests - this is owned by profile_manager_.
182 TestingProfile
* profile_
;
185 DISALLOW_COPY_AND_ASSIGN(BackgroundModeManagerTest
);
188 class BackgroundModeManagerWithExtensionsTest
: public testing::Test
{
190 BackgroundModeManagerWithExtensionsTest() {}
191 ~BackgroundModeManagerWithExtensionsTest() override
{}
193 void SetUp() override
{
194 command_line_
.reset(new base::CommandLine(base::CommandLine::NO_PROGRAM
));
195 profile_manager_
= CreateTestingProfileManager();
196 profile_
= profile_manager_
->CreateTestingProfile("p1");
198 // Aura clears notifications from the message center at shutdown.
199 message_center::MessageCenter::Initialize();
201 // BackgroundModeManager actually affects Chrome start/stop state,
202 // tearing down our thread bundle before we've had chance to clean
203 // everything up. Keeping Chrome alive prevents this.
204 // We aren't interested in if the keep alive works correctly in this test.
205 chrome::IncrementKeepAliveCount();
207 #if defined(OS_CHROMEOS)
208 // On ChromeOS shutdown, HandleAppExitingForPlatform will call
209 // chrome::DecrementKeepAliveCount because it assumes the aura shell
210 // called chrome::IncrementKeepAliveCount. Simulate the call here.
211 chrome::IncrementKeepAliveCount();
214 // Create our test BackgroundModeManager.
215 manager_
.reset(new TestBackgroundModeManager(
216 *command_line_
, profile_manager_
->profile_info_cache()));
217 manager_
->RegisterProfile(profile_
);
220 void TearDown() override
{
221 // Clean up the status icon. If this is not done before profile deletes,
222 // the context menu updates will DCHECK with the now deleted profiles.
223 StatusIcon
* status_icon
= manager_
->status_icon_
;
224 manager_
->status_icon_
= NULL
;
227 // We have to destroy the profiles now because we created them with real
228 // thread state. This causes a lot of machinery to spin up that stops
229 // working when we tear down our thread state at the end of the test.
230 // Deleting our testing profile may have the side-effect of disabling
231 // background mode if it was enabled for that profile (explicitly note that
232 // here to satisfy StrictMock requirements.
233 EXPECT_CALL(*manager_
, EnableLaunchOnStartup(false)).Times(AtMost(1));
234 profile_manager_
->DeleteAllTestingProfiles();
235 Mock::VerifyAndClearExpectations(manager_
.get());
237 // We're getting ready to shutdown the message loop. Clear everything out!
238 base::MessageLoop::current()->RunUntilIdle();
239 // Matching the call to IncrementKeepAliveCount in SetUp().
240 chrome::DecrementKeepAliveCount();
242 // TestBackgroundModeManager has dependencies on the infrastructure.
243 // It should get cleared first.
246 // The Profile Manager references the Browser Process.
247 // The Browser Process references the Notification UI Manager.
248 // The Notification UI Manager references the Message Center.
249 // As a result, we have to clear the browser process state here
250 // before tearing down the Message Center.
251 profile_manager_
.reset();
253 // Message Center shutdown must occur after the DecrementKeepAliveCount
254 // because DecrementKeepAliveCount will end up referencing the message
255 // center during cleanup.
256 message_center::MessageCenter::Shutdown();
258 // Clear the shutdown flag to isolate the remaining effect of this test.
259 browser_shutdown::SetTryingToQuit(false);
263 scoped_refptr
<extensions::Extension
> CreateExtension(
264 extensions::Manifest::Location location
,
265 const std::string
& data
,
266 const std::string
& id
) {
267 scoped_ptr
<base::DictionaryValue
> parsed_manifest(
268 extensions::api_test_utils::ParseDictionary(data
));
269 return extensions::api_test_utils::CreateExtension(
270 location
, parsed_manifest
.get(), id
);
273 // From views::MenuModelAdapter::IsCommandEnabled with modification.
274 bool IsCommandEnabled(ui::MenuModel
* model
, int id
) const {
276 if (ui::MenuModel::GetModelAndIndexForCommandId(id
, &model
, &index
))
277 return model
->IsEnabledAt(index
);
282 void AddEphemeralApp(const extensions::Extension
* extension
,
283 ExtensionService
* service
) {
284 extensions::ExtensionPrefs
* prefs
=
285 extensions::ExtensionPrefs::Get(service
->profile());
287 prefs
->OnExtensionInstalled(extension
,
288 extensions::Extension::ENABLED
,
289 syncer::StringOrdinal(),
290 extensions::kInstallFlagIsEphemeral
,
293 service
->AddExtension(extension
);
296 scoped_ptr
<TestBackgroundModeManager
> manager_
;
298 scoped_ptr
<base::CommandLine
> command_line_
;
300 scoped_ptr
<TestingProfileManager
> profile_manager_
;
301 // Test profile used by all tests - this is owned by profile_manager_.
302 TestingProfile
* profile_
;
305 // Required for extension service.
306 content::TestBrowserThreadBundle thread_bundle_
;
308 #if defined(OS_CHROMEOS)
309 // ChromeOS needs extra services to run in the following order.
310 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_
;
311 chromeos::ScopedTestCrosSettings test_cros_settings_
;
312 chromeos::ScopedTestUserManager test_user_manager_
;
315 DISALLOW_COPY_AND_ASSIGN(BackgroundModeManagerWithExtensionsTest
);
319 TEST_F(BackgroundModeManagerTest
, BackgroundAppLoadUnload
) {
320 AdvancedTestBackgroundModeManager
manager(
321 *command_line_
, profile_manager_
->profile_info_cache(), true);
322 manager
.RegisterProfile(profile_
);
323 EXPECT_FALSE(chrome::WillKeepAlive());
326 EXPECT_CALL(manager
, EnableLaunchOnStartup(true)).Times(Exactly(1));
327 manager
.OnBackgroundAppInstalled(NULL
);
328 manager
.SetBackgroundAppCountForProfile(profile_
, 1);
329 manager
.OnApplicationListChanged(profile_
);
330 Mock::VerifyAndClearExpectations(&manager
);
331 AssertBackgroundModeActive(manager
);
333 manager
.SuspendBackgroundMode();
334 AssertBackgroundModeInactive(manager
);
335 manager
.ResumeBackgroundMode();
338 EXPECT_CALL(manager
, EnableLaunchOnStartup(false)).Times(Exactly(1));
339 manager
.SetBackgroundAppCountForProfile(profile_
, 0);
340 manager
.OnApplicationListChanged(profile_
);
341 Mock::VerifyAndClearExpectations(&manager
);
342 AssertBackgroundModeInactive(manager
);
344 manager
.SuspendBackgroundMode();
345 AssertBackgroundModeInactive(manager
);
347 // Mimic app load while suspended, e.g. from sync. This should enable and
348 // resume background mode.
349 EXPECT_CALL(manager
, EnableLaunchOnStartup(true)).Times(Exactly(1));
350 manager
.OnBackgroundAppInstalled(NULL
);
351 manager
.SetBackgroundAppCountForProfile(profile_
, 1);
352 manager
.OnApplicationListChanged(profile_
);
353 Mock::VerifyAndClearExpectations(&manager
);
354 AssertBackgroundModeActive(manager
);
357 // App installs while background mode is disabled should do nothing.
358 TEST_F(BackgroundModeManagerTest
, BackgroundAppInstallUninstallWhileDisabled
) {
359 AdvancedTestBackgroundModeManager
manager(
360 *command_line_
, profile_manager_
->profile_info_cache(), true);
361 manager
.RegisterProfile(profile_
);
363 // Turn off background mode (shouldn't explicitly disable launch-on-startup as
364 // the app-count is zero and launch-on-startup shouldn't be considered on).
365 manager
.SetEnabled(false);
366 manager
.DisableBackgroundMode();
367 AssertBackgroundModeInactive(manager
);
369 // Status tray icons will not be created, launch on startup status will not
371 manager
.OnBackgroundAppInstalled(NULL
);
372 manager
.SetBackgroundAppCountForProfile(profile_
, 1);
373 manager
.OnApplicationListChanged(profile_
);
374 AssertBackgroundModeInactive(manager
);
376 manager
.SetBackgroundAppCountForProfile(profile_
, 0);
377 manager
.OnApplicationListChanged(profile_
);
378 AssertBackgroundModeInactive(manager
);
380 // Re-enable background mode (shouldn't actually enable launch-on-startup as
381 // the app-count is zero).
382 manager
.SetEnabled(true);
383 manager
.EnableBackgroundMode();
384 AssertBackgroundModeInactive(manager
);
388 // App installs while disabled should do nothing until background mode is
390 TEST_F(BackgroundModeManagerTest
, EnableAfterBackgroundAppInstall
) {
391 AdvancedTestBackgroundModeManager
manager(
392 *command_line_
, profile_manager_
->profile_info_cache(), true);
393 manager
.RegisterProfile(profile_
);
395 // Install app, should show status tray icon.
396 EXPECT_CALL(manager
, EnableLaunchOnStartup(true)).Times(Exactly(1));
397 manager
.OnBackgroundAppInstalled(NULL
);
398 // OnBackgroundAppInstalled does not actually add an app to the
399 // BackgroundApplicationListModel which would result in another
400 // call to CreateStatusTray.
401 manager
.SetBackgroundAppCountForProfile(profile_
, 1);
402 manager
.OnApplicationListChanged(profile_
);
403 AssertBackgroundModeActive(manager
);
404 Mock::VerifyAndClearExpectations(&manager
);
406 // Turn off background mode - should hide status tray icon.
407 EXPECT_CALL(manager
, EnableLaunchOnStartup(false)).Times(Exactly(1));
408 manager
.SetEnabled(false);
409 manager
.DisableBackgroundMode();
410 Mock::VerifyAndClearExpectations(&manager
);
411 AssertBackgroundModeInactive(manager
);
413 // Turn back on background mode - again, no status tray icon
414 // will show up since we didn't actually add anything to the list.
415 EXPECT_CALL(manager
, EnableLaunchOnStartup(true)).Times(Exactly(1));
416 manager
.SetEnabled(true);
417 manager
.EnableBackgroundMode();
418 Mock::VerifyAndClearExpectations(&manager
);
419 AssertBackgroundModeActive(manager
);
421 // Uninstall app, should hide status tray icon again.
422 EXPECT_CALL(manager
, EnableLaunchOnStartup(false)).Times(Exactly(1));
423 manager
.SetBackgroundAppCountForProfile(profile_
, 0);
424 manager
.OnApplicationListChanged(profile_
);
425 Mock::VerifyAndClearExpectations(&manager
);
426 AssertBackgroundModeInactive(manager
);
429 TEST_F(BackgroundModeManagerTest
, MultiProfile
) {
430 TestingProfile
* profile2
= profile_manager_
->CreateTestingProfile("p2");
431 AdvancedTestBackgroundModeManager
manager(
432 *command_line_
, profile_manager_
->profile_info_cache(), true);
433 manager
.RegisterProfile(profile_
);
434 manager
.RegisterProfile(profile2
);
435 EXPECT_FALSE(chrome::WillKeepAlive());
437 // Install app, should show status tray icon.
438 EXPECT_CALL(manager
, EnableLaunchOnStartup(true)).Times(Exactly(1));
439 manager
.OnBackgroundAppInstalled(NULL
);
440 manager
.SetBackgroundAppCountForProfile(profile_
, 1);
441 manager
.OnApplicationListChanged(profile_
);
442 Mock::VerifyAndClearExpectations(&manager
);
443 AssertBackgroundModeActive(manager
);
445 // Install app for other profile, should show other status tray icon.
446 manager
.OnBackgroundAppInstalled(NULL
);
447 manager
.SetBackgroundAppCountForProfile(profile2
, 2);
448 manager
.OnApplicationListChanged(profile2
);
449 AssertBackgroundModeActive(manager
);
451 // Should hide both status tray icons.
452 EXPECT_CALL(manager
, EnableLaunchOnStartup(false)).Times(Exactly(1));
453 manager
.SetEnabled(false);
454 manager
.DisableBackgroundMode();
455 Mock::VerifyAndClearExpectations(&manager
);
456 AssertBackgroundModeInactive(manager
);
458 // Turn back on background mode - should show both status tray icons.
459 EXPECT_CALL(manager
, EnableLaunchOnStartup(true)).Times(Exactly(1));
460 manager
.SetEnabled(true);
461 manager
.EnableBackgroundMode();
462 Mock::VerifyAndClearExpectations(&manager
);
463 AssertBackgroundModeActive(manager
);
465 manager
.SetBackgroundAppCountForProfile(profile_
, 0);
466 manager
.OnApplicationListChanged(profile_
);
467 manager
.SetBackgroundAppCountForProfile(profile2
, 1);
468 manager
.OnApplicationListChanged(profile2
);
469 // There is still one background app alive
470 AssertBackgroundModeActive(manager
);
471 // Verify the implicit expectations of no calls on this StrictMock.
472 Mock::VerifyAndClearExpectations(&manager
);
474 EXPECT_CALL(manager
, EnableLaunchOnStartup(false)).Times(Exactly(1));
475 manager
.SetBackgroundAppCountForProfile(profile2
, 0);
476 manager
.OnApplicationListChanged(profile_
);
477 Mock::VerifyAndClearExpectations(&manager
);
478 AssertBackgroundModeInactive(manager
);
481 TEST_F(BackgroundModeManagerTest
, ProfileInfoCacheStorage
) {
482 TestingProfile
* profile2
= profile_manager_
->CreateTestingProfile("p2");
483 AdvancedTestBackgroundModeManager
manager(
484 *command_line_
, profile_manager_
->profile_info_cache(), true);
485 manager
.RegisterProfile(profile_
);
486 manager
.RegisterProfile(profile2
);
487 EXPECT_FALSE(chrome::WillKeepAlive());
489 ProfileInfoCache
* cache
= profile_manager_
->profile_info_cache();
490 EXPECT_EQ(2u, cache
->GetNumberOfProfiles());
492 EXPECT_FALSE(cache
->GetBackgroundStatusOfProfileAtIndex(0));
493 EXPECT_FALSE(cache
->GetBackgroundStatusOfProfileAtIndex(1));
495 // Install app, should show status tray icon.
496 EXPECT_CALL(manager
, EnableLaunchOnStartup(true)).Times(Exactly(1));
497 manager
.OnBackgroundAppInstalled(NULL
);
498 manager
.SetBackgroundAppCountForProfile(profile_
, 1);
499 manager
.OnApplicationListChanged(profile_
);
500 Mock::VerifyAndClearExpectations(&manager
);
502 // Install app for other profile.
503 manager
.OnBackgroundAppInstalled(NULL
);
504 manager
.SetBackgroundAppCountForProfile(profile2
, 1);
505 manager
.OnApplicationListChanged(profile2
);
507 EXPECT_TRUE(cache
->GetBackgroundStatusOfProfileAtIndex(0));
508 EXPECT_TRUE(cache
->GetBackgroundStatusOfProfileAtIndex(1));
510 manager
.SetBackgroundAppCountForProfile(profile_
, 0);
511 manager
.OnApplicationListChanged(profile_
);
513 size_t p1_index
= cache
->GetIndexOfProfileWithPath(profile_
->GetPath());
514 EXPECT_FALSE(cache
->GetBackgroundStatusOfProfileAtIndex(p1_index
));
516 EXPECT_CALL(manager
, EnableLaunchOnStartup(false)).Times(Exactly(1));
517 manager
.SetBackgroundAppCountForProfile(profile2
, 0);
518 manager
.OnApplicationListChanged(profile2
);
519 Mock::VerifyAndClearExpectations(&manager
);
521 size_t p2_index
= cache
->GetIndexOfProfileWithPath(profile_
->GetPath());
522 EXPECT_FALSE(cache
->GetBackgroundStatusOfProfileAtIndex(p2_index
));
524 // Even though neither has background status on, there should still be two
525 // profiles in the cache.
526 EXPECT_EQ(2u, cache
->GetNumberOfProfiles());
529 TEST_F(BackgroundModeManagerTest
, ProfileInfoCacheObserver
) {
530 AdvancedTestBackgroundModeManager
manager(
531 *command_line_
, profile_manager_
->profile_info_cache(), true);
532 manager
.RegisterProfile(profile_
);
533 EXPECT_FALSE(chrome::WillKeepAlive());
535 // Install app, should show status tray icon.
536 EXPECT_CALL(manager
, EnableLaunchOnStartup(true)).Times(Exactly(1));
537 manager
.OnBackgroundAppInstalled(NULL
);
538 manager
.SetBackgroundAppCountForProfile(profile_
, 1);
539 manager
.OnApplicationListChanged(profile_
);
540 Mock::VerifyAndClearExpectations(&manager
);
542 // Background mode should remain active for the remainder of this test.
544 manager
.OnProfileNameChanged(
546 manager
.GetBackgroundModeData(profile_
)->name());
548 EXPECT_EQ(base::UTF8ToUTF16("p1"),
549 manager
.GetBackgroundModeData(profile_
)->name());
551 EXPECT_TRUE(chrome::WillKeepAlive());
552 TestingProfile
* profile2
= profile_manager_
->CreateTestingProfile("p2");
553 manager
.RegisterProfile(profile2
);
554 EXPECT_EQ(2, manager
.NumberOfBackgroundModeData());
556 manager
.OnProfileAdded(profile2
->GetPath());
557 EXPECT_EQ(base::UTF8ToUTF16("p2"),
558 manager
.GetBackgroundModeData(profile2
)->name());
560 manager
.OnProfileWillBeRemoved(profile2
->GetPath());
561 // Should still be in background mode after deleting profile.
562 EXPECT_TRUE(chrome::WillKeepAlive());
563 EXPECT_EQ(1, manager
.NumberOfBackgroundModeData());
565 // Check that the background mode data we think is in the map actually is.
566 EXPECT_EQ(base::UTF8ToUTF16("p1"),
567 manager
.GetBackgroundModeData(profile_
)->name());
570 TEST_F(BackgroundModeManagerTest
, DeleteBackgroundProfile
) {
571 // Tests whether deleting the only profile when it is a BG profile works
572 // or not (http://crbug.com/346214).
573 AdvancedTestBackgroundModeManager
manager(
574 *command_line_
, profile_manager_
->profile_info_cache(), true);
575 manager
.RegisterProfile(profile_
);
576 EXPECT_FALSE(chrome::WillKeepAlive());
578 // Install app, should show status tray icon.
579 EXPECT_CALL(manager
, EnableLaunchOnStartup(true)).Times(Exactly(1));
580 manager
.OnBackgroundAppInstalled(NULL
);
581 manager
.SetBackgroundAppCountForProfile(profile_
, 1);
582 manager
.OnApplicationListChanged(profile_
);
583 Mock::VerifyAndClearExpectations(&manager
);
585 manager
.OnProfileNameChanged(
587 manager
.GetBackgroundModeData(profile_
)->name());
589 EXPECT_CALL(manager
, EnableLaunchOnStartup(false)).Times(Exactly(1));
590 EXPECT_TRUE(chrome::WillKeepAlive());
591 manager
.SetBackgroundAppCountForProfile(profile_
, 0);
592 manager
.OnProfileWillBeRemoved(profile_
->GetPath());
593 Mock::VerifyAndClearExpectations(&manager
);
594 EXPECT_FALSE(chrome::WillKeepAlive());
597 TEST_F(BackgroundModeManagerTest
, DisableBackgroundModeUnderTestFlag
) {
598 command_line_
->AppendSwitch(switches::kKeepAliveForTest
);
599 AdvancedTestBackgroundModeManager
manager(
600 *command_line_
, profile_manager_
->profile_info_cache(), true);
601 manager
.RegisterProfile(profile_
);
602 EXPECT_TRUE(manager
.ShouldBeInBackgroundMode());
604 // No enable-launch-on-startup calls expected yet.
605 Mock::VerifyAndClearExpectations(&manager
);
606 EXPECT_CALL(manager
, EnableLaunchOnStartup(false)).Times(Exactly(1));
607 manager
.SetEnabled(false);
608 EXPECT_FALSE(manager
.ShouldBeInBackgroundMode());
611 TEST_F(BackgroundModeManagerTest
,
612 BackgroundModeDisabledPreventsKeepAliveOnStartup
) {
613 command_line_
->AppendSwitch(switches::kKeepAliveForTest
);
614 AdvancedTestBackgroundModeManager
manager(
615 *command_line_
, profile_manager_
->profile_info_cache(), false);
616 manager
.RegisterProfile(profile_
);
617 EXPECT_FALSE(manager
.ShouldBeInBackgroundMode());
620 TEST_F(BackgroundModeManagerWithExtensionsTest
, BackgroundMenuGeneration
) {
621 scoped_refptr
<extensions::Extension
> component_extension(
623 extensions::Manifest::COMPONENT
,
624 "{\"name\": \"Component Extension\","
625 "\"version\": \"1.0\","
626 "\"manifest_version\": 2,"
627 "\"permissions\": [\"background\"]}",
630 scoped_refptr
<extensions::Extension
> component_extension_with_options(
632 extensions::Manifest::COMPONENT
,
633 "{\"name\": \"Component Extension with Options\","
634 "\"version\": \"1.0\","
635 "\"manifest_version\": 2,"
636 "\"permissions\": [\"background\"],"
637 "\"options_page\": \"test.html\"}",
640 scoped_refptr
<extensions::Extension
> regular_extension(
642 extensions::Manifest::COMMAND_LINE
,
643 "{\"name\": \"Regular Extension\", "
644 "\"version\": \"1.0\","
645 "\"manifest_version\": 2,"
646 "\"permissions\": [\"background\"]}",
649 scoped_refptr
<extensions::Extension
> regular_extension_with_options(
651 extensions::Manifest::COMMAND_LINE
,
652 "{\"name\": \"Regular Extension with Options\","
653 "\"version\": \"1.0\","
654 "\"manifest_version\": 2,"
655 "\"permissions\": [\"background\"],"
656 "\"options_page\": \"test.html\"}",
659 static_cast<extensions::TestExtensionSystem
*>(
660 extensions::ExtensionSystem::Get(profile_
))
661 ->CreateExtensionService(base::CommandLine::ForCurrentProcess(),
662 base::FilePath(), false);
663 ExtensionService
* service
=
664 extensions::ExtensionSystem::Get(profile_
)->extension_service();
667 EXPECT_CALL(*manager_
, EnableLaunchOnStartup(true)).Times(Exactly(1));
668 service
->AddComponentExtension(component_extension
.get());
669 service
->AddComponentExtension(component_extension_with_options
.get());
670 service
->AddExtension(regular_extension
.get());
671 service
->AddExtension(regular_extension_with_options
.get());
672 Mock::VerifyAndClearExpectations(manager_
.get());
674 scoped_ptr
<StatusIconMenuModel
> menu(new StatusIconMenuModel(NULL
));
675 scoped_ptr
<StatusIconMenuModel
> submenu(new StatusIconMenuModel(NULL
));
676 BackgroundModeManager::BackgroundModeData
* bmd
=
677 manager_
->GetBackgroundModeData(profile_
);
678 bmd
->BuildProfileMenu(submenu
.get(), menu
.get());
680 submenu
->GetLabelAt(0) ==
681 base::UTF8ToUTF16("Component Extension"));
682 EXPECT_FALSE(submenu
->IsCommandIdEnabled(submenu
->GetCommandIdAt(0)));
684 submenu
->GetLabelAt(1) ==
685 base::UTF8ToUTF16("Component Extension with Options"));
686 EXPECT_TRUE(submenu
->IsCommandIdEnabled(submenu
->GetCommandIdAt(1)));
688 submenu
->GetLabelAt(2) ==
689 base::UTF8ToUTF16("Regular Extension"));
690 EXPECT_TRUE(submenu
->IsCommandIdEnabled(submenu
->GetCommandIdAt(2)));
692 submenu
->GetLabelAt(3) ==
693 base::UTF8ToUTF16("Regular Extension with Options"));
694 EXPECT_TRUE(submenu
->IsCommandIdEnabled(submenu
->GetCommandIdAt(3)));
697 TEST_F(BackgroundModeManagerWithExtensionsTest
,
698 BackgroundMenuGenerationMultipleProfile
) {
699 TestingProfile
* profile2
= profile_manager_
->CreateTestingProfile("p2");
700 scoped_refptr
<extensions::Extension
> component_extension(
702 extensions::Manifest::COMPONENT
,
703 "{\"name\": \"Component Extension\","
704 "\"version\": \"1.0\","
705 "\"manifest_version\": 2,"
706 "\"permissions\": [\"background\"]}",
709 scoped_refptr
<extensions::Extension
> component_extension_with_options(
711 extensions::Manifest::COMPONENT
,
712 "{\"name\": \"Component Extension with Options\","
713 "\"version\": \"1.0\","
714 "\"manifest_version\": 2,"
715 "\"permissions\": [\"background\"],"
716 "\"options_page\": \"test.html\"}",
719 scoped_refptr
<extensions::Extension
> regular_extension(
721 extensions::Manifest::COMMAND_LINE
,
722 "{\"name\": \"Regular Extension\", "
723 "\"version\": \"1.0\","
724 "\"manifest_version\": 2,"
725 "\"permissions\": [\"background\"]}",
728 scoped_refptr
<extensions::Extension
> regular_extension_with_options(
730 extensions::Manifest::COMMAND_LINE
,
731 "{\"name\": \"Regular Extension with Options\","
732 "\"version\": \"1.0\","
733 "\"manifest_version\": 2,"
734 "\"permissions\": [\"background\"],"
735 "\"options_page\": \"test.html\"}",
738 static_cast<extensions::TestExtensionSystem
*>(
739 extensions::ExtensionSystem::Get(profile_
))
740 ->CreateExtensionService(base::CommandLine::ForCurrentProcess(),
741 base::FilePath(), false);
742 ExtensionService
* service1
=
743 extensions::ExtensionSystem::Get(profile_
)->extension_service();
746 EXPECT_CALL(*manager_
, EnableLaunchOnStartup(true)).Times(Exactly(1));
747 service1
->AddComponentExtension(component_extension
.get());
748 service1
->AddComponentExtension(component_extension_with_options
.get());
749 service1
->AddExtension(regular_extension
.get());
750 service1
->AddExtension(regular_extension_with_options
.get());
751 Mock::VerifyAndClearExpectations(manager_
.get());
753 static_cast<extensions::TestExtensionSystem
*>(
754 extensions::ExtensionSystem::Get(profile2
))
755 ->CreateExtensionService(base::CommandLine::ForCurrentProcess(),
756 base::FilePath(), false);
757 ExtensionService
* service2
=
758 extensions::ExtensionSystem::Get(profile2
)->extension_service();
761 service2
->AddComponentExtension(component_extension
.get());
762 service2
->AddExtension(regular_extension
.get());
763 service2
->AddExtension(regular_extension_with_options
.get());
765 manager_
->RegisterProfile(profile2
);
767 manager_
->status_icon_
= new TestStatusIcon();
768 manager_
->UpdateStatusTrayIconContextMenu();
769 StatusIconMenuModel
* context_menu
= manager_
->context_menu_
;
770 EXPECT_TRUE(context_menu
!= NULL
);
772 // Background Profile Enable Checks
773 EXPECT_TRUE(context_menu
->GetLabelAt(3) == base::UTF8ToUTF16("p1"));
775 context_menu
->IsCommandIdEnabled(context_menu
->GetCommandIdAt(3)));
776 EXPECT_TRUE(context_menu
->GetCommandIdAt(3) == 4);
778 EXPECT_TRUE(context_menu
->GetLabelAt(4) == base::UTF8ToUTF16("p2"));
780 context_menu
->IsCommandIdEnabled(context_menu
->GetCommandIdAt(4)));
781 EXPECT_TRUE(context_menu
->GetCommandIdAt(4) == 8);
783 // Profile 1 Submenu Checks
784 StatusIconMenuModel
* profile1_submenu
=
785 static_cast<StatusIconMenuModel
*>(context_menu
->GetSubmenuModelAt(3));
787 profile1_submenu
->GetLabelAt(0) ==
788 base::UTF8ToUTF16("Component Extension"));
790 profile1_submenu
->IsCommandIdEnabled(
791 profile1_submenu
->GetCommandIdAt(0)));
792 EXPECT_TRUE(profile1_submenu
->GetCommandIdAt(0) == 0);
794 profile1_submenu
->GetLabelAt(1) ==
795 base::UTF8ToUTF16("Component Extension with Options"));
797 profile1_submenu
->IsCommandIdEnabled(
798 profile1_submenu
->GetCommandIdAt(1)));
799 EXPECT_TRUE(profile1_submenu
->GetCommandIdAt(1) == 1);
801 profile1_submenu
->GetLabelAt(2) ==
802 base::UTF8ToUTF16("Regular Extension"));
804 profile1_submenu
->IsCommandIdEnabled(
805 profile1_submenu
->GetCommandIdAt(2)));
806 EXPECT_TRUE(profile1_submenu
->GetCommandIdAt(2) == 2);
808 profile1_submenu
->GetLabelAt(3) ==
809 base::UTF8ToUTF16("Regular Extension with Options"));
811 profile1_submenu
->IsCommandIdEnabled(
812 profile1_submenu
->GetCommandIdAt(3)));
813 EXPECT_TRUE(profile1_submenu
->GetCommandIdAt(3) == 3);
815 // Profile 2 Submenu Checks
816 StatusIconMenuModel
* profile2_submenu
=
817 static_cast<StatusIconMenuModel
*>(context_menu
->GetSubmenuModelAt(4));
819 profile2_submenu
->GetLabelAt(0) ==
820 base::UTF8ToUTF16("Component Extension"));
822 profile2_submenu
->IsCommandIdEnabled(
823 profile2_submenu
->GetCommandIdAt(0)));
824 EXPECT_TRUE(profile2_submenu
->GetCommandIdAt(0) == 5);
826 profile2_submenu
->GetLabelAt(1) ==
827 base::UTF8ToUTF16("Regular Extension"));
829 profile2_submenu
->IsCommandIdEnabled(
830 profile2_submenu
->GetCommandIdAt(1)));
831 EXPECT_TRUE(profile2_submenu
->GetCommandIdAt(1) == 6);
833 profile2_submenu
->GetLabelAt(2) ==
834 base::UTF8ToUTF16("Regular Extension with Options"));
836 profile2_submenu
->IsCommandIdEnabled(
837 profile2_submenu
->GetCommandIdAt(2)));
838 EXPECT_TRUE(profile2_submenu
->GetCommandIdAt(2) == 7);
840 // Model Adapter Checks for crbug.com/315164
841 // P1: Profile 1 Menu Item
842 // P2: Profile 2 Menu Item
843 // CE: Component Extension Menu Item
844 // CEO: Component Extenison with Options Menu Item
845 // RE: Regular Extension Menu Item
846 // REO: Regular Extension with Options Menu Item
847 EXPECT_FALSE(IsCommandEnabled(context_menu
, 0)); // P1 - CE
848 EXPECT_TRUE(IsCommandEnabled(context_menu
, 1)); // P1 - CEO
849 EXPECT_TRUE(IsCommandEnabled(context_menu
, 2)); // P1 - RE
850 EXPECT_TRUE(IsCommandEnabled(context_menu
, 3)); // P1 - REO
851 EXPECT_TRUE(IsCommandEnabled(context_menu
, 4)); // P1
852 EXPECT_FALSE(IsCommandEnabled(context_menu
, 5)); // P2 - CE
853 EXPECT_TRUE(IsCommandEnabled(context_menu
, 6)); // P2 - RE
854 EXPECT_TRUE(IsCommandEnabled(context_menu
, 7)); // P2 - REO
855 EXPECT_TRUE(IsCommandEnabled(context_menu
, 8)); // P2
858 TEST_F(BackgroundModeManagerWithExtensionsTest
, BalloonDisplay
) {
859 scoped_refptr
<extensions::Extension
> bg_ext(
861 extensions::Manifest::COMMAND_LINE
,
862 "{\"name\": \"Background Extension\", "
863 "\"version\": \"1.0\","
864 "\"manifest_version\": 2,"
865 "\"permissions\": [\"background\"]}",
868 scoped_refptr
<extensions::Extension
> upgraded_bg_ext(
870 extensions::Manifest::COMMAND_LINE
,
871 "{\"name\": \"Background Extension\", "
872 "\"version\": \"2.0\","
873 "\"manifest_version\": 2,"
874 "\"permissions\": [\"background\"]}",
877 scoped_refptr
<extensions::Extension
> no_bg_ext(
879 extensions::Manifest::COMMAND_LINE
,
880 "{\"name\": \"Regular Extension\", "
881 "\"version\": \"1.0\","
882 "\"manifest_version\": 2,"
883 "\"permissions\": []}",
886 scoped_refptr
<extensions::Extension
> upgraded_no_bg_ext_has_bg(
888 extensions::Manifest::COMMAND_LINE
,
889 "{\"name\": \"Regular Extension\", "
890 "\"version\": \"2.0\","
891 "\"manifest_version\": 2,"
892 "\"permissions\": [\"background\"]}",
895 static_cast<extensions::TestExtensionSystem
*>(
896 extensions::ExtensionSystem::Get(profile_
))
897 ->CreateExtensionService(base::CommandLine::ForCurrentProcess(),
898 base::FilePath(), false);
900 ExtensionService
* service
=
901 extensions::ExtensionSystem::Get(profile_
)->extension_service();
902 ASSERT_FALSE(service
->is_ready());
905 ASSERT_TRUE(service
->is_ready());
906 manager_
->status_icon_
= new TestStatusIcon();
907 manager_
->UpdateStatusTrayIconContextMenu();
909 // Adding a background extension should show the balloon.
910 EXPECT_FALSE(manager_
->HasShownBalloon());
911 EXPECT_CALL(*manager_
, EnableLaunchOnStartup(true)).Times(Exactly(1));
912 service
->AddExtension(bg_ext
.get());
913 Mock::VerifyAndClearExpectations(manager_
.get());
914 EXPECT_TRUE(manager_
->HasShownBalloon());
916 // Adding an extension without background should not show the balloon.
917 manager_
->SetHasShownBalloon(false);
918 service
->AddExtension(no_bg_ext
.get());
919 EXPECT_FALSE(manager_
->HasShownBalloon());
921 // Upgrading an extension that has background should not reshow the balloon.
923 // TODO: Fix crbug.com/438376 and remove these checks.
924 InSequence expected_call_sequence
;
925 EXPECT_CALL(*manager_
, EnableLaunchOnStartup(false)).Times(Exactly(1));
926 EXPECT_CALL(*manager_
, EnableLaunchOnStartup(true)).Times(Exactly(1));
928 service
->AddExtension(upgraded_bg_ext
.get());
929 Mock::VerifyAndClearExpectations(manager_
.get());
930 EXPECT_FALSE(manager_
->HasShownBalloon());
932 // Upgrading an extension that didn't have background to one that does should
934 service
->AddExtension(upgraded_no_bg_ext_has_bg
.get());
935 EXPECT_TRUE(manager_
->HasShownBalloon());