chromium/chrome/browser/ui/web_applications/web_app_browser_controller.cc

// Copyright 2015 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/web_applications/web_app_browser_controller.h"

#include "base/callback_list.h"
#include "base/check_is_test.h"
#include "base/containers/flat_set.h"
#include "base/feature_list.h"
#include "base/functional/callback.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
#include "chrome/browser/apps/app_service/app_service_proxy.h"
#include "chrome/browser/apps/app_service/app_service_proxy_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_commands.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/tabs/tab_menu_model_factory.h"
#include "chrome/browser/ui/web_applications/web_app_launch_utils.h"
#include "chrome/browser/ui/web_applications/web_app_tabbed_utils.h"
#include "chrome/browser/web_applications/locks/app_lock.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_helpers.h"
#include "chrome/browser/web_applications/web_app_icon_manager.h"
#include "chrome/browser/web_applications/web_app_id_constants.h"
#include "chrome/browser/web_applications/web_app_install_manager.h"
#include "chrome/browser/web_applications/web_app_provider.h"
#include "chrome/browser/web_applications/web_app_registrar.h"
#include "chrome/browser/web_applications/web_app_sync_bridge.h"
#include "chrome/browser/web_applications/web_app_tab_helper.h"
#include "chrome/browser/web_applications/web_app_ui_manager.h"
#include "chrome/grit/generated_resources.h"
#include "components/password_manager/core/common/password_manager_features.h"
#include "components/services/app_service/public/cpp/app_registry_cache.h"
#include "components/services/app_service/public/cpp/app_types.h"
#include "components/webapps/browser/installable/installable_metrics.h"
#include "components/webapps/common/web_app_id.h"
#include "content/public/browser/site_isolation_policy.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_features.h"
#include "third_party/blink/public/common/features.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/favicon_size.h"
#include "ui/gfx/image/image.h"
#include "ui/native_theme/native_theme.h"
#include "url/gurl.h"

#if BUILDFLAG(IS_CHROMEOS)
#include "chrome/browser/web_applications/chromeos_web_app_experiments.h"
#include "chrome/common/chrome_features.h"
#include "chromeos/constants/chromeos_features.h"
#endif

#if BUILDFLAG(IS_CHROMEOS_ASH)
#include "ash/constants/ash_features.h"
#include "chrome/browser/ash/apps/apk_web_app_service.h"
#include "chrome/browser/ash/system_web_apps/color_helpers.h"
#include "chrome/browser/ash/system_web_apps/types/system_web_app_delegate.h"
#include "chromeos/constants/chromeos_features.h"
#endif

#if BUILDFLAG(IS_CHROMEOS_LACROS)
#include "chromeos/crosapi/mojom/web_app_service.mojom.h"
#include "chromeos/lacros/lacros_service.h"
#include "chromeos/startup/browser_params_proxy.h"
#endif

namespace web_app {

namespace {

#if BUILDFLAG(IS_CHROMEOS)
constexpr char kRelationship[] = "delegate_permission/common.handle_all_urls";
#endif

#if BUILDFLAG(IS_CHROMEOS_ASH)
// SystemWebAppDelegate provides menu.
class SystemAppTabMenuModelFactory : public TabMenuModelFactory {
 public:
  explicit SystemAppTabMenuModelFactory(
      const ash::SystemWebAppDelegate* system_app)
      : system_app_(system_app) {}
  SystemAppTabMenuModelFactory(const SystemAppTabMenuModelFactory&) = delete;
  SystemAppTabMenuModelFactory& operator=(const SystemAppTabMenuModelFactory&) =
      delete;
  ~SystemAppTabMenuModelFactory() override = default;

  std::unique_ptr<ui::SimpleMenuModel> Create(
      ui::SimpleMenuModel::Delegate* delegate,
      TabMenuModelDelegate* tab_menu_model_delegate,
      TabStripModel*,
      int) override {
    return system_app_->GetTabMenuModel(delegate);
  }

