chromium/chrome/browser/ash/crosapi/url_handler_ash.cc

// Copyright 2021 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/ash/crosapi/url_handler_ash.h"

#include "ash/webui/camera_app_ui/url_constants.h"
#include "ash/webui/connectivity_diagnostics/url_constants.h"
#include "ash/webui/diagnostics_ui/url_constants.h"
#include "ash/webui/firmware_update_ui/url_constants.h"
#include "ash/webui/help_app_ui/url_constants.h"
#include "ash/webui/print_management/url_constants.h"
#include "ash/webui/scanning/url_constants.h"
#include "ash/webui/system_apps/public/system_web_app_type.h"
#include "chrome/browser/ash/guest_os/guest_os_external_protocol_handler.h"
#include "chrome/browser/ash/system_web_apps/system_web_app_manager.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/ui/ash/system_web_apps/system_web_app_ui_utils.h"
#include "chrome/browser/ui/browser_window.h"
#include "chrome/browser/ui/settings_window_manager_chromeos.h"
#include "chrome/browser/ui/webui/chrome_web_ui_controller_factory.h"
#include "chrome/browser/web_applications/web_app_utils.h"
#include "chrome/common/webui_url_constants.h"
#include "chromeos/ash/components/browser_context_helper/browser_context_helper.h"
#include "chromeos/crosapi/cpp/gurl_os_handler_utils.h"
#include "components/services/app_service/public/cpp/app_launch_util.h"
#include "components/user_manager/user_manager.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "url/url_constants.h"

namespace crosapi {

UrlHandlerAsh::UrlHandlerAsh() = default;
UrlHandlerAsh::~UrlHandlerAsh() = default;

void UrlHandlerAsh::BindReceiver(
    mojo::PendingReceiver<mojom::UrlHandler> receiver) {
  receivers_.Add(this, std::move(receiver));
}

void UrlHandlerAsh::OpenUrl(const GURL& url) {
  OpenUrlInternal(url);
}

void UrlHandlerAsh::GetExternalHandler(const GURL& url,
                                       GetExternalHandlerCallback callback) {
  Profile* profile = Profile::FromBrowserContext(
      ash::BrowserContextHelper::Get()->GetBrowserContextByUser(
          user_manager::UserManager::Get()->GetPrimaryUser()));
  std::optional<std::string> name;
  std::optional<guest_os::GuestOsUrlHandler> registration =
      guest_os::GuestOsUrlHandler::GetForUrl(profile, url);
  if (registration) {
    name = registration->name();
  }
  std::move(callback).Run(name);
}

void UrlHandlerAsh::OpenExternal(const GURL& url) {
  Profile* profile = Profile::FromBrowserContext(
      ash::BrowserContextHelper::Get()->GetBrowserContextByUser(
          user_manager::UserManager::Get()->GetPrimaryUser()));
  platform_util::OpenExternal(profile, url);
}

namespace {

std::optional<ash::SystemWebAppType> GetSystemAppForURL(Profile* profile,
                                                        const GURL& url) {
  ash::SystemWebAppManager* swa_manager =
      ash::SystemWebAppManager::Get(profile);
  return swa_manager ? swa_manager->GetSystemAppForURL(url) : std::nullopt;
}

void OpenUrlInternalContinue(Profile* profile, const GURL& url) {
  DCHECK(ash::SystemWebAppManager::Get(profile)->IsAppEnabled(
      ash::SystemWebAppType::OS_URL_HANDLER));

  ash::SystemWebAppType swa_type =
      GetSystemAppForURL(profile, url)
          .value_or(ash::SystemWebAppType::OS_URL_HANDLER);

  ash::SystemAppLaunchParams launch_params;
  launch_params.url = url;
  int64_t display_id =
      display::Screen::GetScreen()->GetDisplayForNewWindows().id();
  ash::LaunchSystemWebAppAsync(profile, swa_type, launch_params,
                               std::make_unique<apps::WindowInfo>(display_id));
}

}  // namespace

// TODO(neis): Find a way to unify this code with the one in os_url_handler.cc.
bool UrlHandlerAsh::OpenUrlInternal(GURL url) {
  url = gurl_os_handler_utils::SanitizeAshUrl(url);

  Profile* profile = Profile::FromBrowserContext(
      ash::BrowserContextHelper::Get()->GetBrowserContextByUser(
          user_manager::UserManager::Get()->GetPrimaryUser()));
  if (!profile) {
    base::debug::DumpWithoutCrashing();
    DVLOG(1)
        << "UrlHandlerAsh::OpenUrl is called when the primary user profile "
           "does not exist. This is a bug.";
    NOTREACHED_IN_MIGRATION();
    return false;
  }

  if (!ChromeWebUIControllerFactory::GetInstance()->CanHandleUrl(url)) {
    LOG(ERROR) << "Invalid URL passed to UrlHandlerAsh::OpenUrl: " << url;
    return false;
  }

  // Wait for all SWAs to be registered before continuing.
  ash::SystemWebAppManager::Get(profile)->on_apps_synchronized().Post(
      FROM_HERE, base::BindOnce(&OpenUrlInternalContinue, profile, url));
  return true;
}

}  // namespace crosapi