// 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 "components/omnibox/browser/clipboard_provider.h"

#include <algorithm>
#include <memory>
#include <optional>
#include <utility>
#include <vector>

#include "base/feature_list.h"
#include "base/functional/bind.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/weak_ptr.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/user_metrics.h"
#include "base/strings/string_view_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/thread_pool.h"
#include "build/build_config.h"
#include "components/omnibox/browser/autocomplete_enums.h"
#include "components/omnibox/browser/autocomplete_input.h"
#include "components/omnibox/browser/autocomplete_match.h"
#include "components/omnibox/browser/autocomplete_provider_client.h"
#include "components/omnibox/browser/autocomplete_provider_listener.h"
#include "components/omnibox/browser/omnibox_field_trial.h"
#include "components/omnibox/browser/omnibox_text_util.h"
#include "components/omnibox/browser/omnibox_view.h"
#include "components/omnibox/browser/page_classification_functions.h"
#include "components/omnibox/browser/suggestion_group_util.h"
#include "components/omnibox/browser/verbatim_match.h"
#include "components/omnibox/common/omnibox_features.h"
#include "components/open_from_clipboard/clipboard_recent_content.h"
#include "components/search_engines/template_url_service.h"
#include "components/strings/grit/components_strings.h"
#include "components/url_formatter/url_formatter.h"
#include "third_party/metrics_proto/omnibox_focus_type.pb.h"
#include "third_party/omnibox_proto/groups.pb.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_util.h"

#if !BUILDFLAG(IS_IOS)
#include "ui/base/clipboard/clipboard.h"  // nogncheck
#endif                                    // !BUILDFLAG(IS_IOS)

namespace {
constexpr bool is_android = !!BUILDFLAG(IS_ANDROID);

const size_t kMaxClipboardSuggestionShownNumTimesSimpleSize = 20;

bool IsMatchDeletionEnabled() {
  return base::FeatureList::IsEnabled(
      omnibox::kOmniboxRemoveSuggestionsFromClipboard);
}

void RecordCreatingClipboardSuggestionMetrics(
    size_t current_url_suggested_times,
    bool matches_is_empty,
    AutocompleteMatchType::Type match_type,
    const base::TimeDelta clipboard_contents_age) {
  DCHECK(match_type == AutocompleteMatchType::CLIPBOARD_URL ||
         match_type == AutocompleteMatchType::CLIPBOARD_TEXT ||
         match_type == AutocompleteMatchType::CLIPBOARD_IMAGE);

  base::UmaHistogramSparse(
      "Omnibox.ClipboardSuggestionShownNumTimes",
      std::min(current_url_suggested_times,
               kMaxClipboardSuggestionShownNumTimesSimpleSize));
  UMA_HISTOGRAM_BOOLEAN("Omnibox.ClipboardSuggestionShownWithCurrentURL",
                        !matches_is_empty);
  UMA_HISTOGRAM_LONG_TIMES_100("Omnibox.ClipboardSuggestionShownAge",
                               clipboard_contents_age);
  if (match_type == AutocompleteMatchType::CLIPBOARD_URL) {
    base::UmaHistogramSparse(
        "Omnibox.ClipboardSuggestionShownNumTimes.URL",
        std::min(current_url_suggested_times,
                 kMaxClipboardSuggestionShownNumTimesSimpleSize));
    UMA_HISTOGRAM_BOOLEAN("Omnibox.ClipboardSuggestionShownWithCurrentURL.URL",
                          !matches_is_empty);
    UMA_HISTOGRAM_LONG_TIMES_100("Omnibox.ClipboardSuggestionShownAge.URL",
                                 clipboard_contents_age);
  } else if (match_type == AutocompleteMatchType::CLIPBOARD_TEXT) {
    base::UmaHistogramSparse(
        "Omnibox.ClipboardSuggestionShownNumTimes.TEXT",
        std::min(current_url_suggested_times,
                 kMaxClipboardSuggestionShownNumTimesSimpleSize));
    UMA_HISTOGRAM_BOOLEAN("Omnibox.ClipboardSuggestionShownWithCurrentURL.TEXT",
                          !matches_is_empty);
    UMA_HISTOGRAM_LONG_TIMES_100("Omnibox.ClipboardSuggestionShownAge.TEXT",
                                 clipboard_contents_age);
  } else if (match_type == AutocompleteMatchType::CLIPBOARD_IMAGE) {
    base::UmaHistogramSparse(
        "Omnibox.ClipboardSuggestionShownNumTimes.IMAGE",
        std::min(current_url_suggested_times,
                 kMaxClipboardSuggestionShownNumTimesSimpleSize));
    UMA_HISTOGRAM_BOOLEAN(
        "Omnibox.ClipboardSuggestionShownWithCurrentURL.IMAGE",
        !matches_is_empty);
    UMA_HISTOGRAM_LONG_TIMES_100("Omnibox.ClipboardSuggestionShownAge.IMAGE",
                                 clipboard_contents_age);
  }
}

void RecordDeletingClipboardSuggestionMetrics(
    AutocompleteMatchType::Type match_type,
    const base::TimeDelta clipboard_contents_age) {
  base::RecordAction(
      base::UserMetricsAction("Omnibox.ClipboardSuggestionRemoved"));

  UMA_HISTOGRAM_LONG_TIMES_100("Omnibox.ClipboardSuggestionRemovedAge",
                               clipboard_contents_age);
  if (match_type == AutocompleteMatchType::CLIPBOARD_URL) {
    UMA_HISTOGRAM_LONG_TIMES_100("Omnibox.ClipboardSuggestionRemovedAge.URL",
                                 clipboard_contents_age);
  } else if (match_type == AutocompleteMatchType::CLIPBOARD_TEXT) {
    UMA_HISTOGRAM_LONG_TIMES_100("Omnibox.ClipboardSuggestionRemovedAge.TEXT",
                                 clipboard_contents_age);
  } else if (match_type == AutocompleteMatchType::CLIPBOARD_IMAGE) {
    UMA_HISTOGRAM_LONG_TIMES_100("Omnibox.ClipboardSuggestionRemovedAge.IMAGE",
                                 clipboard_contents_age);
  }
}
}  // namespace

