chromium/chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view_controller_unittest.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 "chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view_controller.h"

#include <memory>
#include <string>
#include <string_view>

#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_future.h"
#include "base/version.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/apps/app_service/app_launch_params.h"
#include "chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_model.h"
#include "chrome/browser/ui/views/web_apps/isolated_web_apps/isolated_web_app_installer_view.h"
#include "chrome/browser/ui/views/web_apps/isolated_web_apps/test_isolated_web_app_installer_model_observer.h"
#include "chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.h"
#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_source.h"
#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_storage_location.h"
#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_trust_checker.h"
#include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h"
#include "chrome/browser/web_applications/isolated_web_apps/signed_web_bundle_metadata.h"
#include "chrome/browser/web_applications/isolated_web_apps/test/test_signed_web_bundle_builder.h"
#include "chrome/browser/web_applications/test/fake_web_app_provider.h"
#include "chrome/browser/web_applications/test/fake_web_app_ui_manager.h"
#include "chrome/browser/web_applications/test/fake_web_contents_manager.h"
#include "chrome/browser/web_applications/test/os_integration_test_override_impl.h"
#include "chrome/browser/web_applications/test/web_app_icon_test_utils.h"
#include "chrome/browser/web_applications/test/web_app_install_test_utils.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/browser/web_applications/web_app_ui_manager.h"
#include "chrome/common/chrome_features.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/generated_resources.h"
#include "chrome/test/base/scoped_testing_local_state.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "components/web_package/signed_web_bundles/signed_web_bundle_id.h"
#include "content/public/common/content_features.h"
#include "content/public/test/browser_task_environment.h"
#include "services/data_decoder/public/cpp/test_support/in_process_data_decoder.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/common/manifest/manifest.h"
#include "url/gurl.h"

#if BUILDFLAG(IS_CHROMEOS)
#include "ash/constants/ash_pref_names.h"
#include "base/values.h"
#include "chrome/browser/ui/views/web_apps/isolated_web_apps/pref_observer.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#endif  // BUILDFLAG(IS_CHROMEOS)

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "chrome/browser/ash/app_restore/full_restore_service_factory.h"
#include "components/keyed_service/core/keyed_service.h"
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

#if BUILDFLAG(IS_CHROMEOS_LACROS)
#include "chrome/browser/extensions/extension_keeplist_chromeos.h"
#include "chrome/browser/web_applications/app_service/test/loopback_crosapi_app_service_proxy.h"
#include "chromeos/crosapi/mojom/prefs.mojom.h"
#include "chromeos/lacros/lacros_service.h"
#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)

