| // Copyright 2018 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "extensions/shell/browser/shell_desktop_controller_aura.h" |
| |
| #include "base/macros.h" |
| #include "base/task/post_task.h" |
| #include "base/test/bind_test_util.h" |
| #include "base/time/time.h" |
| #include "components/keep_alive_registry/keep_alive_registry.h" |
| #include "extensions/browser/app_window/app_window.h" |
| #include "extensions/browser/app_window/app_window_registry.h" |
| #include "extensions/browser/browsertest_util.h" |
| #include "extensions/shell/browser/desktop_controller.h" |
| #include "extensions/shell/test/shell_apitest.h" |
| #include "extensions/test/result_catcher.h" |
| |
| namespace extensions { |
| |
| // Tests that spin up the ShellDesktopControllerAura and run async tasks like |
| // launching and reloading apps. |
| class ShellDesktopControllerAuraBrowserTest : public ShellApiTest { |
| public: |
| ShellDesktopControllerAuraBrowserTest() = default; |
| ~ShellDesktopControllerAuraBrowserTest() override = default; |
| |
| // Loads and launches a platform app that opens an app window. |
| void LoadAndLaunchApp() { |
| ASSERT_FALSE(app_); |
| app_ = LoadApp("platform_app"); |
| ASSERT_TRUE(app_); |
| |
| // Wait for app window to load. |
| ResultCatcher catcher; |
| EXPECT_TRUE(catcher.GetNextResult()); |
| |
| // A window was created. |
| EXPECT_EQ(1u, |
| AppWindowRegistry::Get(browser_context())->app_windows().size()); |
| } |
| |
| protected: |
| // Returns an open app window. |
| AppWindow* GetAppWindow() { |
| EXPECT_GT(AppWindowRegistry::Get(browser_context())->app_windows().size(), |
| 0u); |
| return AppWindowRegistry::Get(browser_context())->app_windows().front(); |
| } |
| |
| // ShellApiTest: |
| void SetUpOnMainThread() override { |
| ShellApiTest::SetUpOnMainThread(); |
| desktop_controller_ = |
| static_cast<ShellDesktopControllerAura*>(DesktopController::instance()); |
| ASSERT_TRUE(desktop_controller_); |
| } |
| |
| void TearDownOnMainThread() override { |
| EXPECT_FALSE(KeepAliveRegistry::GetInstance()->IsKeepingAlive()); |
| ShellApiTest::TearDownOnMainThread(); |
| } |
| |
| ShellDesktopControllerAura* desktop_controller_ = nullptr; |
| scoped_refptr<const Extension> app_; |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(ShellDesktopControllerAuraBrowserTest); |
| }; |
| |
| // Test that closing the app window stops the DesktopController. |
| IN_PROC_BROWSER_TEST_F(ShellDesktopControllerAuraBrowserTest, CloseAppWindow) { |
| bool test_succeeded = false; |
| |
| // Post a task so everything runs after the DesktopController starts. |
| base::ThreadTaskRunnerHandle::Get()->PostTaskAndReply( |
| FROM_HERE, |
| // Asynchronously launch the app. |
| base::BindOnce(&ShellDesktopControllerAuraBrowserTest::LoadAndLaunchApp, |
| base::Unretained(this)), |
| |
| // Once the app launches, run the test. |
| base::BindLambdaForTesting([this, &test_succeeded]() { |
| // Close the app window so DesktopController quits. |
| GetAppWindow()->OnNativeClose(); |
| test_succeeded = true; |
| })); |
| |
| // Start DesktopController. It should run until the last app window closes. |
| desktop_controller_->Run(); |
| EXPECT_TRUE(test_succeeded) |
| << "DesktopController quit before test completed."; |
| } |
| |
| // Test that the DesktopController runs until all app windows close. |
| IN_PROC_BROWSER_TEST_F(ShellDesktopControllerAuraBrowserTest, TwoAppWindows) { |
| bool test_succeeded = false; |
| |
| // Post a task so everything runs after the DesktopController starts. |
| base::ThreadTaskRunnerHandle::Get()->PostTaskAndReply( |
| FROM_HERE, |
| // Asynchronously launch the app. |
| base::BindOnce(&ShellDesktopControllerAuraBrowserTest::LoadAndLaunchApp, |
| base::Unretained(this)), |
| |
| // Once the app launches, run the test. |
| base::BindLambdaForTesting([this, &test_succeeded]() { |
| // Create a second app window. |
| ASSERT_TRUE(browsertest_util::ExecuteScriptInBackgroundPageNoWait( |
| browser_context(), app_->id(), |
| "chrome.app.window.create('/hello.html');")); |
| ResultCatcher catcher; |
| catcher.GetNextResult(); |
| |
| // Close the first app window. |
| GetAppWindow()->OnNativeClose(); |
| |
| // One window is still open, so the DesktopController should still be |
| // running. Post a task to close the last window. |
| base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| FROM_HERE, base::BindLambdaForTesting([this, &test_succeeded]() { |
| GetAppWindow()->OnNativeClose(); |
| test_succeeded = true; |
| }), |
| // A regression might cause DesktopController to quit before the |
| // last window closes. To ensure we catch this, wait a while before |
| // closing the last window. If DesktopController::Run() finishes |
| // before we close the last window and update |test_succeeded|, the |
| // test fails. |
| base::TimeDelta::FromMilliseconds(500)); |
| })); |
| |
| desktop_controller_->Run(); |
| EXPECT_TRUE(test_succeeded) |
| << "DesktopController quit before test completed."; |
| } |
| |
| // Test that the DesktopController stays open while an app reloads, even though |
| // the app window closes. |
| IN_PROC_BROWSER_TEST_F(ShellDesktopControllerAuraBrowserTest, ReloadApp) { |
| bool test_succeeded = false; |
| |
| // Post a task so everything runs after the DesktopController starts. |
| base::ThreadTaskRunnerHandle::Get()->PostTaskAndReply( |
| FROM_HERE, |
| // Asynchronously launch the app. |
| base::BindOnce(&ShellDesktopControllerAuraBrowserTest::LoadAndLaunchApp, |
| base::Unretained(this)), |
| |
| // Once the app launches, run the test. |
| base::BindLambdaForTesting([this, &test_succeeded]() { |
| // Reload the app. |
| ASSERT_TRUE(browsertest_util::ExecuteScriptInBackgroundPageNoWait( |
| browser_context(), app_->id(), "chrome.runtime.reload();")); |
| |
| // Wait for the app window to re-open. |
| ResultCatcher catcher; |
| ASSERT_TRUE(catcher.GetNextResult()); |
| |
| // Close the new window after a delay. DesktopController should remain |
| // open until the window closes. |
| base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| FROM_HERE, base::BindLambdaForTesting([this, &test_succeeded]() { |
| AppWindow* app_window = AppWindowRegistry::Get(browser_context()) |
| ->app_windows() |
| .front(); |
| app_window->OnNativeClose(); |
| test_succeeded = true; |
| }), |
| base::TimeDelta::FromMilliseconds(500)); |
| })); |
| |
| desktop_controller_->Run(); |
| EXPECT_TRUE(test_succeeded) |
| << "DesktopController quit before test completed."; |
| } |
| |
| } // namespace extensions |