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