| Index: chrome/browser/search_engines/template_url.cc
|
| diff --git a/chrome/browser/search_engines/template_url.cc b/chrome/browser/search_engines/template_url.cc
|
| index 1612f5a408da560bf1d264b4a67941daae9efa9f..0a0a73196fa6a52b6d18c98c0d0aca8b809af8b9 100644
|
| --- a/chrome/browser/search_engines/template_url.cc
|
| +++ b/chrome/browser/search_engines/template_url.cc
|
| @@ -123,11 +123,27 @@ TemplateURLRef::SearchTermsArgs::SearchTermsArgs(const string16& search_terms)
|
| TemplateURLRef::TemplateURLRef(TemplateURL* owner, Type type)
|
| : owner_(owner),
|
| type_(type),
|
| + index_in_owner_(-1),
|
| parsed_(false),
|
| valid_(false),
|
| supports_replacements_(false),
|
| + search_term_key_location_(url_parse::Parsed::QUERY),
|
| prepopulated_(false) {
|
| DCHECK(owner_);
|
| + DCHECK(type_ != INDEXED);
|
| +}
|
| +
|
| +TemplateURLRef::TemplateURLRef(TemplateURL* owner, size_t index_in_owner)
|
| + : owner_(owner),
|
| + type_(INDEXED),
|
| + index_in_owner_(index_in_owner),
|
| + parsed_(false),
|
| + valid_(false),
|
| + supports_replacements_(false),
|
| + search_term_key_location_(url_parse::Parsed::QUERY),
|
| + prepopulated_(false) {
|
| + DCHECK(owner_);
|
| + DCHECK(index_in_owner_ >= 0L && index_in_owner_ < owner_->URLCount());
|
| }
|
|
|
| TemplateURLRef::~TemplateURLRef() {
|
| @@ -138,6 +154,7 @@ std::string TemplateURLRef::GetURL() const {
|
| case SEARCH: return owner_->url();
|
| case SUGGEST: return owner_->suggestions_url();
|
| case INSTANT: return owner_->instant_url();
|
| + case INDEXED: return owner_->GetURL(index_in_owner_);
|
| default: NOTREACHED(); return std::string(); // NOLINT
|
| }
|
| }
|
| @@ -404,6 +421,66 @@ bool TemplateURLRef::HasGoogleBaseURLs() const {
|
| return false;
|
| }
|
|
|
| +
|
| +bool TemplateURLRef::ExtractSearchTermsFromURL(
|
| + const GURL& url, string16* search_terms) const {
|
| + DCHECK(search_terms);
|
| + search_terms->clear();
|
| +
|
| + ParseIfNecessary();
|
| +
|
| + // We need a search term in the template URL to extract something.
|
| + if (search_term_key_.empty())
|
| + return false;
|
| +
|
| + // TODO(beaudoin): Support {Anything} parameter to act as a path wildcard.
|
| + // See crbug/139176
|
| +
|
| + // Fill-in the replacements. We don't care about search terms in the pattern,
|
| + // so we use the empty string.
|
| + GURL pattern(ReplaceSearchTerms(SearchTermsArgs(string16())));
|
| + // Scheme, host, path and port must match.
|
| + if (!url.SchemeIs(pattern.scheme().c_str()) ||
|
| + url.port() != pattern.port() ||
|
| + url.host() != host_ ||
|
| + url.path() != path_) {
|
| + return false;
|
| + }
|
| +
|
| + // Parameter must be present either in the query or the ref.
|
| + std::string params;
|
| + switch (search_term_key_location_) {
|
| + case url_parse::Parsed::QUERY:
|
| + params = url.query();
|
| + break;
|
| + case url_parse::Parsed::REF:
|
| + params = url.ref();
|
| + break;
|
| + default:
|
| + NOTREACHED();
|
| + return false;
|
| + }
|
| +
|
| + url_parse::Component query, key, value;
|
| + query.len = static_cast<int>(params.size());
|
| + while (url_parse::ExtractQueryKeyValue(params.c_str(), &query, &key,
|
| + &value)) {
|
| + if (key.is_nonempty()) {
|
| + if (params.substr(key.begin, key.len) == search_term_key_) {
|
| + // Extract the search term.
|
| + *search_terms = net::UnescapeAndDecodeUTF8URLComponent(
|
| + params.substr(value.begin, value.len),
|
| + net::UnescapeRule::SPACES |
|
| + net::UnescapeRule::URL_SPECIAL_CHARS |
|
| + net::UnescapeRule::REPLACE_PLUS_WITH_SPACE,
|
| + NULL);
|
| + return true;
|
| + }
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| void TemplateURLRef::InvalidateCachedValues() const {
|
| supports_replacements_ = valid_ = parsed_ = false;
|
| host_.clear();
|
| @@ -556,27 +633,44 @@ void TemplateURLRef::ParseHostAndSearchTermKey(
|
| kGoogleBaseSuggestURLParameterFull,
|
| search_terms_data.GoogleBaseSuggestURLValue());
|
|
|
| + search_term_key_.clear();
|
| + host_.clear();
|
| + path_.clear();
|
| + search_term_key_location_ = url_parse::Parsed::REF;
|
| +
|
| GURL url(url_string);
|
| if (!url.is_valid())
|
| return;
|
|
|
| - std::string query_string = url.query();
|
| - if (query_string.empty())
|
| - return;
|
| + // We want to prioritize search terms in the ref rather than ones in the
|
| + // query.
|
| + if (!url.ref().empty())
|
| + FindSearchTermsKey(url.ref());
|
| +
|
| + // If not found in ref string, look for them in query.
|
| + if (search_term_key_.empty() && !url.query().empty()) {
|
| + search_term_key_location_ = url_parse::Parsed::QUERY;
|
| + FindSearchTermsKey(url.query());
|
| + }
|
|
|
| + if (!search_term_key_.empty()) {
|
| + host_ = url.host();
|
| + path_ = url.path();
|
| + }
|
| +}
|
| +
|
| +void TemplateURLRef::FindSearchTermsKey(const std::string& params) const {
|
| url_parse::Component query, key, value;
|
| - query.len = static_cast<int>(query_string.size());
|
| - while (url_parse::ExtractQueryKeyValue(query_string.c_str(), &query, &key,
|
| + query.len = static_cast<int>(params.size());
|
| + while (url_parse::ExtractQueryKeyValue(params.c_str(), &query, &key,
|
| &value)) {
|
| if (key.is_nonempty() && value.is_nonempty()) {
|
| - std::string value_string = query_string.substr(value.begin, value.len);
|
| + std::string value_string = params.substr(value.begin, value.len);
|
| if (value_string.find(kSearchTermsParameterFull, 0) !=
|
| std::string::npos ||
|
| value_string.find(kGoogleUnescapedSearchTermsParameterFull, 0) !=
|
| std::string::npos) {
|
| - search_term_key_ = query_string.substr(key.begin, key.len);
|
| - host_ = url.host();
|
| - path_ = url.path();
|
| + search_term_key_ = params.substr(key.begin, key.len);
|
| break;
|
| }
|
| }
|
| @@ -616,7 +710,6 @@ void TemplateURLData::SetURL(const std::string& url) {
|
| url_ = url;
|
| }
|
|
|
| -
|
| // TemplateURL ----------------------------------------------------------------
|
|
|
| TemplateURL::TemplateURL(Profile* profile, const TemplateURLData& data)
|
| @@ -690,6 +783,61 @@ bool TemplateURL::IsExtensionKeyword() const {
|
| return GURL(data_.url()).SchemeIs(chrome::kExtensionScheme);
|
| }
|
|
|
| +size_t TemplateURL::URLCount() const {
|
| + DCHECK(!url().empty());
|
| + // Add 1 for the regular search URL.
|
| + return data_.alternate_urls.size() + 1;
|
| +}
|
| +
|
| +const std::string& TemplateURL::GetURL(size_t index) const {
|
| + DCHECK(!url().empty());
|
| + DCHECK(index >= 0 && index < URLCount());
|
| +
|
| + if (index < data_.alternate_urls.size())
|
| + return data_.alternate_urls[index];
|
| + return url();
|
| +}
|
| +
|
| +bool TemplateURL::ExtractSearchTermsFromInstantExtendedURL(
|
| + const GURL& url, string16* search_terms) {
|
| + DCHECK(search_terms);
|
| + search_terms->clear();
|
| +
|
| + // Ensure this is an instant extended URL.
|
| + std::string params = url.query();
|
| + url_parse::Component query, key, value;
|
| + query.len = static_cast<int>(params.size());
|
| + bool is_instant_extended = false;
|
| + while (url_parse::ExtractQueryKeyValue(params.c_str(), &query, &key,
|
| + &value)) {
|
| + if (!params.compare(key.begin, key.len,
|
| + google_util::kInstantExtendedAPIParam)) {
|
| + // If the parameter key is |kInstantExtendedAPIParam| and the value is
|
| + // not 0 this is an Instant Extended API search URL.
|
| + int int_value = 0;
|
| + if (value.is_nonempty())
|
| + base::StringToInt(params.substr(value.begin, value.len), &int_value);
|
| + if (int_value == 0)
|
| + return false;
|
| + is_instant_extended = true;
|
| + break;
|
| + }
|
| + }
|
| + if (!is_instant_extended)
|
| + return false;
|
| +
|
| + // Then try to match with every pattern.
|
| + for (size_t i = 0; i < URLCount(); ++i) {
|
| + TemplateURLRef ref(this, i);
|
| + if (ref.ExtractSearchTermsFromURL(url, search_terms)) {
|
| + // Never accept an empty string as a valid result, but exit early if
|
| + // one is found. This ensures 'http://google.com/?q=foo#q=' fails.
|
| + return !search_terms->empty();
|
| + }
|
| + }
|
| + return false;
|
| +}
|
| +
|
| void TemplateURL::CopyFrom(const TemplateURL& other) {
|
| if (this == &other)
|
| return;
|
|
|