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