Commit f1e4b577 authored by Daniel Kenji Toyama's avatar Daniel Kenji Toyama Committed by Commit Bot

Add ContextualSuggestionsService to Omnibox.

This CL was cloned from https://codereview.chromium.org/2965173002/.

Create a new class `ContextualSuggestionsService` to fetch experimental
contextual suggestions for the omnibox.

Bug: 692471,609084, 750985
Change-Id: Ib54be91b1c0e2cb1fcdaf9a7a43b71984e5c358c
Reviewed-on: https://chromium-review.googlesource.com/576284
Commit-Queue: Owen Min <zmin@chromium.org>
Reviewed-by: default avatarRoger Tawa <rogerta@chromium.org>
Reviewed-by: default avatarRohit Rao (ping after 24h) <rohitrao@chromium.org>
Reviewed-by: default avatarMark Pearson <mpearson@chromium.org>
Cr-Commit-Position: refs/heads/master@{#491762}
parent 91feaec9
...@@ -83,6 +83,8 @@ split_static_library("browser") { ...@@ -83,6 +83,8 @@ split_static_library("browser") {
"autocomplete/chrome_autocomplete_provider_client.h", "autocomplete/chrome_autocomplete_provider_client.h",
"autocomplete/chrome_autocomplete_scheme_classifier.cc", "autocomplete/chrome_autocomplete_scheme_classifier.cc",
"autocomplete/chrome_autocomplete_scheme_classifier.h", "autocomplete/chrome_autocomplete_scheme_classifier.h",
"autocomplete/contextual_suggestions_service_factory.cc",
"autocomplete/contextual_suggestions_service_factory.h",
"autocomplete/in_memory_url_index_factory.cc", "autocomplete/in_memory_url_index_factory.cc",
"autocomplete/in_memory_url_index_factory.h", "autocomplete/in_memory_url_index_factory.h",
"autocomplete/shortcuts_backend_factory.cc", "autocomplete/shortcuts_backend_factory.cc",
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "chrome/browser/autocomplete/autocomplete_classifier_factory.h" #include "chrome/browser/autocomplete/autocomplete_classifier_factory.h"
#include "chrome/browser/autocomplete/contextual_suggestions_service_factory.h"
#include "chrome/browser/autocomplete/in_memory_url_index_factory.h" #include "chrome/browser/autocomplete/in_memory_url_index_factory.h"
#include "chrome/browser/autocomplete/shortcuts_backend_factory.h" #include "chrome/browser/autocomplete/shortcuts_backend_factory.h"
#include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service.h" #include "chrome/browser/bitmap_fetcher/bitmap_fetcher_service.h"
...@@ -133,6 +134,11 @@ ChromeAutocompleteProviderClient::GetTemplateURLService() const { ...@@ -133,6 +134,11 @@ ChromeAutocompleteProviderClient::GetTemplateURLService() const {
return TemplateURLServiceFactory::GetForProfile(profile_); return TemplateURLServiceFactory::GetForProfile(profile_);
} }
ContextualSuggestionsService*
ChromeAutocompleteProviderClient::GetContextualSuggestionsService() const {
return ContextualSuggestionsServiceFactory::GetForProfile(profile_);
}
const const
SearchTermsData& ChromeAutocompleteProviderClient::GetSearchTermsData() const { SearchTermsData& ChromeAutocompleteProviderClient::GetSearchTermsData() const {
return search_terms_data_; return search_terms_data_;
......
...@@ -33,6 +33,8 @@ class ChromeAutocompleteProviderClient : public AutocompleteProviderClient { ...@@ -33,6 +33,8 @@ class ChromeAutocompleteProviderClient : public AutocompleteProviderClient {
InMemoryURLIndex* GetInMemoryURLIndex() override; InMemoryURLIndex* GetInMemoryURLIndex() override;
TemplateURLService* GetTemplateURLService() override; TemplateURLService* GetTemplateURLService() override;
const TemplateURLService* GetTemplateURLService() const override; const TemplateURLService* GetTemplateURLService() const override;
ContextualSuggestionsService* GetContextualSuggestionsService()
const override;
const SearchTermsData& GetSearchTermsData() const override; const SearchTermsData& GetSearchTermsData() const override;
scoped_refptr<ShortcutsBackend> GetShortcutsBackend() override; scoped_refptr<ShortcutsBackend> GetShortcutsBackend() override;
scoped_refptr<ShortcutsBackend> GetShortcutsBackendIfExists() override; scoped_refptr<ShortcutsBackend> GetShortcutsBackendIfExists() override;
......
// 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/autocomplete/contextual_suggestions_service_factory.h"
#include "base/memory/singleton.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "components/omnibox/browser/contextual_suggestions_service.h"
#include "components/signin/core/browser/profile_oauth2_token_service.h"
#include "components/signin/core/browser/signin_manager.h"
// static
ContextualSuggestionsService*
ContextualSuggestionsServiceFactory::GetForProfile(Profile* profile) {
return static_cast<ContextualSuggestionsService*>(
GetInstance()->GetServiceForBrowserContext(profile, true));
}
// static
ContextualSuggestionsServiceFactory*
ContextualSuggestionsServiceFactory::GetInstance() {
return base::Singleton<ContextualSuggestionsServiceFactory>::get();
}
KeyedService* ContextualSuggestionsServiceFactory::BuildServiceInstanceFor(
content::BrowserContext* context) const {
Profile* profile = Profile::FromBrowserContext(context);
SigninManagerBase* signin_manager =
SigninManagerFactory::GetForProfile(profile);
ProfileOAuth2TokenService* token_service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
return new ContextualSuggestionsService(signin_manager, token_service,
profile->GetRequestContext());
}
ContextualSuggestionsServiceFactory::ContextualSuggestionsServiceFactory()
: BrowserContextKeyedServiceFactory(
"ContextualSuggestionsService",
BrowserContextDependencyManager::GetInstance()) {
DependsOn(SigninManagerFactory::GetInstance());
DependsOn(ProfileOAuth2TokenServiceFactory::GetInstance());
}
ContextualSuggestionsServiceFactory::~ContextualSuggestionsServiceFactory() {}
// 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.
#ifndef CHROME_BROWSER_AUTOCOMPLETE_CONTEXTUAL_SUGGESTIONS_SERVICE_FACTORY_H_
#define CHROME_BROWSER_AUTOCOMPLETE_CONTEXTUAL_SUGGESTIONS_SERVICE_FACTORY_H_
#include "base/macros.h"
#include "base/memory/singleton.h"
#include "components/keyed_service/content/browser_context_keyed_service_factory.h"
class ContextualSuggestionsService;
class Profile;
class ContextualSuggestionsServiceFactory
: public BrowserContextKeyedServiceFactory {
public:
static ContextualSuggestionsService* GetForProfile(Profile* profile);
static ContextualSuggestionsServiceFactory* GetInstance();
private:
friend struct base::DefaultSingletonTraits<
ContextualSuggestionsServiceFactory>;
ContextualSuggestionsServiceFactory();
~ContextualSuggestionsServiceFactory() override;
// Overrides from BrowserContextKeyedServiceFactory:
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* context) const override;
DISALLOW_COPY_AND_ASSIGN(ContextualSuggestionsServiceFactory);
};
#endif // CHROME_BROWSER_AUTOCOMPLETE_CONTEXTUAL_SUGGESTIONS_SERVICE_FACTORY_H_
...@@ -52,6 +52,8 @@ static_library("browser") { ...@@ -52,6 +52,8 @@ static_library("browser") {
"builtin_provider.h", "builtin_provider.h",
"clipboard_url_provider.cc", "clipboard_url_provider.cc",
"clipboard_url_provider.h", "clipboard_url_provider.h",
"contextual_suggestions_service.cc",
"contextual_suggestions_service.h",
"history_match.cc", "history_match.cc",
"history_match.h", "history_match.h",
"history_provider.cc", "history_provider.cc",
...@@ -152,6 +154,7 @@ static_library("browser") { ...@@ -152,6 +154,7 @@ static_library("browser") {
"//components/search", "//components/search",
"//components/search_engines", "//components/search_engines",
"//components/sessions", "//components/sessions",
"//components/signin/core/browser",
"//components/strings", "//components/strings",
"//components/toolbar", "//components/toolbar",
"//components/url_formatter", "//components/url_formatter",
......
...@@ -15,6 +15,7 @@ include_rules = [ ...@@ -15,6 +15,7 @@ include_rules = [
"+components/search", "+components/search",
"+components/search_engines", "+components/search_engines",
"+components/sessions", "+components/sessions",
"+components/signin/core/browser",
"+components/strings/grit/components_strings.h", "+components/strings/grit/components_strings.h",
"+components/toolbar", "+components/toolbar",
"+components/url_formatter", "+components/url_formatter",
......
...@@ -19,6 +19,7 @@ class AutocompleteController; ...@@ -19,6 +19,7 @@ class AutocompleteController;
struct AutocompleteMatch; struct AutocompleteMatch;
class AutocompleteClassifier; class AutocompleteClassifier;
class AutocompleteSchemeClassifier; class AutocompleteSchemeClassifier;
class ContextualSuggestionsService;
class GURL; class GURL;
class InMemoryURLIndex; class InMemoryURLIndex;
class KeywordProvider; class KeywordProvider;
...@@ -60,6 +61,8 @@ class AutocompleteProviderClient { ...@@ -60,6 +61,8 @@ class AutocompleteProviderClient {
virtual InMemoryURLIndex* GetInMemoryURLIndex() = 0; virtual InMemoryURLIndex* GetInMemoryURLIndex() = 0;
virtual TemplateURLService* GetTemplateURLService() = 0; virtual TemplateURLService* GetTemplateURLService() = 0;
virtual const TemplateURLService* GetTemplateURLService() const = 0; virtual const TemplateURLService* GetTemplateURLService() const = 0;
virtual ContextualSuggestionsService* GetContextualSuggestionsService()
const = 0;
virtual const SearchTermsData& GetSearchTermsData() const = 0; virtual const SearchTermsData& GetSearchTermsData() const = 0;
virtual scoped_refptr<ShortcutsBackend> GetShortcutsBackend() = 0; virtual scoped_refptr<ShortcutsBackend> GetShortcutsBackend() = 0;
virtual scoped_refptr<ShortcutsBackend> GetShortcutsBackendIfExists() = 0; virtual scoped_refptr<ShortcutsBackend> GetShortcutsBackendIfExists() = 0;
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include "base/strings/string16.h" #include "base/strings/string16.h"
#include "base/strings/string_number_conversions.h" #include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_task_environment.h"
#include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_match.h"
#include "components/omnibox/browser/autocomplete_match_type.h" #include "components/omnibox/browser/autocomplete_match_type.h"
#include "components/omnibox/browser/autocomplete_scheme_classifier.h" #include "components/omnibox/browser/autocomplete_scheme_classifier.h"
...@@ -82,6 +83,7 @@ class BaseSearchProviderTest : public testing::Test { ...@@ -82,6 +83,7 @@ class BaseSearchProviderTest : public testing::Test {
AutocompleteProvider::TYPE_SEARCH, client_.get()); AutocompleteProvider::TYPE_SEARCH, client_.get());
} }
base::test::ScopedTaskEnvironment scoped_task_environment_;
scoped_refptr<NiceMock<TestBaseSearchProvider> > provider_; scoped_refptr<NiceMock<TestBaseSearchProvider> > provider_;
std::unique_ptr<NiceMock<MockAutocompleteProviderClient>> client_; std::unique_ptr<NiceMock<MockAutocompleteProviderClient>> client_;
}; };
......
// 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 "components/omnibox/browser/contextual_suggestions_service.h"
#include "base/feature_list.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/stringprintf.h"
#include "components/data_use_measurement/core/data_use_user_data.h"
#include "components/omnibox/browser/omnibox_field_trial.h"
#include "components/search_engines/template_url_service.h"
#include "components/variations/net/variations_http_headers.h"
#include "net/base/escape.h"
#include "net/base/load_flags.h"
#include "net/http/http_response_headers.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request_context_getter.h"
namespace {
// Server address for the experimental suggestions service.
const char kExperimentalServerAddress[] =
"https://cuscochromeextension-pa.googleapis.com/v1/zerosuggestions";
} // namespace
ContextualSuggestionsService::ContextualSuggestionsService(
SigninManagerBase* signin_manager,
OAuth2TokenService* token_service,
net::URLRequestContextGetter* request_context)
: request_context_(request_context),
signin_manager_(signin_manager),
token_service_(token_service) {}
ContextualSuggestionsService::~ContextualSuggestionsService() {}
void ContextualSuggestionsService::CreateContextualSuggestionsRequest(
const std::string& current_url,
const TemplateURLService* template_url_service,
net::URLFetcherDelegate* fetcher_delegate,
ContextualSuggestionsCallback callback) {
const GURL experimental_suggest_url =
ExperimentalZeroSuggestURL(current_url, template_url_service);
const bool is_experimental = experimental_suggest_url.is_valid();
const GURL suggest_url =
is_experimental
? experimental_suggest_url
: ContextualSuggestionsUrl(current_url, template_url_service);
std::unique_ptr<net::URLFetcher> fetcher =
CreateRequest(suggest_url, is_experimental, fetcher_delegate);
const bool should_fetch_access_token = is_experimental &&
(signin_manager_ != nullptr) &&
(token_service_ != nullptr);
// If authentication services are unavailable or if this request is still
// waiting for an oauth2 token, run the contextual service without access
// tokens.
if (!should_fetch_access_token || (token_fetcher_ != nullptr)) {
std::move(callback).Run(std::move(fetcher));
return;
}
// Create the oauth2 token fetcher.
const OAuth2TokenService::ScopeSet scopes{
"https://www.googleapis.com/auth/cusco-chrome-extension"};
token_fetcher_ = base::MakeUnique<AccessTokenFetcher>(
"contextual_suggestions_service", signin_manager_, token_service_, scopes,
base::BindOnce(&ContextualSuggestionsService::AccessTokenAvailable,
base::Unretained(this), std::move(fetcher),
std::move(callback)));
}
// static
GURL ContextualSuggestionsService::ContextualSuggestionsUrl(
const std::string& current_url,
const TemplateURLService* template_url_service) {
if (template_url_service == nullptr) {
return GURL();
}
const TemplateURL* search_engine =
template_url_service->GetDefaultSearchProvider();
if (search_engine == nullptr) {
return GURL();
}
const TemplateURLRef& suggestion_url_ref =
search_engine->suggestions_url_ref();
const SearchTermsData& search_terms_data =
template_url_service->search_terms_data();
base::string16 prefix;
TemplateURLRef::SearchTermsArgs search_term_args(prefix);
if (!current_url.empty()) {
search_term_args.current_page_url = current_url;
}
return GURL(suggestion_url_ref.ReplaceSearchTerms(search_term_args,
search_terms_data));
}
GURL ContextualSuggestionsService::ExperimentalZeroSuggestURL(
const std::string& current_url,
const TemplateURLService* template_url_service) const {
if (current_url.empty()) {
return GURL();
}
if (!base::FeatureList::IsEnabled(omnibox::kZeroSuggestRedirectToChrome) ||
template_url_service == nullptr) {
return GURL();
}
// Check that the default search engine is Google.
const TemplateURL& default_provider_url =
*template_url_service->GetDefaultSearchProvider();
const SearchTermsData& search_terms_data =
template_url_service->search_terms_data();
if (default_provider_url.GetEngineType(search_terms_data) !=
SEARCH_ENGINE_GOOGLE) {
return GURL();
}
// Assemble the actual suggest URL.
const std::string server_address(kExperimentalServerAddress);
const int experiment_id =
OmniboxFieldTrial::GetZeroSuggestRedirectToChromeExperimentId();
// The experimental suggest endpoint does not handle URLs terminating with a
// slash properly, causing some urls like http://example.com/some/path/ to
// lose the last slash, which changes the URL. If we add an extra ampersand,
// as in the else case here it handles the URL properly.
const std::string additional_parameters =
(experiment_id >= 0)
? base::StringPrintf("&experiment_id=%d", experiment_id)
: "&";
GURL suggest_url(server_address + "/url=" + net::EscapePath(current_url) +
additional_parameters);
// Check that the suggest URL for redirect to chrome field trial is valid.
if (!suggest_url.is_valid()) {
return GURL();
}
// Check that the suggest URL for redirect to chrome is HTTPS.
if (!suggest_url.SchemeIsCryptographic()) {
return GURL();
}
return suggest_url;
}
std::unique_ptr<net::URLFetcher> ContextualSuggestionsService::CreateRequest(
const GURL& suggest_url,
bool is_experimental,
net::URLFetcherDelegate* fetcher_delegate) const {
DCHECK(suggest_url.is_valid());
net::NetworkTrafficAnnotationTag annotation_tag =
is_experimental
? net::DefineNetworkTrafficAnnotation(
"omnibox_zerosuggest_experimental", R"(
semantics {
sender: "Omnibox"
description:
"When the user focuses the omnibox, Chrome can provide search or "
"navigation suggestions from the default search provider in the "
"omnibox dropdown, based on the current page URL.\n"
"This is limited to users whose default search engine is Google, "
"as no other search engines currently support this kind of "
"suggestion."
trigger: "The omnibox receives focus."
data: "The user's OAuth2 credentials and the URL of the current page."
destination: GOOGLE_OWNED_SERVICE
}
policy {
cookies_allowed: false
setting:
"Users can control this feature via the 'Use a prediction service "
"to help complete searches and URLs typed in the address bar' "
"settings under 'Privacy'. The feature is enabled by default."
chrome_policy {
SearchSuggestEnabled {
policy_options {mode: MANDATORY}
SearchSuggestEnabled: false
}
}
})")
: net::DefineNetworkTrafficAnnotation("omnibox_zerosuggest", R"(
semantics {
sender: "Omnibox"
description:
"When the user focuses the omnibox, Chrome can provide search or "
"navigation suggestions from the default search provider in the "
"omnibox dropdown, based on the current page URL.\n"
"This is limited to users whose default search engine is Google, "
"as no other search engines currently support this kind of "
"suggestion."
trigger: "The omnibox receives focus."
data: "The URL of the current page."
destination: GOOGLE_OWNED_SERVICE
}
policy {
cookies_allowed: true
cookies_store: "user"
setting:
"Users can control this feature via the 'Use a prediction service "
"to help complete searches and URLs typed in the address bar' "
"settings under 'Privacy'. The feature is enabled by default."
chrome_policy {
SearchSuggestEnabled {
policy_options {mode: MANDATORY}
SearchSuggestEnabled: false
}
}
})");
const int kFetcherID = 1;
std::unique_ptr<net::URLFetcher> fetcher =
net::URLFetcher::Create(kFetcherID, suggest_url, net::URLFetcher::GET,
fetcher_delegate, annotation_tag);
fetcher->SetRequestContext(request_context_);
data_use_measurement::DataUseUserData::AttachToFetcher(
fetcher.get(), data_use_measurement::DataUseUserData::OMNIBOX);
// Add Chrome experiment state to the request headers.
net::HttpRequestHeaders headers;
// Note: It's OK to pass |is_signed_in| false if it's unknown, as it does
// not affect transmission of experiments coming from the variations server.
variations::AppendVariationHeaders(fetcher->GetOriginalURL(),
/*incognito=*/false, /*uma_enabled=*/false,
/*is_signed_in=*/false, &headers);
for (net::HttpRequestHeaders::Iterator it(headers); it.GetNext();) {
fetcher->AddExtraRequestHeader(it.name() + ":" + it.value());
}
if (is_experimental) {
fetcher->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
net::LOAD_DO_NOT_SAVE_COOKIES);
} else {
fetcher->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES);
}
return fetcher;
}
void ContextualSuggestionsService::AccessTokenAvailable(
std::unique_ptr<net::URLFetcher> fetcher,
ContextualSuggestionsCallback callback,
const GoogleServiceAuthError& error,
const std::string& access_token) {
DCHECK(token_fetcher_);
token_fetcher_.reset();
// If there were no errors obtaining the access token, append it to the
// request as a header.
if (error.state() == GoogleServiceAuthError::NONE) {
DCHECK(!access_token.empty());
fetcher->AddExtraRequestHeader(
base::StringPrintf("Authorization: Bearer %s", access_token.c_str()));
}
std::move(callback).Run(std::move(fetcher));
}
// 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.
#ifndef COMPONENTS_OMNIBOX_BROWSER_CONTEXTUAL_SUGGESTIONS_SERVICE_H_
#define COMPONENTS_OMNIBOX_BROWSER_CONTEXTUAL_SUGGESTIONS_SERVICE_H_
#include <memory>
#include <string>
#include "components/keyed_service/core/keyed_service.h"
#include "components/signin/core/browser/access_token_fetcher.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "url/gurl.h"
class OAuth2TokenService;
class SigninManagerBase;
class TemplateURLService;
// A service to fetch suggestions from a remote endpoint given a URL.
class ContextualSuggestionsService : public KeyedService {
public:
// |signin_manager| and |token_service| may be null but only unauthenticated
// requests will issued.
// |request_context| may be null, but some services may be disabled.
ContextualSuggestionsService(SigninManagerBase* signin_manager,
OAuth2TokenService* token_service,
net::URLRequestContextGetter* request_context);
~ContextualSuggestionsService() override;
using ContextualSuggestionsCallback =
base::OnceCallback<void(std::unique_ptr<net::URLFetcher> fetcher)>;
// Creates a fetcher for contextual suggestions for |current_url| and passes
// the fetcher to the provided callback.
//
// |current_url| may be empty, in which case the system will never use the
// experimental suggestions service. It's possible the non-experimental
// service may decide to offer general-purpose suggestions.
//
// |template_url_service| may be null, but some services may be disabled.
//
// |fetcher_delegate| is used to create a fetcher that is used to perform a
// network request. It uses a number of signals to create the fetcher,
// including field trial / experimental parameters, and it may pass a nullptr
// fetcher to the callback.
//
// |callback| is called with the fetcher produced by the |fetcher_delegate| as
// an argument. |callback| is called with a nullptr argument if:
// * The service is waiting for a previously-requested authentication token.
// * The authentication token had any issues.
//
// This method sends a request for an OAuth2 token and temporarily
// instantiates |token_fetcher_|.
void CreateContextualSuggestionsRequest(
const std::string& current_url,
const TemplateURLService* template_url_service,
net::URLFetcherDelegate* fetcher_delegate,
ContextualSuggestionsCallback callback);
// Returns a URL representing the address of the server where the zero suggest
// request is being sent. Does not take into account whether sending this
// request is prohibited (e.g. in an incognito window).
// Returns an invalid URL (i.e.: GURL::is_valid() == false) in case of an
// error.
//
// |current_url| is the page the user is currently browsing and may be empty.
//
// Note that this method is public and is also used by ZeroSuggestProvider for
// suggestions that do not take |current_url| into consideration.
static GURL ContextualSuggestionsUrl(
const std::string& current_url,
const TemplateURLService* template_url_service);
private:
// Returns a URL representing the address of the server where the zero suggest
// requests are being redirected when serving experimental suggestions.
//
// Returns a valid URL only if all the folowing conditions are true:
// * The |current_url| is non-empty.
// * The |default_provider| is Google.
// * The user is in the ZeroSuggestRedirectToChrome field trial.
// * The field trial provides a valid server address where the suggest request
// is redirected.
// * The suggest request is over HTTPS. This avoids leaking the current page
// URL or personal data in unencrypted network traffic.
// Note: these checks are in addition to CanSendUrl() on the default
// contextual suggestion URL.
GURL ExperimentalZeroSuggestURL(
const std::string& current_url,
const TemplateURLService* template_url_service) const;
// Creates an HTTP GET request for contextual suggestions. The returned
// fetcher does not include a header corresponding with an authorization
// token.
std::unique_ptr<net::URLFetcher> CreateRequest(
const GURL& suggest_url,
bool is_experimental,
net::URLFetcherDelegate* fetcher_delegate) const;
// Called when an access token request completes (successfully or not).
void AccessTokenAvailable(std::unique_ptr<net::URLFetcher> fetcher,
ContextualSuggestionsCallback callback,
const GoogleServiceAuthError& error,
const std::string& access_token);
net::URLRequestContextGetter* request_context_;
SigninManagerBase* signin_manager_;
OAuth2TokenService* token_service_;
// Helper for fetching OAuth2 access tokens. This is non-null when an access
// token request is currently in progress.
std::unique_ptr<AccessTokenFetcher> token_fetcher_;
DISALLOW_COPY_AND_ASSIGN(ContextualSuggestionsService);
};
#endif // COMPONENTS_OMNIBOX_BROWSER_CONTEXTUAL_SUGGESTIONS_SERVICE_H_
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "base/message_loop/message_loop.h" #include "base/message_loop/message_loop.h"
#include "base/metrics/field_trial.h" #include "base/metrics/field_trial.h"
#include "base/strings/utf_string_conversions.h" #include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_task_environment.h"
#include "components/metrics/proto/omnibox_event.pb.h" #include "components/metrics/proto/omnibox_event.pb.h"
#include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_match.h"
#include "components/omnibox/browser/autocomplete_scheme_classifier.h" #include "components/omnibox/browser/autocomplete_scheme_classifier.h"
...@@ -84,6 +85,7 @@ class KeywordProviderTest : public testing::Test { ...@@ -84,6 +85,7 @@ class KeywordProviderTest : public testing::Test {
protected: protected:
static const TemplateURLService::Initializer kTestData[]; static const TemplateURLService::Initializer kTestData[];
base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<base::FieldTrialList> field_trial_list_; std::unique_ptr<base::FieldTrialList> field_trial_list_;
scoped_refptr<KeywordProvider> kw_provider_; scoped_refptr<KeywordProvider> kw_provider_;
std::unique_ptr<MockAutocompleteProviderClient> client_; std::unique_ptr<MockAutocompleteProviderClient> client_;
......
...@@ -4,7 +4,13 @@ ...@@ -4,7 +4,13 @@
#include "components/omnibox/browser/mock_autocomplete_provider_client.h" #include "components/omnibox/browser/mock_autocomplete_provider_client.h"
#include "base/memory/ptr_util.h"
MockAutocompleteProviderClient::MockAutocompleteProviderClient() { MockAutocompleteProviderClient::MockAutocompleteProviderClient() {
contextual_suggestions_service_ =
base::MakeUnique<ContextualSuggestionsService>(
/*signin_manager=*/nullptr, /*token_service=*/nullptr,
GetRequestContext());
} }
MockAutocompleteProviderClient::~MockAutocompleteProviderClient() { MockAutocompleteProviderClient::~MockAutocompleteProviderClient() {
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/macros.h" #include "base/macros.h"
#include "components/omnibox/browser/autocomplete_provider_client.h" #include "components/omnibox/browser/autocomplete_provider_client.h"
#include "components/omnibox/browser/autocomplete_scheme_classifier.h" #include "components/omnibox/browser/autocomplete_scheme_classifier.h"
#include "components/omnibox/browser/contextual_suggestions_service.h"
#include "components/search_engines/search_terms_data.h" #include "components/search_engines/search_terms_data.h"
#include "components/search_engines/template_url_service.h" #include "components/search_engines/template_url_service.h"
#include "testing/gmock/include/gmock/gmock.h" #include "testing/gmock/include/gmock/gmock.h"
...@@ -43,6 +44,11 @@ class MockAutocompleteProviderClient : public AutocompleteProviderClient { ...@@ -43,6 +44,11 @@ class MockAutocompleteProviderClient : public AutocompleteProviderClient {
const TemplateURLService* GetTemplateURLService() const override { const TemplateURLService* GetTemplateURLService() const override {
return template_url_service_.get(); return template_url_service_.get();
} }
ContextualSuggestionsService* GetContextualSuggestionsService()
const override {
return contextual_suggestions_service_.get();
}
std::unique_ptr<KeywordExtensionsDelegate> GetKeywordExtensionsDelegate( std::unique_ptr<KeywordExtensionsDelegate> GetKeywordExtensionsDelegate(
KeywordProvider* keyword_provider) override { KeywordProvider* keyword_provider) override {
return nullptr; return nullptr;
...@@ -85,6 +91,7 @@ class MockAutocompleteProviderClient : public AutocompleteProviderClient { ...@@ -85,6 +91,7 @@ class MockAutocompleteProviderClient : public AutocompleteProviderClient {
} }
private: private:
std::unique_ptr<ContextualSuggestionsService> contextual_suggestions_service_;
std::unique_ptr<TemplateURLService> template_url_service_; std::unique_ptr<TemplateURLService> template_url_service_;
DISALLOW_COPY_AND_ASSIGN(MockAutocompleteProviderClient); DISALLOW_COPY_AND_ASSIGN(MockAutocompleteProviderClient);
......
...@@ -317,6 +317,14 @@ bool OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial() { ...@@ -317,6 +317,14 @@ bool OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial() {
kZeroSuggestVariantRule) == "Personalized"; kZeroSuggestVariantRule) == "Personalized";
} }
// static
int OmniboxFieldTrial::GetZeroSuggestRedirectToChromeExperimentId() {
return base::GetFieldTrialParamByFeatureAsInt(
omnibox::kZeroSuggestRedirectToChrome,
OmniboxFieldTrial::kZeroSuggestRedirectToChromeExperimentIdParam,
/*default_value=*/-1);
}
bool OmniboxFieldTrial::ShortcutsScoringMaxRelevance( bool OmniboxFieldTrial::ShortcutsScoringMaxRelevance(
OmniboxEventProto::PageClassification current_page_classification, OmniboxEventProto::PageClassification current_page_classification,
int* max_relevance) { int* max_relevance) {
...@@ -705,25 +713,6 @@ int OmniboxFieldTrial::GetPhysicalWebAfterTypingBaseRelevance() { ...@@ -705,25 +713,6 @@ int OmniboxFieldTrial::GetPhysicalWebAfterTypingBaseRelevance() {
return 700; return 700;
} }
// static
bool OmniboxFieldTrial::InZeroSuggestRedirectToChromeFieldTrial() {
return base::FeatureList::IsEnabled(omnibox::kZeroSuggestRedirectToChrome);
}
// static
std::string OmniboxFieldTrial::ZeroSuggestRedirectToChromeServerAddress() {
return base::GetFieldTrialParamValueByFeature(
omnibox::kZeroSuggestRedirectToChrome,
kZeroSuggestRedirectToChromeServerAddressParam);
}
// static
std::string OmniboxFieldTrial::ZeroSuggestRedirectToChromeAdditionalFields() {
return base::GetFieldTrialParamValueByFeature(
omnibox::kZeroSuggestRedirectToChrome,
kZeroSuggestRedirectToChromeAdditionalFieldsParam);
}
const char OmniboxFieldTrial::kBundledExperimentFieldTrialName[] = const char OmniboxFieldTrial::kBundledExperimentFieldTrialName[] =
"OmniboxBundledExperimentV1"; "OmniboxBundledExperimentV1";
const char OmniboxFieldTrial::kDisableProvidersRule[] = "DisableProviders"; const char OmniboxFieldTrial::kDisableProvidersRule[] = "DisableProviders";
...@@ -805,16 +794,13 @@ const char OmniboxFieldTrial::kPhysicalWebZeroSuggestBaseRelevanceParam[] = ...@@ -805,16 +794,13 @@ const char OmniboxFieldTrial::kPhysicalWebZeroSuggestBaseRelevanceParam[] =
const char OmniboxFieldTrial::kPhysicalWebAfterTypingBaseRelevanceParam[] = const char OmniboxFieldTrial::kPhysicalWebAfterTypingBaseRelevanceParam[] =
"PhysicalWebAfterTypingBaseRelevanceParam"; "PhysicalWebAfterTypingBaseRelevanceParam";
const char OmniboxFieldTrial::kZeroSuggestRedirectToChromeServerAddressParam[] =
"ZeroSuggestRedirectToChromeServerAddress";
const char
OmniboxFieldTrial::kZeroSuggestRedirectToChromeAdditionalFieldsParam[] =
"ZeroSuggestRedirectToChromeAdditionalFields";
const char OmniboxFieldTrial::kUIMaxAutocompleteMatchesParam[] = const char OmniboxFieldTrial::kUIMaxAutocompleteMatchesParam[] =
"UIMaxAutocompleteMatches"; "UIMaxAutocompleteMatches";
const char OmniboxFieldTrial::kUIVerticalMarginParam[] = "UIVerticalMargin"; const char OmniboxFieldTrial::kUIVerticalMarginParam[] = "UIVerticalMargin";
const char OmniboxFieldTrial::kZeroSuggestRedirectToChromeExperimentIdParam[] =
"ZeroSuggestRedirectToChromeExperimentID";
// static // static
int OmniboxFieldTrial::kDefaultMinimumTimeBetweenSuggestQueriesMs = 100; int OmniboxFieldTrial::kDefaultMinimumTimeBetweenSuggestQueriesMs = 100;
......
...@@ -199,6 +199,13 @@ class OmniboxFieldTrial { ...@@ -199,6 +199,13 @@ class OmniboxFieldTrial {
// show recently searched-for queries instead. // show recently searched-for queries instead.
static bool InZeroSuggestPersonalizedFieldTrial(); static bool InZeroSuggestPersonalizedFieldTrial();
// ---------------------------------------------------------
// For the Zero Suggest Redirect to Chrome field trial.
// Returns the server-side experiment ID to use for contextual suggestions.
// Returns -1 if there is no associated experiment ID.
static int GetZeroSuggestRedirectToChromeExperimentId();
// --------------------------------------------------------- // ---------------------------------------------------------
// For the ShortcutsScoringMaxRelevance experiment that's part of the // For the ShortcutsScoringMaxRelevance experiment that's part of the
// bundled omnibox field trial. // bundled omnibox field trial.
...@@ -419,26 +426,6 @@ class OmniboxFieldTrial { ...@@ -419,26 +426,6 @@ class OmniboxFieldTrial {
// the user has started typing in the omnibox. // the user has started typing in the omnibox.
static int GetPhysicalWebAfterTypingBaseRelevance(); static int GetPhysicalWebAfterTypingBaseRelevance();
// ---------------------------------------------------------
// For experiment redirecting zero suggest requests to a service provided by
// the Chrome team.
// Returns true whether the user is in the field trial which redirects zero
// suggest requests to the service provided by the Chrome team.
static bool InZeroSuggestRedirectToChromeFieldTrial();
// Returns a string representing the address of the server where the zero
// suggest requests are being redirected. The return value is a URL
// (https://example.com/test) and it doesn't include any query component
// (no "?").
static std::string ZeroSuggestRedirectToChromeServerAddress();
// Returns a string representing the parameters that are sent to the
// alternative service providing zero suggestions. The returned value is
// properly escaped. It can be appended to the string representaiton of a
// request URL.
static std::string ZeroSuggestRedirectToChromeAdditionalFields();
// --------------------------------------------------------- // ---------------------------------------------------------
// Clipboard URL suggestions: // Clipboard URL suggestions:
...@@ -505,15 +492,13 @@ class OmniboxFieldTrial { ...@@ -505,15 +492,13 @@ class OmniboxFieldTrial {
static const char kPhysicalWebZeroSuggestBaseRelevanceParam[]; static const char kPhysicalWebZeroSuggestBaseRelevanceParam[];
static const char kPhysicalWebAfterTypingBaseRelevanceParam[]; static const char kPhysicalWebAfterTypingBaseRelevanceParam[];
// Parameter names used by the experiment redirecting Zero Suggestion requests
// to a service provided by the Chrome team.
static const char kZeroSuggestRedirectToChromeServerAddressParam[];
static const char kZeroSuggestRedirectToChromeAdditionalFieldsParam[];
// Parameter names used by UI experiments. // Parameter names used by UI experiments.
static const char kUIMaxAutocompleteMatchesParam[]; static const char kUIMaxAutocompleteMatchesParam[];
static const char kUIVerticalMarginParam[]; static const char kUIVerticalMarginParam[];
// Parameter names used by Zero Suggest Redirect to Chrome.
static const char kZeroSuggestRedirectToChromeExperimentIdParam[];
// The amount of time to wait before sending a new suggest request after the // The amount of time to wait before sending a new suggest request after the
// previous one unless overridden by a field trial parameter. // previous one unless overridden by a field trial parameter.
// Non-const because some unittests modify this value. // Non-const because some unittests modify this value.
......
...@@ -207,7 +207,6 @@ class FakeAutocompleteProviderClient ...@@ -207,7 +207,6 @@ class FakeAutocompleteProviderClient
} }
private: private:
base::test::ScopedTaskEnvironment scoped_task_environment_;
base::SequencedWorkerPoolOwner pool_owner_; base::SequencedWorkerPoolOwner pool_owner_;
base::ScopedTempDir history_dir_; base::ScopedTempDir history_dir_;
std::unique_ptr<history::HistoryService> history_service_; std::unique_ptr<history::HistoryService> history_service_;
...@@ -261,6 +260,7 @@ class ShortcutsProviderTest : public testing::Test { ...@@ -261,6 +260,7 @@ class ShortcutsProviderTest : public testing::Test {
const ShortcutsDatabase::Shortcut& shortcut, const ShortcutsDatabase::Shortcut& shortcut,
int max_relevance); int max_relevance);
base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<FakeAutocompleteProviderClient> client_; std::unique_ptr<FakeAutocompleteProviderClient> client_;
scoped_refptr<ShortcutsProvider> provider_; scoped_refptr<ShortcutsProvider> provider_;
}; };
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "components/omnibox/browser/autocomplete_input.h" #include "components/omnibox/browser/autocomplete_input.h"
#include "components/omnibox/browser/autocomplete_match.h" #include "components/omnibox/browser/autocomplete_match.h"
#include "components/omnibox/browser/autocomplete_provider_listener.h" #include "components/omnibox/browser/autocomplete_provider_listener.h"
#include "components/omnibox/browser/contextual_suggestions_service.h"
#include "components/omnibox/browser/history_url_provider.h" #include "components/omnibox/browser/history_url_provider.h"
#include "components/omnibox/browser/omnibox_field_trial.h" #include "components/omnibox/browser/omnibox_field_trial.h"
#include "components/omnibox/browser/omnibox_pref_names.h" #include "components/omnibox/browser/omnibox_pref_names.h"
...@@ -37,9 +38,6 @@ ...@@ -37,9 +38,6 @@
#include "components/url_formatter/url_formatter.h" #include "components/url_formatter/url_formatter.h"
#include "components/variations/net/variations_http_headers.h" #include "components/variations/net/variations_http_headers.h"
#include "net/base/escape.h" #include "net/base/escape.h"
#include "net/base/load_flags.h"
#include "net/http/http_request_headers.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/url_fetcher.h" #include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request_status.h" #include "net/url_request/url_request_status.h"
#include "url/gurl.h" #include "url/gurl.h"
...@@ -85,32 +83,6 @@ const int kDefaultZeroSuggestRelevance = 100; ...@@ -85,32 +83,6 @@ const int kDefaultZeroSuggestRelevance = 100;
// Used for testing whether zero suggest is ever available. // Used for testing whether zero suggest is ever available.
constexpr char kArbitraryInsecureUrlString[] = "http://www.google.com/"; constexpr char kArbitraryInsecureUrlString[] = "http://www.google.com/";
// Returns true if the folowing conditions are valid:
// * The |default_provider| is Google.
// * The user is in the ZeroSuggestRedirectToChrome field trial.
// * The field trial provides a valid server address where the suggest request
// is redirected.
// * The suggest request is over HTTPS. This avoids leaking the current page URL
// or personal data in unencrypted network traffic.
// Note: these checks are in addition to CanSendUrl() on the default contextual
// suggestion URL.
bool UseExperimentalSuggestService(const TemplateURLService& default_provider) {
const TemplateURL& default_provider_url =
*default_provider.GetDefaultSearchProvider();
const SearchTermsData& search_terms_data =
default_provider.search_terms_data();
if ((default_provider_url.GetEngineType(search_terms_data) !=
SEARCH_ENGINE_GOOGLE) ||
!OmniboxFieldTrial::InZeroSuggestRedirectToChromeFieldTrial())
return false;
// Check that the suggest URL for redirect to chrome field trial is valid.
const GURL suggest_url(
OmniboxFieldTrial::ZeroSuggestRedirectToChromeServerAddress());
if (!suggest_url.is_valid())
return false;
return suggest_url.SchemeIsCryptographic();
}
} // namespace } // namespace
// static // static
...@@ -146,7 +118,8 @@ void ZeroSuggestProvider::Start(const AutocompleteInput& input, ...@@ -146,7 +118,8 @@ void ZeroSuggestProvider::Start(const AutocompleteInput& input,
current_page_classification_ = input.current_page_classification(); current_page_classification_ = input.current_page_classification();
current_url_match_ = MatchForCurrentURL(); current_url_match_ = MatchForCurrentURL();
GURL suggest_url(GetContextualSuggestionsUrl()); GURL suggest_url = ContextualSuggestionsService::ContextualSuggestionsUrl(
/*current_url=*/"", client()->GetTemplateURLService());
if (!suggest_url.is_valid()) if (!suggest_url.is_valid())
return; return;
...@@ -174,33 +147,47 @@ void ZeroSuggestProvider::Start(const AutocompleteInput& input, ...@@ -174,33 +147,47 @@ void ZeroSuggestProvider::Start(const AutocompleteInput& input,
UMA_HISTOGRAM_ENUMERATION( UMA_HISTOGRAM_ENUMERATION(
"Omnibox.ZeroSuggest.Eligible.OnFocus", static_cast<int>(eligibility), "Omnibox.ZeroSuggest.Eligible.OnFocus", static_cast<int>(eligibility),
static_cast<int>(ZeroSuggestEligibility::ELIGIBLE_MAX_VALUE)); static_cast<int>(ZeroSuggestEligibility::ELIGIBLE_MAX_VALUE));
if (can_send_current_url &&
bool can_attach_current_url =
can_send_current_url &&
!OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial() && !OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial() &&
!OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()) { !OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial();
// Update suggest_url to include the current_page_url.
if (UseExperimentalSuggestService(*template_url_service)) { if (!can_attach_current_url &&
suggest_url = GURL( !ShouldShowNonContextualZeroSuggest(input.current_url())) {
OmniboxFieldTrial::ZeroSuggestRedirectToChromeServerAddress() +
"/url=" + net::EscapePath(current_query_) +
OmniboxFieldTrial::ZeroSuggestRedirectToChromeAdditionalFields());
} else {
base::string16 prefix;
TemplateURLRef::SearchTermsArgs search_term_args(prefix);
search_term_args.current_page_url = current_query_;
suggest_url =
GURL(default_provider->suggestions_url_ref().ReplaceSearchTerms(
search_term_args, template_url_service->search_terms_data()));
}
} else if (!ShouldShowNonContextualZeroSuggest(input.current_url())) {
return; return;
} }
done_ = false; done_ = false;
// TODO(jered): Consider adding locally-sourced zero-suggestions here too. // TODO(jered): Consider adding locally-sourced zero-suggestions here too.
// These may be useful on the NTP or more relevant to the user than server // These may be useful on the NTP or more relevant to the user than server
// suggestions, if based on local browsing history. // suggestions, if based on local browsing history.
MaybeUseCachedSuggestions(); MaybeUseCachedSuggestions();
Run(suggest_url);
if (OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()) {
most_visited_urls_.clear();
scoped_refptr<history::TopSites> ts = client()->GetTopSites();
if (ts) {
waiting_for_most_visited_urls_request_ = true;
ts->GetMostVisitedURLs(
base::Bind(&ZeroSuggestProvider::OnMostVisitedUrlsAvailable,
weak_ptr_factory_.GetWeakPtr()),
false);
}
return;
}
// Create a request for suggestions with |this| as the fetcher delegate.
client()
->GetContextualSuggestionsService()
->CreateContextualSuggestionsRequest(
can_attach_current_url ? current_query_ : std::string(),
client()->GetTemplateURLService(),
/*fetcher_delegate=*/this,
base::BindOnce(
&ZeroSuggestProvider::OnContextualSuggestionsFetcherAvailable,
weak_ptr_factory_.GetWeakPtr()));
} }
void ZeroSuggestProvider::Stop(bool clear_cached_results, void ZeroSuggestProvider::Stop(bool clear_cached_results,
...@@ -264,7 +251,8 @@ ZeroSuggestProvider::ZeroSuggestProvider( ...@@ -264,7 +251,8 @@ ZeroSuggestProvider::ZeroSuggestProvider(
client->GetTemplateURLService(); client->GetTemplateURLService();
// Template URL service can be null in tests. // Template URL service can be null in tests.
if (template_url_service != nullptr) { if (template_url_service != nullptr) {
GURL suggest_url(GetContextualSuggestionsUrl()); GURL suggest_url = ContextualSuggestionsService::ContextualSuggestionsUrl(
/*current_url=*/"", template_url_service);
// To check whether this is allowed, use an arbitrary insecure (http) URL // To check whether this is allowed, use an arbitrary insecure (http) URL
// as the URL we'd want suggestions for. The value of OTHER as the current // as the URL we'd want suggestions for. The value of OTHER as the current
// page classification is to correspond with that URL. // page classification is to correspond with that URL.
...@@ -396,68 +384,6 @@ AutocompleteMatch ZeroSuggestProvider::NavigationToMatch( ...@@ -396,68 +384,6 @@ AutocompleteMatch ZeroSuggestProvider::NavigationToMatch(
return match; return match;
} }
void ZeroSuggestProvider::Run(const GURL& suggest_url) {
if (OmniboxFieldTrial::InZeroSuggestMostVisitedFieldTrial()) {
most_visited_urls_.clear();
scoped_refptr<history::TopSites> ts = client()->GetTopSites();
if (ts) {
waiting_for_most_visited_urls_request_ = true;
ts->GetMostVisitedURLs(
base::Bind(&ZeroSuggestProvider::OnMostVisitedUrlsAvailable,
weak_ptr_factory_.GetWeakPtr()), false);
}
} else {
net::NetworkTrafficAnnotationTag traffic_annotation =
net::DefineNetworkTrafficAnnotation("omnibox_zerosuggest", R"(
semantics {
sender: "Omnibox"
description:
"When the user focuses the omnibox, Chrome can provide search or "
"navigation suggestions from the default search provider in the "
"omnibox dropdown, based on the current page URL.\n"
"This is limited to users whose default search engine is Google, "
"as no other search engines currently support this kind of "
"suggestion."
trigger: "The omnibox receives focus."
data: "The URL of the current page."
destination: GOOGLE_OWNED_SERVICE
}
policy {
cookies_allowed: YES
cookies_store: "user"
setting:
"Users can control this feature via the 'Use a prediction service "
"to help complete searches and URLs typed in the address bar' "
"settings under 'Privacy'. The feature is enabled by default."
chrome_policy {
SearchSuggestEnabled {
policy_options {mode: MANDATORY}
SearchSuggestEnabled: false
}
}
})");
const int kFetcherID = 1;
fetcher_ =
net::URLFetcher::Create(kFetcherID, suggest_url, net::URLFetcher::GET,
this, traffic_annotation);
data_use_measurement::DataUseUserData::AttachToFetcher(
fetcher_.get(), data_use_measurement::DataUseUserData::OMNIBOX);
fetcher_->SetRequestContext(client()->GetRequestContext());
fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES);
// Add Chrome experiment state to the request headers.
net::HttpRequestHeaders headers;
// Note: It's OK to pass |is_signed_in| false if it's unknown, as it does
// not affect transmission of experiments coming from the variations server.
bool is_signed_in = false;
variations::AppendVariationHeaders(fetcher_->GetOriginalURL(),
client()->IsOffTheRecord(), false,
is_signed_in, &headers);
fetcher_->SetExtraRequestHeaders(headers.ToString());
fetcher_->Start();
LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_SENT);
}
}
void ZeroSuggestProvider::OnMostVisitedUrlsAvailable( void ZeroSuggestProvider::OnMostVisitedUrlsAvailable(
const history::MostVisitedURLList& urls) { const history::MostVisitedURLList& urls) {
if (!waiting_for_most_visited_urls_request_) return; if (!waiting_for_most_visited_urls_request_) return;
...@@ -468,6 +394,13 @@ void ZeroSuggestProvider::OnMostVisitedUrlsAvailable( ...@@ -468,6 +394,13 @@ void ZeroSuggestProvider::OnMostVisitedUrlsAvailable(
listener_->OnProviderUpdate(true); listener_->OnProviderUpdate(true);
} }
void ZeroSuggestProvider::OnContextualSuggestionsFetcherAvailable(
std::unique_ptr<net::URLFetcher> fetcher) {
fetcher_ = std::move(fetcher);
fetcher_->Start();
LogOmniboxZeroSuggestRequest(ZERO_SUGGEST_REQUEST_SENT);
}
void ZeroSuggestProvider::ConvertResultsToAutocompleteMatches() { void ZeroSuggestProvider::ConvertResultsToAutocompleteMatches() {
matches_.clear(); matches_.clear();
...@@ -578,20 +511,6 @@ bool ZeroSuggestProvider::ShouldShowNonContextualZeroSuggest( ...@@ -578,20 +511,6 @@ bool ZeroSuggestProvider::ShouldShowNonContextualZeroSuggest(
return true; return true;
} }
std::string ZeroSuggestProvider::GetContextualSuggestionsUrl() const {
const TemplateURLService* template_url_service =
client()->GetTemplateURLService();
const TemplateURL* default_provider =
template_url_service->GetDefaultSearchProvider();
if (default_provider == nullptr)
return std::string();
base::string16 prefix;
TemplateURLRef::SearchTermsArgs search_term_args(prefix);
return default_provider->suggestions_url_ref().ReplaceSearchTerms(
search_term_args, template_url_service->search_terms_data());
}
void ZeroSuggestProvider::MaybeUseCachedSuggestions() { void ZeroSuggestProvider::MaybeUseCachedSuggestions() {
if (!OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial()) if (!OmniboxFieldTrial::InZeroSuggestPersonalizedFieldTrial())
return; return;
......
...@@ -98,9 +98,6 @@ class ZeroSuggestProvider : public BaseSearchProvider, ...@@ -98,9 +98,6 @@ class ZeroSuggestProvider : public BaseSearchProvider,
AutocompleteMatch NavigationToMatch( AutocompleteMatch NavigationToMatch(
const SearchSuggestionParser::NavigationResult& navigation); const SearchSuggestionParser::NavigationResult& navigation);
// Fetches zero-suggest suggestions by sending a request using |suggest_url|.
void Run(const GURL& suggest_url);
// Converts the parsed results to a set of AutocompleteMatches and adds them // Converts the parsed results to a set of AutocompleteMatches and adds them
// to |matches_|. Also update the histograms for how many results were // to |matches_|. Also update the histograms for how many results were
// received. // received.
...@@ -112,21 +109,22 @@ class ZeroSuggestProvider : public BaseSearchProvider, ...@@ -112,21 +109,22 @@ class ZeroSuggestProvider : public BaseSearchProvider,
AutocompleteMatch MatchForCurrentURL(); AutocompleteMatch MatchForCurrentURL();
// When the user is in the Most Visited field trial, we ask the TopSites // When the user is in the Most Visited field trial, we ask the TopSites
// service for the most visited URLs during Run(). It calls back to this // service for the most visited URLs. It then calls back to this function to
// function to return those |urls|. // return those |urls|.
void OnMostVisitedUrlsAvailable(const history::MostVisitedURLList& urls); void OnMostVisitedUrlsAvailable(const history::MostVisitedURLList& urls);
// When the user is in the contextual omnibox suggestions field trial, we ask
// the ContextualSuggestionsService for a fetcher to retrieve recommendations.
// When the fetcher is ready, the contextual suggestion service then calls
// back to this function with the |fetcher| to use for the request.
void OnContextualSuggestionsFetcherAvailable(
std::unique_ptr<net::URLFetcher> fetcher);
// Whether we can show zero suggest suggestions that are not based on // Whether we can show zero suggest suggestions that are not based on
// |current_page_url|. Also checks that other conditions for non-contextual // |current_page_url|. Also checks that other conditions for non-contextual
// zero suggest are satisfied. // zero suggest are satisfied.
bool ShouldShowNonContextualZeroSuggest(const GURL& current_page_url) const; bool ShouldShowNonContextualZeroSuggest(const GURL& current_page_url) const;
// Returns a URL string that should be used to to request contextual
// suggestions from the default provider. Does not take into account whether
// sending this request is prohibited (e.g., in an incognito window). Returns
// an empty string in case of an error.
std::string GetContextualSuggestionsUrl() const;
// Checks whether we have a set of zero suggest results cached, and if so // Checks whether we have a set of zero suggest results cached, and if so
// populates |matches_| with cached results. // populates |matches_| with cached results.
void MaybeUseCachedSuggestions(); void MaybeUseCachedSuggestions();
......
...@@ -82,6 +82,11 @@ AutocompleteProviderClientImpl::GetTemplateURLService() const { ...@@ -82,6 +82,11 @@ AutocompleteProviderClientImpl::GetTemplateURLService() const {
return ios::TemplateURLServiceFactory::GetForBrowserState(browser_state_); return ios::TemplateURLServiceFactory::GetForBrowserState(browser_state_);
} }
ContextualSuggestionsService*
AutocompleteProviderClientImpl::GetContextualSuggestionsService() const {
return nullptr;
}
const SearchTermsData& AutocompleteProviderClientImpl::GetSearchTermsData() const SearchTermsData& AutocompleteProviderClientImpl::GetSearchTermsData()
const { const {
return search_terms_data_; return search_terms_data_;
......
...@@ -34,6 +34,8 @@ class AutocompleteProviderClientImpl : public AutocompleteProviderClient { ...@@ -34,6 +34,8 @@ class AutocompleteProviderClientImpl : public AutocompleteProviderClient {
InMemoryURLIndex* GetInMemoryURLIndex() override; InMemoryURLIndex* GetInMemoryURLIndex() override;
TemplateURLService* GetTemplateURLService() override; TemplateURLService* GetTemplateURLService() override;
const TemplateURLService* GetTemplateURLService() const override; const TemplateURLService* GetTemplateURLService() const override;
ContextualSuggestionsService* GetContextualSuggestionsService()
const override;
const SearchTermsData& GetSearchTermsData() const override; const SearchTermsData& GetSearchTermsData() const override;
scoped_refptr<ShortcutsBackend> GetShortcutsBackend() override; scoped_refptr<ShortcutsBackend> GetShortcutsBackend() override;
scoped_refptr<ShortcutsBackend> GetShortcutsBackendIfExists() override; scoped_refptr<ShortcutsBackend> GetShortcutsBackendIfExists() override;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment