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