ClipboardProvider::ClipboardProvider(AutocompleteProviderClient* client,
                                     AutocompleteProviderListener* listener,
                                     ClipboardRecentContent* clipboard_content)
    : AutocompleteProvider(AutocompleteProvider::TYPE_CLIPBOARD),
      client_(client),
      clipboard_content_(clipboard_content),
      current_url_suggested_times_(0) {
  DCHECK(clipboard_content_);
  AddListener(listener);
}

ClipboardProvider::~ClipboardProvider() = default;

void ClipboardProvider::Start(const AutocompleteInput& input,
                              bool minimal_changes) {
  using OEP = ::metrics::OmniboxEventProto;

  matches_.clear();

  // If the user started typing, do not offer clipboard based match.
  if (!input.IsZeroSuggest()) {
    return;
  }

  auto page_class = input.current_page_classification();
  if (page_class == OEP::OTHER_ON_CCT ||
      page_class == OEP::SEARCH_RESULT_PAGE_ON_CCT) {
    return;
  }

  done_ = true;

  // On iOS and Android, accessing the clipboard contents shows a notification
  // to the user. To avoid this, all the methods above will not check the
  // contents and will return false/std::nullopt. Instead, check the existence
  // of content without accessing the actual content and create blank matches.
  if (!input.omit_asynchronous_matches()) {
    // Image matched was kicked off asynchronously, so proceed when that ends.
    CheckClipboardContent(input);
  }
}

void ClipboardProvider::Stop(AutocompleteStopReason stop_reason) {
  AutocompleteProvider::Stop(stop_reason);
  callback_weak_ptr_factory_.InvalidateWeakPtrs();
}

void ClipboardProvider::DeleteMatch(const AutocompleteMatch& match) {
  RecordDeletingClipboardSuggestionMetrics(
      match.type, clipboard_content_->GetClipboardContentAge());
  clipboard_content_->ClearClipboardContent();

  const auto pred = [&match](const AutocompleteMatch& i) {
    return i.contents == match.contents && i.type == match.type;
  };
  std::erase_if(matches_, pred);
}

