// Copyright (c) 2011 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_SEARCH_ENGINES_TEMPLATE_URL_H_ #define CHROME_BROWSER_SEARCH_ENGINES_TEMPLATE_URL_H_ #pragma once #include <string> #include <vector> #include "base/gtest_prod_util.h" #include "base/time.h" #include "chrome/browser/search_engines/search_engine_type.h" #include "chrome/browser/search_engines/template_url_id.h" #include "googleurl/src/gurl.h" class PrefService; class SearchTermsData; class TemplateURL; class WebDataService; struct WDKeywordsResult; // TemplateURL represents the relevant portions of the Open Search Description // Document (http://www.opensearch.org/Specifications/OpenSearch). // The main use case for TemplateURL is to use the TemplateURLRef returned by // suggestions_url or url for keyword/suggestion expansion: // . suggestions_url describes a URL that is ideal for as you type suggestions. // The returned results are in the mime type application/x-suggestions+json. // . url describes a URL that may be used as a shortcut. Returned results are // are text/html. // Before using either one, make sure it's non-NULL, and if you intend to use // it to replace search terms, make sure SupportsReplacement returns true. // To use either URL invoke the ReplaceSearchTerms method on the corresponding // TemplateURLRef. // // For files parsed from the Web, be sure and invoke IsValid. IsValid returns // true if the URL could be parsed. // // Both TemplateURL and TemplateURLRef have value semantics. This allows the // UI to create a copy while the user modifies the values. class TemplateURLRef { public: // Magic numbers to pass to ReplaceSearchTerms() for the |accepted_suggestion| // parameter. Most callers aren't using Suggest capabilities and should just // pass NO_SUGGESTIONS_AVAILABLE. // NOTE: Because positive values are meaningful, make sure these are negative! enum AcceptedSuggestion { NO_SUGGESTION_CHOSEN = -1, NO_SUGGESTIONS_AVAILABLE = -2, }; TemplateURLRef(); TemplateURLRef(const std::string& url, int index_offset, int page_offset); ~TemplateURLRef(); // Returns true if this URL supports replacement. bool SupportsReplacement() const; // Like SupportsReplacement but usable on threads other than the UI thread. bool SupportsReplacementUsingTermsData( const SearchTermsData& search_terms_data) const; // Returns a string that is the result of replacing the search terms in // the url with the specified value. // // If this TemplateURLRef does not support replacement (SupportsReplacement // returns false), an empty string is returned. // // The TemplateURL is used to determine the input encoding for the term. std::string ReplaceSearchTerms( const TemplateURL& host, const string16& terms, int accepted_suggestion, const string16& original_query_for_suggestion) const; // Just like ReplaceSearchTerms except that it takes SearchTermsData to supply // the data for some search terms. Most of the time ReplaceSearchTerms should // be called. std::string ReplaceSearchTermsUsingTermsData( const TemplateURL& host, const string16& terms, int accepted_suggestion, const string16& original_query_for_suggestion, const SearchTermsData& search_terms_data) const; // Returns the raw URL. None of the parameters will have been replaced. const std::string& url() const { return url_; } // Returns the index number of the first search result. int index_offset() const { return index_offset_; } // Returns the page number of the first search results. int page_offset() const { return page_offset_; } // Returns true if the TemplateURLRef is valid. An invalid TemplateURLRef is // one that contains unknown terms, or invalid characters. bool IsValid() const; // Like IsValid but usable on threads other than the UI thread. bool IsValidUsingTermsData(const SearchTermsData& search_terms_data) const; // Returns a string representation of this TemplateURLRef suitable for // display. The display format is the same as the format used by Firefox. string16 DisplayURL() const; // Converts a string as returned by DisplayURL back into a string as // understood by TemplateURLRef. static std::string DisplayURLToURLRef(const string16& display_url); // If this TemplateURLRef is valid and contains one search term, this returns // the host/path of the URL, otherwise this returns an empty string. const std::string& GetHost() const; const std::string& GetPath() const; // If this TemplateURLRef is valid and contains one search term, this returns // the key of the search term, otherwise this returns an empty string. const std::string& GetSearchTermKey() const; // Converts the specified term in the encoding of the host TemplateURL to a // string16. string16 SearchTermToString16(const TemplateURL& host, const std::string& term) const; // Returns true if this TemplateURLRef has a replacement term of // {google:baseURL} or {google:baseSuggestURL}. bool HasGoogleBaseURLs() const; // Returns true if both refs are NULL or have the same values. static bool SameUrlRefs(const TemplateURLRef* ref1, const TemplateURLRef* ref2); // Collects metrics whether searches through Google are sent with RLZ string. void CollectRLZMetrics() const; private: friend class SearchHostToURLsMapTest; friend class TemplateURL; friend class TemplateURLModelTestUtil; friend class TemplateURLTest; FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseParameterKnown); FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseParameterUnknown); FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLEmpty); FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLNoTemplateEnd); FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLNoKnownParameters); FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLTwoParameters); FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, ParseURLNestedParameter); // Enumeration of the known types. enum ReplacementType { ENCODING, GOOGLE_ACCEPTED_SUGGESTION, GOOGLE_BASE_URL, GOOGLE_BASE_SUGGEST_URL, GOOGLE_ORIGINAL_QUERY_FOR_SUGGESTION, GOOGLE_RLZ, GOOGLE_UNESCAPED_SEARCH_TERMS, LANGUAGE, SEARCH_TERMS, }; // Used to identify an element of the raw url that can be replaced. struct Replacement { Replacement(ReplacementType type, size_t index) : type(type), index(index) {} ReplacementType type; size_t index; }; // The list of elements to replace. typedef std::vector<struct Replacement> Replacements; // TemplateURLRef internally caches values to make replacement quick. This // method invalidates any cached values. void InvalidateCachedValues() const; // Resets the url. void Set(const std::string& url, int index_offset, int page_offset); // Parses the parameter in url at the specified offset. start/end specify the // range of the parameter in the url, including the braces. If the parameter // is valid, url is updated to reflect the appropriate parameter. If // the parameter is one of the known parameters an element is added to // replacements indicating the type and range of the element. The original // parameter is erased from the url. // // If the parameter is not a known parameter, it's not erased and false is // returned. bool ParseParameter(size_t start, size_t end, std::string* url, Replacements* replacements) const; // Parses the specified url, replacing parameters as necessary. If // successful, valid is set to true, and the parsed url is returned. For all // known parameters that are encountered an entry is added to replacements. // If there is an error parsing the url, valid is set to false, and an empty // string is returned. std::string ParseURL(const std::string& url, Replacements* replacements, bool* valid) const; // If the url has not yet been parsed, ParseURL is invoked. // NOTE: While this is const, it modifies parsed_, valid_, parsed_url_ and // search_offset_. void ParseIfNecessary() const; // Like ParseIfNecessary but usable on threads other than the UI thread. void ParseIfNecessaryUsingTermsData( const SearchTermsData& search_terms_data) const; // Extracts the query key and host from the url. void ParseHostAndSearchTermKey( const SearchTermsData& search_terms_data) const; // Used by tests to set the value for the Google base url. This takes // ownership of the given std::string. static void SetGoogleBaseURL(std::string* google_base_url); // The raw URL. Where as this contains all the terms (such as {searchTerms}), // parsed_url_ has them all stripped out. std::string url_; // indexOffset defined for the Url element. int index_offset_; // searchOffset defined for the Url element. int page_offset_; // Whether the URL has been parsed. mutable bool parsed_; // Whether the url was successfully parsed. mutable bool valid_; // The parsed URL. All terms have been stripped out of this with // replacements_ giving the index of the terms to replace. mutable std::string parsed_url_; // Do we support replacement? mutable bool supports_replacements_; // The replaceable parts of url (parsed_url_). These are ordered by index // into the string, and may be empty. mutable Replacements replacements_; // Host, path and key of the search term. These are only set if the url // contains one search term. mutable std::string host_; mutable std::string path_; mutable std::string search_term_key_; }; // Describes the relevant portions of a single OSD document. class TemplateURL { public: // Describes a single image reference. Each TemplateURL may have // any number (including 0) of ImageRefs. // // If a TemplateURL has no images, the favicon for the generated URL // should be used. struct ImageRef { ImageRef(const std::string& type, int width, int height) : type(type), width(width), height(height) { } ImageRef(const std::string& type, int width, int height, const GURL& url) : type(type), width(width), height(height), url(url) { } // Mime type for the image. // ICO image will have the format: image/x-icon or image/vnd.microsoft.icon std::string type; // Size of the image int width; int height; // URL of the image. GURL url; }; // Generates a favicon URL from the specified url. static GURL GenerateFaviconURL(const GURL& url); // Returns true if |turl| is non-null and has a search URL that supports // replacement. static bool SupportsReplacement(const TemplateURL* turl); // Like SupportsReplacement but usable on threads other than the UI thread. static bool SupportsReplacementUsingTermsData( const TemplateURL* turl, const SearchTermsData& search_terms_data); TemplateURL(); ~TemplateURL(); // A short description of the template. This is the name we show to the user // in various places that use keywords. For example, the location bar shows // this when the user selects the keyword. void set_short_name(const string16& short_name) { short_name_ = short_name; } string16 short_name() const { return short_name_; } // An accessor for the short_name, but adjusted so it can be appropriately // displayed even if it is LTR and the UI is RTL. string16 AdjustedShortNameForLocaleDirection() const; // A description of the template; this may be empty. void set_description(const string16& description) { description_ = description; } string16 description() const { return description_; } // URL providing JSON results. This is typically used to provide suggestions // as your type. If NULL, this url does not support suggestions. // Be sure and check the resulting TemplateURLRef for SupportsReplacement // before using. void SetSuggestionsURL(const std::string& suggestions_url, int index_offset, int page_offset); const TemplateURLRef* suggestions_url() const { return suggestions_url_.url().empty() ? NULL : &suggestions_url_; } // Parameterized URL for providing the results. This may be NULL. // Be sure and check the resulting TemplateURLRef for SupportsReplacement // before using. void SetURL(const std::string& url, int index_offset, int page_offset); // Returns the TemplateURLRef that may be used for search results. This // returns NULL if a url element was not specified. const TemplateURLRef* url() const { return url_.url().empty() ? NULL : &url_; } // Parameterized URL for instant results. This may be NULL. Be sure and check // the resulting TemplateURLRef for SupportsReplacement before using. See // TemplateURLRef for a description of |index_offset| and |page_offset|. void SetInstantURL(const std::string& url, int index_offset, int page_offset); // Returns the TemplateURLRef that may be used for search results. This // returns NULL if a url element was not specified. const TemplateURLRef* instant_url() const { return instant_url_.url().empty() ? NULL : &instant_url_; } // URL to the OSD file this came from. May be empty. void set_originating_url(const GURL& url) { originating_url_ = url; } const GURL& originating_url() const { return originating_url_; } // The shortcut for this template url. May be empty. void set_keyword(const string16& keyword); string16 keyword() const; // Whether to autogenerate a keyword from the url() in GetKeyword(). Most // consumers should not need this. // NOTE: Calling set_keyword() turns this back off. Manual and automatic // keywords are mutually exclusive. void set_autogenerate_keyword(bool autogenerate_keyword) { autogenerate_keyword_ = autogenerate_keyword; if (autogenerate_keyword_) { keyword_.clear(); keyword_generated_ = false; } } bool autogenerate_keyword() const { return autogenerate_keyword_; } // Ensures that the keyword is generated. Most consumers should not need this // because it is done automatically. Use this method on the UI thread, so // the keyword may be accessed on another thread. void EnsureKeyword() const; // Whether this keyword is shown in the default list of search providers. This // is just a property and does not indicate whether this TemplateURL has // a TemplateURLRef that supports replacement. Use ShowInDefaultList to // test both. // The default value is false. void set_show_in_default_list(bool show_in_default_list) { show_in_default_list_ = show_in_default_list; } bool show_in_default_list() const { return show_in_default_list_; } // Returns true if show_in_default_list() is true and this TemplateURL has a // TemplateURLRef that supports replacement. bool ShowInDefaultList() const; // Whether it's safe for auto-modification code (the autogenerator and the // code that imports data from other browsers) to replace the TemplateURL. // This should be set to false for any keyword the user edits, or any keyword // that the user clearly manually edited in the past, like a bookmark keyword // from another browser. void set_safe_for_autoreplace(bool safe_for_autoreplace) { safe_for_autoreplace_ = safe_for_autoreplace; } bool safe_for_autoreplace() const { return safe_for_autoreplace_; } // Images for this URL. May be empty. void add_image_ref(const ImageRef& ref) { image_refs_.push_back(ref); } const std::vector<ImageRef>& image_refs() const { return image_refs_; } // Convenience methods for getting/setting an ImageRef that points to a // favicon. A TemplateURL need not have an ImageRef for a favicon. In such // a situation GetFaviconURL returns an invalid url. // // If url is empty and there is an image ref for a favicon, it is removed. void SetFaviconURL(const GURL& url); GURL GetFaviconURL() const; // Set of languages supported. This may be empty. void add_language(const string16& language) { languages_.push_back(language); } std::vector<string16> languages() const { return languages_; } // Date this keyword was created. // // NOTE: this may be 0, which indicates the keyword was created before we // started tracking creation time. void set_date_created(base::Time time) { date_created_ = time; } base::Time date_created() const { return date_created_; } // True if this TemplateURL was automatically created by the administrator via // group policy. void set_created_by_policy(bool created_by_policy) { created_by_policy_ = created_by_policy; } bool created_by_policy() const { return created_by_policy_; } // Number of times this keyword has been explicitly used to load a URL. We // don't increment this for uses as the "default search engine" since that's // not really "explicit" usage and incrementing would result in pinning the // user's default search engine(s) to the top of the list of searches on the // New Tab page, de-emphasizing the omnibox as "where you go to search". void set_usage_count(int count) { usage_count_ = count; } int usage_count() const { return usage_count_; } // The list of supported encodings for the search terms. This may be empty, // which indicates the terms should be encoded with UTF-8. void set_input_encodings(const std::vector<std::string>& encodings) { input_encodings_ = encodings; } void add_input_encoding(const std::string& encoding) { input_encodings_.push_back(encoding); } const std::vector<std::string>& input_encodings() const { return input_encodings_; } void set_search_engine_type(SearchEngineType search_engine_type) { search_engine_type_ = search_engine_type; } SearchEngineType search_engine_type() const { return search_engine_type_; } void set_logo_id(int logo_id) { logo_id_ = logo_id; } int logo_id() const { return logo_id_; } // Returns the unique identifier of this TemplateURL. The unique ID is set // by the TemplateURLModel when the TemplateURL is added to it. TemplateURLID id() const { return id_; } // If this TemplateURL comes from prepopulated data the prepopulate_id is > 0. void set_prepopulate_id(int id) { prepopulate_id_ = id; } int prepopulate_id() const { return prepopulate_id_; } std::string GetExtensionId() const; bool IsExtensionKeyword() const; private: friend void MergeEnginesFromPrepopulateData( PrefService* prefs, WebDataService* service, std::vector<TemplateURL*>* template_urls, const TemplateURL** default_search_provider); friend class KeywordTable; friend class KeywordTableTest; friend class SearchHostToURLsMap; friend class TemplateURLModel; // Invalidates cached values on this object and its child TemplateURLRefs. void InvalidateCachedValues() const; // Unique identifier, used when archived to the database. void set_id(TemplateURLID id) { id_ = id; } string16 short_name_; string16 description_; TemplateURLRef suggestions_url_; TemplateURLRef url_; TemplateURLRef instant_url_; GURL originating_url_; mutable string16 keyword_; bool autogenerate_keyword_; // If this is set, |keyword_| holds the cached // generated keyword if available. mutable bool keyword_generated_; // True if the keyword was generated. This // is used to avoid multiple attempts if // generating a keyword failed. bool show_in_default_list_; bool safe_for_autoreplace_; std::vector<ImageRef> image_refs_; std::vector<string16> languages_; // List of supported input encodings. std::vector<std::string> input_encodings_; TemplateURLID id_; base::Time date_created_; bool created_by_policy_; int usage_count_; SearchEngineType search_engine_type_; int logo_id_; int prepopulate_id_; // TODO(sky): Add date last parsed OSD file. }; #endif // CHROME_BROWSER_SEARCH_ENGINES_TEMPLATE_URL_H_