 private:
  raw_ptr<const ash::SystemWebAppDelegate> system_app_ = nullptr;
};
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

base::OnceClosure& IconLoadCallbackForTesting() {}

base::OnceClosure& ManifestUpdateAppliedCallbackForTesting() {}

// Returns the list of patterns to match URLs against for tabbed mode home
// tab navigations.
std::vector<TabbedModeScopeMatcher> CreateTabbedHomeTabScope(
    const WebApp* web_app) {}

}  // namespace

WebAppBrowserController::WebAppBrowserController(
    WebAppProvider& provider,
    Browser* browser,
    webapps::AppId app_id,
#if BUILDFLAG(IS_CHROMEOS_ASH)
    const ash::SystemWebAppDelegate* system_app,
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)
    bool has_tab_strip)
    :{}

WebAppBrowserController::~WebAppBrowserController() = default;

bool WebAppBrowserController::HasMinimalUiButtons() const {}

bool WebAppBrowserController::IsHostedApp() const {}

std::unique_ptr<TabMenuModelFactory>
WebAppBrowserController::GetTabMenuModelFactory() const {}

bool WebAppBrowserController::AppUsesWindowControlsOverlay() const {}

bool WebAppBrowserController::IsWindowControlsOverlayEnabled() const {}

void WebAppBrowserController::ToggleWindowControlsOverlayEnabled(
    base::OnceClosure on_complete) {}

bool WebAppBrowserController::AppUsesBorderlessMode() const {}

bool WebAppBrowserController::AppUsesTabbed() const {}

bool WebAppBrowserController::IsIsolatedWebApp() const {}

void WebAppBrowserController::SetIsolatedWebAppTrueForTesting() {}

gfx::Rect WebAppBrowserController::GetDefaultBounds() const {}

bool WebAppBrowserController::HasReloadButton() const {}

#if !BUILDFLAG(IS_CHROMEOS)
bool WebAppBrowserController::HasProfileMenuButton() const {}

bool WebAppBrowserController::IsProfileMenuButtonVisible() const {}
#endif  // !BUILDFLAG(IS_CHROMEOS)

#if BUILDFLAG(IS_CHROMEOS_ASH)
const ash::SystemWebAppDelegate* WebAppBrowserController::system_app() const {
  return system_app_;
}
#endif  // BUILDFLAG(IS_CHROMEOS_ASH)

#if BUILDFLAG(IS_MAC)
bool WebAppBrowserController::AlwaysShowToolbarInFullscreen() const {
  // Reading this setting synchronously rather than going through the command
  // manager greatly simplifies where this is read. This should be fine, since
  // this is only persisted in the web app db.
  return registrar().AlwaysShowToolbarInFullscreen(app_id());
}

void WebAppBrowserController::ToggleAlwaysShowToolbarInFullscreen() {
  provider_->scheduler().ScheduleCallback(
      "WebAppBrowserController::ToggleAlwaysShowToolbarInFullscreen",
      AppLockDescription(app_id()),
      base::BindOnce(
          [](const webapps::AppId& app_id, AppLock& lock,
             base::Value::Dict& debug_value) {
            lock.sync_bridge().SetAlwaysShowToolbarInFullscreen(
                app_id,
                !lock.registrar().AlwaysShowToolbarInFullscreen(app_id));
          },
          app_id()),
      /*on_complete=*/base::DoNothing());
}
#endif

#if BUILDFLAG(IS_CHROMEOS)
bool WebAppBrowserController::ShouldShowCustomTabBar() const {
  if (AppBrowserController::ShouldShowCustomTabBar()) {
    return true;
  }

  return is_verified_.value_or(false);
}

void WebAppBrowserController::CheckDigitalAssetLinkRelationshipForAndroidApp(
    const std::string& package_name,
    const std::string& fingerprint) {
  // base::Unretained is safe as |asset_link_handler_| is owned by this object
  // and will be destroyed if this object is destroyed.
  // TODO(swestphal): Support passing several fingerprints for verification.
  std::vector<std::string> fingerprints{fingerprint};
  asset_link_handler_->CheckDigitalAssetLinkRelationshipForAndroidApp(
      url::Origin::Create(GetAppStartUrl()), kRelationship,
      std::move(fingerprints), package_name,
      base::BindOnce(&WebAppBrowserController::OnRelationshipCheckComplete,
                     base::Unretained(this)));
}

