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" | |
8 #include "base/command_line.h" | 7 #include "base/command_line.h" |
9 #include "base/environment.h" | 8 #include "base/environment.h" |
10 #include "base/i18n/case_conversion.h" | 9 #include "base/i18n/case_conversion.h" |
11 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
12 #include "base/string_number_conversions.h" | 11 #include "base/string_number_conversions.h" |
13 #include "base/string_split.h" | 12 #include "base/string_split.h" |
14 #include "base/string_util.h" | 13 #include "base/string_util.h" |
15 #include "base/threading/thread_restrictions.h" | 14 #include "base/threading/thread_restrictions.h" |
16 #include "base/utf_string_conversions.h" | 15 #include "base/utf_string_conversions.h" |
17 #include "chrome/browser/extensions/extension_service.h" | 16 #include "chrome/browser/extensions/extension_service.h" |
18 #include "chrome/browser/google/google_url_tracker.h" | 17 #include "chrome/browser/google/google_url_tracker.h" |
19 #include "chrome/browser/history/history.h" | 18 #include "chrome/browser/history/history.h" |
20 #include "chrome/browser/history/history_notifications.h" | 19 #include "chrome/browser/history/history_notifications.h" |
21 #include "chrome/browser/net/url_fixer_upper.h" | 20 #include "chrome/browser/net/url_fixer_upper.h" |
22 #include "chrome/browser/prefs/pref_service.h" | 21 #include "chrome/browser/prefs/pref_service.h" |
23 #include "chrome/browser/prefs/pref_set_observer.h" | 22 #include "chrome/browser/prefs/pref_set_observer.h" |
24 #include "chrome/browser/profiles/profile.h" | 23 #include "chrome/browser/profiles/profile.h" |
25 #include "chrome/browser/rlz/rlz.h" | 24 #include "chrome/browser/rlz/rlz.h" |
26 #include "chrome/browser/search_engines/search_host_to_urls_map.h" | 25 #include "chrome/browser/search_engines/search_host_to_urls_map.h" |
27 #include "chrome/browser/search_engines/search_terms_data.h" | 26 #include "chrome/browser/search_engines/search_terms_data.h" |
28 #include "chrome/browser/search_engines/template_url.h" | 27 #include "chrome/browser/search_engines/template_url.h" |
29 #include "chrome/browser/search_engines/template_url_service_observer.h" | 28 #include "chrome/browser/search_engines/template_url_service_observer.h" |
30 #include "chrome/browser/search_engines/template_url_prepopulate_data.h" | 29 #include "chrome/browser/search_engines/template_url_prepopulate_data.h" |
31 #include "chrome/browser/search_engines/util.h" | 30 #include "chrome/browser/search_engines/util.h" |
32 #include "chrome/browser/sync/api/sync_change.h" | |
33 #include "chrome/browser/sync/protocol/search_engine_specifics.pb.h" | |
34 #include "chrome/common/chrome_notification_types.h" | 31 #include "chrome/common/chrome_notification_types.h" |
35 #include "chrome/common/chrome_switches.h" | 32 #include "chrome/common/chrome_switches.h" |
36 #include "chrome/common/env_vars.h" | 33 #include "chrome/common/env_vars.h" |
37 #include "chrome/common/extensions/extension.h" | 34 #include "chrome/common/extensions/extension.h" |
38 #include "chrome/common/guid.h" | |
39 #include "chrome/common/pref_names.h" | 35 #include "chrome/common/pref_names.h" |
40 #include "chrome/common/url_constants.h" | 36 #include "chrome/common/url_constants.h" |
41 #include "content/common/notification_service.h" | 37 #include "content/common/notification_service.h" |
42 #include "net/base/net_util.h" | 38 #include "net/base/net_util.h" |
43 #include "ui/base/l10n/l10n_util.h" | 39 #include "ui/base/l10n/l10n_util.h" |
44 | 40 |
| 41 using base::Time; |
45 typedef SearchHostToURLsMap::TemplateURLSet TemplateURLSet; | 42 typedef SearchHostToURLsMap::TemplateURLSet TemplateURLSet; |
46 typedef TemplateURLService::SyncDataMap SyncDataMap; | |
47 | 43 |
48 namespace { | 44 namespace { |
49 | 45 |
50 // String in the URL that is replaced by the search term. | 46 // String in the URL that is replaced by the search term. |
51 const char kSearchTermParameter[] = "{searchTerms}"; | 47 const char kSearchTermParameter[] = "{searchTerms}"; |
52 | 48 |
53 // String in Initializer that is replaced with kSearchTermParameter. | 49 // String in Initializer that is replaced with kSearchTermParameter. |
54 const char kTemplateParameter[] = "%s"; | 50 const char kTemplateParameter[] = "%s"; |
55 | 51 |
56 // Term used when generating a search url. Use something obscure so that on | 52 // Term used when generating a search url. Use something obscure so that on |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
101 }; | 97 }; |
102 | 98 |
103 TemplateURLService::TemplateURLService(Profile* profile) | 99 TemplateURLService::TemplateURLService(Profile* profile) |
104 : profile_(profile), | 100 : profile_(profile), |
105 loaded_(false), | 101 loaded_(false), |
106 load_failed_(false), | 102 load_failed_(false), |
107 load_handle_(0), | 103 load_handle_(0), |
108 default_search_provider_(NULL), | 104 default_search_provider_(NULL), |
109 is_default_search_managed_(false), | 105 is_default_search_managed_(false), |
110 next_id_(1), | 106 next_id_(1), |
111 time_provider_(&base::Time::Now), | 107 time_provider_(&base::Time::Now) { |
112 models_associated_(false), | |
113 processing_syncer_changes_(false), | |
114 sync_processor_(NULL) { | |
115 DCHECK(profile_); | 108 DCHECK(profile_); |
116 Init(NULL, 0); | 109 Init(NULL, 0); |
117 } | 110 } |
118 | 111 |
119 TemplateURLService::TemplateURLService(const Initializer* initializers, | 112 TemplateURLService::TemplateURLService(const Initializer* initializers, |
120 const int count) | 113 const int count) |
121 : profile_(NULL), | 114 : profile_(NULL), |
122 loaded_(false), | 115 loaded_(false), |
123 load_failed_(false), | 116 load_failed_(false), |
124 load_handle_(0), | 117 load_handle_(0), |
125 service_(NULL), | 118 service_(NULL), |
126 default_search_provider_(NULL), | 119 default_search_provider_(NULL), |
127 is_default_search_managed_(false), | 120 is_default_search_managed_(false), |
128 next_id_(1), | 121 next_id_(1), |
129 time_provider_(&base::Time::Now), | 122 time_provider_(&base::Time::Now) { |
130 models_associated_(false), | |
131 processing_syncer_changes_(false), | |
132 sync_processor_(NULL) { | |
133 Init(initializers, count); | 123 Init(initializers, count); |
134 } | 124 } |
135 | 125 |
136 TemplateURLService::~TemplateURLService() { | 126 TemplateURLService::~TemplateURLService() { |
137 if (load_handle_) { | 127 if (load_handle_) { |
138 DCHECK(service_.get()); | 128 DCHECK(service_.get()); |
139 service_->CancelRequest(load_handle_); | 129 service_->CancelRequest(load_handle_); |
140 } | 130 } |
141 | 131 |
142 STLDeleteElements(&template_urls_); | 132 STLDeleteElements(&template_urls_); |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 } | 279 } |
290 } | 280 } |
291 | 281 |
292 const TemplateURL* TemplateURLService::GetTemplateURLForKeyword( | 282 const TemplateURL* TemplateURLService::GetTemplateURLForKeyword( |
293 const string16& keyword) const { | 283 const string16& keyword) const { |
294 KeywordToTemplateMap::const_iterator elem( | 284 KeywordToTemplateMap::const_iterator elem( |
295 keyword_to_template_map_.find(keyword)); | 285 keyword_to_template_map_.find(keyword)); |
296 return (elem == keyword_to_template_map_.end()) ? NULL : elem->second; | 286 return (elem == keyword_to_template_map_.end()) ? NULL : elem->second; |
297 } | 287 } |
298 | 288 |
299 const TemplateURL* TemplateURLService::GetTemplateURLForGUID( | |
300 const std::string& sync_guid) const { | |
301 GUIDToTemplateMap::const_iterator elem( | |
302 guid_to_template_map_.find(sync_guid)); | |
303 return (elem == guid_to_template_map_.end()) ? NULL : elem->second; | |
304 } | |
305 | |
306 const TemplateURL* TemplateURLService::GetTemplateURLForHost( | 289 const TemplateURL* TemplateURLService::GetTemplateURLForHost( |
307 const std::string& host) const { | 290 const std::string& host) const { |
308 return provider_map_.GetTemplateURLForHost(host); | 291 return provider_map_.GetTemplateURLForHost(host); |
309 } | 292 } |
310 | 293 |
311 void TemplateURLService::Add(TemplateURL* template_url) { | 294 void TemplateURLService::Add(TemplateURL* template_url) { |
312 AddNoNotify(template_url); | 295 AddNoNotify(template_url); |
313 NotifyObservers(); | 296 NotifyObservers(); |
314 } | 297 } |
315 | 298 |
316 void TemplateURLService::Remove(const TemplateURL* template_url) { | 299 void TemplateURLService::Remove(const TemplateURL* template_url) { |
317 RemoveNoNotify(template_url); | 300 RemoveNoNotify(template_url); |
318 NotifyObservers(); | 301 NotifyObservers(); |
319 } | 302 } |
320 | 303 |
321 void TemplateURLService::RemoveAutoGeneratedBetween(base::Time created_after, | 304 void TemplateURLService::RemoveAutoGeneratedBetween(Time created_after, |
322 base::Time created_before) { | 305 Time created_before) { |
323 bool should_notify = false; | 306 bool should_notify = false; |
324 for (size_t i = 0; i < template_urls_.size();) { | 307 for (size_t i = 0; i < template_urls_.size();) { |
325 if (template_urls_[i]->date_created() >= created_after && | 308 if (template_urls_[i]->date_created() >= created_after && |
326 (created_before.is_null() || | 309 (created_before.is_null() || |
327 template_urls_[i]->date_created() < created_before) && | 310 template_urls_[i]->date_created() < created_before) && |
328 CanReplace(template_urls_[i])) { | 311 CanReplace(template_urls_[i])) { |
329 RemoveNoNotify(template_urls_[i]); | 312 RemoveNoNotify(template_urls_[i]); |
330 should_notify = true; | 313 should_notify = true; |
331 } else { | 314 } else { |
332 ++i; | 315 ++i; |
333 } | 316 } |
334 } | 317 } |
335 if (should_notify) | 318 if (should_notify) |
336 NotifyObservers(); | 319 NotifyObservers(); |
337 } | 320 } |
338 | 321 |
339 void TemplateURLService::RemoveAutoGeneratedSince(base::Time created_after) { | 322 void TemplateURLService::RemoveAutoGeneratedSince(Time created_after) { |
340 RemoveAutoGeneratedBetween(created_after, base::Time()); | 323 RemoveAutoGeneratedBetween(created_after, Time()); |
341 } | 324 } |
342 | 325 |
343 void TemplateURLService::RegisterExtensionKeyword(const Extension* extension) { | 326 void TemplateURLService::RegisterExtensionKeyword(const Extension* extension) { |
344 // TODO(mpcomplete): disable the keyword when the extension is disabled. | 327 // TODO(mpcomplete): disable the keyword when the extension is disabled. |
345 if (extension->omnibox_keyword().empty()) | 328 if (extension->omnibox_keyword().empty()) |
346 return; | 329 return; |
347 | 330 |
348 Load(); | 331 Load(); |
349 if (!loaded_) { | 332 if (!loaded_) { |
350 pending_extension_ids_.push_back(extension->id()); | 333 pending_extension_ids_.push_back(extension->id()); |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
614 if (!pref_name || default_search_prefs_->IsObserved(*pref_name)) { | 597 if (!pref_name || default_search_prefs_->IsObserved(*pref_name)) { |
615 // A preference related to default search engine has changed. | 598 // A preference related to default search engine has changed. |
616 // Update the model if needed. | 599 // Update the model if needed. |
617 UpdateDefaultSearch(); | 600 UpdateDefaultSearch(); |
618 } | 601 } |
619 } else { | 602 } else { |
620 NOTREACHED(); | 603 NOTREACHED(); |
621 } | 604 } |
622 } | 605 } |
623 | 606 |
624 SyncDataList TemplateURLService::GetAllSyncData( | |
625 syncable::ModelType type) const { | |
626 DCHECK_EQ(syncable::SEARCH_ENGINES, type); | |
627 | |
628 SyncDataList current_data; | |
629 for (TemplateURLVector::const_iterator iter = template_urls_.begin(); | |
630 iter != template_urls_.end(); ++iter) { | |
631 // We don't sync extension keywords. | |
632 if ((*iter)->IsExtensionKeyword()) | |
633 continue; | |
634 current_data.push_back(CreateSyncDataFromTemplateURL(**iter)); | |
635 } | |
636 | |
637 return current_data; | |
638 } | |
639 | |
640 SyncError TemplateURLService::ProcessSyncChanges( | |
641 const tracked_objects::Location& from_here, | |
642 const SyncChangeList& change_list) { | |
643 if (!models_associated_) { | |
644 SyncError error(FROM_HERE, "Models not yet associated.", | |
645 syncable::SEARCH_ENGINES); | |
646 return error; | |
647 } | |
648 | |
649 AutoReset<bool> processing_changes(&processing_syncer_changes_, true); | |
650 | |
651 SyncChangeList new_changes; | |
652 for (SyncChangeList::const_iterator iter = change_list.begin(); | |
653 iter != change_list.end(); ++iter) { | |
654 DCHECK_EQ(syncable::SEARCH_ENGINES, iter->sync_data().GetDataType()); | |
655 | |
656 scoped_ptr<TemplateURL> turl( | |
657 CreateTemplateURLFromSyncData(iter->sync_data())); | |
658 if (!turl.get()) { | |
659 NOTREACHED() << "Failed to read search engine."; | |
660 continue; | |
661 } | |
662 | |
663 const TemplateURL* existing_turl = GetTemplateURLForGUID(turl->sync_guid()); | |
664 const TemplateURL* existing_keyword_turl = | |
665 GetTemplateURLForKeyword(turl->keyword()); | |
666 | |
667 if (iter->change_type() == SyncChange::ACTION_DELETE && existing_turl) { | |
668 Remove(existing_turl); | |
669 } else if (iter->change_type() == SyncChange::ACTION_ADD && | |
670 !existing_turl) { | |
671 if (existing_keyword_turl) | |
672 ResolveSyncKeywordConflict(turl.get(), new_changes); | |
673 // Force the local ID to 0 so we can add it. | |
674 turl->set_id(0); | |
675 Add(turl.release()); | |
676 } else if (iter->change_type() == SyncChange::ACTION_UPDATE && | |
677 existing_turl) { | |
678 if (existing_keyword_turl) | |
679 ResolveSyncKeywordConflict(turl.get(), new_changes); | |
680 ResetTemplateURL(existing_turl, turl->short_name(), turl->keyword(), | |
681 turl->url() ? turl->url()->url() : std::string()); | |
682 } else { | |
683 // Something really unexpected happened. Either we received an | |
684 // ACTION_INVALID, or Sync is in a crazy state: | |
685 // . Trying to DELETE or UPDATE a non-existent search engine. | |
686 // . Trying to ADD a search engine that already exists. | |
687 NOTREACHED() << "Unexpected sync change state."; | |
688 SyncError error(FROM_HERE, "ProcessSyncChanges failed on ChangeType " + | |
689 SyncChange::ChangeTypeToString(iter->change_type()), | |
690 syncable::SEARCH_ENGINES); | |
691 return error; | |
692 } | |
693 } | |
694 | |
695 SyncError sync_error = | |
696 sync_processor_->ProcessSyncChanges(from_here, new_changes); | |
697 | |
698 return sync_error; | |
699 } | |
700 | |
701 SyncError TemplateURLService::MergeDataAndStartSyncing( | |
702 syncable::ModelType type, | |
703 const SyncDataList& initial_sync_data, | |
704 SyncChangeProcessor* sync_processor) { | |
705 DCHECK_EQ(type, syncable::SEARCH_ENGINES); | |
706 DCHECK(!sync_processor_); | |
707 sync_processor_ = sync_processor; | |
708 | |
709 // We do a lot of calls to Add/Remove/ResetTemplateURL here, so ensure we | |
710 // don't step on our own toes. | |
711 AutoReset<bool> processing_changes(&processing_syncer_changes_, true); | |
712 | |
713 SyncChangeList new_changes; | |
714 | |
715 // Build maps of our sync GUIDs to SyncData. | |
716 SyncDataMap local_data_map = CreateGUIDToSyncDataMap( | |
717 GetAllSyncData(syncable::SEARCH_ENGINES)); | |
718 SyncDataMap sync_data_map = CreateGUIDToSyncDataMap(initial_sync_data); | |
719 | |
720 for (SyncDataMap::const_iterator iter = sync_data_map.begin(); | |
721 iter != sync_data_map.end(); ++iter) { | |
722 TemplateURL* sync_turl = CreateTemplateURLFromSyncData(iter->second); | |
723 DCHECK(sync_turl); | |
724 const TemplateURL* local_turl = GetTemplateURLForGUID(iter->first); | |
725 | |
726 if (local_turl) { | |
727 // This local search engine is already synced. If the timestamp differs | |
728 // from Sync, we need to update locally or to the cloud. Note that if the | |
729 // timestamps are equal, we touch neither. | |
730 if (sync_turl->last_modified() > local_turl->last_modified()) { | |
731 // TODO(stevet): For now we just reset the local TemplateURL with the | |
732 // more important Sync data fields. We may want to transfer over | |
733 // additional fields. | |
734 ResetTemplateURL( | |
735 local_turl, | |
736 sync_turl->short_name(), | |
737 sync_turl->keyword(), | |
738 sync_turl->url() ? sync_turl->url()->url() : std::string()); | |
739 } else if (sync_turl->last_modified() < local_turl->last_modified()) { | |
740 new_changes.push_back(SyncChange(SyncChange::ACTION_UPDATE, | |
741 local_data_map[local_turl->sync_guid()])); | |
742 } | |
743 local_data_map.erase(iter->first); | |
744 } else { | |
745 // The search engine from the cloud has not been synced locally, but there | |
746 // might be a local search engine that is a duplicate that needs to be | |
747 // merged. | |
748 const TemplateURL* dupe_turl = FindDuplicateOfSyncTemplateURL(*sync_turl); | |
749 if (dupe_turl) { | |
750 // Merge duplicates and remove the processed local TURL from the map. | |
751 TemplateURL* modifiable_dupe_turl = | |
752 const_cast<TemplateURL*>(dupe_turl); | |
753 std::string old_guid = dupe_turl->sync_guid(); | |
754 MergeSyncAndLocalURLDuplicates(sync_turl, | |
755 modifiable_dupe_turl, | |
756 new_changes); | |
757 local_data_map.erase(old_guid); | |
758 } else { | |
759 // Keyword conflict is possible in this case. Resolve it first before | |
760 // adding the new TemplateURL. Note that we don't remove the local TURL | |
761 // from local_data_map in this case as it may still need to be pushed to | |
762 // the cloud. | |
763 ResolveSyncKeywordConflict(sync_turl, new_changes); | |
764 // Force the local ID to 0 so we can add it. | |
765 sync_turl->set_id(0); | |
766 Add(sync_turl); | |
767 } | |
768 } | |
769 } // for | |
770 | |
771 // The remaining SyncData in local_data_map should be everything that needs to | |
772 // be pushed as ADDs to sync. | |
773 for (SyncDataMap::const_iterator iter = local_data_map.begin(); | |
774 iter != local_data_map.end(); ++iter) { | |
775 new_changes.push_back(SyncChange(SyncChange::ACTION_ADD, iter->second)); | |
776 } | |
777 | |
778 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes); | |
779 if (error.IsSet()) | |
780 return error; | |
781 | |
782 models_associated_ = true; | |
783 return SyncError(); | |
784 } | |
785 | |
786 void TemplateURLService::StopSyncing(syncable::ModelType type) { | |
787 DCHECK_EQ(type, syncable::SEARCH_ENGINES); | |
788 models_associated_ = false; | |
789 sync_processor_ = NULL; | |
790 } | |
791 | |
792 void TemplateURLService::ProcessTemplateURLChange( | |
793 const TemplateURL* turl, | |
794 SyncChange::SyncChangeType type) { | |
795 DCHECK_NE(type, SyncChange::ACTION_INVALID); | |
796 DCHECK(turl); | |
797 | |
798 if (!models_associated_) | |
799 return; // Not syncing. | |
800 | |
801 if (processing_syncer_changes_) | |
802 return; // These are changes originating from us. Ignore. | |
803 | |
804 // Avoid syncing Extension keywords. | |
805 if (turl->IsExtensionKeyword()) | |
806 return; | |
807 | |
808 SyncChangeList changes; | |
809 | |
810 SyncData sync_data = CreateSyncDataFromTemplateURL(*turl); | |
811 changes.push_back(SyncChange(type, sync_data)); | |
812 | |
813 sync_processor_->ProcessSyncChanges(FROM_HERE, changes); | |
814 } | |
815 | |
816 // static | 607 // static |
817 void TemplateURLService::RegisterUserPrefs(PrefService* prefs) { | 608 void TemplateURLService::RegisterUserPrefs(PrefService* prefs) { |
818 prefs->RegisterBooleanPref(prefs::kDefaultSearchProviderEnabled, | 609 prefs->RegisterBooleanPref(prefs::kDefaultSearchProviderEnabled, |
819 true, | 610 true, |
820 PrefService::UNSYNCABLE_PREF); | 611 PrefService::UNSYNCABLE_PREF); |
821 prefs->RegisterStringPref(prefs::kDefaultSearchProviderName, | 612 prefs->RegisterStringPref(prefs::kDefaultSearchProviderName, |
822 std::string(), | 613 std::string(), |
823 PrefService::UNSYNCABLE_PREF); | 614 PrefService::UNSYNCABLE_PREF); |
824 prefs->RegisterStringPref(prefs::kDefaultSearchProviderID, | 615 prefs->RegisterStringPref(prefs::kDefaultSearchProviderID, |
825 std::string(), | 616 std::string(), |
(...skipping 14 matching lines...) Expand all Loading... |
840 std::string(), | 631 std::string(), |
841 PrefService::UNSYNCABLE_PREF); | 632 PrefService::UNSYNCABLE_PREF); |
842 prefs->RegisterStringPref(prefs::kDefaultSearchProviderIconURL, | 633 prefs->RegisterStringPref(prefs::kDefaultSearchProviderIconURL, |
843 std::string(), | 634 std::string(), |
844 PrefService::UNSYNCABLE_PREF); | 635 PrefService::UNSYNCABLE_PREF); |
845 prefs->RegisterStringPref(prefs::kDefaultSearchProviderEncodings, | 636 prefs->RegisterStringPref(prefs::kDefaultSearchProviderEncodings, |
846 std::string(), | 637 std::string(), |
847 PrefService::UNSYNCABLE_PREF); | 638 PrefService::UNSYNCABLE_PREF); |
848 } | 639 } |
849 | 640 |
850 // static | |
851 SyncData TemplateURLService::CreateSyncDataFromTemplateURL( | |
852 const TemplateURL& turl) { | |
853 sync_pb::EntitySpecifics specifics; | |
854 sync_pb::SearchEngineSpecifics* se_specifics = specifics.MutableExtension( | |
855 sync_pb::search_engine); | |
856 se_specifics->set_short_name(UTF16ToUTF8(turl.short_name())); | |
857 se_specifics->set_keyword(UTF16ToUTF8(turl.keyword())); | |
858 se_specifics->set_favicon_url(turl.GetFaviconURL().spec()); | |
859 se_specifics->set_url(turl.url() ? turl.url()->url() : std::string()); | |
860 se_specifics->set_safe_for_autoreplace(turl.safe_for_autoreplace()); | |
861 se_specifics->set_originating_url(turl.originating_url().spec()); | |
862 se_specifics->set_date_created(turl.date_created().ToInternalValue()); | |
863 se_specifics->set_input_encodings(JoinString(turl.input_encodings(), ';')); | |
864 se_specifics->set_show_in_default_list(turl.show_in_default_list()); | |
865 se_specifics->set_suggestions_url(turl.suggestions_url() ? | |
866 turl.suggestions_url()->url() : std::string()); | |
867 se_specifics->set_prepopulate_id(turl.prepopulate_id()); | |
868 se_specifics->set_autogenerate_keyword(turl.autogenerate_keyword()); | |
869 se_specifics->set_logo_id(turl.logo_id()); | |
870 se_specifics->set_created_by_policy(turl.created_by_policy()); | |
871 se_specifics->set_instant_url(turl.instant_url() ? | |
872 turl.instant_url()->url() : std::string()); | |
873 se_specifics->set_id(turl.id()); | |
874 se_specifics->set_last_modified(turl.last_modified().ToInternalValue()); | |
875 se_specifics->set_sync_guid(turl.sync_guid()); | |
876 return SyncData::CreateLocalData(se_specifics->sync_guid(), | |
877 se_specifics->keyword(), | |
878 specifics); | |
879 } | |
880 | |
881 // static | |
882 TemplateURL* TemplateURLService::CreateTemplateURLFromSyncData( | |
883 const SyncData& sync_data) { | |
884 sync_pb::SearchEngineSpecifics specifics = | |
885 sync_data.GetSpecifics().GetExtension(sync_pb::search_engine); | |
886 TemplateURL* turl = new TemplateURL(); | |
887 turl->set_short_name(UTF8ToUTF16(specifics.short_name())); | |
888 turl->set_keyword(UTF8ToUTF16(specifics.keyword())); | |
889 turl->SetFaviconURL(GURL(specifics.favicon_url())); | |
890 turl->SetURL(specifics.url(), 0, 0); | |
891 turl->set_safe_for_autoreplace(specifics.safe_for_autoreplace()); | |
892 turl->set_originating_url(GURL(specifics.originating_url())); | |
893 turl->set_date_created( | |
894 base::Time::FromInternalValue(specifics.date_created())); | |
895 std::vector<std::string> input_encodings; | |
896 base::SplitString(specifics.input_encodings(), ';', &input_encodings); | |
897 turl->set_input_encodings(input_encodings); | |
898 turl->set_show_in_default_list(specifics.show_in_default_list()); | |
899 turl->SetSuggestionsURL(specifics.suggestions_url(), 0, 0); | |
900 turl->SetPrepopulateId(specifics.prepopulate_id()); | |
901 turl->set_autogenerate_keyword(specifics.autogenerate_keyword()); | |
902 turl->set_logo_id(specifics.logo_id()); | |
903 turl->set_created_by_policy(specifics.created_by_policy()); | |
904 turl->SetInstantURL(specifics.instant_url(), 0, 0); | |
905 turl->set_id(specifics.id()); | |
906 turl->set_last_modified( | |
907 base::Time::FromInternalValue(specifics.last_modified())); | |
908 turl->set_sync_guid(specifics.sync_guid()); | |
909 return turl; | |
910 } | |
911 | |
912 // static | |
913 SyncDataMap TemplateURLService::CreateGUIDToSyncDataMap( | |
914 const SyncDataList& sync_data) { | |
915 SyncDataMap data_map; | |
916 SyncDataList::const_iterator iter; | |
917 for (iter = sync_data.begin(); iter != sync_data.end(); ++iter) { | |
918 data_map[iter->GetSpecifics().GetExtension( | |
919 sync_pb::search_engine).sync_guid()] = *iter; | |
920 } | |
921 return data_map; | |
922 } | |
923 | |
924 void TemplateURLService::SetKeywordSearchTermsForURL(const TemplateURL* t_url, | 641 void TemplateURLService::SetKeywordSearchTermsForURL(const TemplateURL* t_url, |
925 const GURL& url, | 642 const GURL& url, |
926 const string16& term) { | 643 const string16& term) { |
927 HistoryService* history = profile_ ? | 644 HistoryService* history = profile_ ? |
928 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS) : NULL; | 645 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS) : NULL; |
929 if (!history) | 646 if (!history) |
930 return; | 647 return; |
931 history->SetKeywordSearchTermsForURL(url, t_url->id(), term); | 648 history->SetKeywordSearchTermsForURL(url, t_url->id(), term); |
932 } | 649 } |
933 | 650 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
989 if (!env->HasVar(env_vars::kHeadless) && | 706 if (!env->HasVar(env_vars::kHeadless) && |
990 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kChromeFrame)) | 707 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kChromeFrame)) |
991 GoogleURLTracker::RequestServerCheck(); | 708 GoogleURLTracker::RequestServerCheck(); |
992 } | 709 } |
993 } | 710 } |
994 } | 711 } |
995 | 712 |
996 void TemplateURLService::RemoveFromMaps(const TemplateURL* template_url) { | 713 void TemplateURLService::RemoveFromMaps(const TemplateURL* template_url) { |
997 if (!template_url->keyword().empty()) | 714 if (!template_url->keyword().empty()) |
998 keyword_to_template_map_.erase(template_url->keyword()); | 715 keyword_to_template_map_.erase(template_url->keyword()); |
999 if (!template_url->sync_guid().empty()) | |
1000 guid_to_template_map_.erase(template_url->sync_guid()); | |
1001 if (loaded_) | 716 if (loaded_) |
1002 provider_map_.Remove(template_url); | 717 provider_map_.Remove(template_url); |
1003 } | 718 } |
1004 | 719 |
1005 void TemplateURLService::RemoveFromKeywordMapByPointer( | 720 void TemplateURLService::RemoveFromKeywordMapByPointer( |
1006 const TemplateURL* template_url) { | 721 const TemplateURL* template_url) { |
1007 DCHECK(template_url); | 722 DCHECK(template_url); |
1008 for (KeywordToTemplateMap::iterator i = keyword_to_template_map_.begin(); | 723 for (KeywordToTemplateMap::iterator i = keyword_to_template_map_.begin(); |
1009 i != keyword_to_template_map_.end(); ++i) { | 724 i != keyword_to_template_map_.end(); ++i) { |
1010 if (i->second == template_url) { | 725 if (i->second == template_url) { |
1011 keyword_to_template_map_.erase(i); | 726 keyword_to_template_map_.erase(i); |
1012 // A given TemplateURL only occurs once in the map. As soon as we find the | 727 // A given TemplateURL only occurs once in the map. As soon as we find the |
1013 // entry, stop. | 728 // entry, stop. |
1014 break; | 729 break; |
1015 } | 730 } |
1016 } | 731 } |
1017 } | 732 } |
1018 | 733 |
1019 void TemplateURLService::AddToMaps(const TemplateURL* template_url) { | 734 void TemplateURLService::AddToMaps(const TemplateURL* template_url) { |
1020 if (!template_url->keyword().empty()) | 735 if (!template_url->keyword().empty()) |
1021 keyword_to_template_map_[template_url->keyword()] = template_url; | 736 keyword_to_template_map_[template_url->keyword()] = template_url; |
1022 if (!template_url->sync_guid().empty()) | |
1023 guid_to_template_map_[template_url->sync_guid()] = template_url; | |
1024 if (loaded_) { | 737 if (loaded_) { |
1025 UIThreadSearchTermsData search_terms_data; | 738 UIThreadSearchTermsData search_terms_data; |
1026 provider_map_.Add(template_url, search_terms_data); | 739 provider_map_.Add(template_url, search_terms_data); |
1027 } | 740 } |
1028 } | 741 } |
1029 | 742 |
1030 void TemplateURLService::SetTemplateURLs( | 743 void TemplateURLService::SetTemplateURLs( |
1031 const std::vector<TemplateURL*>& urls) { | 744 const std::vector<TemplateURL*>& urls) { |
1032 // Add mappings for the new items. | 745 // Add mappings for the new items. |
1033 | 746 |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1213 | 926 |
1214 void TemplateURLService::UpdateNoNotify(const TemplateURL* existing_turl, | 927 void TemplateURLService::UpdateNoNotify(const TemplateURL* existing_turl, |
1215 const TemplateURL& new_values) { | 928 const TemplateURL& new_values) { |
1216 DCHECK(loaded_); | 929 DCHECK(loaded_); |
1217 DCHECK(existing_turl); | 930 DCHECK(existing_turl); |
1218 DCHECK(find(template_urls_.begin(), template_urls_.end(), existing_turl) != | 931 DCHECK(find(template_urls_.begin(), template_urls_.end(), existing_turl) != |
1219 template_urls_.end()); | 932 template_urls_.end()); |
1220 | 933 |
1221 if (!existing_turl->keyword().empty()) | 934 if (!existing_turl->keyword().empty()) |
1222 keyword_to_template_map_.erase(existing_turl->keyword()); | 935 keyword_to_template_map_.erase(existing_turl->keyword()); |
1223 if (!existing_turl->sync_guid().empty()) | |
1224 guid_to_template_map_.erase(existing_turl->sync_guid()); | |
1225 | 936 |
1226 // This call handles copying over the values (while retaining the id). | 937 // This call handles copying over the values (while retaining the id). |
1227 UIThreadSearchTermsData search_terms_data; | 938 UIThreadSearchTermsData search_terms_data; |
1228 provider_map_.Update(existing_turl, new_values, search_terms_data); | 939 provider_map_.Update(existing_turl, new_values, search_terms_data); |
1229 | 940 |
1230 if (!existing_turl->keyword().empty()) | 941 if (!existing_turl->keyword().empty()) |
1231 keyword_to_template_map_[existing_turl->keyword()] = existing_turl; | 942 keyword_to_template_map_[existing_turl->keyword()] = existing_turl; |
1232 if (!existing_turl->sync_guid().empty()) | |
1233 guid_to_template_map_[existing_turl->sync_guid()] = existing_turl; | |
1234 | 943 |
1235 if (service_.get()) | 944 if (service_.get()) |
1236 service_->UpdateKeyword(*existing_turl); | 945 service_->UpdateKeyword(*existing_turl); |
1237 | 946 |
1238 // Inform sync of the update. | |
1239 ProcessTemplateURLChange(existing_turl, SyncChange::ACTION_UPDATE); | |
1240 | |
1241 if (default_search_provider_ == existing_turl) | 947 if (default_search_provider_ == existing_turl) |
1242 SetDefaultSearchProviderNoNotify(existing_turl); | 948 SetDefaultSearchProviderNoNotify(existing_turl); |
1243 } | 949 } |
1244 | 950 |
1245 PrefService* TemplateURLService::GetPrefs() { | 951 PrefService* TemplateURLService::GetPrefs() { |
1246 return profile_ ? profile_->GetPrefs() : NULL; | 952 return profile_ ? profile_->GetPrefs() : NULL; |
1247 } | 953 } |
1248 | 954 |
1249 void TemplateURLService::UpdateKeywordSearchTermsForURL( | 955 void TemplateURLService::UpdateKeywordSearchTermsForURL( |
1250 const history::URLVisitedDetails& details) { | 956 const history::URLVisitedDetails& details) { |
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1527 DCHECK(template_url); | 1233 DCHECK(template_url); |
1528 DCHECK(template_url->id() == 0); | 1234 DCHECK(template_url->id() == 0); |
1529 DCHECK(find(template_urls_.begin(), template_urls_.end(), template_url) == | 1235 DCHECK(find(template_urls_.begin(), template_urls_.end(), template_url) == |
1530 template_urls_.end()); | 1236 template_urls_.end()); |
1531 template_url->set_id(++next_id_); | 1237 template_url->set_id(++next_id_); |
1532 template_urls_.push_back(template_url); | 1238 template_urls_.push_back(template_url); |
1533 AddToMaps(template_url); | 1239 AddToMaps(template_url); |
1534 | 1240 |
1535 if (service_.get()) | 1241 if (service_.get()) |
1536 service_->AddKeyword(*template_url); | 1242 service_->AddKeyword(*template_url); |
1537 | |
1538 // Inform sync of the addition. Note that this will assign a GUID to | |
1539 // template_url and add it to the guid_to_template_map_. | |
1540 ProcessTemplateURLChange(template_url, SyncChange::ACTION_ADD); | |
1541 } | 1243 } |
1542 | 1244 |
1543 void TemplateURLService::RemoveNoNotify(const TemplateURL* template_url) { | 1245 void TemplateURLService::RemoveNoNotify(const TemplateURL* template_url) { |
1544 TemplateURLVector::iterator i = find(template_urls_.begin(), | 1246 TemplateURLVector::iterator i = find(template_urls_.begin(), |
1545 template_urls_.end(), | 1247 template_urls_.end(), |
1546 template_url); | 1248 template_url); |
1547 if (i == template_urls_.end()) | 1249 if (i == template_urls_.end()) |
1548 return; | 1250 return; |
1549 | 1251 |
1550 if (template_url == default_search_provider_) { | 1252 if (template_url == default_search_provider_) { |
1551 // Should never delete the default search provider. | 1253 // Should never delete the default search provider. |
1552 NOTREACHED(); | 1254 NOTREACHED(); |
1553 return; | 1255 return; |
1554 } | 1256 } |
1555 | 1257 |
1556 RemoveFromMaps(template_url); | 1258 RemoveFromMaps(template_url); |
1557 | 1259 |
1558 // Remove it from the vector containing all TemplateURLs. | 1260 // Remove it from the vector containing all TemplateURLs. |
1559 template_urls_.erase(i); | 1261 template_urls_.erase(i); |
1560 | 1262 |
1561 if (service_.get()) | 1263 if (service_.get()) |
1562 service_->RemoveKeyword(*template_url); | 1264 service_->RemoveKeyword(*template_url); |
1563 | 1265 |
1564 // Inform sync of the deletion. | |
1565 ProcessTemplateURLChange(template_url, SyncChange::ACTION_DELETE); | |
1566 | |
1567 if (profile_) { | 1266 if (profile_) { |
1568 Source<Profile> source(profile_); | 1267 Source<Profile> source(profile_); |
1569 TemplateURLID id = template_url->id(); | 1268 TemplateURLID id = template_url->id(); |
1570 NotificationService::current()->Notify( | 1269 NotificationService::current()->Notify( |
1571 chrome::NOTIFICATION_TEMPLATE_URL_REMOVED, | 1270 chrome::NOTIFICATION_TEMPLATE_URL_REMOVED, |
1572 source, | 1271 source, |
1573 Details<TemplateURLID>(&id)); | 1272 Details<TemplateURLID>(&id)); |
1574 } | 1273 } |
1575 | 1274 |
1576 // We own the TemplateURL and need to delete it. | 1275 // We own the TemplateURL and need to delete it. |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1624 | 1323 |
1625 i = template_urls->erase(i); | 1324 i = template_urls->erase(i); |
1626 if (service_.get()) | 1325 if (service_.get()) |
1627 service_->RemoveKeyword(*template_url); | 1326 service_->RemoveKeyword(*template_url); |
1628 delete template_url; | 1327 delete template_url; |
1629 } else { | 1328 } else { |
1630 ++i; | 1329 ++i; |
1631 } | 1330 } |
1632 } | 1331 } |
1633 } | 1332 } |
1634 | |
1635 void TemplateURLService::ResetTemplateURLGUID(const TemplateURL* url, | |
1636 const std::string& guid) { | |
1637 DCHECK(!guid.empty()); | |
1638 | |
1639 TemplateURL new_url(*url); | |
1640 new_url.set_sync_guid(guid); | |
1641 UpdateNoNotify(url, new_url); | |
1642 } | |
1643 | |
1644 string16 TemplateURLService::UniquifyKeyword(const TemplateURL& turl) const { | |
1645 // Already unique. | |
1646 if (!GetTemplateURLForKeyword(turl.keyword())) | |
1647 return turl.keyword(); | |
1648 | |
1649 // First, try to return the generated keyword for the TemplateURL. | |
1650 string16 keyword_candidate = GenerateKeyword( | |
1651 turl.url() ? GURL(turl.url()->url()) : GURL(), true); | |
1652 if (!GetTemplateURLForKeyword(keyword_candidate) && | |
1653 !keyword_candidate.empty()) { | |
1654 return keyword_candidate; | |
1655 } | |
1656 | |
1657 // We try to uniquify the keyword by appending a special character to the end. | |
1658 // This is a best-effort approach where we try to preserve the original | |
1659 // keyword and let the user do what they will after our attempt. | |
1660 keyword_candidate = turl.keyword(); | |
1661 do { | |
1662 keyword_candidate.append(UTF8ToUTF16("_")); | |
1663 } while (GetTemplateURLForKeyword(keyword_candidate)); | |
1664 | |
1665 return keyword_candidate; | |
1666 } | |
1667 | |
1668 bool TemplateURLService::ResolveSyncKeywordConflict( | |
1669 TemplateURL* sync_turl, | |
1670 SyncChangeList& change_list) { | |
1671 DCHECK(sync_turl); | |
1672 | |
1673 const TemplateURL* existing_turl = | |
1674 GetTemplateURLForKeyword(sync_turl->keyword()); | |
1675 if (!existing_turl) | |
1676 return false; | |
1677 | |
1678 string16 new_keyword; | |
1679 if (existing_turl->last_modified() > sync_turl->last_modified()) { | |
1680 new_keyword = UniquifyKeyword(*sync_turl); | |
1681 DCHECK(!GetTemplateURLForKeyword(new_keyword)); | |
1682 sync_turl->set_keyword(new_keyword); | |
1683 // If we update the cloud TURL, we need to push an update back to sync | |
1684 // informing it that something has changed. | |
1685 SyncData sync_data = CreateSyncDataFromTemplateURL(*sync_turl); | |
1686 change_list.push_back(SyncChange(SyncChange::ACTION_UPDATE, sync_data)); | |
1687 } else { | |
1688 new_keyword = UniquifyKeyword(*existing_turl); | |
1689 ResetTemplateURL(existing_turl, existing_turl->short_name(), new_keyword, | |
1690 existing_turl->url() ? existing_turl->url()->url() : std::string()); | |
1691 } | |
1692 return true; | |
1693 } | |
1694 | |
1695 const TemplateURL* TemplateURLService::FindDuplicateOfSyncTemplateURL( | |
1696 const TemplateURL& sync_turl) { | |
1697 const TemplateURL* existing_turl = | |
1698 GetTemplateURLForKeyword(sync_turl.keyword()); | |
1699 if (!existing_turl) | |
1700 return NULL; | |
1701 | |
1702 if (existing_turl->url() && sync_turl.url() && | |
1703 existing_turl->url()->url() == sync_turl.url()->url()) { | |
1704 return existing_turl; | |
1705 } | |
1706 return NULL; | |
1707 } | |
1708 | |
1709 void TemplateURLService::MergeSyncAndLocalURLDuplicates( | |
1710 TemplateURL* sync_turl, | |
1711 TemplateURL* local_turl, | |
1712 SyncChangeList& change_list) { | |
1713 DCHECK(sync_turl); | |
1714 DCHECK(local_turl); | |
1715 | |
1716 if (sync_turl->last_modified() > local_turl->last_modified()) { | |
1717 // Fully replace local_url with Sync's copy. Note that because use Add | |
1718 // rather than ResetTemplateURL, |sync_url| is added with a fresh | |
1719 // TemplateURLID. We don't need to sync the new ID back to the server since | |
1720 // it's only relevant locally. | |
1721 Remove(local_turl); | |
1722 // Force the local ID to 0 so we can add it. | |
1723 sync_turl->set_id(0); | |
1724 Add(sync_turl); | |
1725 } else { | |
1726 // Change the local TURL's GUID to the server's GUID and push an update to | |
1727 // Sync. This ensures that the rest of local_url's fields are sync'd up to | |
1728 // the server, and the next time local_url is synced, it is recognized by | |
1729 // having the same GUID. | |
1730 ResetTemplateURLGUID(local_turl, sync_turl->sync_guid()); | |
1731 SyncData sync_data = CreateSyncDataFromTemplateURL(*local_turl); | |
1732 change_list.push_back(SyncChange(SyncChange::ACTION_UPDATE, sync_data)); | |
1733 } | |
1734 } | |
OLD | NEW |