File: remote_suggestions_service.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (341 lines) | stat: -rw-r--r-- 15,168 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
// 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 <map>
#include <memory>
#include <optional>
#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/time/time.h"
#include "base/timer/elapsed_timer.h"
#include "base/unguessable_token.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/omnibox/browser/autocomplete_input.h"
#include "components/omnibox/browser/autocomplete_match.h"
#include "components/omnibox/browser/enterprise_search_aggregator_suggestions_service.h"
#include "components/search_engines/template_url.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "url/gurl.h"

class DocumentSuggestionsService;
class EnterpriseSearchAggregatorSuggestionsService;

using EnterpriseSearchAggregatorSuggestionType =
    AutocompleteMatch::EnterpriseSearchAggregatorType;

namespace network {
class SharedURLLoaderFactory;
class SimpleURLLoader;
struct ResourceRequest;
}  // namespace network

// The types of requests for remote suggestions.
// These values are written to logs. New enum values can be added, but existing
// enums must never be renumbered or deleted and reused.
// Must be kept in sync with RemoteRequestType enum and variant.
// LINT.IfChange(RemoteRequestType)
enum class RemoteRequestType {
  // Search suggestion requests.
  kSearch = 0,
  // Search suggestion warm-up requests.
  kSearchWarmup = 1,
  // Search suggestion requests to obtain images.
  kImages = 2,
  // Zero-prefix suggestion requests.
  kZeroSuggest = 3,
  // Zero-prefix suggestion prefetching requests.
  kZeroSuggestPrefetch = 4,
  // Document suggestion requests.
  kDocumentSuggest = 5,
  // Suggestion deletion requests.
  kDeletion = 6,
  // Enterprise Search Aggregator suggestion requests.
  kEnterpriseSearchAggregatorSuggest = 7,
  kMaxValue = kEnterpriseSearchAggregatorSuggest,
};
// LINT.ThenChange(
//     //tools/metrics/histograms/metadata/omnibox/enums.xml:RemoteRequestType,
//     //tools/metrics/histograms/metadata/omnibox/histograms.xml:RemoteRequestType
// )

// The event types recorded by the providers for remote suggestions. Each event
// must be logged at most once from when the provider is started until it is
// stopped.
// These values are written to logs. New enum values can be added, but existing
// enums must never be renumbered or deleted and reused.
enum class RemoteRequestEvent {
  // Cached response was synchronously converted to displayed matches.
  // Recorded for non-prefetch requests only.
  kCachedResponseConvertedToMatches = 0,
  // Request was sent.
  kRequestSent = 1,
  // Request was invalidated.
  kRequestInvalidated = 2,
  // Response was received asynchronously.
  kResponseReceived = 3,
  // Response was cached.
  kResponseCached = 4,
  // Response ended up being converted to displayed matches. This may happen due
  // to an empty displayed result set or an empty remote result set.
  // Recorded for non-prefetch requests only.
  kResponseConvertedToMatches = 5,
  kMaxValue = kResponseConvertedToMatches,
};