void ClipboardProvider::AddProviderInfo(ProvidersInfo* provider_info) const {
  // If a URL wasn't suggested on this most recent focus event, don't bother
  // setting |times_returned_results_in_session|, as in effect this URL has
  // never been suggested during the current session.  (For the purpose of
  // this provider, we define a session as intervals between when a URL
  // clipboard suggestion changes.)
  if (current_url_suggested_times_ == 0)
    return;
  provider_info->push_back(metrics::OmniboxEventProto_ProviderInfo());
  metrics::OmniboxEventProto_ProviderInfo& new_entry = provider_info->back();
  new_entry.set_provider(AsOmniboxEventProviderType());
  new_entry.set_provider_done(done_);
  new_entry.set_times_returned_results_in_session(current_url_suggested_times_);
}

void ClipboardProvider::AddCreatedMatchWithTracking(
    const AutocompleteInput& input,
    AutocompleteMatch match,
    const base::TimeDelta clipboard_contents_age) {
  // Record the number of times the currently-offered URL has been suggested.
  // This only works over this run of Chrome; if the URL was in the clipboard
  // on a previous run, those offerings will not be counted.
  if (match.destination_url == current_url_suggested_) {
    current_url_suggested_times_++;
  } else {
    current_url_suggested_ = match.destination_url;
    current_url_suggested_times_ = 1;
  }

  RecordCreatingClipboardSuggestionMetrics(current_url_suggested_times_,
                                           matches_.empty(), match.type,
                                           clipboard_contents_age);

  if (is_android && omnibox::IsNTPPage(input.current_page_classification())) {
    // Assign the Clipboard to the PZPS group on NTP pages to improve the use
    // of the suggest space.
    match.suggestion_group_id = omnibox::GROUP_PERSONALIZED_ZERO_SUGGEST;
  } else {
    // Leave the clipboard in its dedicated section otherwise.
    match.suggestion_group_id = omnibox::GROUP_MOBILE_CLIPBOARD;
  }

  matches_.push_back(match);
}

bool ClipboardProvider::TemplateURLSupportsTextSearch() {
  TemplateURLService* url_service = client_->GetTemplateURLService();
  const TemplateURL* default_url = url_service->GetDefaultSearchProvider();
  if (!default_url)
    return false;

  DCHECK(!default_url->url().empty());
  DCHECK(default_url->url_ref().IsValid(url_service->search_terms_data()));
  return true;
}

bool ClipboardProvider::TemplateURLSupportsImageSearch() {
  TemplateURLService* url_service = client_->GetTemplateURLService();
  const TemplateURL* default_url = url_service->GetDefaultSearchProvider();

  return default_url && !default_url->image_url().empty() &&
         default_url->image_url_ref().IsValid(url_service->search_terms_data());
}

void ClipboardProvider::CheckClipboardContent(const AutocompleteInput& input) {
  std::set<ClipboardContentType> desired_types;
  desired_types.insert(ClipboardContentType::URL);

  if (TemplateURLSupportsTextSearch()) {
    desired_types.insert(ClipboardContentType::Text);
  }

  if (TemplateURLSupportsImageSearch()) {
    desired_types.insert(ClipboardContentType::Image);
  }

  done_ = false;

  // We want to get the age here because the contents of the clipboard could
  // change after this point. We want the age of the contents we actually use,
  // not the age of whatever's on the clipboard when the histogram is created
  // (i.e when the match is created).
  base::TimeDelta clipboard_contents_age =
      clipboard_content_->GetClipboardContentAge();
  clipboard_content_->HasRecentContentFromClipboard(
      desired_types,
      base::BindOnce(&ClipboardProvider::OnReceiveClipboardContent,
                     callback_weak_ptr_factory_.GetWeakPtr(), input,
                     clipboard_contents_age));
}

