OLD | NEW |
---|---|
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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_service.h" | 5 #include "chrome/browser/search_engines/template_url_service.h" |
6 | 6 |
7 #include "base/auto_reset.h" | |
7 #include "base/command_line.h" | 8 #include "base/command_line.h" |
8 #include "base/environment.h" | 9 #include "base/environment.h" |
9 #include "base/i18n/case_conversion.h" | 10 #include "base/i18n/case_conversion.h" |
10 #include "base/stl_util.h" | 11 #include "base/stl_util.h" |
11 #include "base/string_number_conversions.h" | 12 #include "base/string_number_conversions.h" |
12 #include "base/string_split.h" | 13 #include "base/string_split.h" |
13 #include "base/string_util.h" | 14 #include "base/string_util.h" |
14 #include "base/threading/thread_restrictions.h" | 15 #include "base/threading/thread_restrictions.h" |
15 #include "base/utf_string_conversions.h" | 16 #include "base/utf_string_conversions.h" |
16 #include "chrome/browser/extensions/extension_service.h" | 17 #include "chrome/browser/extensions/extension_service.h" |
17 #include "chrome/browser/google/google_url_tracker.h" | 18 #include "chrome/browser/google/google_url_tracker.h" |
18 #include "chrome/browser/history/history.h" | 19 #include "chrome/browser/history/history.h" |
19 #include "chrome/browser/history/history_notifications.h" | 20 #include "chrome/browser/history/history_notifications.h" |
20 #include "chrome/browser/net/url_fixer_upper.h" | 21 #include "chrome/browser/net/url_fixer_upper.h" |
21 #include "chrome/browser/prefs/pref_service.h" | 22 #include "chrome/browser/prefs/pref_service.h" |
22 #include "chrome/browser/prefs/pref_set_observer.h" | 23 #include "chrome/browser/prefs/pref_set_observer.h" |
23 #include "chrome/browser/profiles/profile.h" | 24 #include "chrome/browser/profiles/profile.h" |
24 #include "chrome/browser/rlz/rlz.h" | 25 #include "chrome/browser/rlz/rlz.h" |
25 #include "chrome/browser/search_engines/search_host_to_urls_map.h" | 26 #include "chrome/browser/search_engines/search_host_to_urls_map.h" |
26 #include "chrome/browser/search_engines/search_terms_data.h" | 27 #include "chrome/browser/search_engines/search_terms_data.h" |
27 #include "chrome/browser/search_engines/template_url.h" | 28 #include "chrome/browser/search_engines/template_url.h" |
28 #include "chrome/browser/search_engines/template_url_service_observer.h" | 29 #include "chrome/browser/search_engines/template_url_service_observer.h" |
29 #include "chrome/browser/search_engines/template_url_prepopulate_data.h" | 30 #include "chrome/browser/search_engines/template_url_prepopulate_data.h" |
30 #include "chrome/browser/search_engines/util.h" | 31 #include "chrome/browser/search_engines/util.h" |
32 #include "chrome/browser/sync/api/sync_change.h" | |
31 #include "chrome/common/chrome_notification_types.h" | 33 #include "chrome/common/chrome_notification_types.h" |
32 #include "chrome/common/chrome_switches.h" | 34 #include "chrome/common/chrome_switches.h" |
33 #include "chrome/common/env_vars.h" | 35 #include "chrome/common/env_vars.h" |
34 #include "chrome/common/extensions/extension.h" | 36 #include "chrome/common/extensions/extension.h" |
37 #include "chrome/common/guid.h" | |
35 #include "chrome/common/pref_names.h" | 38 #include "chrome/common/pref_names.h" |
36 #include "chrome/common/url_constants.h" | 39 #include "chrome/common/url_constants.h" |
37 #include "content/common/notification_service.h" | 40 #include "content/common/notification_service.h" |
38 #include "net/base/net_util.h" | 41 #include "net/base/net_util.h" |
39 #include "ui/base/l10n/l10n_util.h" | 42 #include "ui/base/l10n/l10n_util.h" |
40 | 43 |
41 using base::Time; | 44 using base::Time; |
45 using syncable::SEARCH_ENGINES; | |
Peter Kasting
2011/08/09 21:31:04
Nit: We normally try to avoid using declarations (
SteveT
2011/08/10 15:15:12
Agreed. Cleaned up both using declarations.
| |
46 | |
42 typedef SearchHostToURLsMap::TemplateURLSet TemplateURLSet; | 47 typedef SearchHostToURLsMap::TemplateURLSet TemplateURLSet; |
43 | 48 |
44 namespace { | 49 namespace { |
45 | 50 |
46 // String in the URL that is replaced by the search term. | 51 // String in the URL that is replaced by the search term. |
47 const char kSearchTermParameter[] = "{searchTerms}"; | 52 const char kSearchTermParameter[] = "{searchTerms}"; |
48 | 53 |
49 // String in Initializer that is replaced with kSearchTermParameter. | 54 // String in Initializer that is replaced with kSearchTermParameter. |
50 const char kTemplateParameter[] = "%s"; | 55 const char kTemplateParameter[] = "%s"; |
51 | 56 |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
97 }; | 102 }; |
98 | 103 |
99 TemplateURLService::TemplateURLService(Profile* profile) | 104 TemplateURLService::TemplateURLService(Profile* profile) |
100 : profile_(profile), | 105 : profile_(profile), |
101 loaded_(false), | 106 loaded_(false), |
102 load_failed_(false), | 107 load_failed_(false), |
103 load_handle_(0), | 108 load_handle_(0), |
104 default_search_provider_(NULL), | 109 default_search_provider_(NULL), |
105 is_default_search_managed_(false), | 110 is_default_search_managed_(false), |
106 next_id_(1), | 111 next_id_(1), |
107 time_provider_(&base::Time::Now) { | 112 time_provider_(&base::Time::Now), |
113 models_associated_(false), | |
114 processing_syncer_changes_(false), | |
115 sync_processor_(NULL) { | |
108 DCHECK(profile_); | 116 DCHECK(profile_); |
109 Init(NULL, 0); | 117 Init(NULL, 0); |
110 } | 118 } |
111 | 119 |
112 TemplateURLService::TemplateURLService(const Initializer* initializers, | 120 TemplateURLService::TemplateURLService(const Initializer* initializers, |
113 const int count) | 121 const int count) |
114 : profile_(NULL), | 122 : profile_(NULL), |
115 loaded_(false), | 123 loaded_(false), |
116 load_failed_(false), | 124 load_failed_(false), |
117 load_handle_(0), | 125 load_handle_(0), |
118 service_(NULL), | 126 service_(NULL), |
119 default_search_provider_(NULL), | 127 default_search_provider_(NULL), |
120 is_default_search_managed_(false), | 128 is_default_search_managed_(false), |
121 next_id_(1), | 129 next_id_(1), |
122 time_provider_(&base::Time::Now) { | 130 time_provider_(&base::Time::Now), |
131 models_associated_(false), | |
132 processing_syncer_changes_(false), | |
133 sync_processor_(NULL) { | |
123 Init(initializers, count); | 134 Init(initializers, count); |
124 } | 135 } |
125 | 136 |
126 TemplateURLService::~TemplateURLService() { | 137 TemplateURLService::~TemplateURLService() { |
127 if (load_handle_) { | 138 if (load_handle_) { |
128 DCHECK(service_.get()); | 139 DCHECK(service_.get()); |
129 service_->CancelRequest(load_handle_); | 140 service_->CancelRequest(load_handle_); |
130 } | 141 } |
131 | 142 |
132 STLDeleteElements(&template_urls_); | 143 STLDeleteElements(&template_urls_); |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
279 } | 290 } |
280 } | 291 } |
281 | 292 |
282 const TemplateURL* TemplateURLService::GetTemplateURLForKeyword( | 293 const TemplateURL* TemplateURLService::GetTemplateURLForKeyword( |
283 const string16& keyword) const { | 294 const string16& keyword) const { |
284 KeywordToTemplateMap::const_iterator elem( | 295 KeywordToTemplateMap::const_iterator elem( |
285 keyword_to_template_map_.find(keyword)); | 296 keyword_to_template_map_.find(keyword)); |
286 return (elem == keyword_to_template_map_.end()) ? NULL : elem->second; | 297 return (elem == keyword_to_template_map_.end()) ? NULL : elem->second; |
287 } | 298 } |
288 | 299 |
300 const TemplateURL* TemplateURLService::GetTemplateURLForGUID( | |
301 const std::string& sync_guid) const { | |
302 GUIDToTemplateMap::const_iterator elem( | |
303 guid_to_template_map_.find(sync_guid)); | |
304 return (elem == guid_to_template_map_.end()) ? NULL : elem->second; | |
305 } | |
306 | |
289 const TemplateURL* TemplateURLService::GetTemplateURLForHost( | 307 const TemplateURL* TemplateURLService::GetTemplateURLForHost( |
290 const std::string& host) const { | 308 const std::string& host) const { |
291 return provider_map_.GetTemplateURLForHost(host); | 309 return provider_map_.GetTemplateURLForHost(host); |
292 } | 310 } |
293 | 311 |
294 void TemplateURLService::Add(TemplateURL* template_url) { | 312 void TemplateURLService::Add(TemplateURL* template_url) { |
295 AddNoNotify(template_url); | 313 AddNoNotify(template_url); |
296 NotifyObservers(); | 314 NotifyObservers(); |
297 } | 315 } |
298 | 316 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
384 template_urls_.end()); | 402 template_urls_.end()); |
385 const_cast<TemplateURL*>(url)->set_usage_count(url->usage_count() + 1); | 403 const_cast<TemplateURL*>(url)->set_usage_count(url->usage_count() + 1); |
386 if (service_.get()) | 404 if (service_.get()) |
387 service_.get()->UpdateKeyword(*url); | 405 service_.get()->UpdateKeyword(*url); |
388 } | 406 } |
389 | 407 |
390 void TemplateURLService::ResetTemplateURL(const TemplateURL* url, | 408 void TemplateURLService::ResetTemplateURL(const TemplateURL* url, |
391 const string16& title, | 409 const string16& title, |
392 const string16& keyword, | 410 const string16& keyword, |
393 const std::string& search_url) { | 411 const std::string& search_url) { |
412 ResetTemplateURL(url, title, keyword, search_url, ""); | |
Peter Kasting
2011/08/09 21:31:04
Nit: Use std::string() instead of ""
SteveT
2011/08/10 15:15:12
Done.
| |
413 } | |
414 | |
415 void TemplateURLService::ResetTemplateURL(const TemplateURL* url, | |
416 const string16& title, | |
417 const string16& keyword, | |
418 const std::string& search_url, | |
419 const std::string& guid) { | |
394 TemplateURL new_url(*url); | 420 TemplateURL new_url(*url); |
395 new_url.set_short_name(title); | 421 new_url.set_short_name(title); |
396 new_url.set_keyword(keyword); | 422 new_url.set_keyword(keyword); |
397 if ((new_url.url() && search_url.empty()) || | 423 if ((new_url.url() && search_url.empty()) || |
398 (!new_url.url() && !search_url.empty()) || | 424 (!new_url.url() && !search_url.empty()) || |
399 (new_url.url() && new_url.url()->url() != search_url)) { | 425 (new_url.url() && new_url.url()->url() != search_url)) { |
400 // The urls have changed, reset the favicon url. | 426 // The urls have changed, reset the favicon url. |
401 new_url.SetFaviconURL(GURL()); | 427 new_url.SetFaviconURL(GURL()); |
402 new_url.SetURL(search_url, 0, 0); | 428 new_url.SetURL(search_url, 0, 0); |
403 } | 429 } |
430 if (!guid.empty()) | |
431 new_url.set_sync_guid(guid); | |
404 new_url.set_safe_for_autoreplace(false); | 432 new_url.set_safe_for_autoreplace(false); |
405 new_url.set_last_modified(time_provider_()); | 433 new_url.set_last_modified(time_provider_()); |
406 UpdateNoNotify(url, new_url); | 434 UpdateNoNotify(url, new_url); |
407 NotifyObservers(); | 435 NotifyObservers(); |
408 } | 436 } |
409 | 437 |
410 bool TemplateURLService::CanMakeDefault(const TemplateURL* url) { | 438 bool TemplateURLService::CanMakeDefault(const TemplateURL* url) { |
411 return url != GetDefaultSearchProvider() && | 439 return url != GetDefaultSearchProvider() && |
412 url->url() && | 440 url->url() && |
413 url->url()->SupportsReplacement() && | 441 url->url()->SupportsReplacement() && |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
597 if (!pref_name || default_search_prefs_->IsObserved(*pref_name)) { | 625 if (!pref_name || default_search_prefs_->IsObserved(*pref_name)) { |
598 // A preference related to default search engine has changed. | 626 // A preference related to default search engine has changed. |
599 // Update the model if needed. | 627 // Update the model if needed. |
600 UpdateDefaultSearch(); | 628 UpdateDefaultSearch(); |
601 } | 629 } |
602 } else { | 630 } else { |
603 NOTREACHED(); | 631 NOTREACHED(); |
604 } | 632 } |
605 } | 633 } |
606 | 634 |
635 SyncDataList TemplateURLService::GetAllSyncData(syncable::ModelType type) | |
636 const { | |
Peter Kasting
2011/08/09 21:31:04
Nit: I think our pattern has been to wrap after "(
SteveT
2011/08/10 15:15:12
Done.
| |
637 DCHECK_EQ(SEARCH_ENGINES, type); | |
638 | |
639 SyncDataList current_data; | |
640 for (TemplateURLVector::const_iterator iter = template_urls_.begin(); | |
641 iter != template_urls_.end(); iter++) { | |
642 // We don't sync extension keywords. | |
643 if ((*iter)->IsExtensionKeyword()) | |
644 continue; | |
645 SyncData data; | |
646 if (!CreateSearchEngineSyncData(**iter, &data)) | |
647 continue; | |
648 current_data.push_back(data); | |
649 } | |
650 | |
651 return current_data; | |
652 } | |
653 | |
654 SyncError TemplateURLService::ProcessSyncChanges( | |
655 const tracked_objects::Location& from_here, | |
656 const SyncChangeList& change_list) { | |
657 if (!models_associated_) { | |
658 SyncError error(FROM_HERE, "Models not yet associated.", SEARCH_ENGINES); | |
659 return error; | |
660 } | |
661 | |
662 AutoReset<bool> processing_changes(&processing_syncer_changes_, true); | |
663 | |
664 SyncChangeList new_changes; | |
665 for (SyncChangeList::const_iterator iter = change_list.begin(); | |
666 iter != change_list.end(); ++iter) { | |
667 DCHECK_EQ(SEARCH_ENGINES, iter->sync_data().GetDataType()); | |
668 | |
669 scoped_ptr<TemplateURL> turl(ReadSearchEngineSyncData(iter->sync_data())); | |
670 if (!turl.get()) { | |
671 LOG(ERROR) << "Failed to read search engine."; | |
672 NOTREACHED(); | |
673 continue; | |
674 } | |
675 | |
676 const TemplateURL* existing_turl = GetTemplateURLForGUID(turl->sync_guid()); | |
677 const TemplateURL* existing_keyword_turl = | |
678 GetTemplateURLForKeyword(turl->keyword()); | |
679 | |
680 if (iter->change_type() == SyncChange::ACTION_DELETE && existing_turl) { | |
681 Remove(existing_turl); | |
682 } else if (iter->change_type() == SyncChange::ACTION_ADD && | |
683 !existing_turl) { | |
684 if (existing_keyword_turl) | |
685 ResolveSyncKeywordConflict(turl.get(), new_changes); | |
686 // Force the local ID to 0 so we can add it. | |
687 turl->set_id(0); | |
688 Add(turl.release()); | |
689 } else if (iter->change_type() == SyncChange::ACTION_UPDATE && | |
690 existing_turl) { | |
691 if (existing_keyword_turl) | |
692 ResolveSyncKeywordConflict(turl.get(), new_changes); | |
693 ResetTemplateURL(existing_turl, turl->short_name(), turl->keyword(), | |
694 turl->url() ? turl->url()->url() : std::string()); | |
695 } else { | |
696 // Something really unexpected happened. Either we received an | |
697 // ACTION_INVALID, or Sync is in a crazy state: | |
698 // . Trying to DELETE or UPDATE a non-existent search engine. | |
699 // . Trying to ADD a search engine that already exists. | |
700 LOG(ERROR) << "Unexpected sync change state."; | |
701 NOTREACHED(); | |
702 } | |
703 } | |
704 | |
705 SyncError sync_error = | |
706 sync_processor_->ProcessSyncChanges(from_here, new_changes); | |
707 if (sync_error.IsSet()) | |
708 return sync_error; | |
709 | |
710 return SyncError(); | |
711 } | |
712 | |
713 SyncError TemplateURLService::MergeDataAndStartSyncing( | |
714 syncable::ModelType type, | |
715 const SyncDataList& initial_sync_data, | |
716 SyncChangeProcessor* sync_processor) { | |
717 DCHECK_EQ(type, SEARCH_ENGINES); | |
718 DCHECK(!sync_processor_); | |
719 sync_processor_ = sync_processor; | |
720 | |
721 // We do a lot of calls to Add/Remove/ResetTemplateURL here, so ensure we | |
722 // don't step on our own toes. | |
723 AutoReset<bool> processing_changes(&processing_syncer_changes_, true); | |
724 | |
725 SyncChangeList new_changes; | |
726 | |
727 // Build maps of our sync GUIDs to SyncData. | |
728 SyncDataMap local_data_map = CreateGUIDToSyncDataMap( | |
729 GetAllSyncData(SEARCH_ENGINES)); | |
730 SyncDataMap sync_data_map = CreateGUIDToSyncDataMap(initial_sync_data); | |
731 | |
732 for (SyncDataMap::const_iterator iter = sync_data_map.begin(); | |
733 iter != sync_data_map.end(); ++iter) { | |
734 const TemplateURL* sync_turl = ReadSearchEngineSyncData(iter->second); | |
735 DCHECK(sync_turl); | |
736 const TemplateURL* local_turl = GetTemplateURLForGUID(iter->first); | |
737 | |
738 if (local_turl) { | |
739 // This local search engine is already synced. If the timestamp differs | |
740 // from Sync, we need to update locally or to the cloud. Note that if the | |
741 // timestamps are equal, we touch neither. | |
742 if (sync_turl->last_modified() > local_turl->last_modified()) { | |
743 // TODO(stevet): For now we just reset the local TemplateURL with the | |
744 // more important Sync data fields. We may want to transfer over | |
745 // additional fields. | |
746 ResetTemplateURL( | |
747 local_turl, | |
748 sync_turl->short_name(), | |
749 sync_turl->keyword(), | |
750 sync_turl->url() ? sync_turl->url()->url() : std::string()); | |
751 } else if (sync_turl->last_modified() < local_turl->last_modified()) { | |
752 new_changes.push_back(SyncChange(SyncChange::ACTION_UPDATE, | |
753 local_data_map[local_turl->sync_guid()])); | |
754 } | |
755 local_data_map.erase(iter->first); | |
756 } else { | |
757 // The search engine from the cloud has not been synced locally, but there | |
758 // might be a local search engine that is a duplicate that needs to be | |
759 // merged. | |
760 local_turl = FindDuplicateOfSyncTemplateURL(*sync_turl); | |
761 TemplateURL* modifiable_sync_turl = const_cast<TemplateURL*>(sync_turl); | |
762 if (local_turl) { | |
763 // Merge duplicates and remove the processed local TURL from the map. | |
764 TemplateURL* modifiable_local_turl = | |
765 const_cast<TemplateURL*>(local_turl); | |
766 std::string old_guid = local_turl->sync_guid(); | |
767 MergeSyncAndLocalURLDuplicates(modifiable_sync_turl, | |
768 modifiable_local_turl, | |
769 new_changes); | |
770 local_data_map.erase(old_guid); | |
771 } else { | |
772 // Keyword conflict is possible in this case. Resolve it first before | |
773 // adding the new TemplateURL. Note that we don't remove the local TURL | |
774 // from local_data_map in this case as it may still need to be pushed to | |
775 // the cloud. | |
776 ResolveSyncKeywordConflict(modifiable_sync_turl, new_changes); | |
777 // Force the local ID to 0 so we can add it. | |
778 modifiable_sync_turl->set_id(0); | |
779 Add(modifiable_sync_turl); | |
780 } | |
781 } | |
782 } // for | |
783 | |
784 // The remaining SyncData in local_data_map should be everything that needs to | |
785 // be pushed as ADDs to sync. | |
786 for (SyncDataMap::const_iterator iter = local_data_map.begin(); | |
787 iter != local_data_map.end(); ++iter) { | |
788 new_changes.push_back(SyncChange(SyncChange::ACTION_ADD, iter->second)); | |
789 } | |
790 | |
791 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes); | |
792 if (error.IsSet()) | |
793 return error; | |
794 | |
795 models_associated_ = true; | |
796 return SyncError(); | |
797 } | |
798 | |
799 void TemplateURLService::StopSyncing(syncable::ModelType type) { | |
800 DCHECK_EQ(type, SEARCH_ENGINES); | |
801 models_associated_ = false; | |
802 sync_processor_ = NULL; | |
803 } | |
804 | |
805 void TemplateURLService::ProcessTemplateURLChange( | |
806 const TemplateURL* turl, | |
807 SyncChange::SyncChangeType type) { | |
808 DCHECK_NE(type, SyncChange::ACTION_INVALID); | |
809 DCHECK(turl); | |
810 | |
811 if (!models_associated_) | |
812 return; // Not syncing. | |
813 | |
814 if (processing_syncer_changes_) | |
815 return; // These are changes originating from us. Ignore. | |
816 | |
817 // Avoid syncing Extension keywords. | |
818 if (turl->IsExtensionKeyword()) | |
819 return; | |
820 | |
821 SyncChangeList changes; | |
822 | |
823 AutoReset<bool> processing_changes(&processing_syncer_changes_, true); | |
824 | |
825 SyncData sync_data; | |
826 if (!CreateSearchEngineSyncData(*turl, &sync_data)) { | |
827 LOG(ERROR) << "Failed to update preference."; | |
828 return; | |
829 } | |
830 changes.push_back(SyncChange(type, sync_data)); | |
831 | |
832 sync_processor_->ProcessSyncChanges(FROM_HERE, changes); | |
833 } | |
834 | |
607 // static | 835 // static |
608 void TemplateURLService::RegisterUserPrefs(PrefService* prefs) { | 836 void TemplateURLService::RegisterUserPrefs(PrefService* prefs) { |
609 prefs->RegisterBooleanPref(prefs::kDefaultSearchProviderEnabled, | 837 prefs->RegisterBooleanPref(prefs::kDefaultSearchProviderEnabled, |
610 true, | 838 true, |
611 PrefService::UNSYNCABLE_PREF); | 839 PrefService::UNSYNCABLE_PREF); |
612 prefs->RegisterStringPref(prefs::kDefaultSearchProviderName, | 840 prefs->RegisterStringPref(prefs::kDefaultSearchProviderName, |
613 std::string(), | 841 std::string(), |
614 PrefService::UNSYNCABLE_PREF); | 842 PrefService::UNSYNCABLE_PREF); |
615 prefs->RegisterStringPref(prefs::kDefaultSearchProviderID, | 843 prefs->RegisterStringPref(prefs::kDefaultSearchProviderID, |
616 std::string(), | 844 std::string(), |
(...skipping 14 matching lines...) Expand all Loading... | |
631 std::string(), | 859 std::string(), |
632 PrefService::UNSYNCABLE_PREF); | 860 PrefService::UNSYNCABLE_PREF); |
633 prefs->RegisterStringPref(prefs::kDefaultSearchProviderIconURL, | 861 prefs->RegisterStringPref(prefs::kDefaultSearchProviderIconURL, |
634 std::string(), | 862 std::string(), |
635 PrefService::UNSYNCABLE_PREF); | 863 PrefService::UNSYNCABLE_PREF); |
636 prefs->RegisterStringPref(prefs::kDefaultSearchProviderEncodings, | 864 prefs->RegisterStringPref(prefs::kDefaultSearchProviderEncodings, |
637 std::string(), | 865 std::string(), |
638 PrefService::UNSYNCABLE_PREF); | 866 PrefService::UNSYNCABLE_PREF); |
639 } | 867 } |
640 | 868 |
869 // static | |
870 bool TemplateURLService::CreateSearchEngineSyncData(const TemplateURL& turl, | |
871 SyncData* sync_data) { | |
872 DCHECK(sync_data); | |
873 | |
874 sync_pb::EntitySpecifics specifics; | |
875 sync_pb::SearchEngineSpecifics* se_specifics = specifics.MutableExtension( | |
876 sync_pb::search_engine); | |
877 se_specifics->set_short_name(UTF16ToUTF8(turl.short_name())); | |
878 se_specifics->set_keyword(UTF16ToUTF8(turl.keyword())); | |
879 se_specifics->set_favicon_url(turl.GetFaviconURL().spec()); | |
880 se_specifics->set_url(turl.url() ? turl.url()->url() : std::string()); | |
881 se_specifics->set_safe_for_autoreplace(turl.safe_for_autoreplace()); | |
882 se_specifics->set_originating_url(turl.originating_url().spec()); | |
883 se_specifics->set_date_created(turl.date_created().ToInternalValue()); | |
884 se_specifics->set_input_encodings(JoinString(turl.input_encodings(), ';')); | |
885 se_specifics->set_show_in_default_list(turl.show_in_default_list()); | |
886 se_specifics->set_suggestions_url(turl.suggestions_url() ? | |
887 turl.suggestions_url()->url() : std::string()); | |
888 se_specifics->set_prepopulate_id(turl.prepopulate_id()); | |
889 se_specifics->set_autogenerate_keyword(turl.autogenerate_keyword()); | |
890 se_specifics->set_logo_id(turl.logo_id()); | |
891 se_specifics->set_created_by_policy(turl.created_by_policy()); | |
892 se_specifics->set_instant_url(turl.instant_url() ? | |
893 turl.instant_url()->url() : std::string()); | |
894 se_specifics->set_id(turl.id()); | |
895 se_specifics->set_last_modified(turl.last_modified().ToInternalValue()); | |
896 se_specifics->set_sync_guid(turl.sync_guid()); | |
897 *sync_data = SyncData::CreateLocalData(se_specifics->sync_guid(), | |
898 se_specifics->keyword(), | |
899 specifics); | |
900 return true; | |
901 } | |
902 | |
903 // static | |
904 TemplateURL* TemplateURLService::ReadSearchEngineSyncData( | |
905 const SyncData& sync_data) { | |
906 sync_pb::SearchEngineSpecifics specifics = | |
907 sync_data.GetSpecifics().GetExtension(sync_pb::search_engine); | |
908 TemplateURL* turl = new TemplateURL(); | |
909 turl->set_short_name(UTF8ToUTF16(specifics.short_name())); | |
910 turl->set_keyword(UTF8ToUTF16(specifics.keyword())); | |
911 turl->SetFaviconURL(GURL(specifics.favicon_url())); | |
912 turl->SetURL(specifics.url(), 0, 0); | |
913 turl->set_safe_for_autoreplace(specifics.safe_for_autoreplace()); | |
914 turl->set_originating_url(GURL(specifics.originating_url())); | |
915 turl->set_date_created( | |
916 base::Time::FromInternalValue(specifics.date_created())); | |
917 std::vector<std::string> input_encodings; | |
918 base::SplitString(specifics.input_encodings(), ';', &input_encodings); | |
919 turl->set_input_encodings(input_encodings); | |
920 turl->set_show_in_default_list(specifics.show_in_default_list()); | |
921 turl->SetSuggestionsURL(specifics.suggestions_url(), 0, 0); | |
922 turl->SetPrepopulateId(specifics.prepopulate_id()); | |
923 turl->set_autogenerate_keyword(specifics.autogenerate_keyword()); | |
924 turl->set_logo_id(specifics.logo_id()); | |
925 turl->set_created_by_policy(specifics.created_by_policy()); | |
926 turl->SetInstantURL(specifics.instant_url(), 0, 0); | |
927 turl->set_id(specifics.id()); | |
928 turl->set_last_modified( | |
929 base::Time::FromInternalValue(specifics.last_modified())); | |
930 turl->set_sync_guid(specifics.sync_guid()); | |
931 return turl; | |
932 } | |
933 | |
934 string16 TemplateURLService::UniquifyKeyword(const TemplateURL& turl) const { | |
935 // Already unique. | |
936 if (!GetTemplateURLForKeyword(turl.keyword())) | |
937 return turl.keyword(); | |
938 | |
939 // First, try to return the generated keyword for the TemplateURL. | |
940 string16 keyword_candidate = GenerateKeyword( | |
941 turl.url() ? GURL(turl.url()->url()) : GURL(), true); | |
942 if (!GetTemplateURLForKeyword(keyword_candidate) && | |
943 !keyword_candidate.empty()) { | |
944 return keyword_candidate; | |
945 } | |
946 | |
947 // We try to uniquify the keyword by appending a special character to the end. | |
948 // This is a best-effort approach where we try to preserve the original | |
949 // keyword and let the user do what they will after our attempt. | |
950 keyword_candidate = turl.keyword(); | |
951 do { | |
952 keyword_candidate.append(UTF8ToUTF16("_")); | |
953 } while (GetTemplateURLForKeyword(keyword_candidate)); | |
954 | |
955 return keyword_candidate; | |
956 } | |
957 | |
958 bool TemplateURLService::ResolveSyncKeywordConflict( | |
959 TemplateURL* sync_turl, | |
960 SyncChangeList& change_list) { | |
961 DCHECK(sync_turl); | |
962 | |
963 const TemplateURL* existing_turl = | |
964 GetTemplateURLForKeyword(sync_turl->keyword()); | |
965 if (!existing_turl) | |
966 return false; | |
967 | |
968 string16 new_keyword; | |
969 if (existing_turl->last_modified() > sync_turl->last_modified()) { | |
970 new_keyword = UniquifyKeyword(*sync_turl); | |
971 DCHECK(!GetTemplateURLForKeyword(new_keyword)); | |
972 sync_turl->set_keyword(new_keyword); | |
973 // If we update the cloud TURL, we need to push an update back to sync | |
974 // informing it that something has changed. | |
975 SyncData sync_data; | |
976 if (!CreateSearchEngineSyncData(*sync_turl, &sync_data)) { | |
977 LOG(ERROR) << "Failed to update search engine."; | |
978 return false; | |
979 } | |
980 change_list.push_back(SyncChange(SyncChange::ACTION_UPDATE, sync_data)); | |
981 } else { | |
982 new_keyword = UniquifyKeyword(*existing_turl); | |
983 ResetTemplateURL( | |
984 existing_turl, | |
Peter Kasting
2011/08/09 21:31:04
Nit: No need for one-arg-per-line or putting even
SteveT
2011/08/10 15:15:12
Cool. Hope this works for you. It was mostly the l
| |
985 existing_turl->short_name(), | |
986 new_keyword, | |
987 existing_turl->url() ? existing_turl->url()->url() : std::string()); | |
988 } | |
989 return true; | |
990 } | |
991 | |
992 const TemplateURL* TemplateURLService::FindDuplicateOfSyncTemplateURL( | |
993 const TemplateURL& sync_turl) { | |
994 const TemplateURL* existing_turl = | |
995 GetTemplateURLForKeyword(sync_turl.keyword()); | |
996 if (!existing_turl) | |
997 return NULL; | |
998 | |
999 if (existing_turl->url() && sync_turl.url() && | |
1000 existing_turl->url()->url() == sync_turl.url()->url()) { | |
1001 return existing_turl; | |
1002 } | |
1003 return NULL; | |
1004 } | |
1005 | |
1006 void TemplateURLService::MergeSyncAndLocalURLDuplicates( | |
1007 TemplateURL* sync_turl, | |
1008 TemplateURL* local_turl, | |
1009 SyncChangeList& change_list) { | |
1010 DCHECK(sync_turl); | |
1011 DCHECK(local_turl); | |
1012 | |
1013 if (sync_turl->last_modified() > local_turl->last_modified()) { | |
1014 // Fully replace local_url with Sync's copy. Note that because use Add | |
1015 // rather than ResetTemplateURL, |sync_url| is added with a fresh | |
1016 // TemplateURLID. We don't need to sync the new ID back to the server since | |
1017 // it's only relevant locally. | |
1018 Remove(local_turl); | |
1019 // Force the local ID to 0 so we can add it. | |
1020 sync_turl->set_id(0); | |
1021 Add(sync_turl); | |
1022 } else { | |
1023 // Change the local TURL's GUID to the server's GUID and push an update to | |
1024 // Sync. This ensures that the rest of local_url's fields are sync'd up to | |
1025 // the server, and the next time local_url is synced, it is recognized by | |
1026 // having the same GUID. We ensure that the local_turl's new GUID is | |
1027 // persisted to the database by calling ResetTemplateURL. | |
1028 ResetTemplateURL( | |
1029 local_turl, | |
1030 local_turl->short_name(), | |
1031 local_turl->keyword(), | |
1032 local_turl->url() ? local_turl->url()->url() : std::string(), | |
1033 sync_turl->sync_guid()); | |
1034 SyncData sync_data; | |
1035 if (!CreateSearchEngineSyncData(*local_turl, &sync_data)) { | |
1036 LOG(ERROR) << "Failed to update search engine."; | |
1037 return; | |
1038 } | |
1039 change_list.push_back(SyncChange(SyncChange::ACTION_UPDATE, sync_data)); | |
1040 } | |
1041 } | |
1042 | |
1043 // static | |
1044 SyncDataMap TemplateURLService::CreateGUIDToSyncDataMap( | |
1045 const SyncDataList& sync_data) { | |
1046 SyncDataMap data_map; | |
1047 SyncDataList::const_iterator iter; | |
1048 for (iter = sync_data.begin(); iter != sync_data.end(); ++iter) { | |
1049 data_map[iter->GetSpecifics().GetExtension( | |
1050 sync_pb::search_engine).sync_guid()] = *iter; | |
1051 } | |
1052 return data_map; | |
1053 } | |
1054 | |
641 void TemplateURLService::SetKeywordSearchTermsForURL(const TemplateURL* t_url, | 1055 void TemplateURLService::SetKeywordSearchTermsForURL(const TemplateURL* t_url, |
642 const GURL& url, | 1056 const GURL& url, |
643 const string16& term) { | 1057 const string16& term) { |
644 HistoryService* history = profile_ ? | 1058 HistoryService* history = profile_ ? |
645 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS) : NULL; | 1059 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS) : NULL; |
646 if (!history) | 1060 if (!history) |
647 return; | 1061 return; |
648 history->SetKeywordSearchTermsForURL(url, t_url->id(), term); | 1062 history->SetKeywordSearchTermsForURL(url, t_url->id(), term); |
649 } | 1063 } |
650 | 1064 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
706 if (!env->HasVar(env_vars::kHeadless) && | 1120 if (!env->HasVar(env_vars::kHeadless) && |
707 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kChromeFrame)) | 1121 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kChromeFrame)) |
708 GoogleURLTracker::RequestServerCheck(); | 1122 GoogleURLTracker::RequestServerCheck(); |
709 } | 1123 } |
710 } | 1124 } |
711 } | 1125 } |
712 | 1126 |
713 void TemplateURLService::RemoveFromMaps(const TemplateURL* template_url) { | 1127 void TemplateURLService::RemoveFromMaps(const TemplateURL* template_url) { |
714 if (!template_url->keyword().empty()) | 1128 if (!template_url->keyword().empty()) |
715 keyword_to_template_map_.erase(template_url->keyword()); | 1129 keyword_to_template_map_.erase(template_url->keyword()); |
1130 if (!template_url->sync_guid().empty()) | |
1131 guid_to_template_map_.erase(template_url->sync_guid()); | |
716 if (loaded_) | 1132 if (loaded_) |
717 provider_map_.Remove(template_url); | 1133 provider_map_.Remove(template_url); |
718 } | 1134 } |
719 | 1135 |
720 void TemplateURLService::RemoveFromKeywordMapByPointer( | 1136 void TemplateURLService::RemoveFromKeywordMapByPointer( |
721 const TemplateURL* template_url) { | 1137 const TemplateURL* template_url) { |
722 DCHECK(template_url); | 1138 DCHECK(template_url); |
723 for (KeywordToTemplateMap::iterator i = keyword_to_template_map_.begin(); | 1139 for (KeywordToTemplateMap::iterator i = keyword_to_template_map_.begin(); |
724 i != keyword_to_template_map_.end(); ++i) { | 1140 i != keyword_to_template_map_.end(); ++i) { |
725 if (i->second == template_url) { | 1141 if (i->second == template_url) { |
726 keyword_to_template_map_.erase(i); | 1142 keyword_to_template_map_.erase(i); |
727 // A given TemplateURL only occurs once in the map. As soon as we find the | 1143 // A given TemplateURL only occurs once in the map. As soon as we find the |
728 // entry, stop. | 1144 // entry, stop. |
729 break; | 1145 break; |
730 } | 1146 } |
731 } | 1147 } |
732 } | 1148 } |
733 | 1149 |
734 void TemplateURLService::AddToMaps(const TemplateURL* template_url) { | 1150 void TemplateURLService::AddToMaps(const TemplateURL* template_url) { |
735 if (!template_url->keyword().empty()) | 1151 if (!template_url->keyword().empty()) |
736 keyword_to_template_map_[template_url->keyword()] = template_url; | 1152 keyword_to_template_map_[template_url->keyword()] = template_url; |
1153 if (!template_url->sync_guid().empty()) | |
1154 guid_to_template_map_[template_url->sync_guid()] = template_url; | |
737 if (loaded_) { | 1155 if (loaded_) { |
738 UIThreadSearchTermsData search_terms_data; | 1156 UIThreadSearchTermsData search_terms_data; |
739 provider_map_.Add(template_url, search_terms_data); | 1157 provider_map_.Add(template_url, search_terms_data); |
740 } | 1158 } |
741 } | 1159 } |
742 | 1160 |
743 void TemplateURLService::SetTemplateURLs( | 1161 void TemplateURLService::SetTemplateURLs( |
744 const std::vector<TemplateURL*>& urls) { | 1162 const std::vector<TemplateURL*>& urls) { |
745 // Add mappings for the new items. | 1163 // Add mappings for the new items. |
746 | 1164 |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
926 | 1344 |
927 void TemplateURLService::UpdateNoNotify(const TemplateURL* existing_turl, | 1345 void TemplateURLService::UpdateNoNotify(const TemplateURL* existing_turl, |
928 const TemplateURL& new_values) { | 1346 const TemplateURL& new_values) { |
929 DCHECK(loaded_); | 1347 DCHECK(loaded_); |
930 DCHECK(existing_turl); | 1348 DCHECK(existing_turl); |
931 DCHECK(find(template_urls_.begin(), template_urls_.end(), existing_turl) != | 1349 DCHECK(find(template_urls_.begin(), template_urls_.end(), existing_turl) != |
932 template_urls_.end()); | 1350 template_urls_.end()); |
933 | 1351 |
934 if (!existing_turl->keyword().empty()) | 1352 if (!existing_turl->keyword().empty()) |
935 keyword_to_template_map_.erase(existing_turl->keyword()); | 1353 keyword_to_template_map_.erase(existing_turl->keyword()); |
1354 if (!existing_turl->sync_guid().empty()) | |
1355 guid_to_template_map_.erase(existing_turl->sync_guid()); | |
936 | 1356 |
937 // This call handles copying over the values (while retaining the id). | 1357 // This call handles copying over the values (while retaining the id). |
938 UIThreadSearchTermsData search_terms_data; | 1358 UIThreadSearchTermsData search_terms_data; |
939 provider_map_.Update(existing_turl, new_values, search_terms_data); | 1359 provider_map_.Update(existing_turl, new_values, search_terms_data); |
940 | 1360 |
941 if (!existing_turl->keyword().empty()) | 1361 if (!existing_turl->keyword().empty()) |
942 keyword_to_template_map_[existing_turl->keyword()] = existing_turl; | 1362 keyword_to_template_map_[existing_turl->keyword()] = existing_turl; |
1363 if (!existing_turl->sync_guid().empty()) | |
1364 guid_to_template_map_[existing_turl->sync_guid()] = existing_turl; | |
943 | 1365 |
944 if (service_.get()) | 1366 if (service_.get()) |
945 service_->UpdateKeyword(*existing_turl); | 1367 service_->UpdateKeyword(*existing_turl); |
946 | 1368 |
1369 // Inform sync of the update. | |
1370 ProcessTemplateURLChange(existing_turl, SyncChange::ACTION_UPDATE); | |
1371 | |
947 if (default_search_provider_ == existing_turl) | 1372 if (default_search_provider_ == existing_turl) |
948 SetDefaultSearchProviderNoNotify(existing_turl); | 1373 SetDefaultSearchProviderNoNotify(existing_turl); |
949 } | 1374 } |
950 | 1375 |
951 PrefService* TemplateURLService::GetPrefs() { | 1376 PrefService* TemplateURLService::GetPrefs() { |
952 return profile_ ? profile_->GetPrefs() : NULL; | 1377 return profile_ ? profile_->GetPrefs() : NULL; |
953 } | 1378 } |
954 | 1379 |
955 void TemplateURLService::UpdateKeywordSearchTermsForURL( | 1380 void TemplateURLService::UpdateKeywordSearchTermsForURL( |
956 const history::URLVisitedDetails& details) { | 1381 const history::URLVisitedDetails& details) { |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1233 DCHECK(template_url); | 1658 DCHECK(template_url); |
1234 DCHECK(template_url->id() == 0); | 1659 DCHECK(template_url->id() == 0); |
1235 DCHECK(find(template_urls_.begin(), template_urls_.end(), template_url) == | 1660 DCHECK(find(template_urls_.begin(), template_urls_.end(), template_url) == |
1236 template_urls_.end()); | 1661 template_urls_.end()); |
1237 template_url->set_id(++next_id_); | 1662 template_url->set_id(++next_id_); |
1238 template_urls_.push_back(template_url); | 1663 template_urls_.push_back(template_url); |
1239 AddToMaps(template_url); | 1664 AddToMaps(template_url); |
1240 | 1665 |
1241 if (service_.get()) | 1666 if (service_.get()) |
1242 service_->AddKeyword(*template_url); | 1667 service_->AddKeyword(*template_url); |
1668 | |
1669 // Inform sync of the addition. Note that this will assign a GUID to | |
1670 // template_url and add it to the guid_to_template_map_. | |
1671 ProcessTemplateURLChange(template_url, SyncChange::ACTION_ADD); | |
1243 } | 1672 } |
1244 | 1673 |
1245 void TemplateURLService::RemoveNoNotify(const TemplateURL* template_url) { | 1674 void TemplateURLService::RemoveNoNotify(const TemplateURL* template_url) { |
1246 TemplateURLVector::iterator i = find(template_urls_.begin(), | 1675 TemplateURLVector::iterator i = find(template_urls_.begin(), |
1247 template_urls_.end(), | 1676 template_urls_.end(), |
1248 template_url); | 1677 template_url); |
1249 if (i == template_urls_.end()) | 1678 if (i == template_urls_.end()) |
1250 return; | 1679 return; |
1251 | 1680 |
1252 if (template_url == default_search_provider_) { | 1681 if (template_url == default_search_provider_) { |
1253 // Should never delete the default search provider. | 1682 // Should never delete the default search provider. |
1254 NOTREACHED(); | 1683 NOTREACHED(); |
1255 return; | 1684 return; |
1256 } | 1685 } |
1257 | 1686 |
1258 RemoveFromMaps(template_url); | 1687 RemoveFromMaps(template_url); |
1259 | 1688 |
1260 // Remove it from the vector containing all TemplateURLs. | 1689 // Remove it from the vector containing all TemplateURLs. |
1261 template_urls_.erase(i); | 1690 template_urls_.erase(i); |
1262 | 1691 |
1263 if (service_.get()) | 1692 if (service_.get()) |
1264 service_->RemoveKeyword(*template_url); | 1693 service_->RemoveKeyword(*template_url); |
1265 | 1694 |
1695 // Inform sync of the deletion. | |
1696 ProcessTemplateURLChange(template_url, SyncChange::ACTION_DELETE); | |
1697 | |
1266 if (profile_) { | 1698 if (profile_) { |
1267 Source<Profile> source(profile_); | 1699 Source<Profile> source(profile_); |
1268 TemplateURLID id = template_url->id(); | 1700 TemplateURLID id = template_url->id(); |
1269 NotificationService::current()->Notify( | 1701 NotificationService::current()->Notify( |
1270 chrome::NOTIFICATION_TEMPLATE_URL_REMOVED, | 1702 chrome::NOTIFICATION_TEMPLATE_URL_REMOVED, |
1271 source, | 1703 source, |
1272 Details<TemplateURLID>(&id)); | 1704 Details<TemplateURLID>(&id)); |
1273 } | 1705 } |
1274 | 1706 |
1275 // We own the TemplateURL and need to delete it. | 1707 // We own the TemplateURL and need to delete it. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1323 | 1755 |
1324 i = template_urls->erase(i); | 1756 i = template_urls->erase(i); |
1325 if (service_.get()) | 1757 if (service_.get()) |
1326 service_->RemoveKeyword(*template_url); | 1758 service_->RemoveKeyword(*template_url); |
1327 delete template_url; | 1759 delete template_url; |
1328 } else { | 1760 } else { |
1329 ++i; | 1761 ++i; |
1330 } | 1762 } |
1331 } | 1763 } |
1332 } | 1764 } |
OLD | NEW |