blob: 2f3e251836c50bfe587a1099a381c472d65cbc8f [file] [log] [blame]
// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "chrome/browser/web_applications/commands/install_placeholder_command.h"
#include <memory>
#include "base/test/gmock_callback_support.h"
#include "base/test/test_future.h"
#include "chrome/browser/web_applications/external_install_options.h"
#include "chrome/browser/web_applications/mojom/user_display_mode.mojom.h"
#include "chrome/browser/web_applications/os_integration/os_integration_manager.h"
#include "chrome/browser/web_applications/proto/web_app_os_integration_state.pb.h"
#include "chrome/browser/web_applications/test/fake_os_integration_manager.h"
#include "chrome/browser/web_applications/test/fake_web_app_provider.h"
#include "chrome/browser/web_applications/test/mock_data_retriever.h"
#include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
#include "chrome/browser/web_applications/test/web_app_test.h"
#include "chrome/browser/web_applications/web_app_command_manager.h"
#include "chrome/browser/web_applications/web_app_command_scheduler.h"
#include "chrome/browser/web_applications/web_app_constants.h"
#include "chrome/browser/web_applications/web_app_id.h"
#include "chrome/browser/web_applications/web_app_provider.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "components/webapps/browser/install_result_code.h"
#include "content/public/browser/web_contents.h"
#include "net/http/http_status_code.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
namespace web_app {
namespace {
class InstallPlaceholderCommandTest : public WebAppTest {
public:
const int kIconSize = 96;
const GURL kInstallUrl = GURL("https://example.com");
void SetUp() override {
WebAppTest::SetUp();
auto shortcut_manager = std::make_unique<TestShortcutManager>(profile());
shortcut_manager_ = shortcut_manager.get();
FakeWebAppProvider::Get(profile())
->GetOsIntegrationManager()
.AsTestOsIntegrationManager()
->SetShortcutManager(std::move(shortcut_manager));
test::AwaitStartWebAppProviderAndSubsystems(profile());
}
WebAppProvider* provider() { return WebAppProvider::GetForTest(profile()); }
FakeOsIntegrationManager& fake_os_integration_manager() {
return static_cast<FakeOsIntegrationManager&>(
provider()->os_integration_manager());
}
TestShortcutManager* shortcut_manager() { return shortcut_manager_; }
private:
raw_ptr<TestShortcutManager> shortcut_manager_;
};
TEST_F(InstallPlaceholderCommandTest, InstallPlaceholder) {
ExternalInstallOptions options(kInstallUrl, mojom::UserDisplayMode::kBrowser,
ExternalInstallSource::kExternalPolicy);
base::test::TestFuture<const AppId&, webapps::InstallResultCode, bool> future;
provider()->scheduler().InstallPlaceholder(options, future.GetCallback(),
web_contents()->GetWeakPtr());
EXPECT_EQ(future.Get<webapps::InstallResultCode>(),
webapps::InstallResultCode::kSuccessNewInstall);
const AppId app_id = future.Get<AppId>();
EXPECT_TRUE(provider()->registrar_unsafe().IsPlaceholderApp(
app_id, WebAppManagement::kPolicy));
EXPECT_EQ(fake_os_integration_manager().num_create_shortcuts_calls(), 1u);
auto last_install_options =
fake_os_integration_manager().get_last_install_options();
EXPECT_TRUE(last_install_options->add_to_desktop);
EXPECT_TRUE(last_install_options->add_to_quick_launch_bar);
EXPECT_FALSE(last_install_options->os_hooks[OsHookType::kRunOnOsLogin]);
if (AreOsIntegrationSubManagersEnabled()) {
absl::optional<proto::WebAppOsIntegrationState> os_state =
provider()->registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
ASSERT_TRUE(os_state.has_value());
EXPECT_TRUE(os_state->has_shortcut());
EXPECT_EQ(os_state->run_on_os_login().run_on_os_login_mode(),
proto::RunOnOsLoginMode::NOT_RUN);
}
}
TEST_F(InstallPlaceholderCommandTest, InstallPlaceholderWithOverrideIconUrl) {
ExternalInstallOptions options(kInstallUrl, mojom::UserDisplayMode::kBrowser,
ExternalInstallSource::kExternalPolicy);
const GURL icon_url("https://example.com/test.png");
options.override_icon_url = icon_url;
base::test::TestFuture<const AppId&, webapps::InstallResultCode, bool> future;
auto data_retriever =
std::make_unique<testing::StrictMock<MockDataRetriever>>();
bool skip_page_favicons = true;
SkBitmap bitmap;
std::vector<gfx::Size> icon_sizes(1, gfx::Size(kIconSize, kIconSize));
bitmap.allocN32Pixels(kIconSize, kIconSize);
bitmap.eraseColor(SK_ColorRED);
IconsMap icons = {{icon_url, {bitmap}}};
DownloadedIconsHttpResults http_result = {
{icon_url, net::HttpStatusCode::HTTP_OK}};
EXPECT_CALL(*data_retriever,
GetIcons(testing::_, testing::ElementsAre(icon_url),
skip_page_favicons, base::test::IsNotNullCallback()))
.WillOnce(base::test::RunOnceCallback<3>(
IconsDownloadedResult::kCompleted, std::move(icons), http_result));
auto command = std::make_unique<InstallPlaceholderCommand>(
profile(), options, future.GetCallback(), web_contents()->GetWeakPtr(),
std::move(data_retriever));
provider()->command_manager().ScheduleCommand(std::move(command));
EXPECT_EQ(future.Get<webapps::InstallResultCode>(),
webapps::InstallResultCode::kSuccessNewInstall);
const AppId app_id = future.Get<AppId>();
EXPECT_TRUE(provider()->registrar_unsafe().IsPlaceholderApp(
app_id, WebAppManagement::kPolicy));
EXPECT_EQ(fake_os_integration_manager().num_create_shortcuts_calls(), 1u);
if (AreOsIntegrationSubManagersEnabled()) {
absl::optional<proto::WebAppOsIntegrationState> os_state =
provider()->registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
ASSERT_TRUE(os_state.has_value());
EXPECT_TRUE(os_state->has_shortcut());
}
}
#if !BUILDFLAG(IS_CHROMEOS_LACROS)
TEST_F(InstallPlaceholderCommandTest,
InstallPlaceholderWithUninstallAndReplace) {
GURL old_app_url("http://old-app.com");
const AppId old_app =
test::InstallDummyWebApp(profile(), "old_app", old_app_url);
auto shortcut_info = std::make_unique<ShortcutInfo>();
shortcut_info->url = old_app_url;
shortcut_manager()->SetShortcutInfoForApp(old_app, std::move(shortcut_info));
ShortcutLocations shortcut_locations;
shortcut_locations.on_desktop = false;
shortcut_locations.in_quick_launch_bar = true;
shortcut_locations.in_startup = true;
shortcut_manager()->SetAppExistingShortcuts(old_app_url, shortcut_locations);
ExternalInstallOptions options(kInstallUrl, mojom::UserDisplayMode::kBrowser,
ExternalInstallSource::kExternalPolicy);
options.uninstall_and_replace = {old_app};
base::test::TestFuture<const AppId&, webapps::InstallResultCode, bool> future;
provider()->scheduler().InstallPlaceholder(
options, future.GetCallback(), web_contents()->GetWeakPtr()
);
EXPECT_EQ(future.Get<webapps::InstallResultCode>(),
webapps::InstallResultCode::kSuccessNewInstall);
EXPECT_TRUE(future.Get<bool>());
const AppId app_id = future.Get<AppId>();
EXPECT_TRUE(provider()->registrar_unsafe().IsPlaceholderApp(
app_id, WebAppManagement::kPolicy));
auto last_install_options =
fake_os_integration_manager().get_last_install_options();
EXPECT_FALSE(last_install_options->add_to_desktop);
EXPECT_TRUE(last_install_options->add_to_quick_launch_bar);
EXPECT_TRUE(last_install_options->os_hooks[OsHookType::kRunOnOsLogin]);
if (AreOsIntegrationSubManagersEnabled()) {
absl::optional<proto::WebAppOsIntegrationState> os_state =
provider()->registrar_unsafe().GetAppCurrentOsIntegrationState(app_id);
ASSERT_TRUE(os_state.has_value());
EXPECT_TRUE(os_state->has_shortcut());
EXPECT_TRUE(os_state->has_run_on_os_login());
EXPECT_EQ(os_state->run_on_os_login().run_on_os_login_mode(),
proto::RunOnOsLoginMode::WINDOWED);
}
}
#endif // !BUILDFLAG(IS_CHROMEOS_LACROS)
} // namespace
} // namespace web_app