| // Copyright 2023 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/fake_autocomplete_controller.h" |
| |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "base/memory/raw_ptr.h" |
| #include "base/strings/string_number_conversions.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/test/task_environment.h" |
| #include "components/omnibox/browser/autocomplete_controller.h" |
| #include "components/omnibox/browser/autocomplete_match.h" |
| #include "components/omnibox/browser/autocomplete_match_type.h" |
| #include "components/omnibox/browser/fake_autocomplete_controller.h" |
| #include "components/omnibox/browser/fake_autocomplete_provider.h" |
| #include "components/omnibox/browser/fake_autocomplete_provider_client.h" |
| #include "components/omnibox/browser/omnibox_prefs.h" |
| #include "components/omnibox/browser/test_scheme_classifier.h" |
| #include "components/prefs/pref_registry_simple.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| void FakeAutocompleteControllerObserver::OnResultChanged( |
| AutocompleteController* controller, |
| bool default_match_changed) { |
| on_result_changed_call_count_++; |
| last_default_match_changed = default_match_changed; |
| } |
| |
| void FakeAutocompleteControllerObserver::OnAutocompleteStopTimerTriggered( |
| const AutocompleteInput& input) { |
| on_autocomplete_stop_timer_stopped_call_count++; |
| } |
| |
| FakeAutocompleteController::FakeAutocompleteController( |
| raw_ptr<base::test::SingleThreadTaskEnvironment> task_environment) |
| : AutocompleteController(std::make_unique<FakeAutocompleteProviderClient>(), |
| 0), |
| task_environment_(task_environment) { |
| omnibox::RegisterProfilePrefs(static_cast<PrefRegistrySimple*>( |
| static_cast<FakeAutocompleteProviderClient*>( |
| autocomplete_provider_client()) |
| ->GetPrefs() |
| ->DeprecatedGetPrefRegistry())); |
| |
| providers_.push_back(base::MakeRefCounted<FakeAutocompleteProvider>( |
| AutocompleteProvider::Type::TYPE_BOOKMARK)); |
| providers_.push_back(base::MakeRefCounted<FakeAutocompleteProvider>( |
| AutocompleteProvider::Type::TYPE_BUILTIN)); |
| providers_.push_back(base::MakeRefCounted<FakeAutocompleteProvider>( |
| AutocompleteProvider::Type::TYPE_HISTORY_QUICK)); |
| providers_.push_back(base::MakeRefCounted<FakeAutocompleteProvider>( |
| AutocompleteProvider::Type::TYPE_KEYWORD)); |
| providers_.push_back(base::MakeRefCounted<FakeAutocompleteProvider>( |
| AutocompleteProvider::Type::TYPE_SEARCH)); |
| providers_.push_back(base::MakeRefCounted<FakeAutocompleteProvider>( |
| AutocompleteProvider::Type::TYPE_HISTORY_URL)); |
| providers_.push_back(base::MakeRefCounted<FakeAutocompleteProvider>( |
| AutocompleteProvider::Type::TYPE_DOCUMENT)); |
| providers_.push_back(base::MakeRefCounted<FakeAutocompleteProvider>( |
| AutocompleteProvider::Type::TYPE_HISTORY_CLUSTER_PROVIDER)); |
| |
| observer_ = std::make_unique<FakeAutocompleteControllerObserver>(); |
| AddObserver(observer_.get()); |
| } |
| |
| FakeAutocompleteController::~FakeAutocompleteController() = default; |
| |
| // static |
| AutocompleteInput FakeAutocompleteController::CreateInput( |
| std::u16string text, |
| bool omit_async, |
| bool prevent_inline_autocomplete) { |
| AutocompleteInput input(text, 0, metrics::OmniboxEventProto::OTHER, |
| TestSchemeClassifier()); |
| input.set_omit_asynchronous_matches(omit_async); |
| input.set_prevent_inline_autocomplete(prevent_inline_autocomplete); |
| return input; |
| } |
| |
| std::vector<std::string> FakeAutocompleteController::SimulateAutocompletePass( |
| bool sync, |
| bool done, |
| std::vector<AutocompleteMatch> matches, |
| AutocompleteInput input) { |
| GetFakeProvider().matches_ = matches; |
| GetFakeProvider().done_ = done; |
| AutocompleteController::UpdateType expected_last_update_type = |
| AutocompleteController::UpdateType::kNone; |
| EXPECT_EQ(observer_->on_result_changed_call_count_, 0); |
| if (sync) { |
| Start(input); |
| expected_last_update_type = |
| done ? AutocompleteController::UpdateType::kSyncPassOnly |
| : AutocompleteController::UpdateType::kSyncPass; |
| } else { |
| OnProviderUpdate(true, &GetFakeProvider()); |
| expected_last_update_type = |
| done ? AutocompleteController::UpdateType::kLastAsyncPass |
| : AutocompleteController::UpdateType::kAsyncPass; |
| } |
| |
| ExpectOnResultChanged(sync || done ? 0 : 200, expected_last_update_type); |
| |
| return GetResultContents(true); |
| } |
| |
| std::vector<std::string> |
| FakeAutocompleteController::SimulateCleanAutocompletePass( |
| std::vector<AutocompleteMatch> matches) { |
| internal_result_.ClearMatches(); |
| return SimulateAutocompletePass(true, true, matches); |
| } |
| |
| std::vector<std::string> FakeAutocompleteController::SimulateExpirePass() { |
| EXPECT_EQ(observer_->on_result_changed_call_count_, 0); |
| UpdateResult(AutocompleteController::UpdateType::kExpirePass); |
| ExpectOnResultChanged(200, AutocompleteController::UpdateType::kExpirePass); |
| return GetResultContents(true); |
| } |
| |
| std::vector<std::string> FakeAutocompleteController::GetResultContents( |
| bool published) { |
| std::vector<std::string> names; |
| auto& result = published ? published_result_ : internal_result_; |
| for (const auto& match : result) |
| names.push_back(base::UTF16ToUTF8(match.contents)); |
| return names; |
| } |
| |
| void FakeAutocompleteController::ExpectOnResultChanged( |
| int delay_ms, |
| AutocompleteController::UpdateType last_update_type) { |
| std::string debug = |
| "delay_ms: " + base::NumberToString(delay_ms) + ", last_update_type: " + |
| AutocompleteController::UpdateTypeToDebugString(last_update_type); |
| if (delay_ms) { |
| task_environment_->FastForwardBy(base::Milliseconds(delay_ms - 1)); |
| EXPECT_EQ(observer_->on_result_changed_call_count_, 0) << debug; |
| task_environment_->FastForwardBy(base::Milliseconds(1)); |
| EXPECT_EQ(observer_->on_result_changed_call_count_, 1) << debug; |
| } else { |
| EXPECT_EQ(observer_->on_result_changed_call_count_, 1) << debug; |
| } |
| EXPECT_EQ(last_update_type_, last_update_type) << debug; |
| observer_->on_result_changed_call_count_ = 0; |
| } |
| |
| void FakeAutocompleteController::ExpectStopAfter(int delay_ms, |
| bool explicit_stop) { |
| if (delay_ms) { |
| task_environment_->FastForwardBy(base::Milliseconds(delay_ms - 1)); |
| EXPECT_NE(last_update_type_, AutocompleteController::UpdateType::kStop) |
| << delay_ms; |
| EXPECT_EQ(observer_->on_autocomplete_stop_timer_stopped_call_count, 0) |
| << delay_ms; |
| task_environment_->FastForwardBy(base::Milliseconds(1)); |
| } |
| EXPECT_EQ(last_update_type_, AutocompleteController::UpdateType::kStop) |
| << delay_ms; |
| EXPECT_EQ(observer_->on_autocomplete_stop_timer_stopped_call_count, |
| explicit_stop ? 0 : 1) |
| << delay_ms; |
| // Any expected notifications should be verified with |
| // `ExpectOnResultChanged()` and not slip through polluting subsequent |
| // tests. |
| EXPECT_EQ(observer_->on_result_changed_call_count_, 0) << delay_ms; |
| observer_->on_autocomplete_stop_timer_stopped_call_count = 0; |
| } |
| |
| void FakeAutocompleteController::ExpectNoNotificationOrStop() { |
| // Cache the `last_update_type_` and override, so that we can verify no new |
| // stop updates happen even if the last update was a stop. |
| auto last_update_type = last_update_type_; |
| last_update_type_ = AutocompleteController::UpdateType::kNone; |
| |
| task_environment_->FastForwardBy(base::Milliseconds(10000)); |
| EXPECT_EQ(observer_->on_result_changed_call_count_, 0); |
| EXPECT_NE(last_update_type_, AutocompleteController::UpdateType::kStop); |
| |
| last_update_type_ = last_update_type; |
| } |