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

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

Powered by Google App Engine
This is Rietveld 408576698