blob: cc62fadfac36c3810f888e3a1e190b0dd98f8a7e [file] [log] [blame]
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef COMPONENTS_OMNIBOX_BROWSER_REMOTE_SUGGESTIONS_SERVICE_H_
#define COMPONENTS_OMNIBOX_BROWSER_REMOTE_SUGGESTIONS_SERVICE_H_
#include <memory>
#include <string>
#include "base/functional/callback_forward.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/observer_list_types.h"
#include "base/unguessable_token.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/omnibox/browser/autocomplete_input.h"
#include "components/search_engines/template_url.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "url/gurl.h"
class DocumentSuggestionsService;
namespace network {
class SharedURLLoaderFactory;
class SimpleURLLoader;
struct ResourceRequest;
} // namespace network
// A service to fetch suggestions from a search provider's suggest endpoint.
// Used by the ZeroSuggestProvider, the SearchProvider, and the ImageService.
//
// This service is always sent the user's authentication state, so the
// suggestions always can be personalized. This service is also sometimes sent
// the user's current URL, so the suggestions are sometimes also contextual.
class RemoteSuggestionsService : public KeyedService {
public:
class Observer : public base::CheckedObserver {
public:
// Called when the request has been created. `request_id` identifies the
// request. `request` is deleted after this call once the transfer starts.
virtual void OnSuggestRequestCreated(
const base::UnguessableToken& request_id,
const network::ResourceRequest* request) {}
// Called when the transfer has started. `request_id` identifies the
// request. `request_body` is the HTTP POST upload body, if applicable.
virtual void OnSuggestRequestStarted(
const base::UnguessableToken& request_id,
network::SimpleURLLoader* loader,
const std::string& request_body) {}
// Called when the transfer is done. `request_id` identifies the request.
// `response_code` is the response status code. A status code of 200
// indicates that the request has succeeded and `response_body` is
// populated.
virtual void OnSuggestRequestCompleted(
const base::UnguessableToken& request_id,
const int response_code,
const std::unique_ptr<std::string>& response_body) {}
};
RemoteSuggestionsService(
DocumentSuggestionsService* document_suggestions_service,
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
~RemoteSuggestionsService() override;
RemoteSuggestionsService(const RemoteSuggestionsService&) = delete;
RemoteSuggestionsService& operator=(const RemoteSuggestionsService&) = delete;
// Called when the transfer is done. `response_code` is the response status
// code. A status code of 200 indicates that the request has succeeded and
// `response_body` is populated.
using CompletionCallback =
base::OnceCallback<void(const network::SimpleURLLoader* source,
const int response_code,
std::unique_ptr<std::string> response_body)>;
// Returns the suggest endpoint URL for `template_url`.
//
// `template_url` must not be nullptr.
// `search_terms_args` is used to build the endpoint URL.
// `search_terms_data` is used to build the endpoint URL.
static GURL EndpointUrl(const TemplateURL* template_url,
TemplateURLRef::SearchTermsArgs search_terms_args,
const SearchTermsData& search_terms_data);
// Creates and returns a loader for remote suggestions for `template_url`.
// It uses a number of signals to create the loader, including field trial
// parameters.
//
// `template_url` must not be nullptr.
// `search_terms_args` is used to build the endpoint URL.
// `search_terms_data` is used to build the endpoint URL.
// `completion_callback` will be invoked when the transfer is done.
std::unique_ptr<network::SimpleURLLoader> StartSuggestionsRequest(
const TemplateURL* template_url,
TemplateURLRef::SearchTermsArgs search_terms_args,
const SearchTermsData& search_terms_data,
CompletionCallback completion_callback);
// Creates and returns a loader for remote zero-prefix suggestions for
// `template_url`. It uses a number of signals to create the loader, including
// field trial parameters.
//
// `template_url` must not be nullptr.
// `search_terms_args` is used to build the endpoint URL.
// `search_terms_data` is used to build the endpoint URL.
// `completion_callback` will be invoked when the transfer is done.
std::unique_ptr<network::SimpleURLLoader> StartZeroPrefixSuggestionsRequest(
const TemplateURL* template_url,
TemplateURLRef::SearchTermsArgs search_terms_args,
const SearchTermsData& search_terms_data,
CompletionCallback completion_callback);
// Creates and starts a document suggestion request for |query|.
// May obtain an OAuth2 token for the signed-in users.
using DocumentStartCallback = base::OnceCallback<void(
std::unique_ptr<network::SimpleURLLoader> loader)>;
void CreateDocumentSuggestionsRequest(const std::u16string& query,
bool is_incognito,
DocumentStartCallback start_callback,
CompletionCallback completion_callback);
// Advises the service to stop any process that creates a document suggestion
// request.
void StopCreatingDocumentSuggestionsRequest();
// Creates and returns a loader to delete personalized suggestions.
//
// `deletion_url` must be a valid URL.
// `completion_callback` will be invoked when the transfer is done.
std::unique_ptr<network::SimpleURLLoader> StartDeletionRequest(
const std::string& deletion_url,
CompletionCallback completion_callback);
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
// Exposed for testing.
void set_url_loader_factory_for_testing(
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
private:
// Called when the request has been created, before fetching the OAuth2 token.
// Notifies `observers_`.
void OnDocumentSuggestionsRequestAvailable(
const base::UnguessableToken& request_id,
network::ResourceRequest* request);
// Called when the transfer has started, after receiving the OAuth2 token.
// Notifies `observers_` and calls `start_callback`.
void OnDocumentSuggestionsLoaderAvailable(
const base::UnguessableToken& request_id,
DocumentStartCallback start_callback,
std::unique_ptr<network::SimpleURLLoader> loader,
const std::string& request_body);
// Called when the transfer is done. Notifies `observers_` and calls
// `completion_callback`.
void OnURLLoadComplete(const base::UnguessableToken& request_id,
CompletionCallback completion_callback,
const network::SimpleURLLoader* source,
std::unique_ptr<std::string> response_body);
raw_ptr<DocumentSuggestionsService> document_suggestions_service_;
scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
// Observers being notified of request start and completion events.
base::ObserverList<Observer> observers_;
// Used to bind `OnURLLoadComplete` to the network loader's callback as the
// loader is no longer owned by `this` once returned.
base::WeakPtrFactory<RemoteSuggestionsService> weak_ptr_factory_{this};
};
#endif // COMPONENTS_OMNIBOX_BROWSER_REMOTE_SUGGESTIONS_SERVICE_H_