namespace web_app {
namespace {

_;
AllOf;
AnyNumber;
Exactly;
ExplainMatchResult;
Field;
Invoke;
Property;
VariantWith;
Step;

constexpr std::string_view kIconPath =;

MATCHER_P3(WithMetadata, app_id, app_name, version, "") {}

IsolatedWebAppUrlInfo CreateAndWriteTestBundle(
    const base::FilePath& bundle_path,
    const std::string& version) {}

SignedWebBundleMetadata CreateMetadata(const std::u16string& app_name,
                                       const std::string& version) {}

blink::mojom::ManifestPtr CreateDefaultManifest(const GURL& iwa_url,
                                                const base::Version version) {}

#if BUILDFLAG(IS_CHROMEOS_ASH)
std::unique_ptr<KeyedService> NullServiceFactory(content::BrowserContext*) {
  return nullptr;
}
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

class MockView : public IsolatedWebAppInstallerView {};

// Fake pref observer that mimics the behavior of an actual observer. i.e.
// posts callback to run:
// - Once on `Start()`.
// - Every time the pref value is changed.
class FakeIsolatedWebAppsEnabledPrefObserver
    : public IsolatedWebAppsEnabledPrefObserver {};

}  // namespace

class IsolatedWebAppInstallerViewControllerTest : public ::testing::Test {};

TEST_F(IsolatedWebAppInstallerViewControllerTest,
       ValidBundleTransitionsToShowMetadataScreen) {}

TEST_F(IsolatedWebAppInstallerViewControllerTest,
       InvalidBundleShowsErrorDialog) {}

TEST_F(IsolatedWebAppInstallerViewControllerTest,
       OutdatedBundleShowsAlreadyInstalledDialog) {}

TEST_F(IsolatedWebAppInstallerViewControllerTest,
       NewerBundleShowsAlreadyInstalledDialog) {}

TEST_F(IsolatedWebAppInstallerViewControllerTest,
       InstallButtonLaunchesConfirmationDialog) {}

TEST_F(IsolatedWebAppInstallerViewControllerTest,
       ConfirmationDialogMovesToInstallScreen) {}

TEST_F(IsolatedWebAppInstallerViewControllerTest,
       SuccessfulInstallationMovesToSuccessScreen) {}

TEST_F(IsolatedWebAppInstallerViewControllerTest, CanLaunchAppAfterInstall) {}

TEST_F(IsolatedWebAppInstallerViewControllerTest,
       InstallationErrorShowsErrorDialog) {}

TEST_F(IsolatedWebAppInstallerViewControllerTest,
       InstallationErrorRetryRestartsFlow) {}

#if BUILDFLAG(IS_CHROMEOS)

TEST_F(IsolatedWebAppInstallerViewControllerTest,
       ChangingPrefToFalseDisablesInstaller) {
  base::FilePath bundle_path = CreateBundlePath("test_bundle.swbn");
  IsolatedWebAppUrlInfo url_info = CreateAndWriteTestBundle(bundle_path, "1.0");
  SetTrustedWebBundleIdsForTesting({url_info.web_bundle_id()});
  MockIconAndPageState(url_info);

  IsolatedWebAppInstallerModel model{IwaSourceBundleProdMode(bundle_path)};
  auto pref_observer =
      std::make_unique<FakeIsolatedWebAppsEnabledPrefObserver>(true);
  FakeIsolatedWebAppsEnabledPrefObserver* raw_pref_observer =
      pref_observer.get();
  IsolatedWebAppInstallerViewController controller(
      profile(), fake_provider(), &model, std::move(pref_observer));
  testing::StrictMock<MockView> view;
  controller.SetViewForTesting(&view);

  EXPECT_CALL(view, UpdateGetMetadataProgress(_)).Times(AnyNumber());
  EXPECT_CALL(view, ShowGetMetadataScreen());
  EXPECT_CALL(
      view, ShowMetadataScreen(WithMetadata("hoealecpbefphiclhampllbdbdpfmfpi",
                                            u"test app name", "7.7.7")));

  controller.Start(base::DoNothing(), base::DoNothing());

  TestIsolatedWebAppInstallerModelObserver model_observer(&model);
  model_observer.WaitForStepChange(Step::kShowMetadata);

  EXPECT_CALL(view, ShowDisabledScreen());

  raw_pref_observer->UpdatePref(false);

  model_observer.WaitForStepChange(Step::kDisabled);
}

TEST_F(IsolatedWebAppInstallerViewControllerTest,
       ChangingPrefToTrueRestartsInstaller) {
  base::FilePath bundle_path = CreateBundlePath("test_bundle.swbn");
  IsolatedWebAppUrlInfo url_info = CreateAndWriteTestBundle(bundle_path, "1.0");
  SetTrustedWebBundleIdsForTesting({url_info.web_bundle_id()});
  MockIconAndPageState(url_info);

  IsolatedWebAppInstallerModel model{IwaSourceBundleProdMode(bundle_path)};
  auto pref_observer =
      std::make_unique<FakeIsolatedWebAppsEnabledPrefObserver>(false);
  FakeIsolatedWebAppsEnabledPrefObserver* raw_pref_observer =
      pref_observer.get();
  IsolatedWebAppInstallerViewController controller(
      profile(), fake_provider(), &model, std::move(pref_observer));
  testing::StrictMock<MockView> view;
  controller.SetViewForTesting(&view);

  EXPECT_CALL(view, ShowDisabledScreen());

  controller.Start(base::DoNothing(), base::DoNothing());

  TestIsolatedWebAppInstallerModelObserver model_observer(&model);
  model_observer.WaitForStepChange(Step::kDisabled);

  ASSERT_EQ(model.step(), Step::kDisabled);

  EXPECT_CALL(view, UpdateGetMetadataProgress(_)).Times(AnyNumber());
  EXPECT_CALL(view, ShowGetMetadataScreen());
  EXPECT_CALL(
      view, ShowMetadataScreen(WithMetadata("hoealecpbefphiclhampllbdbdpfmfpi",
                                            u"test app name", "7.7.7")));

  raw_pref_observer->UpdatePref(true);

  model_observer.WaitForStepChange(Step::kShowMetadata);
}
#endif  // BUILDFLAG(IS_CHROMEOS)
}  // namespace web_app