chromium/chrome/browser/web_applications/commands/launch_web_app_command_browsertest.cc

// 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 <memory>
#include <optional>
#include <string>
#include <tuple>

#include "base/command_line.h"
#include "base/files/file_path.h"
#include "base/run_loop.h"
#include "base/test/bind.h"
#include "base/test/test_future.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/apps/app_service/app_launch_params.h"
#include "chrome/browser/apps/app_service/app_registry_cache_waiter.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/browser_navigator_params.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/web_applications/app_browser_controller.h"
#include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h"
#include "chrome/browser/ui/web_applications/web_app_browsertest_base.h"
#include "chrome/browser/ui/web_applications/web_app_launch_utils.h"
#include "chrome/browser/web_applications/proto/web_app_install_state.pb.h"
#include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
#include "chrome/browser/web_applications/test/web_app_test_utils.h"
#include "chrome/browser/web_applications/web_app_command_scheduler.h"
#include "chrome/browser/web_applications/web_app_helpers.h"
#include "chrome/browser/web_applications/web_app_install_info.h"
#include "chrome/browser/web_applications/web_app_install_params.h"
#include "chrome/browser/web_applications/web_app_provider.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/test/base/ui_test_utils.h"
#include "chromeos/constants/chromeos_features.h"
#include "components/services/app_service/public/cpp/app_launch_util.h"
#include "content/public/test/browser_test.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/window_open_disposition.h"
#include "url/gurl.h"

#if BUILDFLAG(IS_CHROMEOS_LACROS)
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/ui/startup/first_run_service.h"
#include "chromeos/crosapi/mojom/crosapi.mojom.h"
#include "chromeos/lacros/lacros_service.h"
#include "chromeos/startup/browser_init_params.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)

_;
Invoke;
Return;
WithArg;

namespace web_app {

namespace {
#if BUILDFLAG(IS_WIN)
const base::FilePath::CharType kCurrentDirectory[] =
    FILE_PATH_LITERAL("\\path");
#else
const base::FilePath::CharType kCurrentDirectory[] =);
#endif  // BUILDFLAG(IS_WIN)

#if BUILDFLAG(IS_CHROMEOS_LACROS)
class FirstRunServiceMock : public FirstRunService {
 public:
  FirstRunServiceMock(Profile& profile,
                      signin::IdentityManager& identity_manager)
      : FirstRunService(profile, identity_manager) {}

  MOCK_METHOD(bool, ShouldOpenFirstRun, (), (const, override));
  MOCK_METHOD(void,
              OpenFirstRunIfNeeded,
              (EntryPoint entry_point, ResumeTaskCallback callback),
              (override));
};

std::unique_ptr<KeyedService> BuildTestFirstRunService(
    bool create_first_run_service,
    content::BrowserContext* context) {
  if (!create_first_run_service) {
    return nullptr;
  }

  Profile* profile = Profile::FromBrowserContext(context);
  CHECK(profile);
  return std::make_unique<FirstRunServiceMock>(
      *profile, *IdentityManagerFactory::GetForProfile(profile));
}

class FirstRunServiceOverrideHelper {
 public:
  explicit FirstRunServiceOverrideHelper(bool create_first_run_service)
      : create_first_run_service_(create_first_run_service) {
    CHECK(BrowserContextDependencyManager::GetInstance());
    create_services_subscription_ =
        BrowserContextDependencyManager::GetInstance()
            ->RegisterCreateServicesCallbackForTesting(
                base::BindRepeating(&FirstRunServiceOverrideHelper::
                                        OnWillCreateBrowserContextServices,
                                    base::Unretained(this)));
  }

 private:
  void OnWillCreateBrowserContextServices(content::BrowserContext* context) {
    FirstRunServiceFactory::GetInstance()->SetTestingFactory(
        context, base::BindRepeating(BuildTestFirstRunService,
                                     create_first_run_service_));
  }

