// Copyright 2012 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/webui/omnibox/omnibox_ui.h"

#include <utility>

#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "build/build_config.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/webui/omnibox/aim_eligibility/aim_eligibility_page_handler.h"
#include "chrome/browser/ui/webui/omnibox/logging/logs_page_handler.h"
#include "chrome/browser/ui/webui/omnibox/omnibox_page_handler.h"
#include "chrome/browser/ui/webui/version/version_handler.h"
#include "chrome/browser/ui/webui/version/version_ui.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/omnibox_resources.h"
#include "chrome/grit/omnibox_resources_map.h"
#include "components/omnibox/browser/omnibox_field_trial.h"
#include "components/omnibox/common/omnibox_features.h"
#include "content/public/browser/web_ui.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/browser/web_ui_data_source.h"
#include "services/network/public/mojom/content_security_policy.mojom.h"
#include "ui/base/webui/web_ui_util.h"
#include "ui/webui/webui_util.h"

#if !BUILDFLAG(IS_ANDROID)
#include "chrome/browser/ui/webui/theme_source.h"
#endif

bool OmniboxUIConfig::SupportsInProcessResourceLoadingV2() const {
  return true;
}

bool OmniboxUIConfig::ShouldCrashOnJavascriptErrorInDevelopmentBuild() const {
  return true;
}

OmniboxUI::OmniboxUI(content::WebUI* web_ui)
    : ui::MojoWebUIController(web_ui, /*enable_chrome_send=*/true) {
  // Set up the chrome://omnibox/ source.
  content::WebUIDataSource* source = content::WebUIDataSource::CreateAndAdd(
      Profile::FromWebUI(web_ui), chrome::kChromeUIOmniboxHost);

  webui::SetupWebUIDataSource(source, kOmniboxResources,
                              IDR_OMNIBOX_OMNIBOX_HTML);

#if !BUILDFLAG(IS_ANDROID)
  content::URLDataSource::Add(
      Profile::FromWebUI(web_ui),
      std::make_unique<ThemeSource>(Profile::FromWebUI(web_ui)));
#endif

  // Expose version information to client because it is useful in output.
  VersionUI::AddVersionDetailStrings(source);

  source->AddResourcePath("ml", IDR_OMNIBOX_ML_ML_HTML);
  source->AddResourcePath("aim-eligibility",
                          IDR_OMNIBOX_AIM_ELIGIBILITY_AIM_ELIGIBILITY_HTML);
  source->AddResourcePath("logging", IDR_OMNIBOX_LOGGING_LOGS_HTML);

  source->AddBoolean("isMlUrlScoringEnabled",
                     OmniboxFieldTrial::IsMlUrlScoringEnabled());

  // The following keys (`aimEligibilityTitle`, `showAimEligibilityFooter`) are
  // for illustration and parity purposes with the component extension version.
  source->AddBoolean("showAimEligibilityFooter", true);
  source->AddString("aimEligibilityTitle", "AIM Eligibility Diagnostic");
}

WEB_UI_CONTROLLER_TYPE_IMPL(OmniboxUI)

OmniboxUI::~OmniboxUI() = default;

void OmniboxUI::BindInterface(
    mojo::PendingReceiver<mojom::OmniboxPageHandler> receiver) {
  omnibox_handler_ = std::make_unique<OmniboxPageHandler>(
      Profile::FromWebUI(web_ui()), std::move(receiver));
}

void OmniboxUI::BindInterface(
    mojo::PendingReceiver<aim_eligibility::mojom::PageHandlerFactory>
        receiver) {
  if (aim_eligibility_factory_receiver_.is_bound()) {
    aim_eligibility_factory_receiver_.reset();
  }
  aim_eligibility_factory_receiver_.Bind(std::move(receiver));
}

void OmniboxUI::BindInterface(
    mojo::PendingReceiver<omnibox::logging::mojom::PageHandlerFactory>
        receiver) {
  if (logs_factory_receiver_.is_bound()) {
    logs_factory_receiver_.reset();
  }
  logs_factory_receiver_.Bind(std::move(receiver));
}

void OmniboxUI::CreatePageHandler(
    mojo::PendingRemote<aim_eligibility::mojom::Page> page,
    mojo::PendingReceiver<aim_eligibility::mojom::PageHandler> handler) {
  aim_eligibility_page_handler_ = std::make_unique<AimEligibilityPageHandler>(
      Profile::FromWebUI(web_ui()), std::move(handler), std::move(page));
}

void OmniboxUI::CreatePageHandler(
    mojo::PendingRemote<omnibox::logging::mojom::Page> page,
    mojo::PendingReceiver<omnibox::logging::mojom::PageHandler> handler) {
  logs_page_handler_ = std::make_unique<omnibox::logging::LogsPageHandler>(
      std::move(handler), std::move(page));
}
