// Copyright 2026 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/location_bar/location_icon_state_helper.h"

#include "build/branding_buildflags.h"
#include "chrome/browser/extensions/extension_ui_util.h"
#include "chrome/browser/ui/omnibox/omnibox_controller.h"
#include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
#include "chrome/grit/branded_strings.h"
#include "chrome/grit/generated_resources.h"
#include "components/contextual_tasks/public/features.h"
#include "components/dom_distiller/core/url_constants.h"
#include "components/omnibox/browser/autocomplete_classifier.h"
#include "components/omnibox/browser/autocomplete_match.h"
#include "components/omnibox/browser/location_bar_model.h"
#include "components/omnibox/browser/omnibox_text_util.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/url_constants.h"
#include "extensions/common/constants.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/image_model.h"

#if BUILDFLAG(GOOGLE_CHROME_BRANDING)              // nocheck
#include "chrome/grit/theme_resources.h"
#include "components/vector_icons/vector_icons.h"  // nogncheck
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/image/image_skia.h"
#endif

namespace location_bar {

std::u16string GetSecurityChipText(const LocationBarModel* model,
                                   content::WebContents* web_contents,
                                   bool is_editing_or_empty) {
  if (is_editing_or_empty) {
    return std::u16string();
  }

  if (model->GetURL().SchemeIs(content::kChromeUIScheme) ||
      (contextual_tasks::ShouldShowExpandedSecurityChip() &&
       model->IsContextualTasksPage())) {
    return l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME);
  }

  // Checked before the scheme labels below: an extension rendering the tab
  // owns its identity even when the URL scheme has a label of its own (e.g. a
  // file:// PDF rendered by a MIME handler). The icon override applies the
  // same precedence, and the two must agree.
  //
  // On ChromeOS, this can be called using web_contents from
  // SimpleWebViewDialog::GetWebContents() which always returns null.
  // TODO(crbug.com/40501128) Remove the null check and make
  // SimpleWebViewDialog::GetWebContents return the proper web contents
  // instead.
  if (web_contents) {
    const std::u16string extension_name =
        extensions::ui_util::GetEnabledExtensionNameForUrl(model->GetURL(),
                                                           *web_contents);
    if (!extension_name.empty()) {
      return extension_name;
    }
  }

  if (model->GetURL().SchemeIs(url::kFileScheme)) {
    return l10n_util::GetStringUTF16(IDS_OMNIBOX_FILE);
  }

  if (model->GetURL().SchemeIs(dom_distiller::kDomDistillerScheme)) {
    return l10n_util::GetStringUTF16(IDS_OMNIBOX_READER_MODE);
  }

  return model->GetSecureDisplayText();
}

bool ShouldShowSecurityChipText(const LocationBarModel* model,
                                content::WebContents* web_contents,
                                bool is_editing_or_empty) {
  if (is_editing_or_empty) {
    return false;
  }

  const GURL& url = model->GetURL();
  if (url.SchemeIs(content::kChromeUIScheme) ||
      url.SchemeIs(extensions::kExtensionScheme) ||
      url.SchemeIs(url::kFileScheme) ||
      url.SchemeIs(dom_distiller::kDomDistillerScheme) ||
      (model->IsContextualTasksPage() &&
       contextual_tasks::ShouldShowExpandedSecurityChip())) {
    return true;
  }

  // Generic MIME handler indicator: show the chip even when no security
  // text is available, so the chip can carry the extension name. The
  // chrome-extension:// scheme is already covered by the scheme test above;
  // this branch covers https:// URLs handled by a generic MIME handler.
  if (web_contents &&
      !extensions::ui_util::GetEnabledExtensionNameForUrl(url, *web_contents)
           .empty()) {
    return true;
  }

  return !model->GetSecureDisplayText().empty();
}

std::optional<int> MaybeGetGradientGoogleSuperGIcon(
    const ui::ImageModel& icon) {
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
  if (!icon.IsImage()) {
    return std::nullopt;
  }
  gfx::ImageSkia image = icon.GetImage().AsImageSkia();
  gfx::ImageSkia target_16 =
      *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
          IDR_GOOGLE_G_GRADIENT_16_ALT);
  gfx::ImageSkia target_20 =
      *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
          IDR_GOOGLE_G_GRADIENT_20);
  if (image.BackedBySameObjectAs(target_16)) {
    return IDR_GOOGLE_G_GRADIENT_16_ALT;
  }
  if (image.BackedBySameObjectAs(target_20)) {
    return IDR_GOOGLE_G_GRADIENT_20;
  }
#endif
  return std::nullopt;
}

SecurityChipAccessibilityState GetSecurityChipAccessibilityState(
    const LocationBarModel* model,
    bool is_editing_or_empty,
    std::u16string_view current_label) {
  SecurityChipAccessibilityState state;
  state.role = is_editing_or_empty ? ax::mojom::Role::kImage
                                   : ax::mojom::Role::kPopUpButton;

  if (is_editing_or_empty) {
    state.name = l10n_util::GetStringUTF16(IDS_ACC_SEARCH_ICON);
  } else {
    state.name = std::u16string(current_label);
    if (current_label.empty()) {
      // If no display text exists, ensure that the accessibility label is
      // added.
      state.description = model->GetSecureAccessibilityText();
    }
  }

  return state;
}

std::u16string GetSecurityChipTooltipText(bool is_editing_or_empty) {
  if (is_editing_or_empty) {
    return std::u16string();
  }
  return l10n_util::GetStringUTF16(IDS_TOOLTIP_LOCATION_ICON);
}

bool ShouldAnimateSecurityChipTextChange(
    bool is_editing_or_empty,
    security_state::SecurityLevel previous_level,
    security_state::SecurityLevel new_level) {
  if (is_editing_or_empty) {
    return false;
  }
  // Do not animate transitions from WARNING to DANGEROUS, since
  // the transition can look confusing/messy.
  if (new_level == security_state::DANGEROUS &&
      previous_level == security_state::WARNING) {
    return false;
  }
  return new_level == security_state::DANGEROUS ||
         new_level == security_state::WARNING;
}

void ExecutePasteAndGo(OmniboxController& omnibox_controller,
                       AutocompleteClassifier* autocomplete_classifier,
                       const std::u16string& text,
                       base::TimeTicks event_timestamp) {
  std::u16string sanitized_text = omnibox::SanitizeTextForPaste(text);

  if (!autocomplete_classifier) {
    return;
  }

  if (!omnibox_controller.edit_model()->CanPasteAndGo(sanitized_text)) {
    return;
  }

  AutocompleteMatch match;
  autocomplete_classifier->Classify(sanitized_text, false, false,
                                    metrics::OmniboxEventProto::BLANK, &match,
                                    nullptr);
  if (!content::ChildProcessSecurityPolicy::GetInstance()->IsWebSafeScheme(
          std::string(match.destination_url.scheme()))) {
    return;
  }

  omnibox_controller.edit_model()->PasteAndGo(sanitized_text, event_timestamp);
}

bool InitiateMiddleClickPasteIfSupported(
    bool is_middle_click,
    base::OnceCallback<void(std::u16string)> paste_callback) {
  if (is_middle_click && ui::Clipboard::IsMiddleClickPasteEnabled() &&
      ui::Clipboard::IsSupportedClipboardBuffer(
          ui::ClipboardBuffer::kSelection)) {
    ui::Clipboard::GetForCurrentThread()->ReadText(
        ui::ClipboardBuffer::kSelection, /*data_dst=*/std::nullopt,
        std::move(paste_callback));
    return true;
  }
  return false;
}

}  // namespace location_bar