  bool create_first_run_service_ = false;

  base::CallbackListSubscription create_services_subscription_;
};
#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)

class LaunchWebAppWithFirstRunServiceBrowserTest
    : public WebAppBrowserTestBase,
      public testing::WithParamInterface<bool> {};

IN_PROC_BROWSER_TEST_P(
    LaunchWebAppWithFirstRunServiceBrowserTest,
    LaunchInWindowWithFirstRunServiceRequiredSetupSuccessful) {}

IN_PROC_BROWSER_TEST_P(LaunchWebAppWithFirstRunServiceBrowserTest,
                       LaunchInTabWithFirstRunServiceRequiredSetupSuccessful) {}

#if BUILDFLAG(IS_CHROMEOS_LACROS)
IN_PROC_BROWSER_TEST_P(LaunchWebAppWithFirstRunServiceBrowserTest,
                       LaunchInWindowWithFirstRunServiceRequiredSetupSkipped) {
  webapps::AppId app_id =
      InstallWebApp(https_server()->GetURL("/banners/manifest_test_page.html"));

  FirstRunServiceMock* first_run_service = static_cast<FirstRunServiceMock*>(
      FirstRunServiceFactory::GetForBrowserContextIfExists(profile()));
  if (GetParam()) {
    EXPECT_CALL(*first_run_service, OpenFirstRunIfNeeded(_, _))
        .WillOnce(WithArg<1>(Invoke([](ResumeTaskCallback callback) {
          std::move(callback).Run(/*proceed=*/false);
        })));
  } else {
    ASSERT_FALSE(first_run_service);
  }

  ASSERT_TRUE(GetProvider().registrar_unsafe().IsInstallState(
      app_id, {proto::INSTALLED_WITHOUT_OS_INTEGRATION,
               proto::INSTALLED_WITH_OS_INTEGRATION}));

  Browser* browser = LaunchWebAppBrowser(app_id);
  ASSERT_EQ(browser == nullptr, GetParam());
}

IN_PROC_BROWSER_TEST_P(LaunchWebAppWithFirstRunServiceBrowserTest,
                       LaunchInTabWithFirstRunServiceRequiredSetupSkipped) {
  webapps::AppId app_id =
      InstallWebApp(https_server()->GetURL("/banners/manifest_test_page.html"));

  FirstRunServiceMock* first_run_service = static_cast<FirstRunServiceMock*>(
      FirstRunServiceFactory::GetForBrowserContextIfExists(profile()));

  if (GetParam()) {
    EXPECT_CALL(*first_run_service, OpenFirstRunIfNeeded(_, _))
        .WillOnce(WithArg<1>(Invoke([](ResumeTaskCallback callback) {
          std::move(callback).Run(/*proceed=*/true);
        })));
  } else {
    ASSERT_FALSE(first_run_service);
  }

  ASSERT_TRUE(GetProvider().registrar_unsafe().IsInstallState(
      app_id, {proto::INSTALLED_WITHOUT_OS_INTEGRATION,
               proto::INSTALLED_WITH_OS_INTEGRATION}));

  Browser* browser = LaunchBrowserForWebAppInTab(app_id);
  ASSERT_TRUE(browser);
}
#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)

INSTANTIATE_TEST_SUITE_P();

class LaunchWebAppCommandTest : public WebAppBrowserTestBase {};

IN_PROC_BROWSER_TEST_F(LaunchWebAppCommandTest, TabbedLaunchCurrentBrowser) {}

IN_PROC_BROWSER_TEST_F(LaunchWebAppCommandTest, StandaloneLaunch) {}

IN_PROC_BROWSER_TEST_F(LaunchWebAppCommandTest, StandaloneLaunchAppConfig) {}

IN_PROC_BROWSER_TEST_F(LaunchWebAppCommandTest, AppLaunchNoIntegration) {}

}  // namespace

}  // namespace web_app