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

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: Recommitting patch. Repaired memory leaks and adjusted unittests to reflect changes. 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 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
473 } 490 }
474 491
475 // initial_default_search_provider_ is only needed before we've finished 492 // initial_default_search_provider_ is only needed before we've finished
476 // loading. Now that we've loaded we can nuke it. 493 // loading. Now that we've loaded we can nuke it.
477 initial_default_search_provider_.reset(); 494 initial_default_search_provider_.reset();
478 is_default_search_managed_ = false; 495 is_default_search_managed_ = false;
479 496
480 std::vector<TemplateURL*> template_urls; 497 std::vector<TemplateURL*> template_urls;
481 const TemplateURL* default_search_provider = NULL; 498 const TemplateURL* default_search_provider = NULL;
482 int new_resource_keyword_version = 0; 499 int new_resource_keyword_version = 0;
483 GetSearchProvidersUsingKeywordResult(*result, 500 GetSearchProvidersUsingKeywordResult(*result,
sky 2011/08/17 23:22:29 This may end up modifying the set of TemplateURLs
484 service_.get(), 501 service_.get(),
485 GetPrefs(), 502 GetPrefs(),
486 &template_urls, 503 &template_urls,
487 &default_search_provider, 504 &default_search_provider,
488 &new_resource_keyword_version); 505 &new_resource_keyword_version);
489 506
490 bool database_specified_a_default = NULL != default_search_provider; 507 bool database_specified_a_default = NULL != default_search_provider;
491 508
492 // Check if default search provider is now managed. 509 // Check if default search provider is now managed.
493 scoped_ptr<TemplateURL> default_from_prefs; 510 scoped_ptr<TemplateURL> default_from_prefs;
(...skipping 103 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;
sky 2011/08/17 23:22:29 Are you sure we want to return here and not contin
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(
sky 2011/08/17 23:22:29 Is it guaranteed these methods are only invoked af
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 scoped_ptr<TemplateURL> sync_turl(
723 CreateTemplateURLFromSyncData(iter->second));
724 DCHECK(sync_turl.get());
725 const TemplateURL* local_turl = GetTemplateURLForGUID(iter->first);
726
727 if (local_turl) {
728 // This local search engine is already synced. If the timestamp differs
729 // from Sync, we need to update locally or to the cloud. Note that if the
730 // timestamps are equal, we touch neither.
731 if (sync_turl->last_modified() > local_turl->last_modified()) {
732 // TODO(stevet): For now we just reset the local TemplateURL with the
733 // more important Sync data fields. We may want to transfer over
734 // additional fields.
735 ResetTemplateURL(
736 local_turl,
737 sync_turl->short_name(),
738 sync_turl->keyword(),
739 sync_turl->url() ? sync_turl->url()->url() : std::string());
sky 2011/08/17 23:22:29 I believe you'll also want safe_for_autoreplace co
740 } else if (sync_turl->last_modified() < local_turl->last_modified()) {
741 new_changes.push_back(SyncChange(SyncChange::ACTION_UPDATE,
742 local_data_map[local_turl->sync_guid()]));
743 }
744 local_data_map.erase(iter->first);
745 } else {
746 // The search engine from the cloud has not been synced locally, but there
747 // might be a local search engine that is a duplicate that needs to be
748 // merged.
749 const TemplateURL* dupe_turl = FindDuplicateOfSyncTemplateURL(*sync_turl);
750 if (dupe_turl) {
751 // Merge duplicates and remove the processed local TURL from the map.
752 TemplateURL* modifiable_dupe_turl =
753 const_cast<TemplateURL*>(dupe_turl);
754 std::string old_guid = dupe_turl->sync_guid();
755 MergeSyncAndLocalURLDuplicates(sync_turl.release(),
756 modifiable_dupe_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(sync_turl.get(), new_changes);
765 // Force the local ID to 0 so we can add it.
766 sync_turl->set_id(0);
767 Add(sync_turl.release());
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 SyncData sync_data = CreateSyncDataFromTemplateURL(*turl);
812 changes.push_back(SyncChange(type, sync_data));
813
814 sync_processor_->ProcessSyncChanges(FROM_HERE, changes);
815 }
816
607 // static 817 // static
608 void TemplateURLService::RegisterUserPrefs(PrefService* prefs) { 818 void TemplateURLService::RegisterUserPrefs(PrefService* prefs) {
609 prefs->RegisterBooleanPref(prefs::kDefaultSearchProviderEnabled, 819 prefs->RegisterBooleanPref(prefs::kDefaultSearchProviderEnabled,
610 true, 820 true,
611 PrefService::UNSYNCABLE_PREF); 821 PrefService::UNSYNCABLE_PREF);
612 prefs->RegisterStringPref(prefs::kDefaultSearchProviderName, 822 prefs->RegisterStringPref(prefs::kDefaultSearchProviderName,
613 std::string(), 823 std::string(),
614 PrefService::UNSYNCABLE_PREF); 824 PrefService::UNSYNCABLE_PREF);
615 prefs->RegisterStringPref(prefs::kDefaultSearchProviderID, 825 prefs->RegisterStringPref(prefs::kDefaultSearchProviderID,
616 std::string(), 826 std::string(),
(...skipping 14 matching lines...) Expand all
631 std::string(), 841 std::string(),
632 PrefService::UNSYNCABLE_PREF); 842 PrefService::UNSYNCABLE_PREF);
633 prefs->RegisterStringPref(prefs::kDefaultSearchProviderIconURL, 843 prefs->RegisterStringPref(prefs::kDefaultSearchProviderIconURL,
634 std::string(), 844 std::string(),
635 PrefService::UNSYNCABLE_PREF); 845 PrefService::UNSYNCABLE_PREF);
636 prefs->RegisterStringPref(prefs::kDefaultSearchProviderEncodings, 846 prefs->RegisterStringPref(prefs::kDefaultSearchProviderEncodings,
637 std::string(), 847 std::string(),
638 PrefService::UNSYNCABLE_PREF); 848 PrefService::UNSYNCABLE_PREF);
639 } 849 }
640 850
851 // static
852 SyncData TemplateURLService::CreateSyncDataFromTemplateURL(
853 const TemplateURL& turl) {
854 sync_pb::EntitySpecifics specifics;
855 sync_pb::SearchEngineSpecifics* se_specifics = specifics.MutableExtension(
856 sync_pb::search_engine);
857 se_specifics->set_short_name(UTF16ToUTF8(turl.short_name()));
858 se_specifics->set_keyword(UTF16ToUTF8(turl.keyword()));
859 se_specifics->set_favicon_url(turl.GetFaviconURL().spec());
860 se_specifics->set_url(turl.url() ? turl.url()->url() : std::string());
861 se_specifics->set_safe_for_autoreplace(turl.safe_for_autoreplace());
862 se_specifics->set_originating_url(turl.originating_url().spec());
863 se_specifics->set_date_created(turl.date_created().ToInternalValue());
864 se_specifics->set_input_encodings(JoinString(turl.input_encodings(), ';'));
865 se_specifics->set_show_in_default_list(turl.show_in_default_list());
866 se_specifics->set_suggestions_url(turl.suggestions_url() ?
867 turl.suggestions_url()->url() : std::string());
868 se_specifics->set_prepopulate_id(turl.prepopulate_id());
869 se_specifics->set_autogenerate_keyword(turl.autogenerate_keyword());
870 se_specifics->set_logo_id(turl.logo_id());
871 se_specifics->set_created_by_policy(turl.created_by_policy());
872 se_specifics->set_instant_url(turl.instant_url() ?
873 turl.instant_url()->url() : std::string());
874 se_specifics->set_id(turl.id());
sky 2011/08/17 23:22:29 Is there any protection to make sure we don't end
875 se_specifics->set_last_modified(turl.last_modified().ToInternalValue());
876 se_specifics->set_sync_guid(turl.sync_guid());
877 return SyncData::CreateLocalData(se_specifics->sync_guid(),
878 se_specifics->keyword(),
879 specifics);
880 }
881
882 // static
883 TemplateURL* TemplateURLService::CreateTemplateURLFromSyncData(
884 const SyncData& sync_data) {
885 sync_pb::SearchEngineSpecifics specifics =
886 sync_data.GetSpecifics().GetExtension(sync_pb::search_engine);
887 TemplateURL* turl = new TemplateURL();
888 turl->set_short_name(UTF8ToUTF16(specifics.short_name()));
889 turl->set_keyword(UTF8ToUTF16(specifics.keyword()));
890 turl->SetFaviconURL(GURL(specifics.favicon_url()));
891 turl->SetURL(specifics.url(), 0, 0);
892 turl->set_safe_for_autoreplace(specifics.safe_for_autoreplace());
893 turl->set_originating_url(GURL(specifics.originating_url()));
894 turl->set_date_created(
895 base::Time::FromInternalValue(specifics.date_created()));
896 std::vector<std::string> input_encodings;
897 base::SplitString(specifics.input_encodings(), ';', &input_encodings);
898 turl->set_input_encodings(input_encodings);
899 turl->set_show_in_default_list(specifics.show_in_default_list());
900 turl->SetSuggestionsURL(specifics.suggestions_url(), 0, 0);
901 turl->SetPrepopulateId(specifics.prepopulate_id());
902 turl->set_autogenerate_keyword(specifics.autogenerate_keyword());
903 turl->set_logo_id(specifics.logo_id());
904 turl->set_created_by_policy(specifics.created_by_policy());
905 turl->SetInstantURL(specifics.instant_url(), 0, 0);
906 turl->set_id(specifics.id());
907 turl->set_last_modified(
908 base::Time::FromInternalValue(specifics.last_modified()));
909 turl->set_sync_guid(specifics.sync_guid());
910 return turl;
911 }
912
913 // static
914 SyncDataMap TemplateURLService::CreateGUIDToSyncDataMap(
915 const SyncDataList& sync_data) {
916 SyncDataMap data_map;
917 SyncDataList::const_iterator iter;
918 for (iter = sync_data.begin(); iter != sync_data.end(); ++iter) {
919 data_map[iter->GetSpecifics().GetExtension(
920 sync_pb::search_engine).sync_guid()] = *iter;
921 }
922 return data_map;
923 }
924
641 void TemplateURLService::SetKeywordSearchTermsForURL(const TemplateURL* t_url, 925 void TemplateURLService::SetKeywordSearchTermsForURL(const TemplateURL* t_url,
642 const GURL& url, 926 const GURL& url,
643 const string16& term) { 927 const string16& term) {
644 HistoryService* history = profile_ ? 928 HistoryService* history = profile_ ?
645 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS) : NULL; 929 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS) : NULL;
646 if (!history) 930 if (!history)
647 return; 931 return;
648 history->SetKeywordSearchTermsForURL(url, t_url->id(), term); 932 history->SetKeywordSearchTermsForURL(url, t_url->id(), term);
649 } 933 }
650 934
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 if (!env->HasVar(env_vars::kHeadless) && 990 if (!env->HasVar(env_vars::kHeadless) &&
707 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kChromeFrame)) 991 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kChromeFrame))
708 GoogleURLTracker::RequestServerCheck(); 992 GoogleURLTracker::RequestServerCheck();
709 } 993 }
710 } 994 }
711 } 995 }
712 996
713 void TemplateURLService::RemoveFromMaps(const TemplateURL* template_url) { 997 void TemplateURLService::RemoveFromMaps(const TemplateURL* template_url) {
714 if (!template_url->keyword().empty()) 998 if (!template_url->keyword().empty())
715 keyword_to_template_map_.erase(template_url->keyword()); 999 keyword_to_template_map_.erase(template_url->keyword());
1000 if (!template_url->sync_guid().empty())
1001 guid_to_template_map_.erase(template_url->sync_guid());
716 if (loaded_) 1002 if (loaded_)
717 provider_map_.Remove(template_url); 1003 provider_map_.Remove(template_url);
718 } 1004 }
719 1005
720 void TemplateURLService::RemoveFromKeywordMapByPointer( 1006 void TemplateURLService::RemoveFromKeywordMapByPointer(
721 const TemplateURL* template_url) { 1007 const TemplateURL* template_url) {
722 DCHECK(template_url); 1008 DCHECK(template_url);
723 for (KeywordToTemplateMap::iterator i = keyword_to_template_map_.begin(); 1009 for (KeywordToTemplateMap::iterator i = keyword_to_template_map_.begin();
724 i != keyword_to_template_map_.end(); ++i) { 1010 i != keyword_to_template_map_.end(); ++i) {
725 if (i->second == template_url) { 1011 if (i->second == template_url) {
726 keyword_to_template_map_.erase(i); 1012 keyword_to_template_map_.erase(i);
727 // A given TemplateURL only occurs once in the map. As soon as we find the 1013 // A given TemplateURL only occurs once in the map. As soon as we find the
728 // entry, stop. 1014 // entry, stop.
729 break; 1015 break;
730 } 1016 }
731 } 1017 }
732 } 1018 }
733 1019
734 void TemplateURLService::AddToMaps(const TemplateURL* template_url) { 1020 void TemplateURLService::AddToMaps(const TemplateURL* template_url) {
735 if (!template_url->keyword().empty()) 1021 if (!template_url->keyword().empty())
736 keyword_to_template_map_[template_url->keyword()] = template_url; 1022 keyword_to_template_map_[template_url->keyword()] = template_url;
1023 if (!template_url->sync_guid().empty())
1024 guid_to_template_map_[template_url->sync_guid()] = template_url;
737 if (loaded_) { 1025 if (loaded_) {
738 UIThreadSearchTermsData search_terms_data; 1026 UIThreadSearchTermsData search_terms_data;
739 provider_map_.Add(template_url, search_terms_data); 1027 provider_map_.Add(template_url, search_terms_data);
740 } 1028 }
741 } 1029 }
742 1030
743 void TemplateURLService::SetTemplateURLs( 1031 void TemplateURLService::SetTemplateURLs(
744 const std::vector<TemplateURL*>& urls) { 1032 const std::vector<TemplateURL*>& urls) {
745 // Add mappings for the new items. 1033 // Add mappings for the new items.
746 1034
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 1214
927 void TemplateURLService::UpdateNoNotify(const TemplateURL* existing_turl, 1215 void TemplateURLService::UpdateNoNotify(const TemplateURL* existing_turl,
928 const TemplateURL& new_values) { 1216 const TemplateURL& new_values) {
929 DCHECK(loaded_); 1217 DCHECK(loaded_);
930 DCHECK(existing_turl); 1218 DCHECK(existing_turl);
931 DCHECK(find(template_urls_.begin(), template_urls_.end(), existing_turl) != 1219 DCHECK(find(template_urls_.begin(), template_urls_.end(), existing_turl) !=
932 template_urls_.end()); 1220 template_urls_.end());
933 1221
934 if (!existing_turl->keyword().empty()) 1222 if (!existing_turl->keyword().empty())
935 keyword_to_template_map_.erase(existing_turl->keyword()); 1223 keyword_to_template_map_.erase(existing_turl->keyword());
1224 if (!existing_turl->sync_guid().empty())
1225 guid_to_template_map_.erase(existing_turl->sync_guid());
936 1226
937 // This call handles copying over the values (while retaining the id). 1227 // This call handles copying over the values (while retaining the id).
938 UIThreadSearchTermsData search_terms_data; 1228 UIThreadSearchTermsData search_terms_data;
939 provider_map_.Update(existing_turl, new_values, search_terms_data); 1229 provider_map_.Update(existing_turl, new_values, search_terms_data);
940 1230
941 if (!existing_turl->keyword().empty()) 1231 if (!existing_turl->keyword().empty())
942 keyword_to_template_map_[existing_turl->keyword()] = existing_turl; 1232 keyword_to_template_map_[existing_turl->keyword()] = existing_turl;
1233 if (!existing_turl->sync_guid().empty())
1234 guid_to_template_map_[existing_turl->sync_guid()] = existing_turl;
943 1235
944 if (service_.get()) 1236 if (service_.get())
945 service_->UpdateKeyword(*existing_turl); 1237 service_->UpdateKeyword(*existing_turl);
946 1238
1239 // Inform sync of the update.
1240 ProcessTemplateURLChange(existing_turl, SyncChange::ACTION_UPDATE);
1241
947 if (default_search_provider_ == existing_turl) 1242 if (default_search_provider_ == existing_turl)
948 SetDefaultSearchProviderNoNotify(existing_turl); 1243 SetDefaultSearchProviderNoNotify(existing_turl);
949 } 1244 }
950 1245
951 PrefService* TemplateURLService::GetPrefs() { 1246 PrefService* TemplateURLService::GetPrefs() {
952 return profile_ ? profile_->GetPrefs() : NULL; 1247 return profile_ ? profile_->GetPrefs() : NULL;
953 } 1248 }
954 1249
955 void TemplateURLService::UpdateKeywordSearchTermsForURL( 1250 void TemplateURLService::UpdateKeywordSearchTermsForURL(
956 const history::URLVisitedDetails& details) { 1251 const history::URLVisitedDetails& details) {
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
1233 DCHECK(template_url); 1528 DCHECK(template_url);
1234 DCHECK(template_url->id() == 0); 1529 DCHECK(template_url->id() == 0);
1235 DCHECK(find(template_urls_.begin(), template_urls_.end(), template_url) == 1530 DCHECK(find(template_urls_.begin(), template_urls_.end(), template_url) ==
1236 template_urls_.end()); 1531 template_urls_.end());
1237 template_url->set_id(++next_id_); 1532 template_url->set_id(++next_id_);
1238 template_urls_.push_back(template_url); 1533 template_urls_.push_back(template_url);
1239 AddToMaps(template_url); 1534 AddToMaps(template_url);
1240 1535
1241 if (service_.get()) 1536 if (service_.get())
1242 service_->AddKeyword(*template_url); 1537 service_->AddKeyword(*template_url);
1538
1539 // Inform sync of the addition. Note that this will assign a GUID to
1540 // template_url and add it to the guid_to_template_map_.
1541 ProcessTemplateURLChange(template_url, SyncChange::ACTION_ADD);
1243 } 1542 }
1244 1543
1245 void TemplateURLService::RemoveNoNotify(const TemplateURL* template_url) { 1544 void TemplateURLService::RemoveNoNotify(const TemplateURL* template_url) {
1246 TemplateURLVector::iterator i = find(template_urls_.begin(), 1545 TemplateURLVector::iterator i = find(template_urls_.begin(),
1247 template_urls_.end(), 1546 template_urls_.end(),
1248 template_url); 1547 template_url);
1249 if (i == template_urls_.end()) 1548 if (i == template_urls_.end())
1250 return; 1549 return;
1251 1550
1252 if (template_url == default_search_provider_) { 1551 if (template_url == default_search_provider_) {
1253 // Should never delete the default search provider. 1552 // Should never delete the default search provider.
1254 NOTREACHED(); 1553 NOTREACHED();
1255 return; 1554 return;
1256 } 1555 }
1257 1556
1258 RemoveFromMaps(template_url); 1557 RemoveFromMaps(template_url);
1259 1558
1260 // Remove it from the vector containing all TemplateURLs. 1559 // Remove it from the vector containing all TemplateURLs.
1261 template_urls_.erase(i); 1560 template_urls_.erase(i);
1262 1561
1263 if (service_.get()) 1562 if (service_.get())
1264 service_->RemoveKeyword(*template_url); 1563 service_->RemoveKeyword(*template_url);
1265 1564
1565 // Inform sync of the deletion.
1566 ProcessTemplateURLChange(template_url, SyncChange::ACTION_DELETE);
1567
1266 if (profile_) { 1568 if (profile_) {
1267 Source<Profile> source(profile_); 1569 Source<Profile> source(profile_);
1268 TemplateURLID id = template_url->id(); 1570 TemplateURLID id = template_url->id();
1269 NotificationService::current()->Notify( 1571 NotificationService::current()->Notify(
1270 chrome::NOTIFICATION_TEMPLATE_URL_REMOVED, 1572 chrome::NOTIFICATION_TEMPLATE_URL_REMOVED,
1271 source, 1573 source,
1272 Details<TemplateURLID>(&id)); 1574 Details<TemplateURLID>(&id));
1273 } 1575 }
1274 1576
1275 // We own the TemplateURL and need to delete it. 1577 // We own the TemplateURL and need to delete it.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1323 1625
1324 i = template_urls->erase(i); 1626 i = template_urls->erase(i);
1325 if (service_.get()) 1627 if (service_.get())
1326 service_->RemoveKeyword(*template_url); 1628 service_->RemoveKeyword(*template_url);
1327 delete template_url; 1629 delete template_url;
1328 } else { 1630 } else {
1329 ++i; 1631 ++i;
1330 } 1632 }
1331 } 1633 }
1332 } 1634 }
1635
1636 void TemplateURLService::ResetTemplateURLGUID(const TemplateURL* url,
1637 const std::string& guid) {
1638 DCHECK(!guid.empty());
1639
1640 TemplateURL new_url(*url);
1641 new_url.set_sync_guid(guid);
1642 UpdateNoNotify(url, new_url);
1643 }
1644
1645 string16 TemplateURLService::UniquifyKeyword(const TemplateURL& turl) const {
1646 // Already unique.
1647 if (!GetTemplateURLForKeyword(turl.keyword()))
1648 return turl.keyword();
1649
1650 // First, try to return the generated keyword for the TemplateURL.
1651 string16 keyword_candidate = GenerateKeyword(
1652 turl.url() ? GURL(turl.url()->url()) : GURL(), true);
1653 if (!GetTemplateURLForKeyword(keyword_candidate) &&
1654 !keyword_candidate.empty()) {
1655 return keyword_candidate;
1656 }
1657
1658 // We try to uniquify the keyword by appending a special character to the end.
1659 // This is a best-effort approach where we try to preserve the original
1660 // keyword and let the user do what they will after our attempt.
1661 keyword_candidate = turl.keyword();
1662 do {
1663 keyword_candidate.append(UTF8ToUTF16("_"));
1664 } while (GetTemplateURLForKeyword(keyword_candidate));
1665
1666 return keyword_candidate;
1667 }
1668
1669 bool TemplateURLService::ResolveSyncKeywordConflict(
1670 TemplateURL* sync_turl,
1671 SyncChangeList& change_list) {
1672 DCHECK(sync_turl);
1673
1674 const TemplateURL* existing_turl =
1675 GetTemplateURLForKeyword(sync_turl->keyword());
1676 if (!existing_turl)
1677 return false;
1678
1679 string16 new_keyword;
sky 2011/08/17 23:22:29 nit: pull into if as you don't use it outside the
1680 if (existing_turl->last_modified() > sync_turl->last_modified()) {
1681 new_keyword = UniquifyKeyword(*sync_turl);
1682 DCHECK(!GetTemplateURLForKeyword(new_keyword));
1683 sync_turl->set_keyword(new_keyword);
1684 // If we update the cloud TURL, we need to push an update back to sync
1685 // informing it that something has changed.
1686 SyncData sync_data = CreateSyncDataFromTemplateURL(*sync_turl);
1687 change_list.push_back(SyncChange(SyncChange::ACTION_UPDATE, sync_data));
1688 } else {
1689 new_keyword = UniquifyKeyword(*existing_turl);
1690 ResetTemplateURL(existing_turl, existing_turl->short_name(), new_keyword,
1691 existing_turl->url() ? existing_turl->url()->url() : std::string());
1692 }
1693 return true;
1694 }
1695
1696 const TemplateURL* TemplateURLService::FindDuplicateOfSyncTemplateURL(
1697 const TemplateURL& sync_turl) {
1698 const TemplateURL* existing_turl =
1699 GetTemplateURLForKeyword(sync_turl.keyword());
1700 if (!existing_turl)
1701 return NULL;
1702
1703 if (existing_turl->url() && sync_turl.url() &&
1704 existing_turl->url()->url() == sync_turl.url()->url()) {
1705 return existing_turl;
1706 }
1707 return NULL;
1708 }
1709
1710 void TemplateURLService::MergeSyncAndLocalURLDuplicates(
1711 TemplateURL* sync_turl,
1712 TemplateURL* local_turl,
1713 SyncChangeList& change_list) {
1714 DCHECK(sync_turl);
1715 DCHECK(local_turl);
1716
1717 scoped_ptr<TemplateURL> scoped_sync_turl(sync_turl);
1718
1719 if (scoped_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 scoped_sync_turl->set_id(0);
1727 Add(scoped_sync_turl.release());
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.
1733 ResetTemplateURLGUID(local_turl, sync_turl->sync_guid());
1734 SyncData sync_data = CreateSyncDataFromTemplateURL(*local_turl);
1735 change_list.push_back(SyncChange(SyncChange::ACTION_UPDATE, sync_data));
1736 }
1737 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698