blob: 427c5c8c3d54aa42693cb380232b3c83683d310c [file] [log] [blame]
// Copyright 2014 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/zero_suggest_provider.h"
#include <list>
#include <map>
#include <memory>
#include <string>
#include "base/metrics/field_trial.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "build/build_config.h"
#include "components/history/core/browser/top_sites.h"
#include "components/omnibox/browser/autocomplete_provider_listener.h"
#include "components/omnibox/browser/mock_autocomplete_provider_client.h"
#include "components/omnibox/browser/omnibox_field_trial.h"
#include "components/omnibox/browser/omnibox_prefs.h"
#include "components/omnibox/browser/test_scheme_classifier.h"
#include "components/omnibox/common/omnibox_features.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
#include "components/search_engines/omnibox_focus_type.h"
#include "components/search_engines/template_url.h"
#include "components/search_engines/template_url_service.h"
#include "components/variations/entropy_provider.h"
#include "components/variations/variations_associated_data.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/metrics_proto/omnibox_event.pb.h"
namespace {
class FakeEmptyTopSites : public history::TopSites {
public:
FakeEmptyTopSites() {
}
FakeEmptyTopSites(const FakeEmptyTopSites&) = delete;
FakeEmptyTopSites& operator=(const FakeEmptyTopSites&) = delete;
// history::TopSites:
void GetMostVisitedURLs(GetMostVisitedURLsCallback callback) override;
void SyncWithHistory() override {}
bool HasBlockedUrls() const override { return false; }
void AddBlockedUrl(const GURL& url) override {}
void RemoveBlockedUrl(const GURL& url) override {}
bool IsBlocked(const GURL& url) override { return false; }
void ClearBlockedUrls() override {}
bool IsFull() override { return false; }
bool loaded() const override {
return false;
}
history::PrepopulatedPageList GetPrepopulatedPages() override {
return history::PrepopulatedPageList();
}
void OnNavigationCommitted(const GURL& url) override {}
// RefcountedKeyedService:
void ShutdownOnUIThread() override {}
// Only runs a single callback, so that the test can specify a different
// set per call.
void RunACallback(const history::MostVisitedURLList& urls) {
DCHECK(!callbacks.empty());
std::move(callbacks.front()).Run(urls);
callbacks.pop_front();
}
protected:
// A test-specific field for controlling when most visited callback is run
// after top sites have been requested.
std::list<GetMostVisitedURLsCallback> callbacks;
~FakeEmptyTopSites() override {}
};
void FakeEmptyTopSites::GetMostVisitedURLs(
GetMostVisitedURLsCallback callback) {
callbacks.push_back(std::move(callback));
}
class FakeAutocompleteProviderClient : public MockAutocompleteProviderClient {
public:
FakeAutocompleteProviderClient()
: template_url_service_(new TemplateURLService(nullptr, 0)),
top_sites_(new FakeEmptyTopSites()) {
pref_service_.registry()->RegisterStringPref(
omnibox::kZeroSuggestCachedResults, std::string());
}
FakeAutocompleteProviderClient(const FakeAutocompleteProviderClient&) =
delete;
FakeAutocompleteProviderClient& operator=(
const FakeAutocompleteProviderClient&) = delete;
bool SearchSuggestEnabled() const override { return true; }
scoped_refptr<history::TopSites> GetTopSites() override { return top_sites_; }
TemplateURLService* GetTemplateURLService() override {
return template_url_service_.get();
}
TemplateURLService* GetTemplateURLService() const override {
return template_url_service_.get();
}
PrefService* GetPrefs() override { return &pref_service_; }
bool IsPersonalizedUrlDataCollectionActive() const override { return true; }
void Classify(
const base::string16& text,
bool prefer_keyword,
bool allow_exact_keyword_match,
metrics::OmniboxEventProto::PageClassification page_classification,
AutocompleteMatch* match,
GURL* alternate_nav_url) override {
// Populate enough of |match| to keep the ZeroSuggestProvider happy.
match->type = AutocompleteMatchType::URL_WHAT_YOU_TYPED;
match->destination_url = GURL(text);
}
const AutocompleteSchemeClassifier& GetSchemeClassifier() const override {
return scheme_classifier_;
}
private:
std::unique_ptr<TemplateURLService> template_url_service_;
scoped_refptr<history::TopSites> top_sites_;
TestingPrefServiceSimple pref_service_;
TestSchemeClassifier scheme_classifier_;
};
} // namespace
class ZeroSuggestProviderTest : public testing::Test,
public AutocompleteProviderListener {
public:
ZeroSuggestProviderTest() = default;
ZeroSuggestProviderTest(const ZeroSuggestProviderTest&) = delete;
ZeroSuggestProviderTest& operator=(const ZeroSuggestProviderTest&) = delete;
void SetUp() override;
protected:
// AutocompleteProviderListener:
void OnProviderUpdate(bool updated_matches) override;
void CreateRemoteNoUrlFieldTrial();
void CreateMostVisitedFieldTrial();
void SetZeroSuggestVariantForAllContexts(const std::string& variant);
base::test::SingleThreadTaskEnvironment task_environment_;
std::unique_ptr<base::test::ScopedFeatureList> scoped_feature_list_;
std::unique_ptr<FakeAutocompleteProviderClient> client_;
scoped_refptr<ZeroSuggestProvider> provider_;
network::TestURLLoaderFactory* test_loader_factory() {
return client_->test_url_loader_factory();
}
GURL GetSuggestURL(
metrics::OmniboxEventProto::PageClassification page_classification) {
TemplateURLRef::SearchTermsArgs search_terms_args;
search_terms_args.page_classification = page_classification;
search_terms_args.focus_type = OmniboxFocusType::ON_FOCUS;
return RemoteSuggestionsService::EndpointUrl(
search_terms_args, client_->GetTemplateURLService());
}
};
void ZeroSuggestProviderTest::SetUp() {
client_.reset(new FakeAutocompleteProviderClient());
TemplateURLService* turl_model = client_->GetTemplateURLService();
turl_model->Load();
// Verify that Google is the default search provider.
ASSERT_EQ(SEARCH_ENGINE_GOOGLE,
turl_model->GetDefaultSearchProvider()->GetEngineType(
turl_model->search_terms_data()));
provider_ = ZeroSuggestProvider::Create(client_.get(), this);
}
void ZeroSuggestProviderTest::OnProviderUpdate(bool updated_matches) {
}
void ZeroSuggestProviderTest::CreateRemoteNoUrlFieldTrial() {
SetZeroSuggestVariantForAllContexts(ZeroSuggestProvider::kRemoteNoUrlVariant);
}
void ZeroSuggestProviderTest::CreateMostVisitedFieldTrial() {
SetZeroSuggestVariantForAllContexts(ZeroSuggestProvider::kMostVisitedVariant);
}
void ZeroSuggestProviderTest::SetZeroSuggestVariantForAllContexts(
const std::string& variant) {
scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
scoped_feature_list_->InitAndEnableFeatureWithParameters(
omnibox::kOnFocusSuggestions,
{{std::string(OmniboxFieldTrial::kZeroSuggestVariantRule) + ":*:*",
variant}});
}
TEST_F(ZeroSuggestProviderTest, AllowZeroSuggestSuggestions) {
std::string input_url = "https://example.com/";
AutocompleteInput prefix_input(base::ASCIIToUTF16(input_url),
metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
prefix_input.set_focus_type(OmniboxFocusType::DEFAULT);
AutocompleteInput on_focus_input(base::ASCIIToUTF16(input_url),
metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
on_focus_input.set_current_url(GURL(input_url));
on_focus_input.set_focus_type(OmniboxFocusType::ON_FOCUS);
AutocompleteInput on_clobber_input(base::string16(),
metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
on_clobber_input.set_current_url(GURL(input_url));
on_clobber_input.set_focus_type(OmniboxFocusType::DELETED_PERMANENT_TEXT);
// ZeroSuggest should never deal with prefix suggestions.
EXPECT_FALSE(provider_->AllowZeroSuggestSuggestions(prefix_input));
// This should always be true, as otherwise we will break MostVisited.
// TODO(tommycli): We should split this into its own provider to avoid
// breaking it again.
EXPECT_TRUE(provider_->AllowZeroSuggestSuggestions(on_focus_input));
EXPECT_FALSE(provider_->AllowZeroSuggestSuggestions(on_clobber_input));
// Enable on-clobber.
{
base::test::ScopedFeatureList features;
features.InitAndEnableFeature(
omnibox::kClobberTriggersContextualWebZeroSuggest);
EXPECT_FALSE(provider_->AllowZeroSuggestSuggestions(prefix_input));
EXPECT_TRUE(provider_->AllowZeroSuggestSuggestions(on_focus_input));
EXPECT_TRUE(provider_->AllowZeroSuggestSuggestions(on_clobber_input));
// Sanity check that we only affect the OTHER page classification.
AutocompleteInput on_clobber_serp(
base::string16(),
metrics::OmniboxEventProto::
SEARCH_RESULT_PAGE_DOING_SEARCH_TERM_REPLACEMENT,
TestSchemeClassifier());
on_clobber_serp.set_current_url(GURL(input_url));
on_clobber_serp.set_focus_type(OmniboxFocusType::DELETED_PERMANENT_TEXT);
EXPECT_FALSE(provider_->AllowZeroSuggestSuggestions(on_clobber_serp));
}
}
// TODO(tommycli): Break up this test into smaller ones.
TEST_F(ZeroSuggestProviderTest, TypeOfResultToRun) {
// Verifies the unconfigured state. Returns platorm-specific defaults.
// TODO(tommycli): The remote_no_url_allowed idiom seems kind of confusing,
// its true meaning seems closer to "expect_remote_no_url". Ideally we can
// simplify the test or make this much more obvious.
auto ExpectPlatformSpecificDefaultZeroSuggestBehavior =
[&](AutocompleteInput& input, const bool remote_no_url_allowed) {
const auto current_page_classification =
input.current_page_classification();
GURL suggest_url = GetSuggestURL(current_page_classification);
const auto result_type = ZeroSuggestProvider::TypeOfResultToRun(
client_.get(), input, suggest_url);
#if !defined(OS_ANDROID) && !defined(OS_IOS) // Desktop
EXPECT_EQ(BaseSearchProvider::IsNTPPage(current_page_classification) &&
remote_no_url_allowed
? ZeroSuggestProvider::ResultType::REMOTE_NO_URL
: ZeroSuggestProvider::ResultType::NONE,
result_type);
#elif !defined(OS_IOS) // Android
EXPECT_EQ(BaseSearchProvider::IsNTPPage(current_page_classification) &&
remote_no_url_allowed
? ZeroSuggestProvider::ResultType::REMOTE_NO_URL
: !BaseSearchProvider::IsSearchResultsPage(
current_page_classification)
? ZeroSuggestProvider::ResultType::MOST_VISITED
: ZeroSuggestProvider::ResultType::NONE,
result_type);
#else // iOS
EXPECT_EQ(!BaseSearchProvider::IsSearchResultsPage(
current_page_classification)
? ZeroSuggestProvider::ResultType::MOST_VISITED
: ZeroSuggestProvider::ResultType::NONE,
result_type);
#endif
};
// Verify OTHER defaults (contextual web).
std::string url("https://www.example.com/");
AutocompleteInput other_input(base::ASCIIToUTF16(url),
metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
other_input.set_current_url(GURL(url));
ExpectPlatformSpecificDefaultZeroSuggestBehavior(
other_input,
/*remote_no_url_allowed=*/false);
// Verify the platorm-specific defaults for the NTP.
AutocompleteInput ntp_input(base::string16(), metrics::OmniboxEventProto::NTP,
TestSchemeClassifier());
ExpectPlatformSpecificDefaultZeroSuggestBehavior(
ntp_input,
/*remote_no_url_allowed=*/false);
// Verify RemoteNoUrl works when the user is signed in.
EXPECT_CALL(*client_, IsAuthenticated())
.WillRepeatedly(testing::Return(true));
ExpectPlatformSpecificDefaultZeroSuggestBehavior(
ntp_input,
/*remote_no_url_allowed=*/true);
CreateRemoteNoUrlFieldTrial();
GURL other_suggest_url = GetSuggestURL(metrics::OmniboxEventProto::OTHER);
EXPECT_EQ(ZeroSuggestProvider::ResultType::REMOTE_NO_URL,
ZeroSuggestProvider::TypeOfResultToRun(client_.get(), other_input,
other_suggest_url));
// But if the user has signed out, fall back to platform-specific defaults.
EXPECT_CALL(*client_, IsAuthenticated())
.WillRepeatedly(testing::Return(false));
ExpectPlatformSpecificDefaultZeroSuggestBehavior(
other_input,
/*remote_no_url_allowed=*/false);
// Unless we allow remote suggestions for signed-out users.
scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
scoped_feature_list_->InitAndEnableFeature(
omnibox::kOmniboxTrendingZeroPrefixSuggestionsOnNTP);
ExpectPlatformSpecificDefaultZeroSuggestBehavior(
other_input,
/*remote_no_url_allowed=*/true);
// Restore authentication state, but now set a non-Google default search
// engine. Verify that we still disallow remote suggestions.
EXPECT_CALL(*client_, IsAuthenticated())
.WillRepeatedly(testing::Return(true));
TemplateURLService* turl_model = client_->GetTemplateURLService();
auto* google_search_provider = turl_model->GetDefaultSearchProvider();
TemplateURLData data;
data.SetURL("https://www.example.com/?q={searchTerms}");
data.suggestions_url = "https://www.example.com/suggest/?q={searchTerms}";
auto* other_search_provider =
turl_model->Add(std::make_unique<TemplateURL>(data));
turl_model->SetUserSelectedDefaultSearchProvider(other_search_provider);
ExpectPlatformSpecificDefaultZeroSuggestBehavior(
other_input,
/*remote_no_url_allowed=*/false);
// Restore Google as the default search provider.
turl_model->SetUserSelectedDefaultSearchProvider(
const_cast<TemplateURL*>(google_search_provider));
// Verify a few globally configured states work.
SetZeroSuggestVariantForAllContexts(
ZeroSuggestProvider::kRemoteSendUrlVariant);
EXPECT_EQ(ZeroSuggestProvider::ResultType::REMOTE_SEND_URL,
ZeroSuggestProvider::TypeOfResultToRun(client_.get(), other_input,
other_suggest_url));
CreateRemoteNoUrlFieldTrial();
EXPECT_EQ(ZeroSuggestProvider::ResultType::REMOTE_NO_URL,
ZeroSuggestProvider::TypeOfResultToRun(client_.get(), other_input,
other_suggest_url));
CreateMostVisitedFieldTrial();
EXPECT_EQ(ZeroSuggestProvider::ResultType::MOST_VISITED,
ZeroSuggestProvider::TypeOfResultToRun(client_.get(), other_input,
other_suggest_url));
// Verify that a wildcard rule works in conjunction with a
// page-classification-specific rule.
scoped_feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
scoped_feature_list_->InitAndEnableFeatureWithParameters(
omnibox::kOnFocusSuggestions,
{
{std::string(OmniboxFieldTrial::kZeroSuggestVariantRule) + ":*:*",
ZeroSuggestProvider::kMostVisitedVariant},
{base::StringPrintf("%s:%d:*",
OmniboxFieldTrial::kZeroSuggestVariantRule,
metrics::OmniboxEventProto::BLANK),
ZeroSuggestProvider::kNoneVariant},
});
EXPECT_EQ(ZeroSuggestProvider::ResultType::MOST_VISITED,
ZeroSuggestProvider::TypeOfResultToRun(client_.get(), other_input,
other_suggest_url));
// Test the BLANK page classification to verify the wildcard rule works.
{
std::string url("chrome://newtab/");
AutocompleteInput blank_input(base::ASCIIToUTF16(url),
metrics::OmniboxEventProto::BLANK,
TestSchemeClassifier());
blank_input.set_current_url(GURL(url));
EXPECT_EQ(ZeroSuggestProvider::ResultType::NONE,
ZeroSuggestProvider::TypeOfResultToRun(
client_.get(), blank_input,
GetSuggestURL(metrics::OmniboxEventProto::BLANK)));
}
}
TEST_F(ZeroSuggestProviderTest, TypeOfResultToRunForContextualWeb) {
std::string input_url = "https://example.com/";
GURL suggest_url = GetSuggestURL(metrics::OmniboxEventProto::OTHER);
AutocompleteInput on_focus_input(base::ASCIIToUTF16(input_url),
metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
on_focus_input.set_current_url(GURL(input_url));
on_focus_input.set_focus_type(OmniboxFocusType::ON_FOCUS);
AutocompleteInput on_clobber_input(base::string16(),
metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
on_clobber_input.set_current_url(GURL(input_url));
on_clobber_input.set_focus_type(OmniboxFocusType::DELETED_PERMANENT_TEXT);
#if defined(OS_ANDROID) || defined(OS_IOS)
const ZeroSuggestProvider::ResultType kDefaultContextualWebResultType =
ZeroSuggestProvider::ResultType::MOST_VISITED;
#else
const ZeroSuggestProvider::ResultType kDefaultContextualWebResultType =
ZeroSuggestProvider::ResultType::NONE;
#endif
EXPECT_EQ(kDefaultContextualWebResultType,
ZeroSuggestProvider::TypeOfResultToRun(
client_.get(), on_focus_input, suggest_url));
EXPECT_EQ(kDefaultContextualWebResultType,
ZeroSuggestProvider::TypeOfResultToRun(
client_.get(), on_clobber_input, suggest_url));
// Enable on-focus only.
{
base::test::ScopedFeatureList features;
features.InitAndEnableFeature(omnibox::kOnFocusSuggestionsContextualWeb);
EXPECT_EQ(ZeroSuggestProvider::ResultType::REMOTE_SEND_URL,
ZeroSuggestProvider::TypeOfResultToRun(
client_.get(), on_focus_input, suggest_url));
EXPECT_EQ(kDefaultContextualWebResultType,
ZeroSuggestProvider::TypeOfResultToRun(
client_.get(), on_clobber_input, suggest_url));
}
// Enable on-clobber only.
{
base::test::ScopedFeatureList features;
features.InitAndEnableFeature(
omnibox::kClobberTriggersContextualWebZeroSuggest);
EXPECT_EQ(kDefaultContextualWebResultType,
ZeroSuggestProvider::TypeOfResultToRun(
client_.get(), on_focus_input, suggest_url));
EXPECT_EQ(ZeroSuggestProvider::ResultType::REMOTE_SEND_URL,
ZeroSuggestProvider::TypeOfResultToRun(
client_.get(), on_clobber_input, suggest_url));
}
// Enable on-focus and on-clobber.
{
base::test::ScopedFeatureList features;
features.InitWithFeatures(
{omnibox::kOnFocusSuggestionsContextualWeb,
omnibox::kClobberTriggersContextualWebZeroSuggest},
{});
EXPECT_EQ(ZeroSuggestProvider::ResultType::REMOTE_SEND_URL,
ZeroSuggestProvider::TypeOfResultToRun(
client_.get(), on_focus_input, suggest_url));
EXPECT_EQ(ZeroSuggestProvider::ResultType::REMOTE_SEND_URL,
ZeroSuggestProvider::TypeOfResultToRun(
client_.get(), on_clobber_input, suggest_url));
}
}
TEST_F(ZeroSuggestProviderTest, TestDoesNotReturnMatchesForPrefix) {
CreateRemoteNoUrlFieldTrial();
std::string url("http://www.cnn.com/");
AutocompleteInput input(base::ASCIIToUTF16(url),
metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
input.set_current_url(GURL(url));
// Set up the pref to cache the response from the previous run.
std::string json_response("[\"\",[\"search1\", \"search2\", \"search3\"],"
"[],[],{\"google:suggestrelevance\":[602, 601, 600],"
"\"google:verbatimrelevance\":1300}]");
PrefService* prefs = client_->GetPrefs();
prefs->SetString(omnibox::kZeroSuggestCachedResults, json_response);
provider_->Start(input, false);
// Expect that matches don't get populated out of cache because we are not
// in zero suggest mode.
EXPECT_TRUE(provider_->matches().empty());
// Expect that loader did not get created.
EXPECT_EQ(0, test_loader_factory()->NumPending());
}
TEST_F(ZeroSuggestProviderTest, TestStartWillStopForSomeInput) {
EXPECT_CALL(*client_, IsAuthenticated())
.WillRepeatedly(testing::Return(true));
CreateRemoteNoUrlFieldTrial();
std::string input_url("http://www.cnn.com/");
AutocompleteInput input(base::ASCIIToUTF16(input_url),
metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
input.set_current_url(GURL(input_url));
input.set_focus_type(OmniboxFocusType::ON_FOCUS);
provider_->Start(input, false);
EXPECT_FALSE(provider_->done_);
// Make sure input stops the provider.
input.set_focus_type(OmniboxFocusType::DEFAULT);
provider_->Start(input, false);
EXPECT_TRUE(provider_->done_);
// Make sure invalid input stops the provider.
input.set_focus_type(OmniboxFocusType::ON_FOCUS);
provider_->Start(input, false);
EXPECT_FALSE(provider_->done_);
AutocompleteInput input2;
provider_->Start(input2, false);
EXPECT_TRUE(provider_->done_);
}
TEST_F(ZeroSuggestProviderTest, TestMostVisitedCallback) {
CreateMostVisitedFieldTrial();
std::string current_url("http://www.foxnews.com/");
std::string input_url("http://www.cnn.com/");
AutocompleteInput input(base::ASCIIToUTF16(input_url),
metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
input.set_current_url(GURL(current_url));
input.set_focus_type(OmniboxFocusType::ON_FOCUS);
history::MostVisitedURLList urls;
history::MostVisitedURL url(GURL("http://foo.com/"),
base::ASCIIToUTF16("Foo"));
urls.push_back(url);
provider_->Start(input, false);
EXPECT_TRUE(provider_->matches().empty());
scoped_refptr<history::TopSites> top_sites = client_->GetTopSites();
static_cast<FakeEmptyTopSites*>(top_sites.get())->RunACallback(urls);
// Should have verbatim match + most visited url match.
EXPECT_EQ(2U, provider_->matches().size());
provider_->Stop(false, false);
provider_->Start(input, false);
provider_->Stop(false, false);
EXPECT_TRUE(provider_->matches().empty());
// Most visited results arriving after Stop() has been called, ensure they
// are not displayed.
static_cast<FakeEmptyTopSites*>(top_sites.get())->RunACallback(urls);
EXPECT_TRUE(provider_->matches().empty());
history::MostVisitedURLList urls2;
urls2.push_back(history::MostVisitedURL(GURL("http://bar.com/"),
base::ASCIIToUTF16("Bar")));
urls2.push_back(history::MostVisitedURL(GURL("http://zinga.com/"),
base::ASCIIToUTF16("Zinga")));
provider_->Start(input, false);
provider_->Stop(false, false);
provider_->Start(input, false);
static_cast<FakeEmptyTopSites*>(top_sites.get())->RunACallback(urls);
// Stale results should get rejected.
EXPECT_TRUE(provider_->matches().empty());
static_cast<FakeEmptyTopSites*>(top_sites.get())->RunACallback(urls2);
EXPECT_FALSE(provider_->matches().empty());
provider_->Stop(false, false);
}
TEST_F(ZeroSuggestProviderTest, TestMostVisitedNavigateToSearchPage) {
CreateMostVisitedFieldTrial();
std::string current_url("http://www.foxnews.com/");
std::string input_url("http://www.cnn.com/");
AutocompleteInput input(base::ASCIIToUTF16(input_url),
metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
input.set_current_url(GURL(current_url));
input.set_focus_type(OmniboxFocusType::ON_FOCUS);
history::MostVisitedURLList urls;
history::MostVisitedURL url(GURL("http://foo.com/"),
base::ASCIIToUTF16("Foo"));
urls.push_back(url);
provider_->Start(input, false);
EXPECT_TRUE(provider_->matches().empty());
// Stop() doesn't always get called.
std::string search_url("https://www.google.com/?q=flowers");
AutocompleteInput srp_input(
base::ASCIIToUTF16(search_url),
metrics::OmniboxEventProto::SEARCH_RESULT_PAGE_NO_SEARCH_TERM_REPLACEMENT,
TestSchemeClassifier());
srp_input.set_current_url(GURL(search_url));
srp_input.set_focus_type(OmniboxFocusType::ON_FOCUS);
provider_->Start(srp_input, false);
EXPECT_TRUE(provider_->matches().empty());
// Most visited results arriving after a new request has been started.
scoped_refptr<history::TopSites> top_sites = client_->GetTopSites();
static_cast<FakeEmptyTopSites*>(top_sites.get())->RunACallback(urls);
EXPECT_TRUE(provider_->matches().empty());
}
TEST_F(ZeroSuggestProviderTest, TestPsuggestZeroSuggestCachingFirstRun) {
CreateRemoteNoUrlFieldTrial();
EXPECT_CALL(*client_, IsAuthenticated())
.WillRepeatedly(testing::Return(true));
// Ensure the cache is empty.
PrefService* prefs = client_->GetPrefs();
prefs->SetString(omnibox::kZeroSuggestCachedResults, std::string());
std::string url("http://www.cnn.com/");
AutocompleteInput input(base::ASCIIToUTF16(url),
metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
input.set_current_url(GURL(url));
input.set_focus_type(OmniboxFocusType::ON_FOCUS);
provider_->Start(input, false);
EXPECT_TRUE(prefs->GetString(omnibox::kZeroSuggestCachedResults).empty());
EXPECT_TRUE(provider_->matches().empty());
GURL suggest_url = GetSuggestURL(metrics::OmniboxEventProto::OTHER);
EXPECT_TRUE(test_loader_factory()->IsPending(suggest_url.spec()));
std::string json_response("[\"\",[\"search1\", \"search2\", \"search3\"],"
"[],[],{\"google:suggestrelevance\":[602, 601, 600],"
"\"google:verbatimrelevance\":1300}]");
test_loader_factory()->AddResponse(suggest_url.spec(), json_response);
base::RunLoop().RunUntilIdle();
#if defined(OS_ANDROID) || defined(OS_IOS)
EXPECT_EQ(4U, provider_->matches().size()); // 3 results + verbatim
#else
EXPECT_EQ(3U, provider_->matches().size()); // 3 results, no verbatim match
#endif
if (base::FeatureList::IsEnabled(omnibox::kOmniboxZeroSuggestCaching)) {
EXPECT_EQ(json_response,
prefs->GetString(omnibox::kZeroSuggestCachedResults));
}
}
TEST_F(ZeroSuggestProviderTest, TestPsuggestZeroSuggestHasCachedResults) {
CreateRemoteNoUrlFieldTrial();
EXPECT_CALL(*client_, IsAuthenticated())
.WillRepeatedly(testing::Return(true));
std::string url("http://www.cnn.com/");
AutocompleteInput input(base::ASCIIToUTF16(url),
metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
input.set_current_url(GURL(url));
input.set_focus_type(OmniboxFocusType::ON_FOCUS);
// Set up the pref to cache the response from the previous run.
std::string json_response("[\"\",[\"search1\", \"search2\", \"search3\"],"
"[],[],{\"google:suggestrelevance\":[602, 601, 600],"
"\"google:verbatimrelevance\":1300}]");
PrefService* prefs = client_->GetPrefs();
prefs->SetString(omnibox::kZeroSuggestCachedResults, json_response);
provider_->Start(input, false);
if (base::FeatureList::IsEnabled(omnibox::kOmniboxZeroSuggestCaching)) {
// Expect that matches get populated synchronously out of the cache.
#if defined(OS_ANDROID) || defined(OS_IOS)
ASSERT_EQ(4U, provider_->matches().size()); // 3 results + verbatim
EXPECT_EQ(base::ASCIIToUTF16("search1"), provider_->matches()[1].contents);
EXPECT_EQ(base::ASCIIToUTF16("search2"), provider_->matches()[2].contents);
EXPECT_EQ(base::ASCIIToUTF16("search3"), provider_->matches()[3].contents);
#else
ASSERT_EQ(3U, provider_->matches().size()); // 3 results, no verbatim match
EXPECT_EQ(base::ASCIIToUTF16("search1"), provider_->matches()[0].contents);
EXPECT_EQ(base::ASCIIToUTF16("search2"), provider_->matches()[1].contents);
EXPECT_EQ(base::ASCIIToUTF16("search3"), provider_->matches()[2].contents);
#endif
}
GURL suggest_url = GetSuggestURL(metrics::OmniboxEventProto::OTHER);
EXPECT_TRUE(test_loader_factory()->IsPending(suggest_url.spec()));
std::string json_response2("[\"\",[\"search4\", \"search5\", \"search6\"],"
"[],[],{\"google:suggestrelevance\":[602, 601, 600],"
"\"google:verbatimrelevance\":1300}]");
test_loader_factory()->AddResponse(suggest_url.spec(), json_response2);
base::RunLoop().RunUntilIdle();
if (base::FeatureList::IsEnabled(omnibox::kOmniboxZeroSuggestCaching)) {
// Expect the same results after the response has been handled.
#if defined(OS_ANDROID) || defined(OS_IOS)
ASSERT_EQ(4U, provider_->matches().size()); // 3 results + verbatim
EXPECT_EQ(base::ASCIIToUTF16("search1"), provider_->matches()[1].contents);
EXPECT_EQ(base::ASCIIToUTF16("search2"), provider_->matches()[2].contents);
EXPECT_EQ(base::ASCIIToUTF16("search3"), provider_->matches()[3].contents);
#else
ASSERT_EQ(3U, provider_->matches().size()); // 3 results, no verbatim match
EXPECT_EQ(base::ASCIIToUTF16("search1"), provider_->matches()[0].contents);
EXPECT_EQ(base::ASCIIToUTF16("search2"), provider_->matches()[1].contents);
EXPECT_EQ(base::ASCIIToUTF16("search3"), provider_->matches()[2].contents);
#endif
// Expect the new results have been stored.
EXPECT_EQ(json_response2,
prefs->GetString(omnibox::kZeroSuggestCachedResults));
} else {
// Expect fresh results after the response has been handled.
#if defined(OS_ANDROID) || defined(OS_IOS)
ASSERT_EQ(4U, provider_->matches().size()); // 3 results + verbatim
EXPECT_EQ(base::ASCIIToUTF16("search4"), provider_->matches()[1].contents);
EXPECT_EQ(base::ASCIIToUTF16("search5"), provider_->matches()[2].contents);
EXPECT_EQ(base::ASCIIToUTF16("search6"), provider_->matches()[3].contents);
#else
ASSERT_EQ(3U, provider_->matches().size()); // 3 results, no verbatim match
EXPECT_EQ(base::ASCIIToUTF16("search4"), provider_->matches()[0].contents);
EXPECT_EQ(base::ASCIIToUTF16("search5"), provider_->matches()[1].contents);
EXPECT_EQ(base::ASCIIToUTF16("search6"), provider_->matches()[2].contents);
#endif
}
}
TEST_F(ZeroSuggestProviderTest, TestPsuggestZeroSuggestReceivedEmptyResults) {
CreateRemoteNoUrlFieldTrial();
EXPECT_CALL(*client_, IsAuthenticated())
.WillRepeatedly(testing::Return(true));
std::string url("http://www.cnn.com/");
AutocompleteInput input(base::ASCIIToUTF16(url),
metrics::OmniboxEventProto::OTHER,
TestSchemeClassifier());
input.set_current_url(GURL(url));
input.set_focus_type(OmniboxFocusType::ON_FOCUS);
// Set up the pref to cache the response from the previous run.
std::string json_response("[\"\",[\"search1\", \"search2\", \"search3\"],"
"[],[],{\"google:suggestrelevance\":[602, 601, 600],"
"\"google:verbatimrelevance\":1300}]");
PrefService* prefs = client_->GetPrefs();
prefs->SetString(omnibox::kZeroSuggestCachedResults, json_response);
provider_->Start(input, false);
if (base::FeatureList::IsEnabled(omnibox::kOmniboxZeroSuggestCaching)) {
// Expect that matches get populated synchronously out of the cache.
#if defined(OS_ANDROID) || defined(OS_IOS)
ASSERT_EQ(4U, provider_->matches().size()); // 3 results + verbatim
EXPECT_EQ(base::ASCIIToUTF16("search1"), provider_->matches()[1].contents);
EXPECT_EQ(base::ASCIIToUTF16("search2"), provider_->matches()[2].contents);
EXPECT_EQ(base::ASCIIToUTF16("search3"), provider_->matches()[3].contents);
#else
ASSERT_EQ(3U, provider_->matches().size()); // 3 results, no verbatim match
EXPECT_EQ(base::ASCIIToUTF16("search1"), provider_->matches()[0].contents);
EXPECT_EQ(base::ASCIIToUTF16("search2"), provider_->matches()[1].contents);
EXPECT_EQ(base::ASCIIToUTF16("search3"), provider_->matches()[2].contents);
#endif
} else {
ASSERT_TRUE(provider_->matches().empty());
}
GURL suggest_url = GetSuggestURL(metrics::OmniboxEventProto::OTHER);
EXPECT_TRUE(test_loader_factory()->IsPending(suggest_url.spec()));
std::string empty_response("[\"\",[],[],[],{}]");
test_loader_factory()->AddResponse(suggest_url.spec(), empty_response);
base::RunLoop().RunUntilIdle();
// Expect that the matches have been cleared.
ASSERT_TRUE(provider_->matches().empty());
if (base::FeatureList::IsEnabled(omnibox::kOmniboxZeroSuggestCaching)) {
// Expect the new results have been stored.
EXPECT_EQ(empty_response,
prefs->GetString(omnibox::kZeroSuggestCachedResults));
}
}