• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CHROME_BROWSER_AUTOCOMPLETE_HISTORY_URL_PROVIDER_H_
6 #define CHROME_BROWSER_AUTOCOMPLETE_HISTORY_URL_PROVIDER_H_
7 #pragma once
8 
9 #include <string>
10 
11 #include "base/compiler_specific.h"
12 #include "chrome/browser/autocomplete/history_provider.h"
13 #include "chrome/browser/autocomplete/history_provider_util.h"
14 
15 class MessageLoop;
16 class Profile;
17 
18 namespace history {
19 
20 class HistoryBackend;
21 class URLDatabase;
22 class URLRow;
23 
24 }  // namespace history
25 
26 // How history autocomplete works
27 // ==============================
28 //
29 // Read down this diagram for temporal ordering.
30 //
31 //   Main thread                History thread
32 //   -----------                --------------
33 //   AutocompleteController::Start
34 //     -> HistoryURLProvider::Start
35 //       -> RunAutocompletePasses
36 //         -> SuggestExactInput
37 //         [params_ allocated]
38 //         -> DoAutocomplete (for inline autocomplete)
39 //           -> URLDatabase::AutocompleteForPrefix (on in-memory DB)
40 //         -> HistoryService::ScheduleAutocomplete
41 //         (return to controller) ----
42 //                                   /
43 //                              HistoryBackend::ScheduleAutocomplete
44 //                                -> HistoryURLProvider::ExecuteWithDB
45 //                                  -> DoAutocomplete
46 //                                    -> URLDatabase::AutocompleteForPrefix
47 //                                /
48 //   HistoryService::QueryComplete
49 //     [params_ destroyed]
50 //     -> AutocompleteProvider::Listener::OnProviderUpdate
51 //
52 // The autocomplete controller calls us, and must be called back, on the main
53 // thread.  When called, we run two autocomplete passes.  The first pass runs
54 // synchronously on the main thread and queries the in-memory URL database.
55 // This pass promotes matches for inline autocomplete if applicable.  We do
56 // this synchronously so that users get consistent behavior when they type
57 // quickly and hit enter, no matter how loaded the main history database is.
58 // Doing this synchronously also prevents inline autocomplete from being
59 // "flickery" in the AutocompleteEdit.  Because the in-memory DB does not have
60 // redirect data, results other than the top match might change between the
61 // two passes, so we can't just decide to use this pass' matches as the final
62 // results.
63 //
64 // The second autocomplete pass uses the full history database, which must be
65 // queried on the history thread.  Start() asks the history service schedule to
66 // callback on the history thread with a pointer to the main database.  When we
67 // are done doing queries, we schedule a task on the main thread that notifies
68 // the AutocompleteController that we're done.
69 //
70 // The communication between these threads is done using a
71 // HistoryURLProviderParams object.  This is allocated in the main thread, and
72 // normally deleted in QueryComplete().  So that both autocomplete passes can
73 // use the same code, we also use this to hold results during the first
74 // autocomplete pass.
75 //
76 // While the second pass is running, the AutocompleteController may cancel the
77 // request.  This can happen frequently when the user is typing quickly.  In
78 // this case, the main thread sets params_->cancel, which the background thread
79 // checks periodically.  If it finds the flag set, it stops what it's doing
80 // immediately and calls back to the main thread.  (We don't delete the params
81 // on the history thread, because we should only do that when we can safely
82 // NULL out params_, and that must be done on the main thread.)
83 
84 // Used to communicate autocomplete parameters between threads via the history
85 // service.
86 struct HistoryURLProviderParams {
87   HistoryURLProviderParams(const AutocompleteInput& input,
88                            bool trim_http,
89                            const std::string& languages);
90   ~HistoryURLProviderParams();
91 
92   MessageLoop* message_loop;
93 
94   // A copy of the autocomplete input. We need the copy since this object will
95   // live beyond the original query while it runs on the history thread.
96   AutocompleteInput input;
97 
98   // Set when "http://" should be trimmed from the beginning of the URLs.
99   bool trim_http;
100 
101   // Set by the main thread to cancel this request. READ ONLY when running in
102   // ExecuteWithDB() on the history thread to prevent deadlock. If this flag is
103   // set when the query runs, the query will be abandoned. This allows us to
104   // avoid running queries that are no longer needed. Since we don't care if
105   // we run the extra queries, the lack of signaling is not a problem.
106   bool cancel;
107 
108   // Set by ExecuteWithDB() on the history thread when the query could not be
109   // performed because the history system failed to properly init the database.
110   // If this is set when the main thread is called back, it avoids changing
111   // |matches_| at all, so it won't delete the default match
112   // RunAutocompletePasses() creates.
113   bool failed;
114 
115   // List of matches written by the history thread.  We keep this separate list
116   // to avoid having the main thread read the provider's matches while the
117   // history thread is manipulating them.  The provider copies this list back
118   // to matches_ on the main thread in QueryComplete().
119   ACMatches matches;
120 
121   // Languages we should pass to gfx::GetCleanStringFromUrl.
122   std::string languages;
123 
124   // When true, we should avoid calling SuggestExactInput().
125   bool dont_suggest_exact_input;
126 
127  private:
128   DISALLOW_COPY_AND_ASSIGN(HistoryURLProviderParams);
129 };
130 
131 // This class is an autocomplete provider and is also a pseudo-internal
132 // component of the history system.  See comments above.
133 //
134 // Note: This object can get leaked on shutdown if there are pending
135 // requests on the database (which hold a reference to us). Normally, these
136 // messages get flushed for each thread. We do a round trip from main, to
137 // history, back to main while holding a reference. If the main thread
138 // completes before the history thread, the message to delegate back to the
139 // main thread will not run and the reference will leak. Therefore, don't do
140 // anything on destruction.
141 class HistoryURLProvider : public HistoryProvider {
142  public:
143   HistoryURLProvider(ACProviderListener* listener, Profile* profile);
144 
145 #ifdef UNIT_TEST
HistoryURLProvider(ACProviderListener * listener,Profile * profile,const std::string & languages)146   HistoryURLProvider(ACProviderListener* listener,
147                      Profile* profile,
148                      const std::string& languages)
149     : HistoryProvider(listener, profile, "History"),
150       prefixes_(GetPrefixes()),
151       params_(NULL),
152       languages_(languages) {}
153 #endif
154   // no destructor (see note above)
155 
156   // AutocompleteProvider
157   virtual void Start(const AutocompleteInput& input,
158                      bool minimal_changes) OVERRIDE;
159   virtual void Stop() OVERRIDE;
160 
161   // Runs the history query on the history thread, called by the history
162   // system. The history database MAY BE NULL in which case it is not
163   // available and we should return no data. Also schedules returning the
164   // results to the main thread
165   void ExecuteWithDB(history::HistoryBackend* backend,
166                      history::URLDatabase* db,
167                      HistoryURLProviderParams* params);
168 
169   // Actually runs the autocomplete job on the given database, which is
170   // guaranteed not to be NULL.
171   void DoAutocomplete(history::HistoryBackend* backend,
172                       history::URLDatabase* db,
173                       HistoryURLProviderParams* params);
174 
175   // Dispatches the results to the autocomplete controller. Called on the
176   // main thread by ExecuteWithDB when the results are available.
177   // Frees params_gets_deleted on exit.
178   void QueryComplete(HistoryURLProviderParams* params_gets_deleted);
179 
180  private:
181   ~HistoryURLProvider();
182 
183   // Returns the set of prefixes to use for prefixes_.
184   static history::Prefixes GetPrefixes();
185 
186   // Determines the relevance for some input, given its type and which match it
187   // is.  If |match_type| is NORMAL, |match_number| is a number
188   // [0, kMaxSuggestions) indicating the relevance of the match (higher == more
189   // relevant).  For other values of |match_type|, |match_number| is ignored.
190   static int CalculateRelevance(AutocompleteInput::Type input_type,
191                                 MatchType match_type,
192                                 size_t match_number);
193 
194   // Given the user's |input| and a |match| created from it, reduce the
195   // match's URL to just a host.  If this host still matches the user input,
196   // return it.  Returns the empty string on failure.
197   static GURL ConvertToHostOnly(const history::HistoryMatch& match,
198                                 const string16& input);
199 
200   // See if a shorter version of the best match should be created, and if so
201   // place it at the front of |matches|.  This can suggest history URLs that
202   // are prefixes of the best match (if they've been visited enough, compared
203   // to the best match), or create host-only suggestions even when they haven't
204   // been visited before: if the user visited http://example.com/asdf once,
205   // we'll suggest http://example.com/ even if they've never been to it.  See
206   // the function body for the exact heuristics used.
207   static void PromoteOrCreateShorterSuggestion(
208       history::URLDatabase* db,
209       const HistoryURLProviderParams& params,
210       bool have_what_you_typed_match,
211       const AutocompleteMatch& what_you_typed_match,
212       history::HistoryMatches* matches);
213 
214   // Ensures that |matches| contains an entry for |info|, which may mean adding
215   // a new such entry (using |input_location| and |match_in_scheme|).
216   //
217   // If |promote| is true, this also ensures the entry is the first element in
218   // |matches|, moving or adding it to the front as appropriate.  When
219   // |promote| is false, existing matches are left in place, and newly added
220   // matches are placed at the back.
221   static void EnsureMatchPresent(const history::URLRow& info,
222                                  string16::size_type input_location,
223                                  bool match_in_scheme,
224                                  history::HistoryMatches* matches,
225                                  bool promote);
226 
227   // Helper function that actually launches the two autocomplete passes.
228   void RunAutocompletePasses(const AutocompleteInput& input,
229                              bool fixup_input_and_run_pass_1);
230 
231   // Returns the best prefix that begins |text|.  "Best" means "greatest number
232   // of components".  This may return NULL if no prefix begins |text|.
233   //
234   // |prefix_suffix| (which may be empty) is appended to every attempted
235   // prefix.  This is useful when you need to figure out the innermost match
236   // for some user input in a URL.
237   const history::Prefix* BestPrefix(const GURL& text,
238                                     const string16& prefix_suffix) const;
239 
240   // Returns a match corresponding to exactly what the user has typed.
241   AutocompleteMatch SuggestExactInput(const AutocompleteInput& input,
242                                       bool trim_http);
243 
244   // Given a |match| containing the "what you typed" suggestion created by
245   // SuggestExactInput(), looks up its info in the DB.  If found, fills in the
246   // title from the DB, promotes the match's priority to that of an inline
247   // autocomplete match (maybe it should be slightly better?), and places it on
248   // the front of |matches| (so we pick the right matches to throw away
249   // when culling redirects to/from it).  Returns whether a match was promoted.
250   bool FixupExactSuggestion(history::URLDatabase* db,
251                             const AutocompleteInput& input,
252                             AutocompleteMatch* match,
253                             history::HistoryMatches* matches) const;
254 
255   // Determines if |match| is suitable for inline autocomplete, and promotes it
256   // if so.
257   bool PromoteMatchForInlineAutocomplete(HistoryURLProviderParams* params,
258                                          const history::HistoryMatch& match);
259 
260   // Sorts the given list of matches.
261   void SortMatches(history::HistoryMatches* matches) const;
262 
263   // Removes results that have been rarely typed or visited, and not any time
264   // recently.  The exact parameters for this heuristic can be found in the
265   // function body.
266   void CullPoorMatches(history::HistoryMatches* matches) const;
267 
268   // Removes results that redirect to each other, leaving at most |max_results|
269   // results.
270   void CullRedirects(history::HistoryBackend* backend,
271                      history::HistoryMatches* matches,
272                      size_t max_results) const;
273 
274   // Helper function for CullRedirects, this removes all but the first
275   // occurance of [any of the set of strings in |remove|] from the |matches|
276   // list.
277   //
278   // The return value is the index of the item that is after the item in the
279   // input identified by |source_index|. If |source_index| or an item before
280   // is removed, the next item will be shifted, and this allows the caller to
281   // pick up on the next one when this happens.
282   size_t RemoveSubsequentMatchesOf(history::HistoryMatches* matches,
283                                    size_t source_index,
284                                    const std::vector<GURL>& remove) const;
285 
286   // Converts a line from the database into an autocomplete match for display.
287   AutocompleteMatch HistoryMatchToACMatch(
288       HistoryURLProviderParams* params,
289       const history::HistoryMatch& history_match,
290       MatchType match_type,
291       size_t match_number);
292 
293   // Prefixes to try appending to user input when looking for a match.
294   const history::Prefixes prefixes_;
295 
296   // Params for the current query.  The provider should not free this directly;
297   // instead, it is passed as a parameter through the history backend, and the
298   // parameter itself is freed once it's no longer needed.  The only reason we
299   // keep this member is so we can set the cancel bit on it.
300   HistoryURLProviderParams* params_;
301 
302   // Only used by unittests; if non-empty, overrides accept-languages in the
303   // profile's pref system.
304   std::string languages_;
305 };
306 
307 #endif  // CHROME_BROWSER_AUTOCOMPLETE_HISTORY_URL_PROVIDER_H_
308