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
|
// Copyright (c) 2012 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_PREDICTORS_AUTOCOMPLETE_ACTION_PREDICTOR_H_
#define CHROME_BROWSER_PREDICTORS_AUTOCOMPLETE_ACTION_PREDICTOR_H_
#include <map>
#include "base/gtest_prod_util.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observer.h"
#include "base/strings/string16.h"
#include "chrome/browser/predictors/autocomplete_action_predictor_table.h"
#include "components/history/core/browser/history_service_observer.h"
#include "components/history/core/browser/history_types.h"
#include "components/keyed_service/core/keyed_service.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "url/gurl.h"
struct AutocompleteMatch;
class AutocompleteResult;
class HistoryService;
struct OmniboxLog;
class PredictorsHandler;
class Profile;
namespace content {
class SessionStorageNamespace;
}
namespace gfx {
class Size;
}
namespace history {
class URLDatabase;
}
namespace prerender {
class PrerenderHandle;
}
namespace predictors {
// This class is responsible for determining the correct predictive network
// action to take given for a given AutocompleteMatch and entered text. It can
// be instantiated for both normal and incognito profiles. For normal profiles,
// it uses an AutocompleteActionPredictorTable accessed asynchronously on the DB
// thread to permanently store the data used to make predictions, and keeps
// local caches of that data to be able to make predictions synchronously on the
// UI thread where it lives. For incognito profiles, there is no table; the
// local caches are copied from the main profile at creation and from there on
// are the only thing used.
//
// This class can be accessed as a weak pointer so that it can safely use
// PostTaskAndReply without fear of crashes if it is destroyed before the reply
// triggers. This is necessary during initialization.
class AutocompleteActionPredictor
: public KeyedService,
public content::NotificationObserver,
public history::HistoryServiceObserver,
public base::SupportsWeakPtr<AutocompleteActionPredictor> {
public:
enum Action {
ACTION_PRERENDER = 0,
ACTION_PRECONNECT,
ACTION_NONE,
LAST_PREDICT_ACTION = ACTION_NONE
};
explicit AutocompleteActionPredictor(Profile* profile);
~AutocompleteActionPredictor() override;
// Registers an AutocompleteResult for a given |user_text|. This will be used
// when the user navigates from the Omnibox to determine early opportunities
// to predict their actions.
void RegisterTransitionalMatches(const base::string16& user_text,
const AutocompleteResult& result);
// Clears any transitional matches that have been registered. Called when, for
// example, the OmniboxEditModel is reverted.
void ClearTransitionalMatches();
// Return the recommended action given |user_text|, the text the user has
// entered in the Omnibox, and |match|, the suggestion from Autocomplete.
// This method uses information from the ShortcutsBackend including how much
// of the matching entry the user typed, and how long it's been since the user
// visited the matching URL, to calculate a score between 0 and 1. This score
// is then mapped to an Action.
Action RecommendAction(const base::string16& user_text,
const AutocompleteMatch& match) const;
// Begin prerendering |url| with |session_storage_namespace|. The |size| gives
// the initial size for the target prerender. The predictor will run at most
// one prerender at a time, so launching a prerender will cancel our previous
// prerenders (if any).
void StartPrerendering(
const GURL& url,
content::SessionStorageNamespace* session_storage_namespace,
const gfx::Size& size);
// Cancels the current prerender, unless it has already been abandoned.
void CancelPrerender();
// Return true if the suggestion type warrants a TCP/IP preconnection.
// i.e., it is now quite likely that the user will select the related domain.
static bool IsPreconnectable(const AutocompleteMatch& match);
// Returns true if there is an active Omnibox prerender and it has been
// abandoned.
bool IsPrerenderAbandonedForTesting();
private:
friend class AutocompleteActionPredictorTest;
friend class ::PredictorsHandler;
struct TransitionalMatch {
TransitionalMatch();
~TransitionalMatch();
base::string16 user_text;
std::vector<GURL> urls;
bool operator==(const base::string16& other_user_text) const {
return user_text == other_user_text;
}
};
struct DBCacheKey {
base::string16 user_text;
GURL url;
bool operator<(const DBCacheKey& rhs) const {
return (user_text != rhs.user_text) ?
(user_text < rhs.user_text) : (url < rhs.url);
}
bool operator==(const DBCacheKey& rhs) const {
return (user_text == rhs.user_text) && (url == rhs.url);
}
};
struct DBCacheValue {
int number_of_hits;
int number_of_misses;
};
typedef std::map<DBCacheKey, DBCacheValue> DBCacheMap;
typedef std::map<DBCacheKey, AutocompleteActionPredictorTable::Row::Id>
DBIdCacheMap;
static const int kMaximumDaysToKeepEntry;
// NotificationObserver
void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) override;
// The first step in initializing the predictor is accessing the database and
// building the local cache. This should be delayed until after critical DB
// and IO processes have completed.
void CreateLocalCachesFromDatabase();
// Removes all rows from the database and caches.
void DeleteAllRows();
// Removes rows from the database and caches that contain a URL in |rows|.
void DeleteRowsWithURLs(const history::URLRows& rows);
// Called when NOTIFICATION_OMNIBOX_OPENED_URL is observed.
void OnOmniboxOpenedUrl(const OmniboxLog& log);
// Adds and updates rows in the database and caches.
void AddAndUpdateRows(
const AutocompleteActionPredictorTable::Rows& rows_to_add,
const AutocompleteActionPredictorTable::Rows& rows_to_update);
// Called to populate the local caches. This also calls DeleteOldEntries
// if the history service is available, or registers for the notification of
// it becoming available.
void CreateCaches(
std::vector<AutocompleteActionPredictorTable::Row>* row_buffer);
// Attempts to call DeleteOldEntries if the in-memory database has been loaded
// by |service|. Returns success as a boolean.
bool TryDeleteOldEntries(HistoryService* service);
// Called to delete any old or invalid entries from the database. Called after
// the local caches are created once the history service is available.
void DeleteOldEntries(history::URLDatabase* url_db);
// Deletes any old or invalid entries from the local caches. |url_db| and
// |id_list| must not be NULL. Every row id deleted will be added to id_list.
void DeleteOldIdsFromCaches(
history::URLDatabase* url_db,
std::vector<AutocompleteActionPredictorTable::Row::Id>* id_list);
// Called on an incognito-owned predictor to copy the current caches from the
// main profile.
void CopyFromMainProfile();
// Registers for notifications and sets the |initialized_| flag.
void FinishInitialization();
// Uses local caches to calculate an exact percentage prediction that the user
// will take a particular match given what they have typed. |is_in_db| is set
// to differentiate trivial zero results resulting from a match not being
// found from actual zero results where the calculation returns 0.0.
double CalculateConfidence(const base::string16& user_text,
const AutocompleteMatch& match,
bool* is_in_db) const;
// Calculates the confidence for an entry in the DBCacheMap.
double CalculateConfidenceForDbEntry(DBCacheMap::const_iterator iter) const;
// KeyedService:
void Shutdown() override;
// history::HistoryServiceObserver:
void OnHistoryServiceLoaded(HistoryService* history_service) override;
Profile* profile_;
// Set when this is a predictor for an incognito profile.
AutocompleteActionPredictor* main_profile_predictor_;
// Set when this is a predictor for a non-incognito profile, and the incognito
// profile creates a predictor. If this is non-NULL when we finish
// initialization, we should call CopyFromMainProfile() on it.
AutocompleteActionPredictor* incognito_predictor_;
// The backing data store. This is NULL for incognito-owned predictors.
scoped_refptr<AutocompleteActionPredictorTable> table_;
content::NotificationRegistrar notification_registrar_;
// This is cleared after every Omnibox navigation.
std::vector<TransitionalMatch> transitional_matches_;
scoped_ptr<prerender::PrerenderHandle> prerender_handle_;
// This allows us to predict the effect of confidence threshold changes on
// accuracy. This is cleared after every omnibox navigation.
mutable std::vector<std::pair<GURL, double> > tracked_urls_;
// Local caches of the data store. For incognito-owned predictors this is the
// only copy of the data.
DBCacheMap db_cache_;
DBIdCacheMap db_id_cache_;
bool initialized_;
ScopedObserver<HistoryService, HistoryServiceObserver>
history_service_observer_;
DISALLOW_COPY_AND_ASSIGN(AutocompleteActionPredictor);
};
} // namespace predictors
#endif // CHROME_BROWSER_PREDICTORS_AUTOCOMPLETE_ACTION_PREDICTOR_H_
|