OLD | NEW |
1 // Copyright (c) 2010 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 #include "app/l10n_util.h" | 7 #include "app/l10n_util.h" |
8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
9 #include "base/environment.h" | 9 #include "base/environment.h" |
10 #include "base/stl_util-inl.h" | 10 #include "base/stl_util-inl.h" |
11 #include "base/string_number_conversions.h" | 11 #include "base/string_number_conversions.h" |
12 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
13 #include "chrome/browser/extensions/extensions_service.h" | 13 #include "chrome/browser/extensions/extensions_service.h" |
14 #include "chrome/browser/google_url_tracker.h" | 14 #include "chrome/browser/google_url_tracker.h" |
15 #include "chrome/browser/history/history.h" | 15 #include "chrome/browser/history/history.h" |
16 #include "chrome/browser/history/history_notifications.h" | 16 #include "chrome/browser/history/history_notifications.h" |
17 #include "chrome/browser/net/url_fixer_upper.h" | 17 #include "chrome/browser/net/url_fixer_upper.h" |
18 #include "chrome/browser/prefs/pref_service.h" | 18 #include "chrome/browser/prefs/pref_service.h" |
19 #include "chrome/browser/profile.h" | 19 #include "chrome/browser/profile.h" |
20 #include "chrome/browser/rlz/rlz.h" | 20 #include "chrome/browser/rlz/rlz.h" |
21 #include "chrome/browser/search_engines/template_url_prepopulate_data.h" | 21 #include "chrome/browser/search_engines/template_url_prepopulate_data.h" |
| 22 #include "chrome/browser/search_engines/util.h" |
22 #include "chrome/common/chrome_switches.h" | 23 #include "chrome/common/chrome_switches.h" |
23 #include "chrome/common/env_vars.h" | 24 #include "chrome/common/env_vars.h" |
24 #include "chrome/common/extensions/extension.h" | 25 #include "chrome/common/extensions/extension.h" |
25 #include "chrome/common/notification_service.h" | 26 #include "chrome/common/notification_service.h" |
26 #include "chrome/common/pref_names.h" | 27 #include "chrome/common/pref_names.h" |
27 #include "chrome/common/url_constants.h" | 28 #include "chrome/common/url_constants.h" |
28 #include "net/base/net_util.h" | 29 #include "net/base/net_util.h" |
29 | 30 |
30 using base::Time; | 31 using base::Time; |
31 | 32 |
(...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
459 | 460 |
460 if (service_.get()) { | 461 if (service_.get()) { |
461 load_handle_ = service_->GetKeywords(this); | 462 load_handle_ = service_->GetKeywords(this); |
462 } else { | 463 } else { |
463 loaded_ = true; | 464 loaded_ = true; |
464 NotifyLoaded(); | 465 NotifyLoaded(); |
465 } | 466 } |
466 } | 467 } |
467 | 468 |
468 void TemplateURLModel::OnWebDataServiceRequestDone( | 469 void TemplateURLModel::OnWebDataServiceRequestDone( |
469 WebDataService::Handle h, | 470 WebDataService::Handle h, |
470 const WDTypedResult* result) { | 471 const WDTypedResult* result) { |
471 // Reset the load_handle so that we don't try and cancel the load in | 472 // Reset the load_handle so that we don't try and cancel the load in |
472 // the destructor. | 473 // the destructor. |
473 load_handle_ = 0; | 474 load_handle_ = 0; |
474 | 475 |
475 if (!result) { | 476 if (!result) { |
476 // Results are null if the database went away or (most likely) wasn't | 477 // Results are null if the database went away or (most likely) wasn't |
477 // loaded. | 478 // loaded. |
478 loaded_ = true; | 479 loaded_ = true; |
479 load_failed_ = true; | 480 load_failed_ = true; |
480 NotifyLoaded(); | 481 NotifyLoaded(); |
481 return; | 482 return; |
482 } | 483 } |
483 | 484 |
484 DCHECK(result->GetType() == KEYWORDS_RESULT); | |
485 | |
486 WDKeywordsResult keyword_result = reinterpret_cast< | |
487 const WDResult<WDKeywordsResult>*>(result)->GetValue(); | |
488 | |
489 // prefs_default_search_provider_ is only needed before we've finished | 485 // prefs_default_search_provider_ is only needed before we've finished |
490 // loading. Now that we've loaded we can nuke it. | 486 // loading. Now that we've loaded we can nuke it. |
491 prefs_default_search_provider_.reset(); | 487 prefs_default_search_provider_.reset(); |
492 | 488 |
493 // Compiler won't implicitly convert std::vector<TemplateURL*> to | 489 std::vector<TemplateURL*> template_urls; |
494 // std::vector<const TemplateURL*>, and reinterpret_cast is unsafe, | 490 int new_resource_keyword_version = 0; |
495 // so we just copy it. | 491 const TemplateURL* default_search_provider = NULL; |
496 std::vector<const TemplateURL*> template_urls(keyword_result.keywords.begin(), | 492 GetSearchProvidersUsingKeywordResult(*result, |
497 keyword_result.keywords.end()); | 493 service_.get(), |
| 494 GetPrefs(), |
| 495 &template_urls, |
| 496 &default_search_provider, |
| 497 &new_resource_keyword_version); |
498 | 498 |
499 const int resource_keyword_version = | 499 // If the default search provider existed previously, then just |
500 TemplateURLPrepopulateData::GetDataVersion(GetPrefs()); | 500 // set the member variable. Otherwise, we'll set it using the method |
501 if (keyword_result.builtin_keyword_version != resource_keyword_version) { | 501 // to ensure that it is saved properly after its id is set. |
502 // There should never be duplicate TemplateURLs. We had a bug such that | 502 if (default_search_provider && default_search_provider->id() != 0) { |
503 // duplicate TemplateURLs existed for one locale. As such we invoke | 503 default_search_provider_ = default_search_provider; |
504 // RemoveDuplicatePrepopulateIDs to nuke the duplicates. | 504 default_search_provider = NULL; |
505 RemoveDuplicatePrepopulateIDs(&template_urls); | |
506 } | 505 } |
507 SetTemplateURLs(template_urls); | 506 SetTemplateURLs(template_urls); |
508 | 507 |
509 if (keyword_result.default_search_provider_id) { | 508 if (default_search_provider) { |
510 // See if we can find the default search provider. | 509 // Note that this saves the default search provider to prefs. |
511 for (TemplateURLVector::iterator i = template_urls_.begin(); | 510 SetDefaultSearchProvider(default_search_provider); |
512 i != template_urls_.end(); ++i) { | 511 } else { |
513 if ((*i)->id() == keyword_result.default_search_provider_id) { | 512 // Always save the default search provider to prefs. That way we don't |
514 default_search_provider_ = *i; | 513 // have to worry about it being out of sync. |
515 break; | 514 if (default_search_provider_) |
516 } | 515 SaveDefaultSearchProviderToPrefs(default_search_provider_); |
517 } | |
518 } | 516 } |
519 | 517 |
520 if (keyword_result.builtin_keyword_version != resource_keyword_version) { | |
521 MergeEnginesFromPrepopulateData(); | |
522 service_->SetBuiltinKeywordVersion(resource_keyword_version); | |
523 } | |
524 | |
525 // Always save the default search provider to prefs. That way we don't have to | |
526 // worry about it being out of sync. | |
527 if (default_search_provider_) | |
528 SaveDefaultSearchProviderToPrefs(default_search_provider_); | |
529 | |
530 // Index any visits that occurred before we finished loading. | 518 // Index any visits that occurred before we finished loading. |
531 for (size_t i = 0; i < visits_to_add_.size(); ++i) | 519 for (size_t i = 0; i < visits_to_add_.size(); ++i) |
532 UpdateKeywordSearchTermsForURL(visits_to_add_[i]); | 520 UpdateKeywordSearchTermsForURL(visits_to_add_[i]); |
533 visits_to_add_.clear(); | 521 visits_to_add_.clear(); |
534 | 522 |
| 523 if (new_resource_keyword_version && service_.get()) |
| 524 service_->SetBuiltinKeywordVersion(new_resource_keyword_version); |
| 525 |
535 loaded_ = true; | 526 loaded_ = true; |
536 | 527 |
537 FOR_EACH_OBSERVER(TemplateURLModelObserver, model_observers_, | 528 FOR_EACH_OBSERVER(TemplateURLModelObserver, model_observers_, |
538 OnTemplateURLModelChanged()); | 529 OnTemplateURLModelChanged()); |
539 | 530 |
540 NotifyLoaded(); | 531 NotifyLoaded(); |
541 } | 532 } |
542 | 533 |
543 void TemplateURLModel::RemoveDuplicatePrepopulateIDs( | |
544 std::vector<const TemplateURL*>* urls) { | |
545 std::set<int> ids; | |
546 for (std::vector<const TemplateURL*>::iterator i = urls->begin(); | |
547 i != urls->end(); ) { | |
548 int prepopulate_id = (*i)->prepopulate_id(); | |
549 if (prepopulate_id) { | |
550 if (ids.find(prepopulate_id) != ids.end()) { | |
551 if (service_.get()) | |
552 service_->RemoveKeyword(**i); | |
553 delete *i; | |
554 i = urls->erase(i); | |
555 } else { | |
556 ids.insert(prepopulate_id); | |
557 ++i; | |
558 } | |
559 } else { | |
560 ++i; | |
561 } | |
562 } | |
563 } | |
564 | |
565 std::wstring TemplateURLModel::GetKeywordShortName(const std::wstring& keyword, | 534 std::wstring TemplateURLModel::GetKeywordShortName(const std::wstring& keyword, |
566 bool* is_extension_keyword) { | 535 bool* is_extension_keyword) { |
567 const TemplateURL* template_url = GetTemplateURLForKeyword(keyword); | 536 const TemplateURL* template_url = GetTemplateURLForKeyword(keyword); |
568 | 537 |
569 // TODO(sky): Once LocationBarView adds a listener to the TemplateURLModel | 538 // TODO(sky): Once LocationBarView adds a listener to the TemplateURLModel |
570 // to track changes to the model, this should become a DCHECK. | 539 // to track changes to the model, this should become a DCHECK. |
571 if (template_url) { | 540 if (template_url) { |
572 *is_extension_keyword = template_url->IsExtensionKeyword(); | 541 *is_extension_keyword = template_url->IsExtensionKeyword(); |
573 return template_url->AdjustedShortNameForLocaleDirection(); | 542 return template_url->AdjustedShortNameForLocaleDirection(); |
574 } | 543 } |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
698 | 667 |
699 void TemplateURLModel::AddToMaps(const TemplateURL* template_url) { | 668 void TemplateURLModel::AddToMaps(const TemplateURL* template_url) { |
700 if (!template_url->keyword().empty()) | 669 if (!template_url->keyword().empty()) |
701 keyword_to_template_map_[template_url->keyword()] = template_url; | 670 keyword_to_template_map_[template_url->keyword()] = template_url; |
702 | 671 |
703 const GURL url(GenerateSearchURL(template_url)); | 672 const GURL url(GenerateSearchURL(template_url)); |
704 if (url.is_valid() && url.has_host()) | 673 if (url.is_valid() && url.has_host()) |
705 host_to_urls_map_[url.host()].insert(template_url); | 674 host_to_urls_map_[url.host()].insert(template_url); |
706 } | 675 } |
707 | 676 |
708 void TemplateURLModel::SetTemplateURLs( | 677 void TemplateURLModel::SetTemplateURLs(const std::vector<TemplateURL*>& urls) { |
709 const std::vector<const TemplateURL*>& urls) { | |
710 // Add mappings for the new items. | 678 // Add mappings for the new items. |
711 for (TemplateURLVector::const_iterator i = urls.begin(); i != urls.end(); | 679 |
| 680 // First, add the items that already have id's, so that the next_id_ |
| 681 // gets properly set. |
| 682 for (std::vector<TemplateURL*>::const_iterator i = urls.begin(); |
| 683 i != urls.end(); |
712 ++i) { | 684 ++i) { |
| 685 if ((*i)->id() == 0) |
| 686 continue; |
713 next_id_ = std::max(next_id_, (*i)->id()); | 687 next_id_ = std::max(next_id_, (*i)->id()); |
714 AddToMaps(*i); | 688 AddToMaps(*i); |
715 template_urls_.push_back(*i); | 689 template_urls_.push_back(*i); |
716 } | 690 } |
| 691 |
| 692 // Next add the new items that don't have id's. |
| 693 for (std::vector<TemplateURL*>::const_iterator i = urls.begin(); |
| 694 i != urls.end(); |
| 695 ++i) { |
| 696 if ((*i)->id() != 0) |
| 697 continue; |
| 698 Add(*i); |
| 699 } |
717 } | 700 } |
718 | 701 |
719 void TemplateURLModel::NotifyLoaded() { | 702 void TemplateURLModel::NotifyLoaded() { |
720 NotificationService::current()->Notify( | 703 NotificationService::current()->Notify( |
721 NotificationType::TEMPLATE_URL_MODEL_LOADED, | 704 NotificationType::TEMPLATE_URL_MODEL_LOADED, |
722 Source<TemplateURLModel>(this), | 705 Source<TemplateURLModel>(this), |
723 NotificationService::NoDetails()); | 706 NotificationService::NoDetails()); |
724 | 707 |
725 for (size_t i = 0; i < pending_extension_ids_.size(); ++i) { | 708 for (size_t i = 0; i < pending_extension_ids_.size(); ++i) { |
726 Extension* extension = profile_->GetExtensionsService()-> | 709 Extension* extension = profile_->GetExtensionsService()-> |
727 GetExtensionById(pending_extension_ids_[i], true); | 710 GetExtensionById(pending_extension_ids_[i], true); |
728 if (extension) | 711 if (extension) |
729 RegisterExtensionKeyword(extension); | 712 RegisterExtensionKeyword(extension); |
730 } | 713 } |
731 pending_extension_ids_.clear(); | 714 pending_extension_ids_.clear(); |
732 } | 715 } |
733 | 716 |
734 void TemplateURLModel::MergeEnginesFromPrepopulateData() { | |
735 // Build a map from prepopulate id to TemplateURL of existing urls. | |
736 typedef std::map<int, const TemplateURL*> IDMap; | |
737 IDMap id_to_turl; | |
738 for (TemplateURLVector::const_iterator i(template_urls_.begin()); | |
739 i != template_urls_.end(); ++i) { | |
740 int prepopulate_id = (*i)->prepopulate_id(); | |
741 if (prepopulate_id > 0) | |
742 id_to_turl[prepopulate_id] = *i; | |
743 } | |
744 | |
745 std::vector<TemplateURL*> loaded_urls; | |
746 size_t default_search_index; | |
747 TemplateURLPrepopulateData::GetPrepopulatedEngines(GetPrefs(), | |
748 &loaded_urls, | |
749 &default_search_index); | |
750 | |
751 std::set<int> updated_ids; | |
752 for (size_t i = 0; i < loaded_urls.size(); ++i) { | |
753 // We take ownership of |t_url|. | |
754 scoped_ptr<TemplateURL> t_url(loaded_urls[i]); | |
755 int t_url_id = t_url->prepopulate_id(); | |
756 if (!t_url_id || updated_ids.count(t_url_id)) { | |
757 // Prepopulate engines need a unique id. | |
758 NOTREACHED(); | |
759 continue; | |
760 } | |
761 | |
762 IDMap::iterator existing_url_iter(id_to_turl.find(t_url_id)); | |
763 if (existing_url_iter != id_to_turl.end()) { | |
764 const TemplateURL* existing_url = existing_url_iter->second; | |
765 if (!existing_url->safe_for_autoreplace()) { | |
766 // User edited the entry, preserve the keyword and description. | |
767 t_url->set_safe_for_autoreplace(false); | |
768 t_url->set_keyword(existing_url->keyword()); | |
769 t_url->set_autogenerate_keyword( | |
770 existing_url->autogenerate_keyword()); | |
771 t_url->set_short_name(existing_url->short_name()); | |
772 } | |
773 Update(existing_url, *t_url); | |
774 id_to_turl.erase(existing_url_iter); | |
775 } else { | |
776 Add(t_url.release()); | |
777 } | |
778 if (i == default_search_index && !default_search_provider_) | |
779 SetDefaultSearchProvider(loaded_urls[i]); | |
780 | |
781 updated_ids.insert(t_url_id); | |
782 } | |
783 | |
784 // Remove any prepopulated engines which are no longer in the master list, as | |
785 // long as the user hasn't modified them or made them the default engine. | |
786 for (IDMap::iterator i(id_to_turl.begin()); i != id_to_turl.end(); ++i) { | |
787 const TemplateURL* template_url = i->second; | |
788 // We use default_search_provider_ instead of GetDefaultSearchProvider() | |
789 // because we're running before |loaded_| is set, and calling | |
790 // GetDefaultSearchProvider() will erroneously try to read the prefs. | |
791 if ((template_url->safe_for_autoreplace()) && | |
792 (template_url != default_search_provider_)) | |
793 Remove(template_url); | |
794 } | |
795 } | |
796 | |
797 void TemplateURLModel::SaveDefaultSearchProviderToPrefs( | 717 void TemplateURLModel::SaveDefaultSearchProviderToPrefs( |
798 const TemplateURL* t_url) { | 718 const TemplateURL* t_url) { |
799 PrefService* prefs = GetPrefs(); | 719 PrefService* prefs = GetPrefs(); |
800 if (!prefs) | 720 if (!prefs) |
801 return; | 721 return; |
802 | 722 |
803 RegisterPrefs(prefs); | 723 RegisterPrefs(prefs); |
804 | 724 |
805 const std::string search_url = | 725 const std::string search_url = |
806 (t_url && t_url->url()) ? t_url->url()->url() : std::string(); | 726 (t_url && t_url->url()) ? t_url->url()->url() : std::string(); |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1085 AddToMaps(t_url); | 1005 AddToMaps(t_url); |
1086 something_changed = true; | 1006 something_changed = true; |
1087 } | 1007 } |
1088 } | 1008 } |
1089 | 1009 |
1090 if (something_changed && loaded_) { | 1010 if (something_changed && loaded_) { |
1091 FOR_EACH_OBSERVER(TemplateURLModelObserver, model_observers_, | 1011 FOR_EACH_OBSERVER(TemplateURLModelObserver, model_observers_, |
1092 OnTemplateURLModelChanged()); | 1012 OnTemplateURLModelChanged()); |
1093 } | 1013 } |
1094 } | 1014 } |
OLD | NEW |