Home | History | Annotate | Download | only in autocomplete
      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
    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