+// Test that the shim's lifetime depends on the visibility of windows. I.e. the
+// shim is only active when there are visible windows.
+IN_PROC_BROWSER_TEST_F(AppShimInteractiveTest, MAYBE_ShowWindow) {
+ const extensions::Extension* app = InstallPlatformApp("hidden");
+
+ base::FilePath shim_path = GetAppShimPath(profile(), app);
+ EXPECT_FALSE(base::PathExists(shim_path));
+
+ UpdateAppAndAwaitShimCreation(profile(), app, shim_path);
+ ASSERT_TRUE(base::PathExists(shim_path));
+ NSString* bundle_id = GetBundleID(shim_path);
+
+ // It's impractical to confirm that the shim did not launch by timing out, so
+ // instead we watch AppLifetimeMonitor::Observer::OnAppActivated.
+ AppLifetimeMonitorObserver lifetime_observer(profile());
+
+ // Launch the app. It should create a hidden window, but the shim should not
+ // launch.
+ {
+ ExtensionTestMessageListener launched_listener("Launched", false);
+ LaunchPlatformApp(app);
+ EXPECT_TRUE(launched_listener.WaitUntilSatisfied());
+ }
+ extensions::AppWindow* window_1 = GetFirstAppWindow();
+ ASSERT_TRUE(window_1);
+ EXPECT_TRUE(window_1->is_hidden());
+ EXPECT_FALSE(HasAppShimHost(profile(), app->id()));
+ EXPECT_EQ(0, lifetime_observer.activated_count());
+
+ // Showing the window causes the shim to launch.
+ {
+ base::scoped_nsobject<WindowedNSNotificationObserver> ns_observer(
+ [[WindowedNSNotificationObserver alloc]
+ initForNotification:NSWorkspaceDidLaunchApplicationNotification
+ andBundleId:bundle_id]);
+ WindowedAppShimLaunchObserver observer(app->id());
+ window_1->Show(extensions::AppWindow::SHOW_INACTIVE);
+ [ns_observer wait];
+ observer.Wait();
+ EXPECT_EQ(1, lifetime_observer.activated_count());
+ EXPECT_TRUE(HasAppShimHost(profile(), app->id()));
+ }
+
+ // Hiding the window causes the shim to quit.
+ {
+ base::scoped_nsobject<WindowedNSNotificationObserver> ns_observer(
+ [[WindowedNSNotificationObserver alloc]
+ initForNotification:NSWorkspaceDidTerminateApplicationNotification
+ andBundleId:bundle_id]);
+ window_1->Hide();
+ [ns_observer wait];
+ EXPECT_FALSE(HasAppShimHost(profile(), app->id()));
+ }
+
+ // Launch a second window. It should not launch the shim.
+ {
+ ExtensionTestMessageListener launched_listener("Launched", false);
+ LaunchPlatformApp(app);
+ EXPECT_TRUE(launched_listener.WaitUntilSatisfied());
+ }
+ const extensions::AppWindowRegistry::AppWindowList& app_windows =
+ extensions::AppWindowRegistry::Get(profile())->app_windows();
+ EXPECT_EQ(2u, app_windows.size());
+ extensions::AppWindow* window_2 = app_windows.front();
+ EXPECT_NE(window_1, window_2);
+ ASSERT_TRUE(window_2);
+ EXPECT_TRUE(window_2->is_hidden());
+ EXPECT_FALSE(HasAppShimHost(profile(), app->id()));
+ EXPECT_EQ(1, lifetime_observer.activated_count());
+
+ // Showing one of the windows should launch the shim.
+ {
+ base::scoped_nsobject<WindowedNSNotificationObserver> ns_observer(
+ [[WindowedNSNotificationObserver alloc]
+ initForNotification:NSWorkspaceDidLaunchApplicationNotification
+ andBundleId:bundle_id]);
+ WindowedAppShimLaunchObserver observer(app->id());
+ window_1->Show(extensions::AppWindow::SHOW_INACTIVE);
+ [ns_observer wait];
+ observer.Wait();
+ EXPECT_EQ(2, lifetime_observer.activated_count());
+ EXPECT_TRUE(HasAppShimHost(profile(), app->id()));
+ EXPECT_TRUE(window_2->is_hidden());
+ }
+
+ // Showing the other window does nothing.
+ {
+ window_2->Show(extensions::AppWindow::SHOW_INACTIVE);
+ EXPECT_EQ(2, lifetime_observer.activated_count());
+ }
+
+ // Showing an already visible window does nothing.
+ {
+ window_1->Show(extensions::AppWindow::SHOW_INACTIVE);
+ EXPECT_EQ(2, lifetime_observer.activated_count());
+ }
+
+ // Hiding one window does nothing.
+ {
+ AppLifetimeMonitorObserver deactivate_observer(profile());
+ window_1->Hide();
+ EXPECT_EQ(0, deactivate_observer.deactivated_count());
+ }
+
+ // Hiding other window causes the shim to quit.
+ {
+ AppLifetimeMonitorObserver deactivate_observer(profile());
+ EXPECT_TRUE(HasAppShimHost(profile(), app->id()));
+ base::scoped_nsobject<WindowedNSNotificationObserver> ns_observer(
+ [[WindowedNSNotificationObserver alloc]
+ initForNotification:NSWorkspaceDidTerminateApplicationNotification
+ andBundleId:bundle_id]);
+ window_2->Hide();
+ [ns_observer wait];
+ EXPECT_EQ(1, deactivate_observer.deactivated_count());
+ EXPECT_FALSE(HasAppShimHost(profile(), app->id()));
+ }
+}
+