void ClipboardProvider::OnReceiveClipboardContent(
    const AutocompleteInput& input,
    base::TimeDelta clipboard_contents_age,
    std::set<ClipboardContentType> matched_types) {
  if (TemplateURLSupportsImageSearch() &&
      matched_types.find(ClipboardContentType::Image) != matched_types.end()) {
    // The image content will be added in later. If the image is large, encoding
    // the image may take some time, so just be wary whenever that step happens
    // (e.g OmniboxView::OpenMatch).
    AutocompleteMatch match = NewBlankImageMatch();
    AddCreatedMatchWithTracking(input, std::move(match),
                                clipboard_contents_age);
    NotifyListeners(true);
  } else if (matched_types.find(ClipboardContentType::URL) !=
             matched_types.end()) {
    AutocompleteMatch match = NewBlankURLMatch();
    AddCreatedMatchWithTracking(input, std::move(match),
                                clipboard_contents_age);
    NotifyListeners(true);
  } else if (TemplateURLSupportsTextSearch() &&
             matched_types.find(ClipboardContentType::Text) !=
                 matched_types.end()) {
    AutocompleteMatch match = NewBlankTextMatch();
    AddCreatedMatchWithTracking(input, std::move(match),
                                clipboard_contents_age);
    NotifyListeners(true);
  }
  done_ = true;
}

AutocompleteMatch ClipboardProvider::NewBlankURLMatch() {
  AutocompleteMatch match(this, omnibox::kClipboardMatchZeroSuggestRelevance,
                          IsMatchDeletionEnabled(),
                          AutocompleteMatchType::CLIPBOARD_URL);

  match.description.assign(l10n_util::GetStringUTF16(IDS_LINK_FROM_CLIPBOARD));
  if (!match.description.empty())
    match.description_class.push_back({0, ACMatchClassification::NONE});
  return match;
}

AutocompleteMatch ClipboardProvider::NewClipboardURLMatch(const GURL& url) {
  DCHECK(url.is_valid());

  AutocompleteMatch match = NewBlankURLMatch();
  UpdateClipboardURLContent(url, &match);
  return match;
}

AutocompleteMatch ClipboardProvider::NewBlankTextMatch() {
  AutocompleteMatch match(this, omnibox::kClipboardMatchZeroSuggestRelevance,
                          IsMatchDeletionEnabled(),
                          AutocompleteMatchType::CLIPBOARD_TEXT);
  // Any path leading here should first verify whether
  // TemplateUrlSupportsTextSearch().
  TemplateURLService* url_service = client_->GetTemplateURLService();
  const TemplateURL* default_url = url_service->GetDefaultSearchProvider();
  DCHECK(!!default_url);
  match.keyword = default_url->keyword();

  match.description.assign(l10n_util::GetStringUTF16(IDS_TEXT_FROM_CLIPBOARD));
  if (!match.description.empty())
    match.description_class.push_back({0, ACMatchClassification::NONE});

  match.transition = ui::PAGE_TRANSITION_GENERATED;
  return match;
}

std::optional<AutocompleteMatch> ClipboardProvider::NewClipboardTextMatch(
    const std::u16string& text) {
  AutocompleteMatch match = NewBlankTextMatch();

  if (!UpdateClipboardTextContent(text, &match))
    return std::nullopt;

  return match;
}

AutocompleteMatch ClipboardProvider::NewBlankImageMatch() {
  AutocompleteMatch match(this, omnibox::kClipboardMatchZeroSuggestRelevance,
                          IsMatchDeletionEnabled(),
                          AutocompleteMatchType::CLIPBOARD_IMAGE);
  // Any path leading here should first verify whether
  // TemplateUrlSupportsImageSearch().
  TemplateURLService* url_service = client_->GetTemplateURLService();
  const TemplateURL* default_url = url_service->GetDefaultSearchProvider();
  DCHECK(!!default_url);
  match.keyword = default_url->keyword();

  match.description.assign(l10n_util::GetStringUTF16(IDS_IMAGE_FROM_CLIPBOARD));
  if (!match.description.empty())
    match.description_class.push_back({0, ACMatchClassification::NONE});

  // This will end up being something like "Search for Copied Image." This may
  // seem strange to use for |fill_into_edit|, but it is because iOS requires
  // some text in the text field for the Enter key to work when using keyboard
  // navigation.
  match.fill_into_edit = match.description;
  match.transition = ui::PAGE_TRANSITION_GENERATED;

  return match;
}

