blob: af230838ff083b186fa6c25ff1e43d306c491bb3 [file] [log] [blame]
// 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/bind.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