blob: 057c489647f75b181728f96d57e752fbcd8ddcb9 [file] [log] [blame]
// Copyright 2017 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 "chrome/browser/android/vr/autocomplete_controller.h"
#include <string>
#include <utility>
#include "base/bind.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/autocomplete/chrome_autocomplete_provider_client.h"
#include "chrome/browser/profiles/profile_manager.h"
#include "chrome/browser/vr/model/omnibox_suggestions.h"
#include "components/omnibox/browser/autocomplete_classifier.h"
#include "components/omnibox/browser/autocomplete_input.h"
#include "components/omnibox/browser/omnibox_controller_emitter.h"
#include "components/search_engines/util.h"
namespace vr {
namespace {
constexpr size_t kMaxNumberOfSuggestions = 4;
constexpr int kSuggestionThrottlingDelayMs = 150;
} // namespace
AutocompleteController::AutocompleteController(SuggestionCallback callback)
: profile_(ProfileManager::GetActiveUserProfile()),
suggestion_callback_(std::move(callback)) {
auto client = std::make_unique<ChromeAutocompleteProviderClient>(profile_);
client_ = client.get();
autocomplete_controller_ = std::make_unique<::AutocompleteController>(
std::move(client), AutocompleteClassifier::DefaultOmniboxProviders());
autocomplete_controller_->AddObserver(this);
OmniboxControllerEmitter* emitter =
OmniboxControllerEmitter::GetForBrowserContext(profile_);
if (emitter)
autocomplete_controller_->AddObserver(emitter);
}
AutocompleteController::~AutocompleteController() = default;
void AutocompleteController::Start(const AutocompleteRequest& request) {
metrics::OmniboxEventProto::PageClassification page_classification =
metrics::OmniboxEventProto::OTHER;
AutocompleteInput input(request.text, request.cursor_position,
page_classification,
ChromeAutocompleteSchemeClassifier(profile_));
input.set_prevent_inline_autocomplete(request.prevent_inline_autocomplete);
autocomplete_controller_->Start(input);
last_request_ = request;
}
void AutocompleteController::Stop() {
autocomplete_controller_->Stop(true);
suggestion_callback_.Run(std::vector<OmniboxSuggestion>{});
}
std::tuple<GURL, bool> AutocompleteController::GetUrlFromVoiceInput(
const std::u16string& input) {
AutocompleteMatch match;
std::u16string culled_input;
base::RemoveChars(input, u" ", &culled_input);
client_->Classify(culled_input, false, false,
metrics::OmniboxEventProto::INVALID_SPEC, &match, nullptr);
if (match.destination_url.is_valid() &&
(match.type == AutocompleteMatchType::URL_WHAT_YOU_TYPED ||
match.type == AutocompleteMatchType::HISTORY_URL ||
match.type == AutocompleteMatchType::NAVSUGGEST)) {
return {match.destination_url, true};
}
return {GURL(GetDefaultSearchURLForSearchTerms(
client_->GetTemplateURLService(), input)),
false};
}
void AutocompleteController::OnResultChanged(
::AutocompleteController* controller,
bool default_match_changed) {
DCHECK(controller == autocomplete_controller_.get());
std::vector<OmniboxSuggestion> suggestions;
for (const auto& match : autocomplete_controller_->result()) {
const gfx::VectorIcon* icon = &match.GetVectorIcon(false);
suggestions.emplace_back(match.contents, match.description,
match.contents_class, match.description_class,
icon, match.destination_url, last_request_.text,
match.inline_autocompletion);
if (suggestions.size() >= kMaxNumberOfSuggestions)
break;
}
suggestions_timeout_.Cancel();
if (suggestions.size() < kMaxNumberOfSuggestions) {
suggestions_timeout_.Reset(
base::BindOnce(suggestion_callback_, std::move(suggestions)));
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE, suggestions_timeout_.callback(),
base::Milliseconds(kSuggestionThrottlingDelayMs));
} else {
suggestion_callback_.Run(std::move(suggestions));
}
}
} // namespace vr