summaryrefslogtreecommitdiffstats
path: root/chrome/browser/autocomplete/autocomplete.h
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser/autocomplete/autocomplete.h')
-rw-r--r--chrome/browser/autocomplete/autocomplete.h800
1 files changed, 800 insertions, 0 deletions
diff --git a/chrome/browser/autocomplete/autocomplete.h b/chrome/browser/autocomplete/autocomplete.h
new file mode 100644
index 0000000..cdcc0d1
--- /dev/null
+++ b/chrome/browser/autocomplete/autocomplete.h
@@ -0,0 +1,800 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_H__
+#define CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_H__
+
+#include <map>
+#include <string>
+#include <vector>
+#include "base/logging.h"
+#include "base/ref_counted.h"
+#include "chrome/common/page_transition_types.h"
+#include "googleurl/src/url_parse.h"
+
+// The AutocompleteController is the center of the autocomplete system. A
+// class implementing AutocompleteController::Listener creates an instance of
+// the controller, which in turn creates a set of AutocompleteProviders to
+// serve it. The listener can ask the controller to Start() a query; the
+// controller in turn passes this call down to the providers, each of which
+// keeps track of its own results and whether it has finished processing the
+// query. When a provider gets more results or finishes processing, it
+// notifies the controller, which merges the combined results together and
+// returns them to the listener.
+//
+// The listener may also cancel the current query by calling Stop(), which the
+// controller will in turn communicate to all the providers. No callbacks will
+// happen after a request has been stopped.
+//
+// IMPORTANT: There is NO THREAD SAFETY built into this portion of the
+// autocomplete system. All calls to and from the AutocompleteController should
+// happen on the same thread. AutocompleteProviders are responsible for doing
+// their own thread management when they need to return results asynchronously.
+//
+// The AutocompleteProviders each return one kind of results, such as history
+// results or search results. These results are given "relevance" scores.
+// Historically the relevance for each column added up to 100, then scores
+// were from 1-100. Both have proved a bit painful, and will be changed going
+// forward. The important part is that higher relevance scores are more
+// important than lower relevance scores. The relevance scores and class
+// providing the result are as follows:
+//
+// UNKNOWN input type:
+// --------------------------------------------------------------------|-----
+// Keyword (non-substituting, exact match) | 1500
+// HistoryURL (exact or inline autocomplete match) | 1400
+// Search (what you typed) | 1300
+// HistoryURL (what you typed) | 1200
+// Keyword (substituting, exact match) | 1100
+// Search (past query in history) | 1050--
+// HistoryContents (any match in title of starred page) | 1000++
+// HistoryURL (inexact match) | 900++
+// Search (navigational suggestion) | 800++
+// HistoryContents (any match in title of nonstarred page) | 700++
+// Search (suggestion) | 600++
+// HistoryContents (any match in body of starred page) | 550++
+// HistoryContents (any match in body of nonstarred page) | 500++
+// Keyword (inexact match) | 450
+//
+// REQUESTED_URL input type:
+// --------------------------------------------------------------------|-----
+// Keyword (non-substituting, exact match) | 1500
+// HistoryURL (exact or inline autocomplete match) | 1400
+// HistoryURL (what you typed) | 1300
+// Search (what you typed) | 1200
+// Keyword (substituting, exact match) | 1100
+// Search (past query in history) | 1050--
+// HistoryContents (any match in title of starred page) | 1000++
+// HistoryURL (inexact match) | 900++
+// Search (navigational suggestion) | 800++
+// HistoryContents (any match in title of nonstarred page) | 700++
+// Search (suggestion) | 600++
+// HistoryContents (any match in body of starred page) | 550++
+// HistoryContents (any match in body of nonstarred page) | 500++
+// Keyword (inexact match) | 450
+//
+// URL input type:
+// --------------------------------------------------------------------|-----
+// Keyword (non-substituting, exact match) | 1500
+// HistoryURL (exact or inline autocomplete match) | 1400
+// HistoryURL (what you typed) | 1200
+// Keyword (substituting, exact match) | 1100
+// HistoryURL (inexact match) | 900++
+// Search (what you typed) | 850
+// Search (navigational suggestion) | 800++
+// Search (past query in history) | 750--
+// Keyword (inexact match) | 700
+// Search (suggestion) | 300++
+//
+// QUERY input type:
+// --------------------------------------------------------------------|-----
+// Keyword (non-substituting, exact match) | 1500
+// Keyword (substituting, exact match) | 1400
+// Search (what you typed) | 1300
+// Search (past query in history) | 1250--
+// HistoryContents (any match in title of starred page) | 1200++
+// Search (navigational suggestion) | 1000++
+// HistoryContents (any match in title of nonstarred page) | 900++
+// Search (suggestion) | 800++
+// HistoryContents (any match in body of starred page) | 750++
+// HistoryContents (any match in body of nonstarred page) | 700++
+// Keyword (inexact match) | 650
+//
+// FORCED_QUERY input type:
+// --------------------------------------------------------------------|-----
+// Search (what you typed) | 1500
+// Search (past query in history) | 1250--
+// HistoryContents (any match in title of starred page) | 1200++
+// Search (navigational suggestion) | 1000++
+// HistoryContents (any match in title of nonstarred page) | 900++
+// Search (suggestion) | 800++
+// HistoryContents (any match in body of starred page) | 750++
+// HistoryContents (any match in body of nonstarred page) | 700++
+//
+// (A search keyword is a keyword with a replacement string; a bookmark keyword
+// is a keyword with no replacement string, that is, a shortcut for a URL.)
+//
+// The value column gives the ranking returned from the various providers.
+// ++: a series of results with relevance from n up to (n + max_matches).
+// --: relevance score falls off over time (discounted 50 points @ 15 minutes,
+// 450 points @ two weeks)
+
+class AutocompleteInput;
+struct AutocompleteMatch;
+class AutocompleteProvider;
+class AutocompleteResult;
+class AutocompleteController;
+class GURL;
+class HistoryContentsProvider;
+class KeywordProvider;
+class Profile;
+class TemplateURL;
+
+typedef std::vector<AutocompleteMatch> ACMatches;
+typedef std::vector<AutocompleteProvider*> ACProviders;
+
+// AutocompleteInput ----------------------------------------------------------
+
+// The user input for an autocomplete query. Allows copying.
+class AutocompleteInput {
+ public:
+ enum Type {
+ INVALID, // Empty input
+ UNKNOWN, // Valid input whose type cannot be determined
+ REQUESTED_URL, // Input autodetected as UNKNOWN, which the user wants to
+ // treat as an URL by specifying a desired_tld
+ URL, // Input autodetected as a URL
+ QUERY, // Input autodetected as a query
+ FORCED_QUERY, // Input forced to be a query by an initial '?'
+ };
+
+ AutocompleteInput() : type_(INVALID), prevent_inline_autocomplete_(false) {}
+ AutocompleteInput(const std::wstring& text,
+ const std::wstring& desired_tld,
+ bool prevent_inline_autocomplete);
+
+ // Parses |text| and returns the type of input this will be interpreted as.
+ // The components of the input are stored in the output parameter |parts|.
+ static Type Parse(const std::wstring& text,
+ const std::wstring& desired_tld,
+ url_parse::Parsed* parts,
+ std::wstring* scheme);
+
+ // User-provided text to be completed.
+ const std::wstring& text() const { return text_; }
+
+ // Use of this setter is risky, since no other internal state is updated
+ // besides |text_|. Only callers who know that they're not changing the
+ // type/scheme/etc. should use this.
+ void set_text(const std::wstring& text) { text_ = text; }
+
+ // The type of input supplied.
+ Type type() const { return type_; }
+
+ // The scheme parsed from the provided text; only meaningful when type_ is
+ // URL.
+ const std::wstring& scheme() const { return scheme_; }
+
+ // User's desired TLD, if one is not already present in the text to
+ // autocomplete. When this is non-empty, it also implies that "www." should
+ // be prepended to the domain where possible. This should not have a leading
+ // '.' (use "com" instead of ".com").
+ const std::wstring& desired_tld() const { return desired_tld_; }
+
+ // Returns whether inline autocompletion should be prevented.
+ const bool prevent_inline_autocomplete() const {
+ return prevent_inline_autocomplete_;
+ }
+
+ // operator==() by another name.
+ bool Equals(const AutocompleteInput& other) const;
+
+ // Resets all internal variables to the null-constructed state.
+ void Clear();
+
+ private:
+ std::wstring text_;
+ Type type_;
+ std::wstring scheme_;
+ std::wstring desired_tld_;
+ bool prevent_inline_autocomplete_;
+};
+
+// AutocompleteMatch ----------------------------------------------------------
+
+// A single result line with classified spans. The autocomplete popup displays
+// the 'contents' and the 'description' (the description is optional) in the
+// autocomplete dropdown, and fills in 'fill_into_edit' into the textbox when
+// that line is selected. fill_into_edit may be the same as 'description' for
+// things like URLs, but may be different for searches or other providers. For
+// example, a search result may say "Search for asdf" as the description, but
+// "asdf" should appear in the box.
+struct AutocompleteMatch {
+ // Autocomple results return strings that are classified according to a
+ // separate vector of styles. This vector must be sorted, and associates
+ // flags with portions of the strings. It is required that all text be
+ // inside a classification range. Even if you have no classification, you
+ // should create an entry at offset 0 with no flags.
+ //
+ // Example: The user typed "goog"
+ // http://www.google.com/ Google
+ // ^ ^ ^ ^ ^
+ // 0, | 15, | 4,
+ // 11,match 0,match
+ //
+ // This structure holds the classifiction information for each span.
+ struct ACMatchClassification {
+ // The values in here are not mutually exclusive -- use them like a
+ // bitfield. This also means we use "int" instead of this enum type when
+ // passing the values around, so the compiler doesn't complain.
+ enum Style {
+ NONE = 0,
+ URL = 1 << 0, // A URL
+ MATCH = 1 << 1, // A match for the user's search term
+ DIM = 1 << 2, // "Helper text"
+ };
+
+ ACMatchClassification(size_t offset, int style)
+ : offset(offset),
+ style(style) {
+ }
+
+ // Offset within the string that this classification starts
+ size_t offset;
+
+ int style;
+ };
+
+ typedef std::vector<ACMatchClassification> ACMatchClassifications;
+
+ // The type of this match.
+ // URL: a url, typically one the user previously entered but it may have
+ // also been suggested. This is the default.
+ // KEYWORD: a keyword.
+ // SEARCH: short cut for typing type into the Google homepage. This should
+ // only be used if the full URL is not shown.
+ enum Type {
+ // Something that looks like a URL ("http://foo.com", "internal-server/").
+ // This is the default.
+ URL,
+
+ // A manually created or auto-generated keyword, with or without a query
+ // component. Auto-generated keywords may look similar to urls. See
+ // keyword_autocomplete.cc.
+ KEYWORD,
+
+ // A search term or phrase for the user's default search provider
+ // ("games", "foo"). These visually look similar to keywords. See
+ // google_autocomplete.cc.
+ SEARCH,
+
+ // Shortcut that takes the user to destinations->history.
+ HISTORY_SEARCH
+ };
+
+ AutocompleteMatch();
+ AutocompleteMatch(AutocompleteProvider* provider,
+ int relevance,
+ bool deletable);
+
+ // Comparison function for determining when one match is better than another.
+ static bool MoreRelevant(const AutocompleteMatch& elem1,
+ const AutocompleteMatch& elem2);
+
+ // Comparison functions for removing matches with duplicate destinations.
+ static bool DestinationSortFunc(const AutocompleteMatch& elem1,
+ const AutocompleteMatch& elem2);
+ static bool DestinationsEqual(const AutocompleteMatch& elem1,
+ const AutocompleteMatch& elem2);
+
+ // Helper functions for classes creating matches:
+ // Fills in the classifications for |text|, using |style| as the base style
+ // and marking the first instance of |find_text| as a match. (This match
+ // will also not be dimmed, if |style| has DIM set.)
+ static void ClassifyMatchInString(const std::wstring& find_text,
+ const std::wstring& text,
+ int style,
+ ACMatchClassifications* classifications);
+
+ // Similar to ClassifyMatchInString(), but for cases where the range to mark
+ // as matching is already known (avoids calling find()). This can be helpful
+ // when find() would be misleading (e.g. you want to mark the second match in
+ // a string instead of the first).
+ static void ClassifyLocationInString(size_t match_location,
+ size_t match_length,
+ size_t overall_length,
+ int style,
+ ACMatchClassifications* classifications);
+
+ // The provider of this match, used to remember which provider the user had
+ // selected when the input changes. This may be NULL, in which case there is
+ // no provider (or memory of the user's selection).
+ AutocompleteProvider* provider;
+
+ // The relevance of this match. See table above for scores returned by
+ // various providers. This is used to rank matches among all responding
+ // providers, so different providers must be carefully tuned to supply
+ // matches with appropriate relevance.
+ //
+ // If the relevance is negative, it will only be displayed if there are not
+ // enough non-negative items in all the providers to max out the popup. In
+ // this case, the relevance of the additional items will be inverted so they
+ // can be mixed in with the rest of the relevances. This allows a provider
+ // to group its results, having the added items appear intermixed with its
+ // other results.
+ //
+ // TODO(pkasting): http://b/1111299 This should be calculated algorithmically,
+ // rather than being a fairly fixed value defined by the table above.
+ int relevance;
+
+ // True if the user should be able to delete this match.
+ bool deletable;
+
+ // This string is loaded into the location bar when the item is selected
+ // by pressing the arrow keys. This may be different than a URL, for example,
+ // for search suggestions, this would just be the search terms.
+ std::wstring fill_into_edit;
+
+ // The position within fill_into_edit from which we'll display the inline
+ // autocomplete string. This will be std::wstring::npos if this match should
+ // not be inline autocompleted.
+ size_t inline_autocomplete_offset;
+
+ // The URL to actually load when the autocomplete item is selected. This URL
+ // should be canonical so we can compare URLs with strcmp to avoid dupes.
+ // It may be empty if there is no possible navigation.
+ std::wstring destination_url;
+
+ // The text displayed on the left in the search results
+ std::wstring contents;
+ ACMatchClassifications contents_class;
+
+ // Displayed to the right of the result as the title or other helper info
+ std::wstring description;
+ ACMatchClassifications description_class;
+
+ // The transition type to use when the user opens this match. By default
+ // this is TYPED. Providers whose matches do not look like URLs should set
+ // it to GENERATED.
+ PageTransition::Type transition;
+
+ // True when this match is the "what you typed" match from the history
+ // system.
+ bool is_history_what_you_typed_match;
+
+ // Type of this match.
+ Type type;
+
+ // If this match corresponds to a keyword, this is the TemplateURL the
+ // keyword was obtained from.
+ const TemplateURL* template_url;
+
+ // True if the user has starred the destination URL.
+ bool starred;
+
+#ifndef NDEBUG
+ // Does a data integrity check on this match.
+ void Validate() const;
+
+ // Checks one text/classifications pair for valid values.
+ void ValidateClassifications(
+ const std::wstring& text,
+ const ACMatchClassifications& classifications) const;
+#endif
+};
+
+typedef AutocompleteMatch::ACMatchClassification ACMatchClassification;
+typedef std::vector<ACMatchClassification> ACMatchClassifications;
+
+// AutocompleteProvider -------------------------------------------------------
+
+// A single result provider for the autocomplete system. Given user input, the
+// provider decides what (if any) matches to return, their relevance, and their
+// classifications.
+class AutocompleteProvider
+ : public base::RefCountedThreadSafe<AutocompleteProvider> {
+ public:
+ class ACProviderListener {
+ public:
+ // Called by a provider as a notification that something has changed.
+ // |updated_matches| should be true iff the matches have changed in some
+ // way (they may not have changed if, for example, the provider did an
+ // asynchronous query to get more results, came up with none, and is now
+ // giving up).
+ //
+ // NOTE: Providers MUST only call this method while processing asynchronous
+ // queries. Do not call this for a synchronous query.
+ //
+ // NOTE: There's no parameter to tell the listener _which_ provider is
+ // calling it. Because the AutocompleteController (the typical listener)
+ // doesn't cache the providers' individual results locally, it has to get
+ // them all again when this is called anyway, so such a parameter wouldn't
+ // actually be useful.
+ virtual void OnProviderUpdate(bool updated_matches) = 0;
+ };
+
+ AutocompleteProvider(ACProviderListener* listener,
+ Profile* profile,
+ char* name)
+ : listener_(listener),
+ profile_(profile),
+ done_(true),
+ name_(name) {
+ }
+
+ virtual ~AutocompleteProvider();
+
+ // Invoked when the profile changes.
+ void SetProfile(Profile* profile);
+
+ // Called to start an autocomplete query. The provider is responsible for
+ // tracking its results for this query and whether it is done processing the
+ // query. When new results are available or the provider finishes, it
+ // calls the controller's OnProviderUpdate() method. The controller can then
+ // get the new results using the provider's accessors.
+ // Exception: Results available immediately after starting the query (that
+ // is, synchronously) do not cause any notifications to be sent. The
+ // controller is expected to check for these without prompting (since
+ // otherwise, starting each provider running would result in a flurry of
+ // notifications).
+ //
+ // Once Stop() has been called, no more notifications should be sent.
+ //
+ // |minimal_changes| is an optimization that lets the provider do less work
+ // when the |input|'s text hasn't changed. See the body of
+ // AutocompletePopup::StartAutocomplete().
+ //
+ // If |synchronous_only| is true, no asynchronous work should be scheduled;
+ // the provider should stop after it has returned all the
+ // synchronously-available results. This also means any in-progress
+ // asynchronous work should be canceled, so the provider does not call back at
+ // a later time.
+ virtual void Start(const AutocompleteInput& input,
+ bool minimal_changes,
+ bool synchronous_only) = 0;
+
+ // Called when a provider must not make any more callbacks for the current
+ // query.
+ virtual void Stop() {
+ done_ = true;
+ }
+
+ // Returns the set of matches for the current query.
+ const ACMatches& matches() const { return matches_; }
+
+ // Returns whether the provider is done processing the query.
+ bool done() const { return done_; }
+
+ // Returns the name of this provider.
+ const char* name() const { return name_; }
+
+ // Called to delete a match and the backing data that produced it. This
+ // match should not appear again in this or future queries. This can only be
+ // called for matches the provider marks as deletable.
+ // NOTE: Remember to call OnProviderUpdate() if matches_ is updated.
+ virtual void DeleteMatch(const AutocompleteMatch& match) {}
+
+ static void set_max_matches(size_t max_matches) {
+ max_matches_ = max_matches;
+ }
+
+ static size_t max_matches() { return max_matches_; }
+
+ protected:
+ // The profile associated with the AutocompleteProvider. Reference is not
+ // owned by us.
+ Profile* profile_;
+
+ ACProviderListener* listener_;
+ ACMatches matches_;
+ bool done_;
+
+ // The name of this provider. Used for logging.
+ const char* name_;
+
+ // A convenience function to call gfx::ElideUrl() with the current set of
+ // "Accept Languages" when check_accept_lang is true. Otherwise, it's called
+ // with an empty list.
+ std::wstring StringForURLDisplay(const GURL& url, bool check_accept_lang);
+
+ private:
+ // A suggested upper bound for how many matches a provider should return.
+ // TODO(pkasting): http://b/1111299 , http://b/933133 This should go away once
+ // we have good relevance heuristics; the controller should handle all
+ // culling.
+ static size_t max_matches_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(AutocompleteProvider);
+};
+
+typedef AutocompleteProvider::ACProviderListener ACProviderListener;
+
+// AutocompleteResult ---------------------------------------------------------
+
+// All matches from all providers for a particular query. This also tracks
+// what the default match should be if the user doesn't manually select another
+// match.
+class AutocompleteResult {
+ public:
+ typedef ACMatches::const_iterator const_iterator;
+ typedef ACMatches::iterator iterator;
+
+ // The "Selection" struct is the information we need to select the same match
+ // in one result set that was selected in another.
+ struct Selection {
+ Selection()
+ : provider_affinity(NULL),
+ is_history_what_you_typed_match(false) {
+ }
+
+ // Clear the selection entirely.
+ void Clear();
+
+ // True when the selection is empty.
+ bool empty() const {
+ return destination_url.empty() && !provider_affinity &&
+ !is_history_what_you_typed_match;
+ }
+
+ // The desired destination URL.
+ std::wstring destination_url;
+
+ // The desired provider. If we can't find a match with the specified
+ // |destination_url|, we'll use the best match from this provider.
+ const AutocompleteProvider* provider_affinity;
+
+ // True when this is the HistoryURLProvider's "what you typed" match. This
+ // can't be tracked using |destination_url| because its URL changes on every
+ // keystroke, so if this is set, we'll preserve the selection by simply
+ // choosing the new "what you typed" entry and ignoring |destination_url|.
+ bool is_history_what_you_typed_match;
+ };
+
+ static void set_max_matches(size_t max_matches) {
+ max_matches_ = max_matches;
+ }
+ static size_t max_matches() { return max_matches_; }
+
+ AutocompleteResult();
+
+ // operator=() by another name.
+ void CopyFrom(const AutocompleteResult& rhs);
+
+ // Adds a single match. The match is inserted at the appropriate position
+ // based on relevancy and display order. This is ONLY for use after
+ // SortAndCull has been invoked.
+ void AddMatch(const AutocompleteMatch& match);
+
+ // Adds a new set of matches to the set of results.
+ void AppendMatches(const ACMatches& matches);
+
+ // Removes duplicates, puts the list in sorted order and culls to leave only
+ // the best kMaxMatches results.
+ void SortAndCull();
+
+ // Vector-style accessors/operators.
+ size_t size() const { return matches_.size(); }
+ bool empty() const { return matches_.empty(); }
+ const_iterator begin() const { return matches_.begin(); }
+ iterator begin() { return matches_.begin(); }
+ const_iterator end() const { return matches_.end(); }
+ iterator end() { return matches_.end(); }
+
+ // Returns the match at the given index.
+ const AutocompleteMatch& match_at(size_t index) const {
+ DCHECK(index < matches_.size());
+ return matches_[index];
+ }
+
+ // Get the default match for the query (not necessarily the first). Returns
+ // end() if there is no default match.
+ const_iterator default_match() const { return default_match_; }
+
+ // Sets the default match to the best result. When a particular URL is
+ // desired, we return that if available; otherwise, if a provider affinity is
+ // specified, we pick the most relevant match from that provider; otherwise,
+ // we return the best match overall.
+ // Returns true if the selection specified an exact match and we were able to
+ // find and use it.
+ bool SetDefaultMatch(const Selection& selection);
+
+ // Given some input and a particular match in this result set, returns the
+ // "alternate navigation URL", if any, for that match. This is a URL to try
+ // offering as a navigational option in case the user didn't actually mean to
+ // navigate to the URL of |match|. For example, if the user's local intranet
+ // contains site "foo", and the user types "foo", we default to searching for
+ // "foo" when the user may have meant to navigate there. In cases like this,
+ // |match| will point to the "search for 'foo'" result, and this function will
+ // return "http://foo/".
+ std::wstring GetAlternateNavURL(const AutocompleteInput& input,
+ const_iterator match) const;
+
+ // Releases the resources associated with this object. Some callers may
+ // want to perform several searches without creating new results each time.
+ // They can call this function to re-use the result for another query.
+ void Reset() {
+ matches_.clear();
+ default_match_ = end();
+ }
+
+#ifndef NDEBUG
+ // Does a data integrity check on this result.
+ void Validate() const;
+#endif
+
+ private:
+ // Max number of matches we'll show from the various providers. We may end
+ // up showing an additional shortcut for Destinations->History, see
+ // AddHistoryContentsShortcut.
+ static size_t max_matches_;
+ ACMatches matches_;
+ const_iterator default_match_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(AutocompleteResult);
+};
+
+// AutocompleteController -----------------------------------------------------
+
+// The coordinator for autocomplete queries, responsible for combining the
+// results from a series of providers into one AutocompleteResult and
+// interacting with the Listener that owns it.
+class AutocompleteController : public ACProviderListener {
+ public:
+ class ACControllerListener {
+ public:
+ // Called by the controller when new results are available and/or the query
+ // is complete. The listener can then call GetResult() and provide an
+ // AutocompleteResult* to be filled in.
+ //
+ // Note that this function is never called for synchronous_only queries
+ // (see Start()). If you're only using those, you can create the controller
+ // with a NULL listener.
+ virtual void OnAutocompleteUpdate(bool updated_result,
+ bool query_complete) = 0;
+ };
+
+ // Used to indicate an index that is not selected in a call to Update()
+ // and for merging results.
+ static const int kNoItemSelected;
+
+ // Normally, you will call the first constructor. Unit tests can use the
+ // second to set the providers to some known testing providers. The default
+ // providers will be overridden and the controller will take ownership of the
+ // providers, Release()ing them on destruction.
+ //
+ // It is safe to pass NULL for |listener| iff you only ever use synchronous
+ // queries.
+ AutocompleteController(ACControllerListener* listener, Profile* profile);
+#ifdef UNIT_TEST
+ AutocompleteController(ACControllerListener* listener,
+ const ACProviders& providers)
+ : listener_(listener),
+ providers_(providers),
+ keyword_provider_(NULL),
+ history_contents_provider_(NULL) {
+ }
+#endif
+ ~AutocompleteController();
+
+ // Invoked when the profile changes. This forwards the call down to all
+ // the AutocompleteProviders.
+ void SetProfile(Profile* profile);
+
+ // Starts an autocomplete query, which continues until all providers are
+ // done or the query is Stop()ed. It is safe to Start() a new query without
+ // Stop()ing the previous one.
+ //
+ // If |minimal_changes| is true, |input| is the same as in the previous
+ // query, except for a different desired_tld_ and possibly type_. Most
+ // providers should just be able to recalculate priorities in this case and
+ // return synchronously, or at least faster than otherwise.
+ //
+ // If |synchronous_only| is true, the controller asks the providers to only
+ // return results which are synchronously available, which should mean that
+ // all providers will be done immediately.
+ //
+ // The controller does not notify the listener about any results available
+ // immediately; the caller should call GetResult() manually if it wants
+ // these. The return value is whether the query is complete; if it is
+ // false, then the controller will call OnAutocompleteUpdate() with future
+ // result updates (unless the query is Stop()ed).
+ bool Start(const AutocompleteInput& input,
+ bool minimal_changes,
+ bool synchronous_only);
+
+ // Cancels the current query, ensuring there will be no future callbacks to
+ // OnAutocompleteUpdate() (until Start() is called again).
+ void Stop() const;
+
+ // Called by the listener to get the current results of the query.
+ void GetResult(AutocompleteResult* result);
+
+ // From AutocompleteProvider::Listener
+ virtual void OnProviderUpdate(bool updated_matches);
+
+ KeywordProvider* keyword_provider() const { return keyword_provider_; }
+
+ private:
+ // Returns true if all providers have finished processing the query.
+ bool QueryComplete() const;
+
+ // Returns the number of matches from provider whose destination urls are
+ // not in result. first_match is set to the first match whose destination url
+ // is NOT in result.
+ size_t CountMatchesNotInResult(const AutocompleteProvider* provider,
+ const AutocompleteResult* result,
+ AutocompleteMatch* first_match);
+
+ // If the HistoryContentsAutocomplete provider is done and there are more
+ // matches in the database than currently shown, an entry is added to
+ // result to show all history matches.
+ void AddHistoryContentsShortcut(AutocompleteResult* result);
+
+ ACControllerListener* listener_; // May be NULL.
+
+ // A list of all providers.
+ ACProviders providers_;
+
+ KeywordProvider* keyword_provider_;
+
+ HistoryContentsProvider* history_contents_provider_;
+
+ // Input passed to Start.
+ AutocompleteInput input_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(AutocompleteController);
+};
+
+typedef AutocompleteController::ACControllerListener ACControllerListener;
+
+// AutocompleteLog ------------------------------------------------------------
+
+// The data to log (via the metrics service) when the user selects an item
+// from the omnibox popup.
+struct AutocompleteLog {
+ AutocompleteLog(std::wstring text,
+ size_t selected_index,
+ size_t inline_autocompleted_length,
+ const AutocompleteResult& result)
+ : text(text),
+ selected_index(selected_index),
+ inline_autocompleted_length(inline_autocompleted_length),
+ result(result) {
+ }
+ // The user's input text in the omnibox.
+ std::wstring text;
+ // Selected index (if selected) or -1 (AutocompletePopup::kNoMatch).
+ size_t selected_index;
+ // Inline autocompleted length (if displayed).
+ size_t inline_autocompleted_length;
+ // Result set.
+ const AutocompleteResult& result;
+};
+
+#endif // CHROME_BROWSER_AUTOCOMPLETE_AUTOCOMPLETE_H__