void WebAppBrowserController::OnRelationshipCheckComplete(
    content_relationship_verification::RelationshipCheckResult result) {
  bool should_show_cct = false;
  switch (result) {
    case content_relationship_verification::RelationshipCheckResult::kSuccess:
      should_show_cct = false;
      break;
    case content_relationship_verification::RelationshipCheckResult::kFailure:
    case content_relationship_verification::RelationshipCheckResult::
        kNoConnection:
      should_show_cct = true;
      break;
  }
  is_verified_ = should_show_cct;
  browser()->window()->UpdateCustomTabBarVisibility(should_show_cct,
                                                    false /* animate */);
}
#endif  // BUILDFLAG(IS_CHROMEOS)

#if BUILDFLAG(IS_CHROMEOS_LACROS)
void WebAppBrowserController::OnGetAssociatedAndroidPackage(
    crosapi::mojom::WebAppAndroidPackagePtr package) {
  if (!package) {
    // Web app was not installed from an Android package, nothing to check.
    return;
  }
  CheckDigitalAssetLinkRelationshipForAndroidApp(package->package_name,
                                                 package->sha256_fingerprint);
}
#endif  // BUILDFLAG(IS_CHROMEOS_LACROS)

void WebAppBrowserController::OnWebAppUninstalled(
    const webapps::AppId& uninstalled_app_id,
    webapps::WebappUninstallSource uninstall_source) {}

void WebAppBrowserController::OnWebAppManifestUpdated(
    const webapps::AppId& updated_app_id) {}

void WebAppBrowserController::OnWebAppInstallManagerDestroyed() {}

ui::ImageModel WebAppBrowserController::GetWindowAppIcon() const {}

gfx::ImageSkia WebAppBrowserController::GetHomeTabIcon() const {}

gfx::ImageSkia WebAppBrowserController::GetFallbackHomeTabIcon() const {}

ui::ImageModel WebAppBrowserController::GetWindowIcon() const {}

std::optional<SkColor> WebAppBrowserController::GetThemeColor() const {}

std::optional<SkColor> WebAppBrowserController::GetBackgroundColor() const {}

GURL WebAppBrowserController::GetAppStartUrl() const {}

GURL WebAppBrowserController::GetAppNewTabUrl() const {}

bool WebAppBrowserController::ShouldHideNewTabButton() const {}

bool WebAppBrowserController::IsUrlInHomeTabScope(const GURL& url) const {}

bool WebAppBrowserController::ShouldShowAppIconOnTab(int index) const {}

bool WebAppBrowserController::IsUrlInAppScope(const GURL& url) const {}

WebAppBrowserController* WebAppBrowserController::AsWebAppBrowserController() {}

std::u16string WebAppBrowserController::GetTitle() const {}

std::u16string WebAppBrowserController::GetAppShortName() const {}

std::u16string WebAppBrowserController::GetFormattedUrlOrigin() const {}

bool WebAppBrowserController::CanUserUninstall() const {}

void WebAppBrowserController::Uninstall(
    webapps::WebappUninstallSource webapp_uninstall_source) {}

bool WebAppBrowserController::IsInstalled() const {}

void WebAppBrowserController::SetIconLoadCallbackForTesting(
    base::OnceClosure callback) {}

void WebAppBrowserController::SetManifestUpdateAppliedCallbackForTesting(
    base::OnceClosure callback) {}

void WebAppBrowserController::OnTabInserted(content::WebContents* contents) {}

void WebAppBrowserController::OnTabRemoved(content::WebContents* contents) {}

const WebAppRegistrar& WebAppBrowserController::registrar() const {}

const WebAppInstallManager& WebAppBrowserController::install_manager() const {}

void WebAppBrowserController::LoadAppIcon(bool allow_placeholder_icon) const {}

void WebAppBrowserController::OnLoadIcon(apps::IconValuePtr icon_value) {}

void WebAppBrowserController::OnReadIcon(IconPurpose purpose, SkBitmap bitmap) {}

void WebAppBrowserController::PerformDigitalAssetLinkVerification(
    Browser* browser) {}

std::optional<SkColor>
WebAppBrowserController::GetResolvedManifestBackgroundColor() const {}

}  // namespace web_app