OLD | NEW |
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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_model.h" | 5 #include "chrome/browser/search_engines/template_url_model.h" |
6 | 6 |
7 | |
8 #include "app/l10n_util.h" | 7 #include "app/l10n_util.h" |
9 #include "base/stl_util-inl.h" | 8 #include "base/stl_util-inl.h" |
10 #include "base/utf_string_conversions.h" | 9 #include "base/utf_string_conversions.h" |
| 10 #include "chrome/browser/extensions/extensions_service.h" |
11 #include "chrome/browser/google_url_tracker.h" | 11 #include "chrome/browser/google_url_tracker.h" |
12 #include "chrome/browser/history/history.h" | 12 #include "chrome/browser/history/history.h" |
13 #include "chrome/browser/history/history_notifications.h" | 13 #include "chrome/browser/history/history_notifications.h" |
14 #include "chrome/browser/net/url_fixer_upper.h" | 14 #include "chrome/browser/net/url_fixer_upper.h" |
15 #include "chrome/browser/pref_service.h" | 15 #include "chrome/browser/pref_service.h" |
16 #include "chrome/browser/profile.h" | 16 #include "chrome/browser/profile.h" |
17 #include "chrome/browser/rlz/rlz.h" | 17 #include "chrome/browser/rlz/rlz.h" |
18 #include "chrome/browser/search_engines/template_url_prepopulate_data.h" | 18 #include "chrome/browser/search_engines/template_url_prepopulate_data.h" |
| 19 #include "chrome/common/extensions/extension.h" |
19 #include "chrome/common/notification_service.h" | 20 #include "chrome/common/notification_service.h" |
20 #include "chrome/common/pref_names.h" | 21 #include "chrome/common/pref_names.h" |
21 #include "chrome/common/url_constants.h" | 22 #include "chrome/common/url_constants.h" |
22 #include "net/base/net_util.h" | 23 #include "net/base/net_util.h" |
23 | 24 |
24 using base::Time; | 25 using base::Time; |
25 | 26 |
26 // String in the URL that is replaced by the search term. | 27 // String in the URL that is replaced by the search term. |
27 static const wchar_t kSearchTermParameter[] = L"{searchTerms}"; | 28 static const wchar_t kSearchTermParameter[] = L"{searchTerms}"; |
28 | 29 |
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 | 178 |
178 // Remove trailing "/". | 179 // Remove trailing "/". |
179 return (result.length() > 0 && result[result.length() - 1] == L'/') ? | 180 return (result.length() > 0 && result[result.length() - 1] == L'/') ? |
180 result.substr(0, result.length() - 1) : result; | 181 result.substr(0, result.length() - 1) : result; |
181 } | 182 } |
182 | 183 |
183 // static | 184 // static |
184 GURL TemplateURLModel::GenerateSearchURL(const TemplateURL* t_url) { | 185 GURL TemplateURLModel::GenerateSearchURL(const TemplateURL* t_url) { |
185 DCHECK(t_url); | 186 DCHECK(t_url); |
186 const TemplateURLRef* search_ref = t_url->url(); | 187 const TemplateURLRef* search_ref = t_url->url(); |
187 if (!search_ref || !search_ref->IsValid()) | 188 // Extension keywords don't have host-based search URLs. |
| 189 if (!search_ref || !search_ref->IsValid() || t_url->IsExtensionKeyword()) |
188 return GURL(); | 190 return GURL(); |
189 | 191 |
190 if (!search_ref->SupportsReplacement()) | 192 if (!search_ref->SupportsReplacement()) |
191 return GURL(WideToUTF8(search_ref->url())); | 193 return GURL(WideToUTF8(search_ref->url())); |
192 | 194 |
193 return GURL(WideToUTF8(search_ref->ReplaceSearchTerms( | 195 return GURL(WideToUTF8(search_ref->ReplaceSearchTerms( |
194 *t_url, kReplacementTerm, TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, | 196 *t_url, kReplacementTerm, TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, |
195 std::wstring()))); | 197 std::wstring()))); |
196 } | 198 } |
197 | 199 |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 host_to_urls_map_.erase(i); | 428 host_to_urls_map_.erase(i); |
427 // A given TemplateURL only occurs once in the map. As soon as we find the | 429 // A given TemplateURL only occurs once in the map. As soon as we find the |
428 // entry, stop. | 430 // entry, stop. |
429 return; | 431 return; |
430 } | 432 } |
431 } | 433 } |
432 } | 434 } |
433 | 435 |
434 void TemplateURLModel::SetTemplateURLs( | 436 void TemplateURLModel::SetTemplateURLs( |
435 const std::vector<const TemplateURL*>& urls) { | 437 const std::vector<const TemplateURL*>& urls) { |
436 DCHECK(template_urls_.empty()); // This should only be called on load, | |
437 // when we have no TemplateURLs. | |
438 | |
439 // Add mappings for the new items. | 438 // Add mappings for the new items. |
440 for (TemplateURLVector::const_iterator i = urls.begin(); i != urls.end(); | 439 for (TemplateURLVector::const_iterator i = urls.begin(); i != urls.end(); |
441 ++i) { | 440 ++i) { |
442 next_id_ = std::max(next_id_, (*i)->id()); | 441 next_id_ = std::max(next_id_, (*i)->id()); |
443 AddToMaps(*i); | 442 AddToMaps(*i); |
| 443 template_urls_.push_back(*i); |
444 } | 444 } |
445 | |
446 template_urls_ = urls; | |
447 } | 445 } |
448 | 446 |
449 std::vector<const TemplateURL*> TemplateURLModel::GetTemplateURLs() const { | 447 std::vector<const TemplateURL*> TemplateURLModel::GetTemplateURLs() const { |
450 return template_urls_; | 448 return template_urls_; |
451 } | 449 } |
452 | 450 |
453 void TemplateURLModel::IncrementUsageCount(const TemplateURL* url) { | 451 void TemplateURLModel::IncrementUsageCount(const TemplateURL* url) { |
454 DCHECK(url && find(template_urls_.begin(), template_urls_.end(), url) != | 452 DCHECK(url && find(template_urls_.begin(), template_urls_.end(), url) != |
455 template_urls_.end()); | 453 template_urls_.end()); |
456 const_cast<TemplateURL*>(url)->set_usage_count(url->usage_count() + 1); | 454 const_cast<TemplateURL*>(url)->set_usage_count(url->usage_count() + 1); |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
667 } else { | 665 } else { |
668 ids.insert(prepopulate_id); | 666 ids.insert(prepopulate_id); |
669 ++i; | 667 ++i; |
670 } | 668 } |
671 } else { | 669 } else { |
672 ++i; | 670 ++i; |
673 } | 671 } |
674 } | 672 } |
675 } | 673 } |
676 | 674 |
| 675 std::wstring TemplateURLModel::GetKeywordShortName(const std::wstring& keyword, |
| 676 bool* is_extension_keyword) { |
| 677 const TemplateURL* template_url = GetTemplateURLForKeyword(keyword); |
| 678 |
| 679 // TODO(sky): Once LocationBarView adds a listener to the TemplateURLModel |
| 680 // to track changes to the model, this should become a DCHECK. |
| 681 if (template_url) { |
| 682 *is_extension_keyword = template_url->IsExtensionKeyword(); |
| 683 return template_url->AdjustedShortNameForLocaleDirection(); |
| 684 } |
| 685 *is_extension_keyword = false; |
| 686 return std::wstring(); |
| 687 } |
| 688 |
677 void TemplateURLModel::Observe(NotificationType type, | 689 void TemplateURLModel::Observe(NotificationType type, |
678 const NotificationSource& source, | 690 const NotificationSource& source, |
679 const NotificationDetails& details) { | 691 const NotificationDetails& details) { |
680 if (type == NotificationType::HISTORY_URL_VISITED) { | 692 if (type == NotificationType::HISTORY_URL_VISITED) { |
681 Details<history::URLVisitedDetails> visit_details(details); | 693 Details<history::URLVisitedDetails> visit_details(details); |
682 | 694 |
683 if (!loaded()) | 695 if (!loaded()) |
684 visits_to_add_.push_back(*visit_details.ptr()); | 696 visits_to_add_.push_back(*visit_details.ptr()); |
685 else | 697 else |
686 UpdateKeywordSearchTermsForURL(*visit_details.ptr()); | 698 UpdateKeywordSearchTermsForURL(*visit_details.ptr()); |
(...skipping 17 matching lines...) Expand all Loading... |
704 Remove(template_urls_[i]); | 716 Remove(template_urls_[i]); |
705 } | 717 } |
706 } | 718 } |
707 } | 719 } |
708 | 720 |
709 void TemplateURLModel::NotifyLoaded() { | 721 void TemplateURLModel::NotifyLoaded() { |
710 NotificationService::current()->Notify( | 722 NotificationService::current()->Notify( |
711 NotificationType::TEMPLATE_URL_MODEL_LOADED, | 723 NotificationType::TEMPLATE_URL_MODEL_LOADED, |
712 Source<TemplateURLModel>(this), | 724 Source<TemplateURLModel>(this), |
713 NotificationService::NoDetails()); | 725 NotificationService::NoDetails()); |
| 726 |
| 727 for (size_t i = 0; i < pending_extension_ids_.size(); ++i) { |
| 728 Extension* extension = profile_->GetExtensionsService()-> |
| 729 GetExtensionById(pending_extension_ids_[i], true); |
| 730 if (extension) |
| 731 RegisterExtensionKeyword(extension); |
| 732 } |
| 733 pending_extension_ids_.clear(); |
714 } | 734 } |
715 | 735 |
716 void TemplateURLModel::MergeEnginesFromPrepopulateData() { | 736 void TemplateURLModel::MergeEnginesFromPrepopulateData() { |
717 // Build a map from prepopulate id to TemplateURL of existing urls. | 737 // Build a map from prepopulate id to TemplateURL of existing urls. |
718 typedef std::map<int, const TemplateURL*> IDMap; | 738 typedef std::map<int, const TemplateURL*> IDMap; |
719 IDMap id_to_turl; | 739 IDMap id_to_turl; |
720 for (TemplateURLVector::const_iterator i(template_urls_.begin()); | 740 for (TemplateURLVector::const_iterator i(template_urls_.begin()); |
721 i != template_urls_.end(); ++i) { | 741 i != template_urls_.end(); ++i) { |
722 int prepopulate_id = (*i)->prepopulate_id(); | 742 int prepopulate_id = (*i)->prepopulate_id(); |
723 if (prepopulate_id > 0) | 743 if (prepopulate_id > 0) |
(...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1029 AddToMaps(t_url); | 1049 AddToMaps(t_url); |
1030 something_changed = true; | 1050 something_changed = true; |
1031 } | 1051 } |
1032 } | 1052 } |
1033 | 1053 |
1034 if (something_changed && loaded_) { | 1054 if (something_changed && loaded_) { |
1035 FOR_EACH_OBSERVER(TemplateURLModelObserver, model_observers_, | 1055 FOR_EACH_OBSERVER(TemplateURLModelObserver, model_observers_, |
1036 OnTemplateURLModelChanged()); | 1056 OnTemplateURLModelChanged()); |
1037 } | 1057 } |
1038 } | 1058 } |
| 1059 |
| 1060 void TemplateURLModel::RegisterExtensionKeyword(Extension* extension) { |
| 1061 // TODO(mpcomplete): disable the keyword when the extension is disabled. |
| 1062 if (extension->omnibox_keyword().empty()) |
| 1063 return; |
| 1064 |
| 1065 Load(); |
| 1066 if (!loaded_) { |
| 1067 pending_extension_ids_.push_back(extension->id()); |
| 1068 return; |
| 1069 } |
| 1070 |
| 1071 if (GetTemplateURLForExtension(extension)) |
| 1072 return; // Already have this one registered (might be an upgrade). |
| 1073 |
| 1074 std::wstring keyword = UTF8ToWide(extension->omnibox_keyword()); |
| 1075 |
| 1076 TemplateURL* template_url = new TemplateURL; |
| 1077 template_url->set_short_name(UTF8ToWide(extension->name())); |
| 1078 template_url->set_keyword(keyword); |
| 1079 // This URL is not actually used for navigation. It holds the extension's |
| 1080 // ID, as well as forcing the TemplateURL to be treated as a search keyword. |
| 1081 template_url->SetURL( |
| 1082 UTF8ToWide(chrome::kExtensionScheme) + L"://" + |
| 1083 UTF8ToWide(extension->id()) + L"/?q={searchTerms}", 0, 0); |
| 1084 template_url->set_safe_for_autoreplace(false); |
| 1085 |
| 1086 Add(template_url); |
| 1087 } |
| 1088 |
| 1089 void TemplateURLModel::UnregisterExtensionKeyword(Extension* extension) { |
| 1090 const TemplateURL* url = GetTemplateURLForExtension(extension); |
| 1091 if (url) |
| 1092 Remove(url); |
| 1093 } |
| 1094 |
| 1095 const TemplateURL* TemplateURLModel::GetTemplateURLForExtension( |
| 1096 Extension* extension) const { |
| 1097 for (TemplateURLVector::const_iterator i = template_urls_.begin(); |
| 1098 i != template_urls_.end(); ++i) { |
| 1099 if ((*i)->IsExtensionKeyword() && (*i)->url()->GetHost() == extension->id()) |
| 1100 return *i; |
| 1101 } |
| 1102 |
| 1103 return NULL; |
| 1104 } |
OLD | NEW |