void ClipboardProvider::NewClipboardImageMatch(
    std::optional<gfx::Image> optional_image,
    ClipboardImageMatchCallback callback) {
  // ImageSkia::ToImageSkia should only be called if the gfx::Image is
  // non-empty. It is unclear when the clipboard returns a non-optional but
  // empty image. See crbug.com/1136759 for more details.
  if (!optional_image || optional_image.value().IsEmpty()) {
    std::move(callback).Run(std::nullopt);
    return;
  }
  gfx::ImageSkia image_skia = *optional_image.value().ToImageSkia();
  image_skia.MakeThreadSafe();
  base::ThreadPool::PostTaskAndReplyWithResult(
      FROM_HERE,
      base::BindOnce(&ClipboardProvider::EncodeClipboardImage, image_skia),
      base::BindOnce(&ClipboardProvider::ConstructImageMatchCallback,
                     callback_weak_ptr_factory_.GetWeakPtr(),
                     std::move(callback)));
}

void ClipboardProvider::UpdateClipboardMatchWithContent(
    AutocompleteMatch* match,
    ClipboardMatchCallback callback) {
  DCHECK(match);
  if (match->type == AutocompleteMatchType::CLIPBOARD_URL) {
    clipboard_content_->GetRecentURLFromClipboard(base::BindOnce(
        &ClipboardProvider::OnReceiveURLForMatchWithContent,
        callback_weak_ptr_factory_.GetWeakPtr(), std::move(callback), match));
    return;
  } else if (match->type == AutocompleteMatchType::CLIPBOARD_TEXT) {
    clipboard_content_->GetRecentTextFromClipboard(base::BindOnce(
        &ClipboardProvider::OnReceiveTextForMatchWithContent,
        callback_weak_ptr_factory_.GetWeakPtr(), std::move(callback), match));
    return;
  } else if (match->type == AutocompleteMatchType::CLIPBOARD_IMAGE) {
    clipboard_content_->GetRecentImageFromClipboard(base::BindOnce(
        &ClipboardProvider::OnReceiveImageForMatchWithContent,
        callback_weak_ptr_factory_.GetWeakPtr(), std::move(callback), match));
    return;
  }
}

scoped_refptr<base::RefCountedMemory> ClipboardProvider::EncodeClipboardImage(
    gfx::ImageSkia image_skia) {
  gfx::Image resized_image =
      gfx::ResizedImageForSearchByImage(gfx::Image(image_skia));
  return resized_image.As1xPNGBytes();
}

void ClipboardProvider::ConstructImageMatchCallback(
    ClipboardImageMatchCallback callback,
    scoped_refptr<base::RefCountedMemory> image_bytes) {
  TemplateURLService* url_service = client_->GetTemplateURLService();
  const TemplateURL* default_url = url_service->GetDefaultSearchProvider();
  DCHECK(default_url);

  AutocompleteMatch match = NewBlankImageMatch();

  match.search_terms_args =
      std::make_unique<TemplateURLRef::SearchTermsArgs>(u"");
  match.search_terms_args->image_thumbnail_content.assign(
      base::as_string_view(*image_bytes));
  TemplateURLRef::PostContent post_content;
  GURL result(default_url->image_url_ref().ReplaceSearchTerms(
      *match.search_terms_args.get(), url_service->search_terms_data(),
      &post_content));

  if (!base::FeatureList::IsEnabled(omnibox::kImageSearchSuggestionThumbnail)) {
    // If Omnibox image suggestion do not need thumbnail, release memory.
    match.search_terms_args.reset();
  }
  match.destination_url = result;
  match.post_content =
      std::make_unique<TemplateURLRef::PostContent>(post_content);

  std::move(callback).Run(match);
}

void ClipboardProvider::OnReceiveURLForMatchWithContent(
    ClipboardMatchCallback callback,
    AutocompleteMatch* match,
    std::optional<GURL> optional_gurl) {
  if (!optional_gurl)
    return;

  GURL url = std::move(optional_gurl).value();
  UpdateClipboardURLContent(url, match);

  std::move(callback).Run();
}

void ClipboardProvider::OnReceiveTextForMatchWithContent(
    ClipboardMatchCallback callback,
    AutocompleteMatch* match,
    std::optional<std::u16string> optional_text) {
  if (!optional_text)
    return;

  std::u16string text = std::move(optional_text).value();
  if (!UpdateClipboardTextContent(text, match))
    return;

  std::move(callback).Run();
}

