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
|
// Copyright 2018 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// This file contains the document autocomplete provider. This experimental
// provider uses an experimental API with keys and endpoint provided at
// developer build-time, so it is feature-flagged off by default.
#ifndef COMPONENTS_OMNIBOX_BROWSER_DOCUMENT_PROVIDER_H_
#define COMPONENTS_OMNIBOX_BROWSER_DOCUMENT_PROVIDER_H_
#include <memory>
#include <string>
#include "base/compiler_specific.h"
#include "base/containers/lru_cache.h"
#include "base/feature_list.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "components/history/core/browser/history_types.h"
#include "components/omnibox/browser/autocomplete_enums.h"
#include "components/omnibox/browser/autocomplete_provider.h"
#include "components/omnibox/browser/autocomplete_provider_debouncer.h"
#include "third_party/metrics_proto/omnibox_event.pb.h"
#include "url/gurl.h"
class AutocompleteProviderListener;
struct AutocompleteMatch;
class AutocompleteProviderClient;
namespace base {
class Value;
}
namespace network {
class SimpleURLLoader;
}
// Autocomplete provider for personalized documents owned or readable by the
// signed-in user. In practice this is a second request in parallel with that
// to the default search provider.
class DocumentProvider : public AutocompleteProvider {
public:
// Creates and returns an instance of this provider.
static DocumentProvider* Create(AutocompleteProviderClient* client,
AutocompleteProviderListener* listener);
// AutocompleteProvider:
void Start(const AutocompleteInput& input, bool minimal_changes) override;
void Stop(AutocompleteStopReason stop_reason) override;
void DeleteMatch(const AutocompleteMatch& match) override;
void AddProviderInfo(ProvidersInfo* provider_info) const override;
// Returns a set of classifications that highlight all the occurrences of
// |input_text| at word breaks in |text|. E.g., given |input_text|
// "rain if you dare" and |text| "how to tell if your kitten is a rainbow",
// will return the classifications:
// __ ___ ____
// how to tell if your kitten is a rainbow
// ^ ^ ^^ ^ ^ ^
// NONE M |M | | NONE
// NONE NONE MATCH
static ACMatchClassifications Classify(const std::u16string& input_text,
const std::u16string& text);
// Builds a GURL to use for deduping against other document/history
// suggestions. Multiple URLs may refer to the same document.
// Returns an empty GURL if not a recognized Docs URL.
// The URL returned is not guaranteed to be navigable and should only be used
// as a deduping token.
static const GURL GetURLForDeduping(const GURL& url);
private:
friend class FakeDocumentProvider;
using MatchesCache = base::LRUCache<GURL, AutocompleteMatch>;
DocumentProvider(AutocompleteProviderClient* client,
AutocompleteProviderListener* listener);
~DocumentProvider() override;
DocumentProvider(const DocumentProvider&) = delete;
DocumentProvider& operator=(const DocumentProvider&) = delete;
// Determines whether the profile/session/window meet the feature
// prerequisites.
bool IsDocumentProviderAllowed(const AutocompleteInput& input);
// Determines if the input is a URL, or is the start of the user entering one.
// We avoid queries for these cases for quality and scaling reasons.
static bool IsInputLikelyURL(const AutocompleteInput& input);
// Called by |debouncer_|, queued when |start| is called.
void Run(const AutocompleteInput& input);
// Called when the network request for suggestions has completed.
void OnURLLoadComplete(const network::SimpleURLLoader* source,
const int response_code,
std::unique_ptr<std::string> response_body);
// Resets the backoff state on DocumentSuggestionsService to false.
void ResetBackoffState();
// The function updates |matches_| with data parsed from |json_data|.
// The update is not performed if |json_data| is invalid.
// Returns whether |matches_| changed.
bool UpdateResults(const std::string& json_data);
// Callback for when the loader is available with a valid token.
void OnDocumentSuggestionsLoaderAvailable(
std::unique_ptr<network::SimpleURLLoader> loader);
// Parses document search result JSON.
// Returns true if |matches| was populated with fresh suggestions.
ACMatches ParseDocumentSearchResults(const base::Value& root_val);
// Appends |matches_cache_| to |matches_|. Updates their classifications
// according to |input_.text()|.
void CopyCachedMatchesToMatches();
// Sets the scores of all cached matches to 0. This is invoked before pushing
// the latest async response returns so that the scores aren't preserved for
// further inputs. E.g., the input 'london' shouldn't display cached docs from
// a previous input 'paris'. This can't be done by automatically (i.e. set
// scores to 0 before pushing to the cache), as the scores are needed for the
// async pass if the user continued their input.
void SetCachedMatchesScoresTo0();
// Sets the scores of matches beyond the first |provider_max_matches_| to 0.
// This ensures the doc provider doesn't exceed it's allocated suggestions
// while also allowing docs from other providers to be deduped and styled like
// docs from the doc provider.
void DemoteMatchesBeyondMax();
// Generates the localized last-modified timestamp to present to the user.
// Full date for old files, mm/dd within the same calendar year, or time-of-
// day if a file was modified on the same date.
// |now| should generally be base::Time::Now() but is passed in for testing.
static std::u16string GenerateLastModifiedString(
const std::string& modified_timestamp_string,
base::Time now);
// Convert mimetype (e.g. "application/vnd.google-apps.document") to a string
// that can be used in the match description (e.g. "Google Docs").
static std::u16string GetProductDescriptionString(
const std::string& mimetype);
// Construct match description; e.g. "Jan 12 - First Last - Google Docs".
static std::u16string GetMatchDescription(const std::string& update_time,
const std::string& mimetype,
const std::string& owner);
// Whether the server has instructed us to backoff. Used when the backoff
// state is scoped to the current window/AutocompleteController.
bool backoff_for_this_instance_only_ = false;
// Client for accessing TemplateUrlService, prefs, etc.
raw_ptr<AutocompleteProviderClient> client_;
// Saved when starting a new autocomplete request so that it can be retrieved
// when responses return asynchronously.
AutocompleteInput input_;
// Loader used to retrieve results.
std::unique_ptr<network::SimpleURLLoader> loader_;
// The time `Run()` was invoked. Used for histogram logging.
base::TimeTicks time_run_invoked_;
// The time `OnDocumentSuggestionsLoaderAvailable()` was invoked and the
// remote request was sent. Used for histogram logging.
base::TimeTicks time_request_sent_;
// Used to ensure that we don't send multiple requests in quick succession.
std::unique_ptr<AutocompleteProviderDebouncer> debouncer_;
// Because the drive server is async and may intermittently provide a
// particular suggestion for consecutive inputs, without caching, doc
// suggestions flicker between drive format (title - date - doc_type) and URL
// format (title - URL) suggestions from the history and bookmark providers.
// Appending cached doc suggestions with relevance 0 ensures cached
// suggestions only display if deduped with a non-cached suggestion and do not
// affect which autocomplete results are displayed and their ranks.
MatchesCache matches_cache_;
// Used to schedule a reset of the backoff state.
scoped_refptr<base::SequencedTaskRunner> task_runner_;
// For callbacks that may be run after destruction. Must be declared last.
base::WeakPtrFactory<DocumentProvider> weak_ptr_factory_{this};
};
#endif // COMPONENTS_OMNIBOX_BROWSER_DOCUMENT_PROVIDER_H_
|