Commit 8d4fb536 authored by Anatoliy Potapchuk's avatar Anatoliy Potapchuk Committed by Commit Bot

[Kiosk] Add WebKioskAppLauncher tests

This part of Web kiosk launch was lacking test coverage. Now it does
not. Also, we add window name to the created window so it does not
fail on DCHECKS.

Bug: 1046364
Change-Id: I569ad66061515bd18fef38e7e150a2c21be0ef3d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2116081Reviewed-by: default avatarAnqing Zhao <anqing@google.com>
Reviewed-by: default avatarSergey Poromov <poromov@chromium.org>
Commit-Queue: Anatoliy Potapchuk <apotapchuk@chromium.org>
Cr-Commit-Position: refs/heads/master@{#753465}
parent e61c549b
...@@ -2686,6 +2686,7 @@ source_set("unit_tests") { ...@@ -2686,6 +2686,7 @@ source_set("unit_tests") {
"android_sms/pairing_lost_notifier_unittest.cc", "android_sms/pairing_lost_notifier_unittest.cc",
"app_mode/app_session_unittest.cc", "app_mode/app_session_unittest.cc",
"app_mode/startup_app_launcher_unittest.cc", "app_mode/startup_app_launcher_unittest.cc",
"app_mode/web_app/web_kiosk_app_launcher_unittest.cc",
"apps/apk_web_app_installer_unittest.cc", "apps/apk_web_app_installer_unittest.cc",
"apps/intent_helper/chromeos_apps_navigation_throttle_unittest.cc", "apps/intent_helper/chromeos_apps_navigation_throttle_unittest.cc",
"apps/metrics/intent_handling_metrics_unittest.cc", "apps/metrics/intent_handling_metrics_unittest.cc",
......
...@@ -30,7 +30,9 @@ WebKioskAppLauncher::WebKioskAppLauncher( ...@@ -30,7 +30,9 @@ WebKioskAppLauncher::WebKioskAppLauncher(
WebKioskAppLauncher::Delegate* delegate) WebKioskAppLauncher::Delegate* delegate)
: profile_(profile), : profile_(profile),
delegate_(delegate), delegate_(delegate),
url_loader_(std::make_unique<web_app::WebAppUrlLoader>()) {} url_loader_(std::make_unique<web_app::WebAppUrlLoader>()),
data_retriever_factory_(base::BindRepeating(
&std::make_unique<web_app::WebAppDataRetriever>)) {}
WebKioskAppLauncher::~WebKioskAppLauncher() = default; WebKioskAppLauncher::~WebKioskAppLauncher() = default;
...@@ -52,9 +54,8 @@ void WebKioskAppLauncher::ContinueWithNetworkReady() { ...@@ -52,9 +54,8 @@ void WebKioskAppLauncher::ContinueWithNetworkReady() {
DCHECK(!is_installed_); DCHECK(!is_installed_);
install_task_.reset(new web_app::WebAppInstallTask( install_task_.reset(new web_app::WebAppInstallTask(
profile_, /*registrar=*/nullptr, /*shortcut_manager=*/nullptr, profile_, /*registrar=*/nullptr, /*shortcut_manager=*/nullptr,
/*file_handler_manager=*/nullptr, /*file_handler_manager=*/nullptr, /*install_finalizer=*/nullptr,
/*install_finalizer=*/nullptr, data_retriever_factory_.Run()));
std::make_unique<web_app::WebAppDataRetriever>()));
install_task_->LoadAndRetrieveWebApplicationInfoWithIcons( install_task_->LoadAndRetrieveWebApplicationInfoWithIcons(
WebKioskAppManager::Get()->GetAppByAccountId(account_id_)->install_url(), WebKioskAppManager::Get()->GetAppByAccountId(account_id_)->install_url(),
url_loader_.get(), url_loader_.get(),
...@@ -99,7 +100,11 @@ void WebKioskAppLauncher::LaunchApp() { ...@@ -99,7 +100,11 @@ void WebKioskAppLauncher::LaunchApp() {
? app->launch_url() ? app->launch_url()
: app->install_url(); : app->install_url();
Browser::CreateParams params(Browser::TYPE_APP, profile_, false); Browser::CreateParams params = Browser::CreateParams::CreateForApp(
app->name(), true, gfx::Rect(), profile_, false);
if (test_browser_window_) {
params.window = test_browser_window_;
}
browser_ = Browser::Create(params); browser_ = Browser::Create(params);
NavigateParams nav_params(browser_, url, NavigateParams nav_params(browser_, url,
...@@ -121,4 +126,19 @@ void WebKioskAppLauncher::CancelCurrentInstallation() { ...@@ -121,4 +126,19 @@ void WebKioskAppLauncher::CancelCurrentInstallation() {
install_task_.reset(); install_task_.reset();
} }
void WebKioskAppLauncher::SetDataRetrieverFactoryForTesting(
base::RepeatingCallback<std::unique_ptr<web_app::WebAppDataRetriever>()>
data_retriever_factory) {
data_retriever_factory_ = data_retriever_factory;
}
void WebKioskAppLauncher::SetBrowserWindowForTesting(BrowserWindow* window) {
test_browser_window_ = window;
}
void WebKioskAppLauncher::SetUrlLoaderForTesting(
std::unique_ptr<web_app::WebAppUrlLoader> url_loader) {
url_loader_ = std::move(url_loader);
}
} // namespace chromeos } // namespace chromeos
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <memory> #include <memory>
#include "base/callback.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/memory/weak_ptr.h" #include "base/memory/weak_ptr.h"
#include "chrome/browser/web_applications/components/web_app_constants.h" #include "chrome/browser/web_applications/components/web_app_constants.h"
...@@ -18,11 +19,13 @@ ...@@ -18,11 +19,13 @@
#include "url/gurl.h" #include "url/gurl.h"
class Browser; class Browser;
class BrowserWindow;
class Profile; class Profile;
namespace web_app { namespace web_app {
class WebAppInstallTask; class WebAppInstallTask;
class WebAppUrlLoader; class WebAppUrlLoader;
class WebAppDataRetriever;
} // namespace web_app } // namespace web_app
namespace chromeos { namespace chromeos {
...@@ -58,6 +61,18 @@ class WebKioskAppLauncher { ...@@ -58,6 +61,18 @@ class WebKioskAppLauncher {
// Stops current installation. // Stops current installation.
virtual void CancelCurrentInstallation(); virtual void CancelCurrentInstallation();
// Replaces data retriever used for new WebAppInstallTask in tests.
void SetDataRetrieverFactoryForTesting(
base::RepeatingCallback<std::unique_ptr<web_app::WebAppDataRetriever>()>
data_retriever_factory);
// Replaces default browser window with |window| during launch.
void SetBrowserWindowForTesting(BrowserWindow* window);
// Replaces current |url_loader_| with one provided.
void SetUrlLoaderForTesting(
std::unique_ptr<web_app::WebAppUrlLoader> url_loader);
private: private:
void OnAppDataObtained(std::unique_ptr<WebApplicationInfo> app_info); void OnAppDataObtained(std::unique_ptr<WebApplicationInfo> app_info);
...@@ -75,6 +90,12 @@ class WebKioskAppLauncher { ...@@ -75,6 +90,12 @@ class WebKioskAppLauncher {
std::unique_ptr<web_app::WebAppUrlLoader> std::unique_ptr<web_app::WebAppUrlLoader>
url_loader_; // Loads the app to be installed. url_loader_; // Loads the app to be installed.
// Produces retrievers used to obtain app data during installation.
base::RepeatingCallback<std::unique_ptr<web_app::WebAppDataRetriever>()>
data_retriever_factory_;
BrowserWindow* test_browser_window_ = nullptr;
base::WeakPtrFactory<WebKioskAppLauncher> weak_ptr_factory_{this}; base::WeakPtrFactory<WebKioskAppLauncher> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(WebKioskAppLauncher); DISALLOW_COPY_AND_ASSIGN(WebKioskAppLauncher);
}; };
......
// Copyright 2020 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 "chrome/browser/chromeos/app_mode/web_app/web_kiosk_app_launcher.h"
#include <memory>
#include "base/test/gmock_callback_support.h"
#include "chrome/browser/chromeos/app_mode/kiosk_app_manager_observer.h"
#include "chrome/browser/chromeos/app_mode/web_app/web_kiosk_app_data.h"
#include "chrome/browser/chromeos/app_mode/web_app/web_kiosk_app_manager.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/web_applications/test/test_data_retriever.h"
#include "chrome/browser/web_applications/test/test_web_app_url_loader.h"
#include "chrome/common/web_application_info.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/scoped_testing_local_state.h"
#include "chrome/test/base/test_browser_window.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "content/public/test/browser_task_environment.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
using ::base::test::RunClosure;
namespace chromeos {
class MockAppLauncherDelegate : public WebKioskAppLauncher::Delegate {
public:
MockAppLauncherDelegate() = default;
~MockAppLauncherDelegate() override = default;
MOCK_METHOD0(InitializeNetwork, void());
MOCK_METHOD0(OnAppStartedInstalling, void());
MOCK_METHOD0(OnAppPrepared, void());
MOCK_METHOD0(OnAppInstallFailed, void());
MOCK_METHOD0(OnAppLaunched, void());
MOCK_METHOD0(OnAppLaunchFailed, void());
};
const char kAppEmail[] = "lala@example.com";
const char kAppInstallUrl[] = "https://example.com";
const char kAppLaunchUrl[] = "https://example.com/launch";
const char kAppLaunchBadUrl[] = "https://badexample.com";
const char kAppTitle[] = "app";
std::unique_ptr<web_app::WebAppDataRetriever> CreateDataRetrieverWithData(
const GURL& url) {
auto data_retriever = std::make_unique<web_app::TestDataRetriever>();
auto info = std::make_unique<WebApplicationInfo>();
info->app_url = url;
info->title = base::UTF8ToUTF16(kAppTitle);
data_retriever->SetRendererWebApplicationInfo(std::move(info));
return std::unique_ptr<web_app::WebAppDataRetriever>(
std::move(data_retriever));
}
class AppWindowCloser : public BrowserListObserver {
public:
AppWindowCloser() { BrowserList::AddObserver(this); }
~AppWindowCloser() override { BrowserList::RemoveObserver(this); }
void OnBrowserAdded(Browser* browser) override { app_browser_ = browser; }
void OnBrowserRemoved(Browser* browser) override {
closed_ = true;
waiter.Quit();
}
void Close() {
DCHECK(app_browser_);
app_browser_->tab_strip_model()->CloseAllTabs();
delete app_browser_;
if (!closed_)
waiter.Run();
}
private:
bool closed_ = false;
Browser* app_browser_ = nullptr;
base::RunLoop waiter;
};
class WebKioskAppLauncherTest : public ChromeRenderViewHostTestHarness {
public:
WebKioskAppLauncherTest()
: ChromeRenderViewHostTestHarness(),
local_state_(TestingBrowserProcess::GetGlobal()) {}
~WebKioskAppLauncherTest() override {}
void SetUp() override {
ChromeRenderViewHostTestHarness::SetUp();
app_manager_ = std::make_unique<WebKioskAppManager>();
delegate_ = std::make_unique<MockAppLauncherDelegate>();
launcher_ =
std::make_unique<WebKioskAppLauncher>(profile(), delegate_.get());
browser_window_ = new TestBrowserWindow();
new TestBrowserWindowOwner(browser_window_);
browser_window_->SetNativeWindow(new aura::Window(nullptr));
launcher_->SetBrowserWindowForTesting(browser_window_);
url_loader_ = new web_app::TestWebAppUrlLoader();
launcher_->SetUrlLoaderForTesting(
std::unique_ptr<web_app::TestWebAppUrlLoader>(url_loader_));
closer_.reset(new AppWindowCloser());
}
void TearDown() override {
closer_.reset();
launcher_.reset();
delegate_.reset();
app_manager_.reset();
ChromeRenderViewHostTestHarness::TearDown();
}
void SetupAppData(bool installed) {
account_id_ = AccountId::FromUserEmail(kAppEmail);
app_manager_->AddAppForTesting(account_id_, GURL(kAppInstallUrl));
if (installed) {
auto info = std::make_unique<WebApplicationInfo>();
info->app_url = GURL(kAppLaunchUrl);
info->title = base::UTF8ToUTF16(kAppTitle);
app_manager_->UpdateAppByAccountId(account_id_, std::move(info));
}
}
void SetupInstallData() {
url_loader_->SetNextLoadUrlResult(
GURL(kAppInstallUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
launcher_->SetDataRetrieverFactoryForTesting(
base::BindRepeating(&CreateDataRetrieverWithData, GURL(kAppLaunchUrl)));
}
void SetupBadInstallData() {
url_loader_->SetNextLoadUrlResult(
GURL(kAppInstallUrl), web_app::WebAppUrlLoader::Result::kUrlLoaded);
launcher_->SetDataRetrieverFactoryForTesting(base::BindRepeating(
&CreateDataRetrieverWithData, GURL(kAppLaunchBadUrl)));
}
void SetupNotLoadedAppData() {
url_loader_->SetNextLoadUrlResult(
GURL(kAppInstallUrl),
web_app::WebAppUrlLoader::Result::kFailedPageTookTooLong);
}
const WebKioskAppData* app_data() {
return app_manager_->GetAppByAccountId(account_id_);
}
void CloseAppWindow() {
// Wait for it to be closed.
closer_->Close();
}
MockAppLauncherDelegate* delegate() { return delegate_.get(); }
WebKioskAppLauncher* launcher() { return launcher_.get(); }
protected:
AccountId account_id_;
web_app::TestWebAppUrlLoader* url_loader_; // Owned by |launcher_|.
private:
std::unique_ptr<WebKioskAppManager> app_manager_;
ScopedTestingLocalState local_state_;
TestBrowserWindow* browser_window_;
std::unique_ptr<MockAppLauncherDelegate> delegate_;
std::unique_ptr<WebKioskAppLauncher> launcher_;
std::unique_ptr<AppWindowCloser> closer_;
};
TEST_F(WebKioskAppLauncherTest, NormalFlowNotInstalled) {
SetupAppData(/*installed*/ false);
base::RunLoop loop1;
EXPECT_CALL(*delegate(), InitializeNetwork())
.WillOnce(RunClosure(loop1.QuitClosure()));
launcher()->Initialize(account_id_);
loop1.Run();
SetupInstallData();
base::RunLoop loop2;
EXPECT_CALL(*delegate(), OnAppStartedInstalling());
EXPECT_CALL(*delegate(), OnAppPrepared())
.WillOnce(RunClosure(loop2.QuitClosure()));
launcher()->ContinueWithNetworkReady();
loop2.Run();
EXPECT_EQ(app_data()->status(), WebKioskAppData::STATUS_INSTALLED);
EXPECT_EQ(app_data()->launch_url(), kAppLaunchUrl);
base::RunLoop loop3;
EXPECT_CALL(*delegate(), OnAppLaunched())
.WillOnce(RunClosure(loop3.QuitClosure()));
launcher()->LaunchApp();
loop3.Run();
CloseAppWindow();
}
TEST_F(WebKioskAppLauncherTest, NormalFlowAlreadyInstalled) {
SetupAppData(/*installed*/ true);
base::RunLoop loop1;
EXPECT_CALL(*delegate(), OnAppPrepared())
.WillOnce(RunClosure(loop1.QuitClosure()));
launcher()->Initialize(account_id_);
loop1.Run();
base::RunLoop loop2;
EXPECT_CALL(*delegate(), OnAppLaunched())
.WillOnce(RunClosure(loop2.QuitClosure()));
launcher()->LaunchApp();
loop2.Run();
CloseAppWindow();
}
TEST_F(WebKioskAppLauncherTest, NormalFlowBadLaunchUrl) {
SetupAppData(/*installed*/ false);
base::RunLoop loop1;
EXPECT_CALL(*delegate(), InitializeNetwork())
.WillOnce(RunClosure(loop1.QuitClosure()));
launcher()->Initialize(account_id_);
loop1.Run();
SetupBadInstallData();
base::RunLoop loop2;
EXPECT_CALL(*delegate(), OnAppStartedInstalling());
EXPECT_CALL(*delegate(), OnAppLaunchFailed())
.WillOnce(RunClosure(loop2.QuitClosure()));
launcher()->ContinueWithNetworkReady();
loop2.Run();
EXPECT_NE(app_data()->status(), WebKioskAppData::STATUS_INSTALLED);
}
TEST_F(WebKioskAppLauncherTest, InstallationRestarted) {
SetupAppData(/*installed*/ false);
// Freezes url requests until they are manually processed.
url_loader_->SaveLoadUrlRequests();
base::RunLoop loop1;
EXPECT_CALL(*delegate(), InitializeNetwork())
.WillOnce(RunClosure(loop1.QuitClosure()));
launcher()->Initialize(account_id_);
loop1.Run();
SetupInstallData();
EXPECT_CALL(*delegate(), OnAppStartedInstalling());
launcher()->ContinueWithNetworkReady();
launcher()->CancelCurrentInstallation();
// App should not be installed yet.
EXPECT_NE(app_data()->status(), WebKioskAppData::STATUS_INSTALLED);
// We should not receive any status updates now.
url_loader_->ProcessLoadUrlRequests();
SetupInstallData();
base::RunLoop loop2;
EXPECT_CALL(*delegate(), OnAppStartedInstalling()).Times(1);
EXPECT_CALL(*delegate(), OnAppPrepared())
.Times(1)
.WillOnce(RunClosure(loop2.QuitClosure()));
launcher()->ContinueWithNetworkReady();
url_loader_->ProcessLoadUrlRequests();
loop2.Run();
EXPECT_EQ(app_data()->status(), WebKioskAppData::STATUS_INSTALLED);
base::RunLoop loop3;
EXPECT_CALL(*delegate(), OnAppLaunched())
.WillOnce(RunClosure(loop3.QuitClosure()));
launcher()->LaunchApp();
loop3.Run();
CloseAppWindow();
}
TEST_F(WebKioskAppLauncherTest, UrlNotLoaded) {
SetupAppData(/*installed*/ false);
base::RunLoop loop1;
EXPECT_CALL(*delegate(), InitializeNetwork())
.WillOnce(RunClosure(loop1.QuitClosure()));
launcher()->Initialize(account_id_);
loop1.Run();
SetupNotLoadedAppData();
base::RunLoop loop2;
EXPECT_CALL(*delegate(), OnAppStartedInstalling());
EXPECT_CALL(*delegate(), OnAppInstallFailed())
.WillOnce(RunClosure(loop2.QuitClosure()));
launcher()->ContinueWithNetworkReady();
loop2.Run();
EXPECT_NE(app_data()->status(), WebKioskAppData::STATUS_INSTALLED);
}
} // namespace chromeos
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment