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

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

Powered by Google App Engine
This is Rietveld 408576698