blob: fe6ef8341c881de10bb4fee0077ddc7624be89ca [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/omnibox/browser/omnibox_pedal.h"
#include <algorithm>
#include <cctype>
#include "base/strings/utf_string_conversions.h"
#include "components/omnibox/browser/omnibox_client.h"
#include "components/omnibox/browser/omnibox_edit_controller.h"
#include "components/omnibox/browser/omnibox_field_trial.h"
#include "ui/base/l10n/l10n_util.h"
#if (!defined(OS_ANDROID) || BUILDFLAG(ENABLE_VR)) && !defined(OS_IOS)
#include "components/omnibox/browser/vector_icons.h" // nogncheck
#endif
namespace {
// Find and erase one or all instances of given sequence from |from| sequence.
bool EraseTokenSubsequence(OmniboxPedal::Tokens* from,
const OmniboxPedal::Tokens& erase_sequence,
bool erase_only_once) {
bool changed = false;
for (;;) {
const auto found =
std::search(from->begin(), from->end(), erase_sequence.begin(),
erase_sequence.end());
if (found != from->end()) {
from->erase(found, found + erase_sequence.size());
changed = true;
if (erase_only_once) {
break;
}
} else {
break;
}
}
return changed;
}
} // namespace
OmniboxPedal::LabelStrings::LabelStrings(int id_hint,
int id_hint_short,
int id_suggestion_contents)
: hint(l10n_util::GetStringUTF16(id_hint)),
hint_short(l10n_util::GetStringUTF16(id_hint_short)),
suggestion_contents(l10n_util::GetStringUTF16(id_suggestion_contents)) {}
// =============================================================================
OmniboxPedal::SynonymGroup::SynonymGroup(bool required,
bool match_once,
size_t reserve_size)
: required_(required), match_once_(match_once) {
synonyms_.reserve(reserve_size);
}
OmniboxPedal::SynonymGroup::SynonymGroup(SynonymGroup&&) = default;
OmniboxPedal::SynonymGroup::~SynonymGroup() = default;
OmniboxPedal::SynonymGroup& OmniboxPedal::SynonymGroup::operator=(
SynonymGroup&&) = default;
bool OmniboxPedal::SynonymGroup::EraseMatchesIn(
OmniboxPedal::Tokens* remaining) const {
bool changed = false;
for (const auto& synonym : synonyms_) {
if (EraseTokenSubsequence(remaining, synonym, match_once_)) {
changed = true;
if (match_once_) {
break;
}
}
}
return changed || !required_;
}
void OmniboxPedal::SynonymGroup::AddSynonym(OmniboxPedal::Tokens&& synonym) {
#if DCHECK_IS_ON()
if (synonyms_.size() > size_t{0}) {
DCHECK_GE(synonyms_.back().size(), synonym.size());
}
#endif
synonyms_.push_back(std::move(synonym));
}
// =============================================================================
OmniboxPedal::OmniboxPedal(LabelStrings strings, GURL url)
: strings_(strings), url_(url) {}
OmniboxPedal::~OmniboxPedal() {}
const OmniboxPedal::LabelStrings& OmniboxPedal::GetLabelStrings() const {
return strings_;
}
bool OmniboxPedal::IsNavigation() const {
return !url_.is_empty();
}
const GURL& OmniboxPedal::GetNavigationUrl() const {
return url_;
}
void OmniboxPedal::Execute(OmniboxPedal::ExecutionContext& context) const {
DCHECK(IsNavigation());
OpenURL(context, url_);
}
bool OmniboxPedal::IsReadyToTrigger(
const AutocompleteProviderClient& client) const {
return true;
}
#if (!defined(OS_ANDROID) || BUILDFLAG(ENABLE_VR)) && !defined(OS_IOS)
const gfx::VectorIcon& OmniboxPedal::GetVectorIcon() const {
return omnibox::kPedalIcon;
}
#endif
bool OmniboxPedal::IsTriggerMatch(const Tokens& match_sequence) const {
return IsConceptMatch(match_sequence);
}
void OmniboxPedal::AddSynonymGroup(SynonymGroup&& group) {
synonym_groups_.push_back(std::move(group));
}
bool OmniboxPedal::IsConceptMatch(const Tokens& match_sequence) const {
Tokens remaining(match_sequence);
for (const auto& group : synonym_groups_) {
if (!group.EraseMatchesIn(&remaining))
return false;
}
return remaining.empty();
}
void OmniboxPedal::OpenURL(OmniboxPedal::ExecutionContext& context,
const GURL& url) const {
context.controller_.OnAutocompleteAccept(
url, nullptr, WindowOpenDisposition::CURRENT_TAB,
ui::PAGE_TRANSITION_GENERATED, AutocompleteMatchType::PEDAL,
context.match_selection_timestamp_);
}