void ClipboardProvider::OnReceiveImageForMatchWithContent(
    ClipboardMatchCallback callback,
    AutocompleteMatch* match,
    std::optional<gfx::Image> optional_image) {
  if (!optional_image)
    return;

  gfx::Image image = std::move(optional_image).value();
  NewClipboardImageMatch(
      image,
      base::BindOnce(&ClipboardProvider::OnReceiveImageMatchForMatchWithContent,
                     callback_weak_ptr_factory_.GetWeakPtr(),
                     std::move(callback), match));
}

void ClipboardProvider::OnReceiveImageMatchForMatchWithContent(
    ClipboardMatchCallback callback,
    AutocompleteMatch* match,
    std::optional<AutocompleteMatch> optional_match) {
  DCHECK(match);
  if (!optional_match)
    return;

  match->destination_url = std::move(optional_match->destination_url);
  match->post_content = std::move(optional_match->post_content);
  match->search_terms_args = std::move(optional_match->search_terms_args);

  std::move(callback).Run();
}

void ClipboardProvider::UpdateClipboardURLContent(const GURL& url,
                                                  AutocompleteMatch* match) {
  DCHECK(url.is_valid());
  DCHECK(match);

  std::u16string text_plain = base::ASCIIToUTF16(url.spec());
  std::u16string text_sanitized = omnibox::SanitizeTextForPaste(text_plain);
  if (text_plain != text_sanitized) {
    UpdateClipboardTextContent(text_sanitized, match);
    return;
  }

  match->destination_url = url;

  // Because the user did not type a related input to get this clipboard
  // suggestion, preserve the subdomain so the user has extra context.
  auto format_types = AutocompleteMatch::GetFormatTypes(false, true);
  match->contents.assign(url_formatter::FormatUrl(url, format_types,
                                                  base::UnescapeRule::SPACES,
                                                  nullptr, nullptr, nullptr));
  if (!match->contents.empty())
    match->contents_class.push_back({0, ACMatchClassification::URL});
  match->fill_into_edit =
      AutocompleteInput::FormattedStringWithEquivalentMeaning(
          url, match->contents, client_->GetSchemeClassifier(), nullptr);

  // Update the match type in the event the Clipboard metadata told us this is a
  // text, but we resolve it as a URL (e.g. "chrome://" URLs on Android).
  match->type = AutocompleteMatchType::CLIPBOARD_URL;
}

bool ClipboardProvider::UpdateClipboardTextContent(
    const std::u16string& raw_text,
    AutocompleteMatch* match) {
  DCHECK(match);

  std::u16string text = omnibox::SanitizeTextForPaste(raw_text);

  // The text in the clipboard is a url. We don't want to prompt the user to
  // search for a url.
  if (GURL(text).is_valid()) {
    // Note: on Android, the clipboard content is evaluated by Android
    // Framework. The Framework is familiar with only a handful of URL schemes,
    // and any non-explicitly annotated URL with scheme not recognized by the
    // Android is immediately annotated as Text. Additionally, any application
    // setting clipboard content may supply its own annotation, which may be
    // inaccurate.
    // we do not have the control over all sources from where such URLs can come
    // from. The change below allows us to still open these URLs. Without this
    // change Clipboard suggestions may be non interactable, if the clipboard
    // contains an unannotated or mis-classified URL not recognized by Android.
    if constexpr (is_android) {
      UpdateClipboardURLContent(GURL(text), match);
      return true;
    }
    return false;
  }

  match->fill_into_edit = text;

  TemplateURLService* url_service = client_->GetTemplateURLService();
  const TemplateURL* default_url = url_service->GetDefaultSearchProvider();
  if (!default_url)
    return false;

  DCHECK(!default_url->url().empty());
  DCHECK(default_url->url_ref().IsValid(url_service->search_terms_data()));
  TemplateURLRef::SearchTermsArgs search_args(text);
  GURL result(default_url->url_ref().ReplaceSearchTerms(
      search_args, url_service->search_terms_data()));

  match->destination_url = result;
  match->contents.assign(AutocompleteMatch::SanitizeString(text));
  if (!match->contents.empty())
    match->contents_class.push_back({0, ACMatchClassification::NONE});

  match->keyword = default_url->keyword();

  // Update the match type in the event the Clipboard metadata told us this is a
  // URL, but we couldn't open it as such (either bad metadata, or javascript
  // url).
  match->type = AutocompleteMatchType::CLIPBOARD_TEXT;

  return true;
}
