Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(476)

Side by Side Diff: chrome/browser/search_engines/template_url_service.cc

Issue 7566036: Implement SyncableServices in TemplateURLService. Add related unittests. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Addressed zea's unittest issues. Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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"
33 #include "chrome/browser/sync/protocol/search_engine_specifics.pb.h"
31 #include "chrome/common/chrome_notification_types.h" 34 #include "chrome/common/chrome_notification_types.h"
32 #include "chrome/common/chrome_switches.h" 35 #include "chrome/common/chrome_switches.h"
33 #include "chrome/common/env_vars.h" 36 #include "chrome/common/env_vars.h"
34 #include "chrome/common/extensions/extension.h" 37 #include "chrome/common/extensions/extension.h"
38 #include "chrome/common/guid.h"
35 #include "chrome/common/pref_names.h" 39 #include "chrome/common/pref_names.h"
36 #include "chrome/common/url_constants.h" 40 #include "chrome/common/url_constants.h"
37 #include "content/common/notification_service.h" 41 #include "content/common/notification_service.h"
38 #include "net/base/net_util.h" 42 #include "net/base/net_util.h"
39 #include "ui/base/l10n/l10n_util.h" 43 #include "ui/base/l10n/l10n_util.h"
40 44
41 using base::Time;
42 typedef SearchHostToURLsMap::TemplateURLSet TemplateURLSet; 45 typedef SearchHostToURLsMap::TemplateURLSet TemplateURLSet;
46 typedef TemplateURLService::SyncDataMap SyncDataMap;
43 47
44 namespace { 48 namespace {
45 49
46 // String in the URL that is replaced by the search term. 50 // String in the URL that is replaced by the search term.
47 const char kSearchTermParameter[] = "{searchTerms}"; 51 const char kSearchTermParameter[] = "{searchTerms}";
48 52
49 // String in Initializer that is replaced with kSearchTermParameter. 53 // String in Initializer that is replaced with kSearchTermParameter.
50 const char kTemplateParameter[] = "%s"; 54 const char kTemplateParameter[] = "%s";
51 55
52 // Term used when generating a search url. Use something obscure so that on 56 // 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
97 }; 101 };
98 102
99 TemplateURLService::TemplateURLService(Profile* profile) 103 TemplateURLService::TemplateURLService(Profile* profile)
100 : profile_(profile), 104 : profile_(profile),
101 loaded_(false), 105 loaded_(false),
102 load_failed_(false), 106 load_failed_(false),
103 load_handle_(0), 107 load_handle_(0),
104 default_search_provider_(NULL), 108 default_search_provider_(NULL),
105 is_default_search_managed_(false), 109 is_default_search_managed_(false),
106 next_id_(1), 110 next_id_(1),
107 time_provider_(&base::Time::Now) { 111 time_provider_(&base::Time::Now),
112 models_associated_(false),
113 processing_syncer_changes_(false),
114 sync_processor_(NULL) {
108 DCHECK(profile_); 115 DCHECK(profile_);
109 Init(NULL, 0); 116 Init(NULL, 0);
110 } 117 }
111 118
112 TemplateURLService::TemplateURLService(const Initializer* initializers, 119 TemplateURLService::TemplateURLService(const Initializer* initializers,
113 const int count) 120 const int count)
114 : profile_(NULL), 121 : profile_(NULL),
115 loaded_(false), 122 loaded_(false),
116 load_failed_(false), 123 load_failed_(false),
117 load_handle_(0), 124 load_handle_(0),
118 service_(NULL), 125 service_(NULL),
119 default_search_provider_(NULL), 126 default_search_provider_(NULL),
120 is_default_search_managed_(false), 127 is_default_search_managed_(false),
121 next_id_(1), 128 next_id_(1),
122 time_provider_(&base::Time::Now) { 129 time_provider_(&base::Time::Now),
130 models_associated_(false),
131 processing_syncer_changes_(false),
132 sync_processor_(NULL) {
123 Init(initializers, count); 133 Init(initializers, count);
124 } 134 }
125 135
126 TemplateURLService::~TemplateURLService() { 136 TemplateURLService::~TemplateURLService() {
127 if (load_handle_) { 137 if (load_handle_) {
128 DCHECK(service_.get()); 138 DCHECK(service_.get());
129 service_->CancelRequest(load_handle_); 139 service_->CancelRequest(load_handle_);
130 } 140 }
131 141
132 STLDeleteElements(&template_urls_); 142 STLDeleteElements(&template_urls_);
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
279 } 289 }
280 } 290 }
281 291
282 const TemplateURL* TemplateURLService::GetTemplateURLForKeyword( 292 const TemplateURL* TemplateURLService::GetTemplateURLForKeyword(
283 const string16& keyword) const { 293 const string16& keyword) const {
284 KeywordToTemplateMap::const_iterator elem( 294 KeywordToTemplateMap::const_iterator elem(
285 keyword_to_template_map_.find(keyword)); 295 keyword_to_template_map_.find(keyword));
286 return (elem == keyword_to_template_map_.end()) ? NULL : elem->second; 296 return (elem == keyword_to_template_map_.end()) ? NULL : elem->second;
287 } 297 }
288 298
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
289 const TemplateURL* TemplateURLService::GetTemplateURLForHost( 306 const TemplateURL* TemplateURLService::GetTemplateURLForHost(
290 const std::string& host) const { 307 const std::string& host) const {
291 return provider_map_.GetTemplateURLForHost(host); 308 return provider_map_.GetTemplateURLForHost(host);
292 } 309 }
293 310
294 void TemplateURLService::Add(TemplateURL* template_url) { 311 void TemplateURLService::Add(TemplateURL* template_url) {
295 AddNoNotify(template_url); 312 AddNoNotify(template_url);
296 NotifyObservers(); 313 NotifyObservers();
297 } 314 }
298 315
299 void TemplateURLService::Remove(const TemplateURL* template_url) { 316 void TemplateURLService::Remove(const TemplateURL* template_url) {
300 RemoveNoNotify(template_url); 317 RemoveNoNotify(template_url);
301 NotifyObservers(); 318 NotifyObservers();
302 } 319 }
303 320
304 void TemplateURLService::RemoveAutoGeneratedBetween(Time created_after, 321 void TemplateURLService::RemoveAutoGeneratedBetween(base::Time created_after,
305 Time created_before) { 322 base::Time created_before) {
306 bool should_notify = false; 323 bool should_notify = false;
307 for (size_t i = 0; i < template_urls_.size();) { 324 for (size_t i = 0; i < template_urls_.size();) {
308 if (template_urls_[i]->date_created() >= created_after && 325 if (template_urls_[i]->date_created() >= created_after &&
309 (created_before.is_null() || 326 (created_before.is_null() ||
310 template_urls_[i]->date_created() < created_before) && 327 template_urls_[i]->date_created() < created_before) &&
311 CanReplace(template_urls_[i])) { 328 CanReplace(template_urls_[i])) {
312 RemoveNoNotify(template_urls_[i]); 329 RemoveNoNotify(template_urls_[i]);
313 should_notify = true; 330 should_notify = true;
314 } else { 331 } else {
315 ++i; 332 ++i;
316 } 333 }
317 } 334 }
318 if (should_notify) 335 if (should_notify)
319 NotifyObservers(); 336 NotifyObservers();
320 } 337 }
321 338
322 void TemplateURLService::RemoveAutoGeneratedSince(Time created_after) { 339 void TemplateURLService::RemoveAutoGeneratedSince(base::Time created_after) {
323 RemoveAutoGeneratedBetween(created_after, Time()); 340 RemoveAutoGeneratedBetween(created_after, base::Time());
324 } 341 }
325 342
326 void TemplateURLService::RegisterExtensionKeyword(const Extension* extension) { 343 void TemplateURLService::RegisterExtensionKeyword(const Extension* extension) {
327 // TODO(mpcomplete): disable the keyword when the extension is disabled. 344 // TODO(mpcomplete): disable the keyword when the extension is disabled.
328 if (extension->omnibox_keyword().empty()) 345 if (extension->omnibox_keyword().empty())
329 return; 346 return;
330 347
331 Load(); 348 Load();
332 if (!loaded_) { 349 if (!loaded_) {
333 pending_extension_ids_.push_back(extension->id()); 350 pending_extension_ids_.push_back(extension->id());
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 if (!pref_name || default_search_prefs_->IsObserved(*pref_name)) { 614 if (!pref_name || default_search_prefs_->IsObserved(*pref_name)) {
598 // A preference related to default search engine has changed. 615 // A preference related to default search engine has changed.
599 // Update the model if needed. 616 // Update the model if needed.
600 UpdateDefaultSearch(); 617 UpdateDefaultSearch();
601 } 618 }
602 } else { 619 } else {
603 NOTREACHED(); 620 NOTREACHED();
604 } 621 }
605 } 622 }
606 623
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
607 // static 816 // static
608 void TemplateURLService::RegisterUserPrefs(PrefService* prefs) { 817 void TemplateURLService::RegisterUserPrefs(PrefService* prefs) {
609 prefs->RegisterBooleanPref(prefs::kDefaultSearchProviderEnabled, 818 prefs->RegisterBooleanPref(prefs::kDefaultSearchProviderEnabled,
610 true, 819 true,
611 PrefService::UNSYNCABLE_PREF); 820 PrefService::UNSYNCABLE_PREF);
612 prefs->RegisterStringPref(prefs::kDefaultSearchProviderName, 821 prefs->RegisterStringPref(prefs::kDefaultSearchProviderName,
613 std::string(), 822 std::string(),
614 PrefService::UNSYNCABLE_PREF); 823 PrefService::UNSYNCABLE_PREF);
615 prefs->RegisterStringPref(prefs::kDefaultSearchProviderID, 824 prefs->RegisterStringPref(prefs::kDefaultSearchProviderID,
616 std::string(), 825 std::string(),
(...skipping 14 matching lines...) Expand all
631 std::string(), 840 std::string(),
632 PrefService::UNSYNCABLE_PREF); 841 PrefService::UNSYNCABLE_PREF);
633 prefs->RegisterStringPref(prefs::kDefaultSearchProviderIconURL, 842 prefs->RegisterStringPref(prefs::kDefaultSearchProviderIconURL,
634 std::string(), 843 std::string(),
635 PrefService::UNSYNCABLE_PREF); 844 PrefService::UNSYNCABLE_PREF);
636 prefs->RegisterStringPref(prefs::kDefaultSearchProviderEncodings, 845 prefs->RegisterStringPref(prefs::kDefaultSearchProviderEncodings,
637 std::string(), 846 std::string(),
638 PrefService::UNSYNCABLE_PREF); 847 PrefService::UNSYNCABLE_PREF);
639 } 848 }
640 849
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
641 void TemplateURLService::SetKeywordSearchTermsForURL(const TemplateURL* t_url, 924 void TemplateURLService::SetKeywordSearchTermsForURL(const TemplateURL* t_url,
642 const GURL& url, 925 const GURL& url,
643 const string16& term) { 926 const string16& term) {
644 HistoryService* history = profile_ ? 927 HistoryService* history = profile_ ?
645 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS) : NULL; 928 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS) : NULL;
646 if (!history) 929 if (!history)
647 return; 930 return;
648 history->SetKeywordSearchTermsForURL(url, t_url->id(), term); 931 history->SetKeywordSearchTermsForURL(url, t_url->id(), term);
649 } 932 }
650 933
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 if (!env->HasVar(env_vars::kHeadless) && 989 if (!env->HasVar(env_vars::kHeadless) &&
707 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kChromeFrame)) 990 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kChromeFrame))
708 GoogleURLTracker::RequestServerCheck(); 991 GoogleURLTracker::RequestServerCheck();
709 } 992 }
710 } 993 }
711 } 994 }
712 995
713 void TemplateURLService::RemoveFromMaps(const TemplateURL* template_url) { 996 void TemplateURLService::RemoveFromMaps(const TemplateURL* template_url) {
714 if (!template_url->keyword().empty()) 997 if (!template_url->keyword().empty())
715 keyword_to_template_map_.erase(template_url->keyword()); 998 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());
716 if (loaded_) 1001 if (loaded_)
717 provider_map_.Remove(template_url); 1002 provider_map_.Remove(template_url);
718 } 1003 }
719 1004
720 void TemplateURLService::RemoveFromKeywordMapByPointer( 1005 void TemplateURLService::RemoveFromKeywordMapByPointer(
721 const TemplateURL* template_url) { 1006 const TemplateURL* template_url) {
722 DCHECK(template_url); 1007 DCHECK(template_url);
723 for (KeywordToTemplateMap::iterator i = keyword_to_template_map_.begin(); 1008 for (KeywordToTemplateMap::iterator i = keyword_to_template_map_.begin();
724 i != keyword_to_template_map_.end(); ++i) { 1009 i != keyword_to_template_map_.end(); ++i) {
725 if (i->second == template_url) { 1010 if (i->second == template_url) {
726 keyword_to_template_map_.erase(i); 1011 keyword_to_template_map_.erase(i);
727 // A given TemplateURL only occurs once in the map. As soon as we find the 1012 // A given TemplateURL only occurs once in the map. As soon as we find the
728 // entry, stop. 1013 // entry, stop.
729 break; 1014 break;
730 } 1015 }
731 } 1016 }
732 } 1017 }
733 1018
734 void TemplateURLService::AddToMaps(const TemplateURL* template_url) { 1019 void TemplateURLService::AddToMaps(const TemplateURL* template_url) {
735 if (!template_url->keyword().empty()) 1020 if (!template_url->keyword().empty())
736 keyword_to_template_map_[template_url->keyword()] = template_url; 1021 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;
737 if (loaded_) { 1024 if (loaded_) {
738 UIThreadSearchTermsData search_terms_data; 1025 UIThreadSearchTermsData search_terms_data;
739 provider_map_.Add(template_url, search_terms_data); 1026 provider_map_.Add(template_url, search_terms_data);
740 } 1027 }
741 } 1028 }
742 1029
743 void TemplateURLService::SetTemplateURLs( 1030 void TemplateURLService::SetTemplateURLs(
744 const std::vector<TemplateURL*>& urls) { 1031 const std::vector<TemplateURL*>& urls) {
745 // Add mappings for the new items. 1032 // Add mappings for the new items.
746 1033
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 1213
927 void TemplateURLService::UpdateNoNotify(const TemplateURL* existing_turl, 1214 void TemplateURLService::UpdateNoNotify(const TemplateURL* existing_turl,
928 const TemplateURL& new_values) { 1215 const TemplateURL& new_values) {
929 DCHECK(loaded_); 1216 DCHECK(loaded_);
930 DCHECK(existing_turl); 1217 DCHECK(existing_turl);
931 DCHECK(find(template_urls_.begin(), template_urls_.end(), existing_turl) != 1218 DCHECK(find(template_urls_.begin(), template_urls_.end(), existing_turl) !=
932 template_urls_.end()); 1219 template_urls_.end());
933 1220
934 if (!existing_turl->keyword().empty()) 1221 if (!existing_turl->keyword().empty())
935 keyword_to_template_map_.erase(existing_turl->keyword()); 1222 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());
936 1225
937 // This call handles copying over the values (while retaining the id). 1226 // This call handles copying over the values (while retaining the id).
938 UIThreadSearchTermsData search_terms_data; 1227 UIThreadSearchTermsData search_terms_data;
939 provider_map_.Update(existing_turl, new_values, search_terms_data); 1228 provider_map_.Update(existing_turl, new_values, search_terms_data);
940 1229
941 if (!existing_turl->keyword().empty()) 1230 if (!existing_turl->keyword().empty())
942 keyword_to_template_map_[existing_turl->keyword()] = existing_turl; 1231 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;
943 1234
944 if (service_.get()) 1235 if (service_.get())
945 service_->UpdateKeyword(*existing_turl); 1236 service_->UpdateKeyword(*existing_turl);
946 1237
1238 // Inform sync of the update.
1239 ProcessTemplateURLChange(existing_turl, SyncChange::ACTION_UPDATE);
1240
947 if (default_search_provider_ == existing_turl) 1241 if (default_search_provider_ == existing_turl)
948 SetDefaultSearchProviderNoNotify(existing_turl); 1242 SetDefaultSearchProviderNoNotify(existing_turl);
949 } 1243 }
950 1244
951 PrefService* TemplateURLService::GetPrefs() { 1245 PrefService* TemplateURLService::GetPrefs() {
952 return profile_ ? profile_->GetPrefs() : NULL; 1246 return profile_ ? profile_->GetPrefs() : NULL;
953 } 1247 }
954 1248
955 void TemplateURLService::UpdateKeywordSearchTermsForURL( 1249 void TemplateURLService::UpdateKeywordSearchTermsForURL(
956 const history::URLVisitedDetails& details) { 1250 const history::URLVisitedDetails& details) {
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
1233 DCHECK(template_url); 1527 DCHECK(template_url);
1234 DCHECK(template_url->id() == 0); 1528 DCHECK(template_url->id() == 0);
1235 DCHECK(find(template_urls_.begin(), template_urls_.end(), template_url) == 1529 DCHECK(find(template_urls_.begin(), template_urls_.end(), template_url) ==
1236 template_urls_.end()); 1530 template_urls_.end());
1237 template_url->set_id(++next_id_); 1531 template_url->set_id(++next_id_);
1238 template_urls_.push_back(template_url); 1532 template_urls_.push_back(template_url);
1239 AddToMaps(template_url); 1533 AddToMaps(template_url);
1240 1534
1241 if (service_.get()) 1535 if (service_.get())
1242 service_->AddKeyword(*template_url); 1536 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);
1243 } 1541 }
1244 1542
1245 void TemplateURLService::RemoveNoNotify(const TemplateURL* template_url) { 1543 void TemplateURLService::RemoveNoNotify(const TemplateURL* template_url) {
1246 TemplateURLVector::iterator i = find(template_urls_.begin(), 1544 TemplateURLVector::iterator i = find(template_urls_.begin(),
1247 template_urls_.end(), 1545 template_urls_.end(),
1248 template_url); 1546 template_url);
1249 if (i == template_urls_.end()) 1547 if (i == template_urls_.end())
1250 return; 1548 return;
1251 1549
1252 if (template_url == default_search_provider_) { 1550 if (template_url == default_search_provider_) {
1253 // Should never delete the default search provider. 1551 // Should never delete the default search provider.
1254 NOTREACHED(); 1552 NOTREACHED();
1255 return; 1553 return;
1256 } 1554 }
1257 1555
1258 RemoveFromMaps(template_url); 1556 RemoveFromMaps(template_url);
1259 1557
1260 // Remove it from the vector containing all TemplateURLs. 1558 // Remove it from the vector containing all TemplateURLs.
1261 template_urls_.erase(i); 1559 template_urls_.erase(i);
1262 1560
1263 if (service_.get()) 1561 if (service_.get())
1264 service_->RemoveKeyword(*template_url); 1562 service_->RemoveKeyword(*template_url);
1265 1563
1564 // Inform sync of the deletion.
1565 ProcessTemplateURLChange(template_url, SyncChange::ACTION_DELETE);
1566
1266 if (profile_) { 1567 if (profile_) {
1267 Source<Profile> source(profile_); 1568 Source<Profile> source(profile_);
1268 TemplateURLID id = template_url->id(); 1569 TemplateURLID id = template_url->id();
1269 NotificationService::current()->Notify( 1570 NotificationService::current()->Notify(
1270 chrome::NOTIFICATION_TEMPLATE_URL_REMOVED, 1571 chrome::NOTIFICATION_TEMPLATE_URL_REMOVED,
1271 source, 1572 source,
1272 Details<TemplateURLID>(&id)); 1573 Details<TemplateURLID>(&id));
1273 } 1574 }
1274 1575
1275 // We own the TemplateURL and need to delete it. 1576 // We own the TemplateURL and need to delete it.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1323 1624
1324 i = template_urls->erase(i); 1625 i = template_urls->erase(i);
1325 if (service_.get()) 1626 if (service_.get())
1326 service_->RemoveKeyword(*template_url); 1627 service_->RemoveKeyword(*template_url);
1327 delete template_url; 1628 delete template_url;
1328 } else { 1629 } else {
1329 ++i; 1630 ++i;
1330 } 1631 }
1331 } 1632 }
1332 } 1633 }
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698