OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/search_engines/template_url.h" | 5 #include "chrome/browser/search_engines/template_url.h" |
6 | 6 |
7 #include "base/guid.h" | 7 #include "base/guid.h" |
8 #include "base/i18n/case_conversion.h" | 8 #include "base/i18n/case_conversion.h" |
9 #include "base/i18n/icu_string_conversions.h" | 9 #include "base/i18n/icu_string_conversions.h" |
10 #include "base/i18n/rtl.h" | 10 #include "base/i18n/rtl.h" |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
116 : search_terms(search_terms), | 116 : search_terms(search_terms), |
117 accepted_suggestion(NO_SUGGESTIONS_AVAILABLE) { | 117 accepted_suggestion(NO_SUGGESTIONS_AVAILABLE) { |
118 } | 118 } |
119 | 119 |
120 | 120 |
121 // TemplateURLRef ------------------------------------------------------------- | 121 // TemplateURLRef ------------------------------------------------------------- |
122 | 122 |
123 TemplateURLRef::TemplateURLRef(TemplateURL* owner, Type type) | 123 TemplateURLRef::TemplateURLRef(TemplateURL* owner, Type type) |
124 : owner_(owner), | 124 : owner_(owner), |
125 type_(type), | 125 type_(type), |
126 index_in_owner_(-1), | |
126 parsed_(false), | 127 parsed_(false), |
127 valid_(false), | 128 valid_(false), |
128 supports_replacements_(false), | 129 supports_replacements_(false), |
130 search_term_key_location_(url_parse::Parsed::QUERY), | |
129 prepopulated_(false) { | 131 prepopulated_(false) { |
130 DCHECK(owner_); | 132 DCHECK(owner_); |
133 DCHECK_NE(INDEXED, type_); | |
134 } | |
135 | |
136 TemplateURLRef::TemplateURLRef(TemplateURL* owner, size_t index_in_owner) | |
137 : owner_(owner), | |
138 type_(INDEXED), | |
139 index_in_owner_(index_in_owner), | |
140 parsed_(false), | |
141 valid_(false), | |
142 supports_replacements_(false), | |
143 search_term_key_location_(url_parse::Parsed::QUERY), | |
144 prepopulated_(false) { | |
145 DCHECK(owner_); | |
146 DCHECK_LT(index_in_owner_, owner_->URLCount()); | |
131 } | 147 } |
132 | 148 |
133 TemplateURLRef::~TemplateURLRef() { | 149 TemplateURLRef::~TemplateURLRef() { |
134 } | 150 } |
135 | 151 |
136 std::string TemplateURLRef::GetURL() const { | 152 std::string TemplateURLRef::GetURL() const { |
137 switch (type_) { | 153 switch (type_) { |
138 case SEARCH: return owner_->url(); | 154 case SEARCH: return owner_->url(); |
139 case SUGGEST: return owner_->suggestions_url(); | 155 case SUGGEST: return owner_->suggestions_url(); |
140 case INSTANT: return owner_->instant_url(); | 156 case INSTANT: return owner_->instant_url(); |
157 case INDEXED: return owner_->GetURL(index_in_owner_); | |
141 default: NOTREACHED(); return std::string(); // NOLINT | 158 default: NOTREACHED(); return std::string(); // NOLINT |
142 } | 159 } |
143 } | 160 } |
144 | 161 |
145 bool TemplateURLRef::SupportsReplacement() const { | 162 bool TemplateURLRef::SupportsReplacement() const { |
146 UIThreadSearchTermsData search_terms_data(owner_->profile()); | 163 UIThreadSearchTermsData search_terms_data(owner_->profile()); |
147 return SupportsReplacementUsingTermsData(search_terms_data); | 164 return SupportsReplacementUsingTermsData(search_terms_data); |
148 } | 165 } |
149 | 166 |
150 bool TemplateURLRef::SupportsReplacementUsingTermsData( | 167 bool TemplateURLRef::SupportsReplacementUsingTermsData( |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
397 bool TemplateURLRef::HasGoogleBaseURLs() const { | 414 bool TemplateURLRef::HasGoogleBaseURLs() const { |
398 ParseIfNecessary(); | 415 ParseIfNecessary(); |
399 for (size_t i = 0; i < replacements_.size(); ++i) { | 416 for (size_t i = 0; i < replacements_.size(); ++i) { |
400 if ((replacements_[i].type == GOOGLE_BASE_URL) || | 417 if ((replacements_[i].type == GOOGLE_BASE_URL) || |
401 (replacements_[i].type == GOOGLE_BASE_SUGGEST_URL)) | 418 (replacements_[i].type == GOOGLE_BASE_SUGGEST_URL)) |
402 return true; | 419 return true; |
403 } | 420 } |
404 return false; | 421 return false; |
405 } | 422 } |
406 | 423 |
424 bool TemplateURLRef::ExtractSearchTermsFromURL(const GURL& url, | |
425 string16* search_terms) const { | |
426 DCHECK(search_terms); | |
427 search_terms->clear(); | |
428 | |
429 ParseIfNecessary(); | |
430 | |
431 // We need a search term in the template URL to extract something. | |
432 if (search_term_key_.empty()) | |
433 return false; | |
434 | |
435 // TODO(beaudoin): Support patterns of the form http://foo/{searchTerms}/ | |
436 // See crbug.com/153798 | |
437 | |
438 // Fill-in the replacements. We don't care about search terms in the pattern, | |
439 // so we use the empty string. | |
440 GURL pattern(ReplaceSearchTerms(SearchTermsArgs(string16()))); | |
441 // Scheme, host, path and port must match. | |
442 if (!url.SchemeIs(pattern.scheme().c_str()) || | |
443 url.port() != pattern.port() || | |
444 url.host() != host_ || | |
445 url.path() != path_) { | |
446 return false; | |
447 } | |
448 | |
449 // Parameter must be present either in the query or the ref. | |
450 const std::string& params( | |
451 (search_term_key_location_ == url_parse::Parsed::QUERY) ? | |
452 url.query() : url.ref()); | |
453 | |
454 url_parse::Component query, key, value; | |
455 query.len = static_cast<int>(params.size()); | |
456 while (url_parse::ExtractQueryKeyValue(params.c_str(), &query, &key, | |
457 &value)) { | |
458 if (key.is_nonempty()) { | |
459 if (params.substr(key.begin, key.len) == search_term_key_) { | |
460 // Extract the search term. | |
461 *search_terms = net::UnescapeAndDecodeUTF8URLComponent( | |
462 params.substr(value.begin, value.len), | |
463 net::UnescapeRule::SPACES | | |
464 net::UnescapeRule::URL_SPECIAL_CHARS | | |
465 net::UnescapeRule::REPLACE_PLUS_WITH_SPACE, | |
466 NULL); | |
467 return true; | |
468 } | |
469 } | |
470 } | |
471 return false; | |
472 } | |
473 | |
407 void TemplateURLRef::InvalidateCachedValues() const { | 474 void TemplateURLRef::InvalidateCachedValues() const { |
408 supports_replacements_ = valid_ = parsed_ = false; | 475 supports_replacements_ = valid_ = parsed_ = false; |
409 host_.clear(); | 476 host_.clear(); |
410 path_.clear(); | 477 path_.clear(); |
411 search_term_key_.clear(); | 478 search_term_key_.clear(); |
412 replacements_.clear(); | 479 replacements_.clear(); |
413 } | 480 } |
414 | 481 |
415 bool TemplateURLRef::ParseParameter(size_t start, | 482 bool TemplateURLRef::ParseParameter(size_t start, |
416 size_t end, | 483 size_t end, |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
549 void TemplateURLRef::ParseHostAndSearchTermKey( | 616 void TemplateURLRef::ParseHostAndSearchTermKey( |
550 const SearchTermsData& search_terms_data) const { | 617 const SearchTermsData& search_terms_data) const { |
551 std::string url_string(GetURL()); | 618 std::string url_string(GetURL()); |
552 ReplaceSubstringsAfterOffset(&url_string, 0, | 619 ReplaceSubstringsAfterOffset(&url_string, 0, |
553 kGoogleBaseURLParameterFull, | 620 kGoogleBaseURLParameterFull, |
554 search_terms_data.GoogleBaseURLValue()); | 621 search_terms_data.GoogleBaseURLValue()); |
555 ReplaceSubstringsAfterOffset(&url_string, 0, | 622 ReplaceSubstringsAfterOffset(&url_string, 0, |
556 kGoogleBaseSuggestURLParameterFull, | 623 kGoogleBaseSuggestURLParameterFull, |
557 search_terms_data.GoogleBaseSuggestURLValue()); | 624 search_terms_data.GoogleBaseSuggestURLValue()); |
558 | 625 |
626 search_term_key_.clear(); | |
627 host_.clear(); | |
628 path_.clear(); | |
629 search_term_key_location_ = url_parse::Parsed::REF; | |
630 | |
559 GURL url(url_string); | 631 GURL url(url_string); |
560 if (!url.is_valid()) | 632 if (!url.is_valid()) |
561 return; | 633 return; |
562 | 634 |
563 std::string query_string = url.query(); | 635 if (!url.ref().empty()) |
Peter Kasting
2012/10/04 19:32:43
Nit: This might be slightly clearer if we move the
beaudoin
2012/10/04 23:10:45
Much cleaner!
Moved FindSearchTermsKey to the ano
| |
564 if (query_string.empty()) | 636 FindSearchTermsKey(url.ref()); |
565 return; | |
566 | 637 |
638 // If not found in ref string, look for them in query. | |
639 if (search_term_key_.empty() && !url.query().empty()) { | |
640 search_term_key_location_ = url_parse::Parsed::QUERY; | |
641 FindSearchTermsKey(url.query()); | |
642 } | |
643 | |
644 if (!search_term_key_.empty()) { | |
645 host_ = url.host(); | |
646 path_ = url.path(); | |
647 } | |
648 } | |
649 | |
650 void TemplateURLRef::FindSearchTermsKey(const std::string& params) const { | |
567 url_parse::Component query, key, value; | 651 url_parse::Component query, key, value; |
568 query.len = static_cast<int>(query_string.size()); | 652 query.len = static_cast<int>(params.size()); |
569 while (url_parse::ExtractQueryKeyValue(query_string.c_str(), &query, &key, | 653 while (url_parse::ExtractQueryKeyValue(params.c_str(), &query, &key, |
570 &value)) { | 654 &value)) { |
571 if (key.is_nonempty() && value.is_nonempty()) { | 655 if (key.is_nonempty() && value.is_nonempty()) { |
572 std::string value_string = query_string.substr(value.begin, value.len); | 656 std::string value_string = params.substr(value.begin, value.len); |
573 if (value_string.find(kSearchTermsParameterFull, 0) != | 657 if (value_string.find(kSearchTermsParameterFull, 0) != |
574 std::string::npos || | 658 std::string::npos || |
575 value_string.find(kGoogleUnescapedSearchTermsParameterFull, 0) != | 659 value_string.find(kGoogleUnescapedSearchTermsParameterFull, 0) != |
576 std::string::npos) { | 660 std::string::npos) { |
577 search_term_key_ = query_string.substr(key.begin, key.len); | 661 search_term_key_ = params.substr(key.begin, key.len); |
578 host_ = url.host(); | |
579 path_ = url.path(); | |
580 break; | 662 break; |
581 } | 663 } |
582 } | 664 } |
583 } | 665 } |
584 } | 666 } |
585 | 667 |
586 | 668 |
587 // TemplateURLData ------------------------------------------------------------ | 669 // TemplateURLData ------------------------------------------------------------ |
588 | 670 |
589 TemplateURLData::TemplateURLData() | 671 TemplateURLData::TemplateURLData() |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
683 | 765 |
684 std::string TemplateURL::GetExtensionId() const { | 766 std::string TemplateURL::GetExtensionId() const { |
685 DCHECK(IsExtensionKeyword()); | 767 DCHECK(IsExtensionKeyword()); |
686 return GURL(data_.url()).host(); | 768 return GURL(data_.url()).host(); |
687 } | 769 } |
688 | 770 |
689 bool TemplateURL::IsExtensionKeyword() const { | 771 bool TemplateURL::IsExtensionKeyword() const { |
690 return GURL(data_.url()).SchemeIs(chrome::kExtensionScheme); | 772 return GURL(data_.url()).SchemeIs(chrome::kExtensionScheme); |
691 } | 773 } |
692 | 774 |
775 size_t TemplateURL::URLCount() const { | |
776 // Add 1 for the regular search URL. | |
777 return data_.alternate_urls.size() + 1; | |
778 } | |
779 | |
780 const std::string& TemplateURL::GetURL(size_t index) const { | |
781 DCHECK_LT(index, URLCount()); | |
782 | |
783 return (index < data_.alternate_urls.size()) ? | |
784 data_.alternate_urls[index] : url(); | |
785 } | |
786 | |
787 bool TemplateURL::ExtractSearchTermsFromURL( | |
788 const GURL& url, string16* search_terms) { | |
789 DCHECK(search_terms); | |
790 search_terms->clear(); | |
791 | |
792 // Then try to match with every pattern. | |
793 for (size_t i = 0; i < URLCount(); ++i) { | |
794 TemplateURLRef ref(this, i); | |
795 if (ref.ExtractSearchTermsFromURL(url, search_terms)) { | |
796 // If ExtractSearchTermsFromURL() returns true and |search_terms| is empty | |
797 // it means the pattern matched but no search terms were present. In this | |
798 // case we fail immediately without looking for matches in subsequent | |
799 // patterns. This means that given patterns | |
Peter Kasting
2012/10/04 19:32:43
Nit: This comment helps. I might add even more ju
beaudoin
2012/10/04 23:10:45
Done.
| |
800 // [ "http://foo/#q={searchTerms}", "http://foo/?q={searchTerms}" ], | |
801 // calling ExtractSearchTermsFromURL() on "http://foo/?q=bar#q=' would | |
802 // return false. | |
803 return !search_terms->empty(); | |
804 } | |
805 } | |
806 return false; | |
807 } | |
808 | |
693 void TemplateURL::CopyFrom(const TemplateURL& other) { | 809 void TemplateURL::CopyFrom(const TemplateURL& other) { |
694 if (this == &other) | 810 if (this == &other) |
695 return; | 811 return; |
696 | 812 |
697 profile_ = other.profile_; | 813 profile_ = other.profile_; |
698 data_ = other.data_; | 814 data_ = other.data_; |
699 url_ref_.InvalidateCachedValues(); | 815 url_ref_.InvalidateCachedValues(); |
700 suggestions_url_ref_.InvalidateCachedValues(); | 816 suggestions_url_ref_.InvalidateCachedValues(); |
701 instant_url_ref_.InvalidateCachedValues(); | 817 instant_url_ref_.InvalidateCachedValues(); |
702 SetPrepopulateId(other.data_.prepopulate_id); | 818 SetPrepopulateId(other.data_.prepopulate_id); |
(...skipping 13 matching lines...) Expand all Loading... | |
716 } | 832 } |
717 | 833 |
718 void TemplateURL::ResetKeywordIfNecessary(bool force) { | 834 void TemplateURL::ResetKeywordIfNecessary(bool force) { |
719 if (IsGoogleSearchURLWithReplaceableKeyword() || force) { | 835 if (IsGoogleSearchURLWithReplaceableKeyword() || force) { |
720 DCHECK(!IsExtensionKeyword()); | 836 DCHECK(!IsExtensionKeyword()); |
721 GURL url(TemplateURLService::GenerateSearchURL(this)); | 837 GURL url(TemplateURLService::GenerateSearchURL(this)); |
722 if (url.is_valid()) | 838 if (url.is_valid()) |
723 data_.SetKeyword(TemplateURLService::GenerateKeyword(url)); | 839 data_.SetKeyword(TemplateURLService::GenerateKeyword(url)); |
724 } | 840 } |
725 } | 841 } |
OLD | NEW |