summaryrefslogtreecommitdiffstats
path: root/chrome/browser/autocomplete/network_action_predictor.h
blob: 0cf02a4d8b70079e71c90bedb14fc85c94b91a80 (plain)
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
// 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_AUTOCOMPLETE_NETWORK_ACTION_PREDICTOR_H_
#define CHROME_BROWSER_AUTOCOMPLETE_NETWORK_ACTION_PREDICTOR_H_
#pragma once

#include <map>

#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/string16.h"
#include "chrome/browser/autocomplete/network_action_predictor_database.h"
#include "chrome/browser/history/history_types.h"
#include "chrome/browser/profiles/profile_keyed_service.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "googleurl/src/gurl.h"

struct AutocompleteLog;
struct AutocompleteMatch;
class AutocompleteResult;
class HistoryService;
class Profile;

namespace history {
class URLDatabase;
}

// This class is responsible for determining the correct predictive network
// action to take given for a given AutocompleteMatch and entered text. it uses
// a NetworkActionPredictorDatabase 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. It 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 NetworkActionPredictor
    : public ProfileKeyedService,
      public content::NotificationObserver,
      public base::SupportsWeakPtr<NetworkActionPredictor> {
 public:
  enum Action {
    ACTION_PRERENDER = 0,
    ACTION_PRECONNECT,
    ACTION_NONE,
    LAST_PREDICT_ACTION = ACTION_NONE
  };

  explicit NetworkActionPredictor(Profile* profile);
  virtual ~NetworkActionPredictor();

  static void set_hit_weight(double weight) { hit_weight_ = weight; }
  static double get_hit_weight() { return hit_weight_; }

  // 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 string16& user_text,
                                   const AutocompleteResult& result);

  // Clears any transitional matches that have been registered. Called when, for
  // example, the AutocompleteEditModel 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 string16& user_text,
                         const AutocompleteMatch& match) const;

  // 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);

 private:
  friend class NetworkActionPredictorTest;
  friend class NetworkActionPredictorDOMHandler;

  struct TransitionalMatch {
    TransitionalMatch();
    ~TransitionalMatch();

    string16 user_text;
    std::vector<GURL> urls;

    bool operator==(const string16& other_user_text) const {
      return user_text == other_user_text;
    }
  };

  struct DBCacheKey {
    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, NetworkActionPredictorDatabase::Row::Id>
      DBIdCacheMap;

  static const int kMaximumDaysToKeepEntry;

  // Multiplying factor applied to the |number_of_hits| for a database entry
  // when calculating the confidence. It is currently set by a field trial so is
  // static. Once the field trial ends, this will be a constant value.
  static double hit_weight_;

  // ProfileKeyedService
  virtual void Shutdown() OVERRIDE;

  // NotificationObserver
  virtual void Observe(int type,
                       const content::NotificationSource& source,
                       const content::NotificationDetails& details) OVERRIDE;

  // Called when NOTIFICATION_OMNIBOX_OPENED_URL is observed.
  void OnOmniboxOpenedUrl(const AutocompleteLog& log);

  // 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<NetworkActionPredictorDatabase::Row::Id>* id_list);

  // 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);

  // 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<NetworkActionPredictorDatabase::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);

  // 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 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;

  // Adds a row to the database and caches.
  void AddRow(const DBCacheKey& key,
              const NetworkActionPredictorDatabase::Row& row);

  // Updates a row in the database and the caches.
  void UpdateRow(DBCacheMap::iterator it,
                 const NetworkActionPredictorDatabase::Row& row);

  // 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);

  // Used to batch operations on the database.
  void BeginTransaction();
  void CommitTransaction();

  Profile* profile_;
  scoped_refptr<NetworkActionPredictorDatabase> db_;
  content::NotificationRegistrar notification_registrar_;

  // This is cleared after every Omnibox navigation.
  std::vector<TransitionalMatch> transitional_matches_;

  // This allows us to predict the effect of confidence threshold changes on
  // accuracy.
  mutable std::vector<std::pair<GURL, double> > tracked_urls_;

  DBCacheMap db_cache_;
  DBIdCacheMap db_id_cache_;

  bool initialized_;

  DISALLOW_COPY_AND_ASSIGN(NetworkActionPredictor);
};

#endif  // CHROME_BROWSER_AUTOCOMPLETE_NETWORK_ACTION_PREDICTOR_H_