Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / background / background_mode_manager_unittest.cc
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/message_loop/message_loop.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/background/background_mode_manager.h"
10 #include "chrome/browser/browser_shutdown.h"
11 #include "chrome/browser/extensions/extension_function_test_utils.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/extensions/test_extension_system.h"
14 #include "chrome/browser/lifetime/application_lifetime.h"
15 #include "chrome/browser/profiles/profile_info_cache.h"
16 #include "chrome/browser/status_icons/status_icon_menu_model.h"
17 #include "chrome/common/chrome_switches.h"
18 #include "chrome/test/base/testing_browser_process.h"
19 #include "chrome/test/base/testing_profile.h"
20 #include "chrome/test/base/testing_profile_manager.h"
21 #include "content/public/test/test_browser_thread_bundle.h"
22 #include "extensions/browser/extension_prefs.h"
23 #include "extensions/browser/extension_system.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "ui/gfx/image/image.h"
26 #include "ui/gfx/image/image_unittest_util.h"
27 #include "ui/message_center/message_center.h"
28
29 #if defined(OS_CHROMEOS)
30 #include "chrome/browser/chromeos/login/users/scoped_test_user_manager.h"
31 #include "chrome/browser/chromeos/settings/cros_settings.h"
32 #include "chrome/browser/chromeos/settings/device_settings_service.h"
33 #endif
34
35 namespace {
36
37 // Helper class that tracks state transitions in BackgroundModeManager and
38 // exposes them via getters.
39 class SimpleTestBackgroundModeManager : public BackgroundModeManager {
40  public:
41   SimpleTestBackgroundModeManager(
42       CommandLine* command_line, ProfileInfoCache* cache)
43       : BackgroundModeManager(command_line, cache),
44         have_status_tray_(false),
45         launch_on_startup_(false),
46         has_shown_balloon_(false) {
47     ResumeBackgroundMode();
48   }
49
50   virtual void EnableLaunchOnStartup(bool launch) OVERRIDE {
51     launch_on_startup_ = launch;
52   }
53
54   virtual void DisplayAppInstalledNotification(
55       const extensions::Extension* extension) OVERRIDE {
56     has_shown_balloon_ = true;
57   }
58   virtual void CreateStatusTrayIcon() OVERRIDE { have_status_tray_ = true; }
59   virtual void RemoveStatusTrayIcon() OVERRIDE { have_status_tray_ = false; }
60
61   bool HaveStatusTray() const { return have_status_tray_; }
62   bool IsLaunchOnStartup() const { return launch_on_startup_; }
63   bool HasShownBalloon() const { return has_shown_balloon_; }
64   void SetHasShownBalloon(bool value) { has_shown_balloon_ = value; }
65
66  private:
67   // Flags to track whether we are launching on startup/have a status tray.
68   bool have_status_tray_;
69   bool launch_on_startup_;
70   bool has_shown_balloon_;
71
72   DISALLOW_COPY_AND_ASSIGN(SimpleTestBackgroundModeManager);
73 };
74
75 class TestStatusIcon : public StatusIcon {
76  public:
77   TestStatusIcon() {}
78   virtual void SetImage(const gfx::ImageSkia& image) OVERRIDE {}
79   virtual void SetPressedImage(const gfx::ImageSkia& image) OVERRIDE {}
80   virtual void SetToolTip(const base::string16& tool_tip) OVERRIDE {}
81   virtual void DisplayBalloon(const gfx::ImageSkia& icon,
82                               const base::string16& title,
83                               const base::string16& contents) OVERRIDE {}
84   virtual void UpdatePlatformContextMenu(
85       StatusIconMenuModel* menu) OVERRIDE {}
86
87  private:
88   DISALLOW_COPY_AND_ASSIGN(TestStatusIcon);
89 };
90
91 } // namespace
92
93 // More complex test helper that exposes APIs for fine grained control of
94 // things like the number of background applications. This allows writing
95 // smaller tests that don't have to install/uninstall extensions.
96 class TestBackgroundModeManager : public SimpleTestBackgroundModeManager {
97  public:
98   TestBackgroundModeManager(
99       CommandLine* command_line, ProfileInfoCache* cache, bool enabled)
100       : SimpleTestBackgroundModeManager(command_line, cache),
101         enabled_(enabled),
102         app_count_(0),
103         profile_app_count_(0) {
104     ResumeBackgroundMode();
105   }
106
107   virtual int GetBackgroundAppCount() const OVERRIDE { return app_count_; }
108   virtual int GetBackgroundAppCountForProfile(
109       Profile* const profile) const OVERRIDE {
110     return profile_app_count_;
111   }
112   void SetBackgroundAppCount(int count) { app_count_ = count; }
113   void SetBackgroundAppCountForProfile(int count) {
114     profile_app_count_ = count;
115   }
116   void SetEnabled(bool enabled) {
117     enabled_ = enabled;
118     OnBackgroundModeEnabledPrefChanged();
119   }
120   virtual bool IsBackgroundModePrefEnabled() const OVERRIDE { return enabled_; }
121
122  private:
123   bool enabled_;
124   int app_count_;
125   int profile_app_count_;
126
127   DISALLOW_COPY_AND_ASSIGN(TestBackgroundModeManager);
128 };
129
130 namespace {
131
132 void AssertBackgroundModeActive(
133     const TestBackgroundModeManager& manager) {
134   EXPECT_TRUE(chrome::WillKeepAlive());
135   EXPECT_TRUE(manager.HaveStatusTray());
136   EXPECT_TRUE(manager.IsLaunchOnStartup());
137 }
138
139 void AssertBackgroundModeInactive(
140     const TestBackgroundModeManager& manager) {
141   EXPECT_FALSE(chrome::WillKeepAlive());
142   EXPECT_FALSE(manager.HaveStatusTray());
143   EXPECT_FALSE(manager.IsLaunchOnStartup());
144 }
145
146 void AssertBackgroundModeSuspended(
147     const TestBackgroundModeManager& manager) {
148   EXPECT_FALSE(chrome::WillKeepAlive());
149   EXPECT_FALSE(manager.HaveStatusTray());
150   EXPECT_TRUE(manager.IsLaunchOnStartup());
151 }
152
153 } // namespace
154
155 class BackgroundModeManagerTest : public testing::Test {
156  public:
157   BackgroundModeManagerTest() {}
158   virtual ~BackgroundModeManagerTest() {}
159   virtual void SetUp() OVERRIDE {
160     command_line_.reset(new CommandLine(CommandLine::NO_PROGRAM));
161     profile_manager_ = CreateTestingProfileManager();
162     profile_ = profile_manager_->CreateTestingProfile("p1");
163   }
164   scoped_ptr<CommandLine> command_line_;
165
166  protected:
167   scoped_refptr<extensions::Extension> CreateExtension(
168       extensions::Manifest::Location location,
169       const std::string& data,
170       const std::string& id) {
171     scoped_ptr<base::DictionaryValue> parsed_manifest(
172         extension_function_test_utils::ParseDictionary(data));
173     return extension_function_test_utils::CreateExtension(
174         location,
175         parsed_manifest.get(),
176         id);
177   }
178
179   // From views::MenuModelAdapter::IsCommandEnabled with modification.
180   bool IsCommandEnabled(ui::MenuModel* model, int id) const {
181     int index = 0;
182     if (ui::MenuModel::GetModelAndIndexForCommandId(id, &model, &index))
183       return model->IsEnabledAt(index);
184
185     return false;
186   }
187
188   scoped_ptr<TestingProfileManager> profile_manager_;
189   // Test profile used by all tests - this is owned by profile_manager_.
190   TestingProfile* profile_;
191
192  private:
193   scoped_ptr<TestingProfileManager> CreateTestingProfileManager() {
194     scoped_ptr<TestingProfileManager> profile_manager
195         (new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
196     EXPECT_TRUE(profile_manager->SetUp());
197     return profile_manager.Pass();
198   }
199
200   DISALLOW_COPY_AND_ASSIGN(BackgroundModeManagerTest);
201 };
202
203 class BackgroundModeManagerWithExtensionsTest
204     : public BackgroundModeManagerTest {
205  public:
206   BackgroundModeManagerWithExtensionsTest() {}
207   virtual ~BackgroundModeManagerWithExtensionsTest() {}
208   virtual void SetUp() OVERRIDE {
209     BackgroundModeManagerTest::SetUp();
210     // Aura clears notifications from the message center at shutdown.
211     message_center::MessageCenter::Initialize();
212
213     // BackgroundModeManager actually affects Chrome start/stop state,
214     // tearing down our thread bundle before we've had chance to clean
215     // everything up. Keeping Chrome alive prevents this.
216     // We aren't interested in if the keep alive works correctly in this test.
217     chrome::IncrementKeepAliveCount();
218
219 #if defined(OS_CHROMEOS)
220     // On ChromeOS shutdown, HandleAppExitingForPlatform will call
221     // chrome::DecrementKeepAliveCount because it assumes the aura shell
222     // called chrome::IncrementKeepAliveCount. Simulate the call here.
223     chrome::IncrementKeepAliveCount();
224 #endif
225
226     // Create our test BackgroundModeManager.
227     manager_.reset(new SimpleTestBackgroundModeManager(
228         command_line_.get(), profile_manager_->profile_info_cache()));
229     manager_->RegisterProfile(profile_);
230   }
231
232   virtual void TearDown() {
233     // Clean up the status icon. If this is not done before profile deletes,
234     // the context menu updates will DCHECK with the now deleted profiles.
235     StatusIcon* status_icon = manager_->status_icon_;
236     manager_->status_icon_ = NULL;
237     delete status_icon;
238
239     // We have to destroy the profiles now because we created them with real
240     // thread state. This causes a lot of machinery to spin up that stops
241     // working when we tear down our thread state at the end of the test.
242     profile_manager_->DeleteAllTestingProfiles();
243
244     // We're getting ready to shutdown the message loop. Clear everything out!
245     base::MessageLoop::current()->RunUntilIdle();
246     // Matching the call to IncrementKeepAliveCount in SetUp().
247     chrome::DecrementKeepAliveCount();
248
249     // SimpleTestBackgroundModeManager has dependencies on the infrastructure.
250     // It should get cleared first.
251     manager_.reset();
252
253     // The Profile Manager references the Browser Process.
254     // The Browser Process references the Notification UI Manager.
255     // The Notification UI Manager references the Message Center.
256     // As a result, we have to clear the browser process state here
257     // before tearing down the Message Center.
258     profile_manager_.reset();
259
260     // Message Center shutdown must occur after the DecrementKeepAliveCount
261     // because DecrementKeepAliveCount will end up referencing the message
262     // center during cleanup.
263     message_center::MessageCenter::Shutdown();
264
265     // Clear the shutdown flag to isolate the remaining effect of this test.
266     browser_shutdown::SetTryingToQuit(false);
267   }
268
269  protected:
270   scoped_ptr<SimpleTestBackgroundModeManager> manager_;
271
272   void AddEphemeralApp(const extensions::Extension* extension,
273                        ExtensionService* service) {
274     extensions::ExtensionPrefs* prefs =
275         extensions::ExtensionPrefs::Get(service->profile());
276     ASSERT_TRUE(prefs);
277     prefs->OnExtensionInstalled(extension,
278                                 extensions::Extension::ENABLED,
279                                 syncer::StringOrdinal(),
280                                 extensions::kInstallFlagIsEphemeral,
281                                 std::string());
282
283     service->AddExtension(extension);
284   }
285
286  private:
287   // Required for extension service.
288   content::TestBrowserThreadBundle thread_bundle_;
289
290 #if defined(OS_CHROMEOS)
291   // ChromeOS needs extra services to run in the following order.
292   chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
293   chromeos::ScopedTestCrosSettings test_cros_settings_;
294   chromeos::ScopedTestUserManager test_user_manager_;
295 #endif
296
297   DISALLOW_COPY_AND_ASSIGN(BackgroundModeManagerWithExtensionsTest);
298 };
299
300
301 TEST_F(BackgroundModeManagerTest, BackgroundAppLoadUnload) {
302   TestBackgroundModeManager manager(
303       command_line_.get(), profile_manager_->profile_info_cache(), true);
304   manager.RegisterProfile(profile_);
305   EXPECT_FALSE(chrome::WillKeepAlive());
306
307   // Mimic app load.
308   manager.OnBackgroundAppInstalled(NULL);
309   manager.SetBackgroundAppCount(1);
310   manager.OnApplicationListChanged(profile_);
311   AssertBackgroundModeActive(manager);
312
313   manager.SuspendBackgroundMode();
314   AssertBackgroundModeSuspended(manager);
315   manager.ResumeBackgroundMode();
316
317   // Mimic app unload.
318   manager.SetBackgroundAppCount(0);
319   manager.OnApplicationListChanged(profile_);
320   AssertBackgroundModeInactive(manager);
321
322   manager.SuspendBackgroundMode();
323   AssertBackgroundModeInactive(manager);
324
325   // Mimic app load while suspended, e.g. from sync. This should enable and
326   // resume background mode.
327   manager.OnBackgroundAppInstalled(NULL);
328   manager.SetBackgroundAppCount(1);
329   manager.OnApplicationListChanged(profile_);
330   AssertBackgroundModeActive(manager);
331 }
332
333 // App installs while background mode is disabled should do nothing.
334 TEST_F(BackgroundModeManagerTest, BackgroundAppInstallUninstallWhileDisabled) {
335   TestBackgroundModeManager manager(
336       command_line_.get(), profile_manager_->profile_info_cache(), true);
337   manager.RegisterProfile(profile_);
338   // Turn off background mode.
339   manager.SetEnabled(false);
340   manager.DisableBackgroundMode();
341   AssertBackgroundModeInactive(manager);
342
343   // Status tray icons will not be created, launch on startup status will not
344   // be modified.
345   manager.OnBackgroundAppInstalled(NULL);
346   manager.SetBackgroundAppCount(1);
347   manager.OnApplicationListChanged(profile_);
348   AssertBackgroundModeInactive(manager);
349
350   manager.SetBackgroundAppCount(0);
351   manager.OnApplicationListChanged(profile_);
352   AssertBackgroundModeInactive(manager);
353
354   // Re-enable background mode.
355   manager.SetEnabled(true);
356   manager.EnableBackgroundMode();
357   AssertBackgroundModeInactive(manager);
358 }
359
360
361 // App installs while disabled should do nothing until background mode is
362 // enabled..
363 TEST_F(BackgroundModeManagerTest, EnableAfterBackgroundAppInstall) {
364   TestBackgroundModeManager manager(
365       command_line_.get(), profile_manager_->profile_info_cache(), true);
366   manager.RegisterProfile(profile_);
367
368   // Install app, should show status tray icon.
369   manager.OnBackgroundAppInstalled(NULL);
370   // OnBackgroundAppInstalled does not actually add an app to the
371   // BackgroundApplicationListModel which would result in another
372   // call to CreateStatusTray.
373   manager.SetBackgroundAppCount(1);
374   manager.OnApplicationListChanged(profile_);
375   AssertBackgroundModeActive(manager);
376
377   // Turn off background mode - should hide status tray icon.
378   manager.SetEnabled(false);
379   manager.DisableBackgroundMode();
380   AssertBackgroundModeInactive(manager);
381
382   // Turn back on background mode - again, no status tray icon
383   // will show up since we didn't actually add anything to the list.
384   manager.SetEnabled(true);
385   manager.EnableBackgroundMode();
386   AssertBackgroundModeActive(manager);
387
388   // Uninstall app, should hide status tray icon again.
389   manager.SetBackgroundAppCount(0);
390   manager.OnApplicationListChanged(profile_);
391   AssertBackgroundModeInactive(manager);
392 }
393
394 TEST_F(BackgroundModeManagerTest, MultiProfile) {
395   TestingProfile* profile2 = profile_manager_->CreateTestingProfile("p2");
396   TestBackgroundModeManager manager(
397       command_line_.get(), profile_manager_->profile_info_cache(), true);
398   manager.RegisterProfile(profile_);
399   manager.RegisterProfile(profile2);
400   EXPECT_FALSE(chrome::WillKeepAlive());
401
402   // Install app, should show status tray icon.
403   manager.OnBackgroundAppInstalled(NULL);
404   manager.SetBackgroundAppCount(1);
405   manager.OnApplicationListChanged(profile_);
406   AssertBackgroundModeActive(manager);
407
408   // Install app for other profile, hsould show other status tray icon.
409   manager.OnBackgroundAppInstalled(NULL);
410   manager.SetBackgroundAppCount(2);
411   manager.OnApplicationListChanged(profile2);
412   AssertBackgroundModeActive(manager);
413
414   // Should hide both status tray icons.
415   manager.SetEnabled(false);
416   manager.DisableBackgroundMode();
417   AssertBackgroundModeInactive(manager);
418
419   // Turn back on background mode - should show both status tray icons.
420   manager.SetEnabled(true);
421   manager.EnableBackgroundMode();
422   AssertBackgroundModeActive(manager);
423
424   manager.SetBackgroundAppCount(1);
425   manager.OnApplicationListChanged(profile2);
426   // There is still one background app alive
427   AssertBackgroundModeActive(manager);
428
429   manager.SetBackgroundAppCount(0);
430   manager.OnApplicationListChanged(profile_);
431   AssertBackgroundModeInactive(manager);
432 }
433
434 TEST_F(BackgroundModeManagerTest, ProfileInfoCacheStorage) {
435   TestingProfile* profile2 = profile_manager_->CreateTestingProfile("p2");
436   TestBackgroundModeManager manager(
437       command_line_.get(), profile_manager_->profile_info_cache(), true);
438   manager.RegisterProfile(profile_);
439   manager.RegisterProfile(profile2);
440   EXPECT_FALSE(chrome::WillKeepAlive());
441
442   ProfileInfoCache* cache = profile_manager_->profile_info_cache();
443   EXPECT_EQ(2u, cache->GetNumberOfProfiles());
444
445   EXPECT_FALSE(cache->GetBackgroundStatusOfProfileAtIndex(0));
446   EXPECT_FALSE(cache->GetBackgroundStatusOfProfileAtIndex(1));
447
448   // Install app, should show status tray icon.
449   manager.OnBackgroundAppInstalled(NULL);
450   manager.SetBackgroundAppCount(1);
451   manager.SetBackgroundAppCountForProfile(1);
452   manager.OnApplicationListChanged(profile_);
453
454   // Install app for other profile.
455   manager.OnBackgroundAppInstalled(NULL);
456   manager.SetBackgroundAppCount(1);
457   manager.SetBackgroundAppCountForProfile(1);
458   manager.OnApplicationListChanged(profile2);
459
460   EXPECT_TRUE(cache->GetBackgroundStatusOfProfileAtIndex(0));
461   EXPECT_TRUE(cache->GetBackgroundStatusOfProfileAtIndex(1));
462
463   manager.SetBackgroundAppCountForProfile(0);
464   manager.OnApplicationListChanged(profile_);
465
466   size_t p1_index = cache->GetIndexOfProfileWithPath(profile_->GetPath());
467   EXPECT_FALSE(cache->GetBackgroundStatusOfProfileAtIndex(p1_index));
468
469   manager.SetBackgroundAppCountForProfile(0);
470   manager.OnApplicationListChanged(profile2);
471
472   size_t p2_index = cache->GetIndexOfProfileWithPath(profile_->GetPath());
473   EXPECT_FALSE(cache->GetBackgroundStatusOfProfileAtIndex(p2_index));
474
475   // Even though neither has background status on, there should still be two
476   // profiles in the cache.
477   EXPECT_EQ(2u, cache->GetNumberOfProfiles());
478 }
479
480 TEST_F(BackgroundModeManagerTest, ProfileInfoCacheObserver) {
481   TestBackgroundModeManager manager(
482       command_line_.get(), profile_manager_->profile_info_cache(), true);
483   manager.RegisterProfile(profile_);
484   EXPECT_FALSE(chrome::WillKeepAlive());
485
486   // Install app, should show status tray icon.
487   manager.OnBackgroundAppInstalled(NULL);
488   manager.SetBackgroundAppCount(1);
489   manager.SetBackgroundAppCountForProfile(1);
490   manager.OnApplicationListChanged(profile_);
491
492   manager.OnProfileNameChanged(
493       profile_->GetPath(),
494       manager.GetBackgroundModeData(profile_)->name());
495
496   EXPECT_EQ(base::UTF8ToUTF16("p1"),
497             manager.GetBackgroundModeData(profile_)->name());
498
499   EXPECT_TRUE(chrome::WillKeepAlive());
500   TestingProfile* profile2 = profile_manager_->CreateTestingProfile("p2");
501   manager.RegisterProfile(profile2);
502   EXPECT_EQ(2, manager.NumberOfBackgroundModeData());
503
504   manager.OnProfileAdded(profile2->GetPath());
505   EXPECT_EQ(base::UTF8ToUTF16("p2"),
506             manager.GetBackgroundModeData(profile2)->name());
507
508   manager.OnProfileWillBeRemoved(profile2->GetPath());
509   // Should still be in background mode after deleting profile.
510   EXPECT_TRUE(chrome::WillKeepAlive());
511   EXPECT_EQ(1, manager.NumberOfBackgroundModeData());
512
513   // Check that the background mode data we think is in the map actually is.
514   EXPECT_EQ(base::UTF8ToUTF16("p1"),
515             manager.GetBackgroundModeData(profile_)->name());
516 }
517
518 TEST_F(BackgroundModeManagerTest, DeleteBackgroundProfile) {
519   // Tests whether deleting the only profile when it is a BG profile works
520   // or not (http://crbug.com/346214).
521   TestBackgroundModeManager manager(
522       command_line_.get(), profile_manager_->profile_info_cache(), true);
523   manager.RegisterProfile(profile_);
524   EXPECT_FALSE(chrome::WillKeepAlive());
525
526   // Install app, should show status tray icon.
527   manager.OnBackgroundAppInstalled(NULL);
528   manager.SetBackgroundAppCount(1);
529   manager.SetBackgroundAppCountForProfile(1);
530   manager.OnApplicationListChanged(profile_);
531
532   manager.OnProfileNameChanged(
533       profile_->GetPath(),
534       manager.GetBackgroundModeData(profile_)->name());
535
536   EXPECT_TRUE(chrome::WillKeepAlive());
537   manager.SetBackgroundAppCount(0);
538   manager.SetBackgroundAppCountForProfile(0);
539   manager.OnProfileWillBeRemoved(profile_->GetPath());
540   EXPECT_FALSE(chrome::WillKeepAlive());
541 }
542
543 TEST_F(BackgroundModeManagerTest, DisableBackgroundModeUnderTestFlag) {
544   command_line_->AppendSwitch(switches::kKeepAliveForTest);
545   TestBackgroundModeManager manager(
546       command_line_.get(), profile_manager_->profile_info_cache(), true);
547   manager.RegisterProfile(profile_);
548   EXPECT_TRUE(manager.ShouldBeInBackgroundMode());
549   manager.SetEnabled(false);
550   EXPECT_FALSE(manager.ShouldBeInBackgroundMode());
551 }
552
553 TEST_F(BackgroundModeManagerTest,
554        BackgroundModeDisabledPreventsKeepAliveOnStartup) {
555   command_line_->AppendSwitch(switches::kKeepAliveForTest);
556   TestBackgroundModeManager manager(
557       command_line_.get(), profile_manager_->profile_info_cache(), false);
558   manager.RegisterProfile(profile_);
559   EXPECT_FALSE(manager.ShouldBeInBackgroundMode());
560 }
561
562 TEST_F(BackgroundModeManagerWithExtensionsTest, BackgroundMenuGeneration) {
563   scoped_refptr<extensions::Extension> component_extension(
564     CreateExtension(
565         extensions::Manifest::COMPONENT,
566         "{\"name\": \"Component Extension\","
567         "\"version\": \"1.0\","
568         "\"manifest_version\": 2,"
569         "\"permissions\": [\"background\"]}",
570         "ID-1"));
571
572   scoped_refptr<extensions::Extension> component_extension_with_options(
573     CreateExtension(
574         extensions::Manifest::COMPONENT,
575         "{\"name\": \"Component Extension with Options\","
576         "\"version\": \"1.0\","
577         "\"manifest_version\": 2,"
578         "\"permissions\": [\"background\"],"
579         "\"options_page\": \"test.html\"}",
580         "ID-2"));
581
582   scoped_refptr<extensions::Extension> regular_extension(
583     CreateExtension(
584         extensions::Manifest::COMMAND_LINE,
585         "{\"name\": \"Regular Extension\", "
586         "\"version\": \"1.0\","
587         "\"manifest_version\": 2,"
588         "\"permissions\": [\"background\"]}",
589         "ID-3"));
590
591   scoped_refptr<extensions::Extension> regular_extension_with_options(
592     CreateExtension(
593         extensions::Manifest::COMMAND_LINE,
594         "{\"name\": \"Regular Extension with Options\","
595         "\"version\": \"1.0\","
596         "\"manifest_version\": 2,"
597         "\"permissions\": [\"background\"],"
598         "\"options_page\": \"test.html\"}",
599         "ID-4"));
600
601   static_cast<extensions::TestExtensionSystem*>(
602       extensions::ExtensionSystem::Get(profile_))->CreateExtensionService(
603           CommandLine::ForCurrentProcess(),
604           base::FilePath(),
605           false);
606   ExtensionService* service =
607       extensions::ExtensionSystem::Get(profile_)->extension_service();
608   service->Init();
609
610   service->AddComponentExtension(component_extension);
611   service->AddComponentExtension(component_extension_with_options);
612   service->AddExtension(regular_extension);
613   service->AddExtension(regular_extension_with_options);
614
615   scoped_ptr<StatusIconMenuModel> menu(new StatusIconMenuModel(NULL));
616   scoped_ptr<StatusIconMenuModel> submenu(new StatusIconMenuModel(NULL));
617   BackgroundModeManager::BackgroundModeData* bmd =
618       manager_->GetBackgroundModeData(profile_);
619   bmd->BuildProfileMenu(submenu.get(), menu.get());
620   EXPECT_TRUE(
621       submenu->GetLabelAt(0) ==
622           base::UTF8ToUTF16("Component Extension"));
623   EXPECT_FALSE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(0)));
624   EXPECT_TRUE(
625       submenu->GetLabelAt(1) ==
626           base::UTF8ToUTF16("Component Extension with Options"));
627   EXPECT_TRUE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(1)));
628   EXPECT_TRUE(
629       submenu->GetLabelAt(2) ==
630           base::UTF8ToUTF16("Regular Extension"));
631   EXPECT_TRUE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(2)));
632   EXPECT_TRUE(
633       submenu->GetLabelAt(3) ==
634           base::UTF8ToUTF16("Regular Extension with Options"));
635   EXPECT_TRUE(submenu->IsCommandIdEnabled(submenu->GetCommandIdAt(3)));
636 }
637
638 TEST_F(BackgroundModeManagerWithExtensionsTest,
639        BackgroundMenuGenerationMultipleProfile) {
640   TestingProfile* profile2 = profile_manager_->CreateTestingProfile("p2");
641   scoped_refptr<extensions::Extension> component_extension(
642     CreateExtension(
643         extensions::Manifest::COMPONENT,
644         "{\"name\": \"Component Extension\","
645         "\"version\": \"1.0\","
646         "\"manifest_version\": 2,"
647         "\"permissions\": [\"background\"]}",
648         "ID-1"));
649
650   scoped_refptr<extensions::Extension> component_extension_with_options(
651     CreateExtension(
652         extensions::Manifest::COMPONENT,
653         "{\"name\": \"Component Extension with Options\","
654         "\"version\": \"1.0\","
655         "\"manifest_version\": 2,"
656         "\"permissions\": [\"background\"],"
657         "\"options_page\": \"test.html\"}",
658         "ID-2"));
659
660   scoped_refptr<extensions::Extension> regular_extension(
661     CreateExtension(
662         extensions::Manifest::COMMAND_LINE,
663         "{\"name\": \"Regular Extension\", "
664         "\"version\": \"1.0\","
665         "\"manifest_version\": 2,"
666         "\"permissions\": [\"background\"]}",
667         "ID-3"));
668
669   scoped_refptr<extensions::Extension> regular_extension_with_options(
670     CreateExtension(
671         extensions::Manifest::COMMAND_LINE,
672         "{\"name\": \"Regular Extension with Options\","
673         "\"version\": \"1.0\","
674         "\"manifest_version\": 2,"
675         "\"permissions\": [\"background\"],"
676         "\"options_page\": \"test.html\"}",
677         "ID-4"));
678
679   static_cast<extensions::TestExtensionSystem*>(
680       extensions::ExtensionSystem::Get(profile_))->CreateExtensionService(
681           CommandLine::ForCurrentProcess(),
682           base::FilePath(),
683           false);
684   ExtensionService* service1 =
685       extensions::ExtensionSystem::Get(profile_)->extension_service();
686   service1->Init();
687
688   service1->AddComponentExtension(component_extension);
689   service1->AddComponentExtension(component_extension_with_options);
690   service1->AddExtension(regular_extension);
691   service1->AddExtension(regular_extension_with_options);
692
693   static_cast<extensions::TestExtensionSystem*>(
694       extensions::ExtensionSystem::Get(profile2))->CreateExtensionService(
695           CommandLine::ForCurrentProcess(),
696           base::FilePath(),
697           false);
698   ExtensionService* service2 =
699       extensions::ExtensionSystem::Get(profile2)->extension_service();
700   service2->Init();
701
702   service2->AddComponentExtension(component_extension);
703   service2->AddExtension(regular_extension);
704   service2->AddExtension(regular_extension_with_options);
705
706   manager_->RegisterProfile(profile2);
707
708   manager_->status_icon_ = new TestStatusIcon();
709   manager_->UpdateStatusTrayIconContextMenu();
710   StatusIconMenuModel* context_menu = manager_->context_menu_;
711   EXPECT_TRUE(context_menu != NULL);
712
713   // Background Profile Enable Checks
714   EXPECT_TRUE(context_menu->GetLabelAt(3) == base::UTF8ToUTF16("p1"));
715   EXPECT_TRUE(
716       context_menu->IsCommandIdEnabled(context_menu->GetCommandIdAt(3)));
717   EXPECT_TRUE(context_menu->GetCommandIdAt(3) == 4);
718
719   EXPECT_TRUE(context_menu->GetLabelAt(4) == base::UTF8ToUTF16("p2"));
720   EXPECT_TRUE(
721       context_menu->IsCommandIdEnabled(context_menu->GetCommandIdAt(4)));
722   EXPECT_TRUE(context_menu->GetCommandIdAt(4) == 8);
723
724   // Profile 1 Submenu Checks
725   StatusIconMenuModel* profile1_submenu =
726       static_cast<StatusIconMenuModel*>(context_menu->GetSubmenuModelAt(3));
727   EXPECT_TRUE(
728       profile1_submenu->GetLabelAt(0) ==
729           base::UTF8ToUTF16("Component Extension"));
730   EXPECT_FALSE(
731       profile1_submenu->IsCommandIdEnabled(
732           profile1_submenu->GetCommandIdAt(0)));
733   EXPECT_TRUE(profile1_submenu->GetCommandIdAt(0) == 0);
734   EXPECT_TRUE(
735       profile1_submenu->GetLabelAt(1) ==
736           base::UTF8ToUTF16("Component Extension with Options"));
737   EXPECT_TRUE(
738       profile1_submenu->IsCommandIdEnabled(
739           profile1_submenu->GetCommandIdAt(1)));
740   EXPECT_TRUE(profile1_submenu->GetCommandIdAt(1) == 1);
741   EXPECT_TRUE(
742       profile1_submenu->GetLabelAt(2) ==
743           base::UTF8ToUTF16("Regular Extension"));
744   EXPECT_TRUE(
745       profile1_submenu->IsCommandIdEnabled(
746           profile1_submenu->GetCommandIdAt(2)));
747   EXPECT_TRUE(profile1_submenu->GetCommandIdAt(2) == 2);
748   EXPECT_TRUE(
749       profile1_submenu->GetLabelAt(3) ==
750           base::UTF8ToUTF16("Regular Extension with Options"));
751   EXPECT_TRUE(
752       profile1_submenu->IsCommandIdEnabled(
753           profile1_submenu->GetCommandIdAt(3)));
754   EXPECT_TRUE(profile1_submenu->GetCommandIdAt(3) == 3);
755
756   // Profile 2 Submenu Checks
757   StatusIconMenuModel* profile2_submenu =
758       static_cast<StatusIconMenuModel*>(context_menu->GetSubmenuModelAt(4));
759   EXPECT_TRUE(
760       profile2_submenu->GetLabelAt(0) ==
761           base::UTF8ToUTF16("Component Extension"));
762   EXPECT_FALSE(
763       profile2_submenu->IsCommandIdEnabled(
764           profile2_submenu->GetCommandIdAt(0)));
765   EXPECT_TRUE(profile2_submenu->GetCommandIdAt(0) == 5);
766   EXPECT_TRUE(
767       profile2_submenu->GetLabelAt(1) ==
768           base::UTF8ToUTF16("Regular Extension"));
769   EXPECT_TRUE(
770       profile2_submenu->IsCommandIdEnabled(
771           profile2_submenu->GetCommandIdAt(1)));
772   EXPECT_TRUE(profile2_submenu->GetCommandIdAt(1) == 6);
773   EXPECT_TRUE(
774       profile2_submenu->GetLabelAt(2) ==
775           base::UTF8ToUTF16("Regular Extension with Options"));
776   EXPECT_TRUE(
777       profile2_submenu->IsCommandIdEnabled(
778           profile2_submenu->GetCommandIdAt(2)));
779   EXPECT_TRUE(profile2_submenu->GetCommandIdAt(2) == 7);
780
781   // Model Adapter Checks for crbug.com/315164
782   // P1: Profile 1 Menu Item
783   // P2: Profile 2 Menu Item
784   // CE: Component Extension Menu Item
785   // CEO: Component Extenison with Options Menu Item
786   // RE: Regular Extension Menu Item
787   // REO: Regular Extension with Options Menu Item
788   EXPECT_FALSE(IsCommandEnabled(context_menu, 0)); // P1 - CE
789   EXPECT_TRUE(IsCommandEnabled(context_menu, 1));  // P1 - CEO
790   EXPECT_TRUE(IsCommandEnabled(context_menu, 2));  // P1 - RE
791   EXPECT_TRUE(IsCommandEnabled(context_menu, 3));  // P1 - REO
792   EXPECT_TRUE(IsCommandEnabled(context_menu, 4));  // P1
793   EXPECT_FALSE(IsCommandEnabled(context_menu, 5)); // P2 - CE
794   EXPECT_TRUE(IsCommandEnabled(context_menu, 6));  // P2 - RE
795   EXPECT_TRUE(IsCommandEnabled(context_menu, 7));  // P2 - REO
796   EXPECT_TRUE(IsCommandEnabled(context_menu, 8));  // P2
797 }
798
799 TEST_F(BackgroundModeManagerWithExtensionsTest, BalloonDisplay) {
800   scoped_refptr<extensions::Extension> bg_ext(
801     CreateExtension(
802         extensions::Manifest::COMMAND_LINE,
803         "{\"name\": \"Background Extension\", "
804         "\"version\": \"1.0\","
805         "\"manifest_version\": 2,"
806         "\"permissions\": [\"background\"]}",
807         "ID-1"));
808
809   scoped_refptr<extensions::Extension> upgraded_bg_ext(
810     CreateExtension(
811         extensions::Manifest::COMMAND_LINE,
812         "{\"name\": \"Background Extension\", "
813         "\"version\": \"2.0\","
814         "\"manifest_version\": 2,"
815         "\"permissions\": [\"background\"]}",
816         "ID-1"));
817
818   scoped_refptr<extensions::Extension> no_bg_ext(
819     CreateExtension(
820         extensions::Manifest::COMMAND_LINE,
821         "{\"name\": \"Regular Extension\", "
822         "\"version\": \"1.0\","
823         "\"manifest_version\": 2,"
824         "\"permissions\": []}",
825         "ID-2"));
826
827   scoped_refptr<extensions::Extension> upgraded_no_bg_ext_has_bg(
828     CreateExtension(
829         extensions::Manifest::COMMAND_LINE,
830         "{\"name\": \"Regular Extension\", "
831         "\"version\": \"2.0\","
832         "\"manifest_version\": 2,"
833         "\"permissions\": [\"background\"]}",
834         "ID-2"));
835
836   scoped_refptr<extensions::Extension> ephemeral_app(
837     CreateExtension(
838         extensions::Manifest::COMMAND_LINE,
839         "{\"name\": \"Ephemeral App\", "
840         "\"version\": \"1.0\","
841         "\"manifest_version\": 2,"
842         "\"permissions\": [\"pushMessaging\"]}",
843         "ID-3"));
844
845   static_cast<extensions::TestExtensionSystem*>(
846       extensions::ExtensionSystem::Get(profile_))->CreateExtensionService(
847           CommandLine::ForCurrentProcess(),
848           base::FilePath(),
849           false);
850
851   ExtensionService* service =
852       extensions::ExtensionSystem::Get(profile_)->extension_service();
853   DCHECK(!service->is_ready());
854   service->Init();
855   DCHECK(service->is_ready());
856   manager_->status_icon_ = new TestStatusIcon();
857   manager_->UpdateStatusTrayIconContextMenu();
858
859   // Adding a background extension should show the balloon.
860   EXPECT_FALSE(manager_->HasShownBalloon());
861   service->AddExtension(bg_ext);
862   EXPECT_TRUE(manager_->HasShownBalloon());
863
864   // Adding an extension without background should not show the balloon.
865   manager_->SetHasShownBalloon(false);
866   service->AddExtension(no_bg_ext);
867   EXPECT_FALSE(manager_->HasShownBalloon());
868
869   // Upgrading an extension that has background should not reshow the balloon.
870   service->AddExtension(upgraded_bg_ext);
871   EXPECT_FALSE(manager_->HasShownBalloon());
872
873   // Upgrading an extension that didn't have background to one that does should
874   // show the balloon.
875   service->AddExtension(upgraded_no_bg_ext_has_bg);
876   EXPECT_TRUE(manager_->HasShownBalloon());
877
878   // Installing an ephemeral app should not show the balloon.
879   manager_->SetHasShownBalloon(false);
880   AddEphemeralApp(ephemeral_app.get(), service);
881   EXPECT_FALSE(manager_->HasShownBalloon());
882
883   // Promoting the ephemeral app to a regular installed app should now show
884   // the balloon.
885   service->PromoteEphemeralApp(ephemeral_app.get(), false /*from sync*/);
886   EXPECT_TRUE(manager_->HasShownBalloon());
887 }