// A service to fetch suggestions from a search provider's suggest endpoint.
// Used by ZeroSuggestProvider, SearchProvider, DocumentProvider, and
// 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 OnRequestCreated(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 OnRequestStarted(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 OnRequestCompleted(
        const base::UnguessableToken& request_id,
        const int response_code,
        const std::unique_ptr<std::string>& response_body) {}
  };

  // Called when the transfer has started asynchronously, e.g., after obtaining
  // an OAuth token.
  using StartCallback = base::OnceCallback<void(
      std::unique_ptr<network::SimpleURLLoader> loader)>;
  // 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)>;
  // Same as `StartCallback` but for requests that are associated with a
  // `request_index`.
  using IndexedStartCallback = base::RepeatingCallback<void(
      const int request_index,
      std::unique_ptr<network::SimpleURLLoader> loader)>;
  // Same as `CompletionCallback` but for requests that are associated with a
  // `request_index`.
  using IndexedCompletionCallback =
      base::RepeatingCallback<void(const int request_index,
                                   const network::SimpleURLLoader* source,
                                   const int response_code,
                                   std::unique_ptr<std::string> response_body)>;

  class Delegate {
   public:
    Delegate();
    virtual ~Delegate();
    Delegate(const Delegate&) = delete;
    Delegate& operator=(const Delegate&) = delete;

    // Called when the transfer is done. Delegates invocation of
    // `completion_callback`
    virtual void OnRequestCompleted(const network::SimpleURLLoader* source,
                                    const int response_code,
                                    std::unique_ptr<std::string> response_body,
                                    CompletionCallback completion_callback) = 0;

    virtual void OnIndexedRequestCompleted(
        const int request_index,
        const network::SimpleURLLoader* source,
        const int response_code,
        std::unique_ptr<std::string> response_body,
        IndexedCompletionCallback completion_callback) = 0;

   protected:
    base::WeakPtrFactory<Delegate> weak_ptr_factory_{this};
  };

  RemoteSuggestionsService(
      DocumentSuggestionsService* document_suggestions_service,
      EnterpriseSearchAggregatorSuggestionsService*
          enterprise_search_aggregator_suggestions_service,
      scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory);
  ~RemoteSuggestionsService() override;
  RemoteSuggestionsService(const RemoteSuggestionsService&) = delete;
  RemoteSuggestionsService& operator=(const RemoteSuggestionsService&) = delete;

  // Helper to set the time request of type `request_type` has started in
  // `time_request_sent_`.
  void SetTimeRequestSent(RemoteRequestType request_type, base::TimeTicks time);

  // Returns the suggest endpoint URL for `template_url`.
  // `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,
      const 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(
      RemoteRequestType request_type,
      bool is_off_the_record,
      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(
      RemoteRequestType request_type,
      bool is_off_the_record,
      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` asynchronously
  // after obtaining an OAuth2 token for the signed-in users.
  void CreateDocumentSuggestionsRequest(
      const std::u16string& query,
      bool is_off_the_record,
      metrics::OmniboxEventProto::PageClassification page_classification,
      StartCallback start_callback,
      CompletionCallback completion_callback);

  // Stops creating the request. Already created requests aren't affected.
  void StopCreatingDocumentSuggestionsRequest();

  // Creates and starts an enterprise search aggregator suggestion request using
  //  `suggest_url` and `response_body` asynchronously after obtaining an OAuth2
  //  token for signed-in enterprise users.
  void CreateEnterpriseSearchAggregatorSuggestionsRequest(
      const std::u16string& query,
      const GURL& suggest_url,
      metrics::OmniboxEventProto::PageClassification page_classification,
      std::vector<int> callback_indexes,
      std::vector<std::vector<int>> suggestion_types,
      IndexedStartCallback start_callback,
      IndexedCompletionCallback completion_callback);

  // Stops creating the request. Already created requests aren't affected.
  void StopCreatingEnterpriseSearchAggregatorSuggestionsRequest();

  // 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,
      bool is_off_the_record,
      CompletionCallback completion_callback);

  void AddObserver(Observer* observer);
  void RemoveObserver(Observer* observer);

  void SetDelegate(base::WeakPtr<Delegate> delegate);

  // 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 the transfer has started.
  // Notifies `observers_`.
  void OnRequestCreated(const base::UnguessableToken& request_id,
                        network::ResourceRequest* request);
  // Called when the transfer has started. Notifies `observers_`.
  void OnRequestStarted(
      const base::UnguessableToken& request_id,
      RemoteRequestType request_type,
      metrics::OmniboxEventProto::PageClassification page_classification,
      network::SimpleURLLoader* loader,
      const std::string& request_body);
  // Called when the transfer has started asynchronously, e.g., after obtaining
  // an OAuth token. Notifies `observers_` and calls `start_callback` to
  // transfer the ownership of `loader` to the caller.
  void OnRequestStartedAsync(
      const base::UnguessableToken& request_id,
      RemoteRequestType request_type,
      metrics::OmniboxEventProto::PageClassification page_classification,
      StartCallback start_callback,
      std::unique_ptr<network::SimpleURLLoader> loader,
      const std::string& request_body);
  void OnIndexedRequestStartedAsync(
      const base::UnguessableToken& request_id,
      RemoteRequestType request_type,
      metrics::OmniboxEventProto::PageClassification page_classification,
      IndexedStartCallback start_callback,
      int request_index,
      std::unique_ptr<network::SimpleURLLoader> loader,
      const std::string& request_body);
  // Called when the transfer is done. Notifies `observers_` and calls
  // `completion_callback` passing the response to the caller.
  void OnRequestCompleted(
      const base::UnguessableToken& request_id,
      RemoteRequestType request_type,
      base::ElapsedTimer request_timer,
      metrics::OmniboxEventProto::PageClassification page_classification,
      CompletionCallback completion_callback,
      const network::SimpleURLLoader* source,
      std::unique_ptr<std::string> response_body);

  void OnIndexedRequestCompleted(
      const base::UnguessableToken& request_id,
      RemoteRequestType request_type,
      metrics::OmniboxEventProto::PageClassification page_classification,
      base::TimeTicks start_time,
      IndexedCompletionCallback completion_callback,
      const network::SimpleURLLoader* source,
      int request_index,
      std::unique_ptr<std::string> response_body);

  // May be nullptr in OTR profiles. Otherwise guaranteed to outlive this due to
  // the factories' dependency.
  raw_ptr<DocumentSuggestionsService> document_suggestions_service_;
  // May be nullptr in OTR profiles. Otherwise guaranteed to outlive this due to
  // the factories' dependency.
  raw_ptr<EnterpriseSearchAggregatorSuggestionsService>
      enterprise_search_aggregator_suggestions_service_;
  scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory_;
  // Time request sent for each RemoteRequestType. Used for histogram logging.
  std::map<RemoteRequestType, base::TimeTicks> time_request_sent_;
  // Observers being notified of request start and completion events.
  base::ObserverList<Observer> observers_;
  // Delegate to which invocation of completion callback is delegated.
  base::WeakPtr<Delegate> delegate_;
  // 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_