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

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: '' 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 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 // The urls have changed, reset the favicon url. 416 // The urls have changed, reset the favicon url.
401 new_url.SetFaviconURL(GURL()); 417 new_url.SetFaviconURL(GURL());
402 new_url.SetURL(search_url, 0, 0); 418 new_url.SetURL(search_url, 0, 0);
403 } 419 }
404 new_url.set_safe_for_autoreplace(false); 420 new_url.set_safe_for_autoreplace(false);
405 new_url.set_last_modified(time_provider_()); 421 new_url.set_last_modified(time_provider_());
406 UpdateNoNotify(url, new_url); 422 UpdateNoNotify(url, new_url);
407 NotifyObservers(); 423 NotifyObservers();
408 } 424 }
409 425
426 void TemplateURLService::ResetTemplateURLGUID(const TemplateURL* url,
427 const std::string& guid) {
428 DCHECK(!guid.empty());
429
430 TemplateURL new_url(*url);
431 new_url.set_sync_guid(guid);
432 UpdateNoNotify(url, new_url);
433 }
434
410 bool TemplateURLService::CanMakeDefault(const TemplateURL* url) { 435 bool TemplateURLService::CanMakeDefault(const TemplateURL* url) {
411 return url != GetDefaultSearchProvider() && 436 return url != GetDefaultSearchProvider() &&
412 url->url() && 437 url->url() &&
413 url->url()->SupportsReplacement() && 438 url->url()->SupportsReplacement() &&
414 !is_default_search_managed(); 439 !is_default_search_managed();
415 } 440 }
416 441
417 void TemplateURLService::SetDefaultSearchProvider(const TemplateURL* url) { 442 void TemplateURLService::SetDefaultSearchProvider(const TemplateURL* url) {
418 if (is_default_search_managed_) { 443 if (is_default_search_managed_) {
419 NOTREACHED(); 444 NOTREACHED();
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 if (!pref_name || default_search_prefs_->IsObserved(*pref_name)) { 622 if (!pref_name || default_search_prefs_->IsObserved(*pref_name)) {
598 // A preference related to default search engine has changed. 623 // A preference related to default search engine has changed.
599 // Update the model if needed. 624 // Update the model if needed.
600 UpdateDefaultSearch(); 625 UpdateDefaultSearch();
601 } 626 }
602 } else { 627 } else {
603 NOTREACHED(); 628 NOTREACHED();
604 } 629 }
605 } 630 }
606 631
632 SyncDataList TemplateURLService::GetAllSyncData(
633 syncable::ModelType type) const {
634 DCHECK_EQ(syncable::SEARCH_ENGINES, type);
635
636 SyncDataList current_data;
637 for (TemplateURLVector::const_iterator iter = template_urls_.begin();
638 iter != template_urls_.end(); ++iter) {
639 // We don't sync extension keywords.
640 if ((*iter)->IsExtensionKeyword())
641 continue;
642 SyncData data = CreateSyncDataFromTemplateURL(**iter);
643 current_data.push_back(data);
644 }
645
646 return current_data;
647 }
648
649 SyncError TemplateURLService::ProcessSyncChanges(
650 const tracked_objects::Location& from_here,
651 const SyncChangeList& change_list) {
652 if (!models_associated_) {
653 SyncError error(FROM_HERE, "Models not yet associated.",
654 syncable::SEARCH_ENGINES);
655 return error;
656 }
657
658 AutoReset<bool> processing_changes(&processing_syncer_changes_, true);
659
660 SyncChangeList new_changes;
661 for (SyncChangeList::const_iterator iter = change_list.begin();
662 iter != change_list.end(); ++iter) {
663 DCHECK_EQ(syncable::SEARCH_ENGINES, iter->sync_data().GetDataType());
664
665 scoped_ptr<TemplateURL> turl(
666 CreateTemplateURLFromSyncData(iter->sync_data()));
667 if (!turl.get()) {
668 LOG(ERROR) << "Failed to read search engine.";
669 NOTREACHED();
670 continue;
671 }
672
673 const TemplateURL* existing_turl = GetTemplateURLForGUID(turl->sync_guid());
674 const TemplateURL* existing_keyword_turl =
675 GetTemplateURLForKeyword(turl->keyword());
676
677 if (iter->change_type() == SyncChange::ACTION_DELETE && existing_turl) {
678 Remove(existing_turl);
679 } else if (iter->change_type() == SyncChange::ACTION_ADD &&
680 !existing_turl) {
681 if (existing_keyword_turl)
682 ResolveSyncKeywordConflict(turl.get(), new_changes);
683 // Force the local ID to 0 so we can add it.
684 turl->set_id(0);
685 Add(turl.release());
686 } else if (iter->change_type() == SyncChange::ACTION_UPDATE &&
687 existing_turl) {
688 if (existing_keyword_turl)
689 ResolveSyncKeywordConflict(turl.get(), new_changes);
690 ResetTemplateURL(existing_turl, turl->short_name(), turl->keyword(),
691 turl->url() ? turl->url()->url() : std::string());
692 } else {
693 // Something really unexpected happened. Either we received an
694 // ACTION_INVALID, or Sync is in a crazy state:
695 // . Trying to DELETE or UPDATE a non-existent search engine.
696 // . Trying to ADD a search engine that already exists.
697 LOG(ERROR) << "Unexpected sync change state.";
698 NOTREACHED();
699 }
700 }
701
702 SyncError sync_error =
703 sync_processor_->ProcessSyncChanges(from_here, new_changes);
704 if (sync_error.IsSet())
705 return sync_error;
706
707 return SyncError();
708 }
709
710 SyncError TemplateURLService::MergeDataAndStartSyncing(
711 syncable::ModelType type,
712 const SyncDataList& initial_sync_data,
713 SyncChangeProcessor* sync_processor) {
714 DCHECK_EQ(type, syncable::SEARCH_ENGINES);
715 DCHECK(!sync_processor_);
716 sync_processor_ = sync_processor;
717
718 // We do a lot of calls to Add/Remove/ResetTemplateURL here, so ensure we
719 // don't step on our own toes.
720 AutoReset<bool> processing_changes(&processing_syncer_changes_, true);
721
722 SyncChangeList new_changes;
723
724 // Build maps of our sync GUIDs to SyncData.
725 SyncDataMap local_data_map = CreateGUIDToSyncDataMap(
726 GetAllSyncData(syncable::SEARCH_ENGINES));
727 SyncDataMap sync_data_map = CreateGUIDToSyncDataMap(initial_sync_data);
728
729 for (SyncDataMap::const_iterator iter = sync_data_map.begin();
730 iter != sync_data_map.end(); ++iter) {
731 const TemplateURL* sync_turl = CreateTemplateURLFromSyncData(iter->second);
732 DCHECK(sync_turl);
733 const TemplateURL* local_turl = GetTemplateURLForGUID(iter->first);
734
735 if (local_turl) {
736 // This local search engine is already synced. If the timestamp differs
737 // from Sync, we need to update locally or to the cloud. Note that if the
738 // timestamps are equal, we touch neither.
739 if (sync_turl->last_modified() > local_turl->last_modified()) {
740 // TODO(stevet): For now we just reset the local TemplateURL with the
741 // more important Sync data fields. We may want to transfer over
742 // additional fields.
743 ResetTemplateURL(
744 local_turl,
745 sync_turl->short_name(),
746 sync_turl->keyword(),
747 sync_turl->url() ? sync_turl->url()->url() : std::string());
748 } else if (sync_turl->last_modified() < local_turl->last_modified()) {
749 new_changes.push_back(SyncChange(SyncChange::ACTION_UPDATE,
750 local_data_map[local_turl->sync_guid()]));
751 }
752 local_data_map.erase(iter->first);
753 } else {
754 // The search engine from the cloud has not been synced locally, but there
755 // might be a local search engine that is a duplicate that needs to be
756 // merged.
757 local_turl = FindDuplicateOfSyncTemplateURL(*sync_turl);
758 TemplateURL* modifiable_sync_turl = const_cast<TemplateURL*>(sync_turl);
759 if (local_turl) {
760 // Merge duplicates and remove the processed local TURL from the map.
761 TemplateURL* modifiable_local_turl =
762 const_cast<TemplateURL*>(local_turl);
763 std::string old_guid = local_turl->sync_guid();
764 MergeSyncAndLocalURLDuplicates(modifiable_sync_turl,
765 modifiable_local_turl,
766 new_changes);
767 local_data_map.erase(old_guid);
768 } else {
769 // Keyword conflict is possible in this case. Resolve it first before
770 // adding the new TemplateURL. Note that we don't remove the local TURL
771 // from local_data_map in this case as it may still need to be pushed to
772 // the cloud.
773 ResolveSyncKeywordConflict(modifiable_sync_turl, new_changes);
774 // Force the local ID to 0 so we can add it.
775 modifiable_sync_turl->set_id(0);
776 Add(modifiable_sync_turl);
777 }
778 }
779 } // for
780
781 // The remaining SyncData in local_data_map should be everything that needs to
782 // be pushed as ADDs to sync.
783 for (SyncDataMap::const_iterator iter = local_data_map.begin();
784 iter != local_data_map.end(); ++iter) {
785 new_changes.push_back(SyncChange(SyncChange::ACTION_ADD, iter->second));
786 }
787
788 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes);
789 if (error.IsSet())
790 return error;
791
792 models_associated_ = true;
793 return SyncError();
794 }
795
796 void TemplateURLService::StopSyncing(syncable::ModelType type) {
797 DCHECK_EQ(type, syncable::SEARCH_ENGINES);
798 models_associated_ = false;
799 sync_processor_ = NULL;
800 }
801
802 void TemplateURLService::ProcessTemplateURLChange(
803 const TemplateURL* turl,
804 SyncChange::SyncChangeType type) {
805 DCHECK_NE(type, SyncChange::ACTION_INVALID);
806 DCHECK(turl);
807
808 if (!models_associated_)
809 return; // Not syncing.
810
811 if (processing_syncer_changes_)
812 return; // These are changes originating from us. Ignore.
813
814 // Avoid syncing Extension keywords.
815 if (turl->IsExtensionKeyword())
816 return;
817
818 SyncChangeList changes;
819
820 AutoReset<bool> processing_changes(&processing_syncer_changes_, true);
821
822 SyncData sync_data = CreateSyncDataFromTemplateURL(*turl);
823 changes.push_back(SyncChange(type, sync_data));
824
825 sync_processor_->ProcessSyncChanges(FROM_HERE, changes);
826 }
827
607 // static 828 // static
608 void TemplateURLService::RegisterUserPrefs(PrefService* prefs) { 829 void TemplateURLService::RegisterUserPrefs(PrefService* prefs) {
609 prefs->RegisterBooleanPref(prefs::kDefaultSearchProviderEnabled, 830 prefs->RegisterBooleanPref(prefs::kDefaultSearchProviderEnabled,
610 true, 831 true,
611 PrefService::UNSYNCABLE_PREF); 832 PrefService::UNSYNCABLE_PREF);
612 prefs->RegisterStringPref(prefs::kDefaultSearchProviderName, 833 prefs->RegisterStringPref(prefs::kDefaultSearchProviderName,
613 std::string(), 834 std::string(),
614 PrefService::UNSYNCABLE_PREF); 835 PrefService::UNSYNCABLE_PREF);
615 prefs->RegisterStringPref(prefs::kDefaultSearchProviderID, 836 prefs->RegisterStringPref(prefs::kDefaultSearchProviderID,
616 std::string(), 837 std::string(),
(...skipping 14 matching lines...) Expand all
631 std::string(), 852 std::string(),
632 PrefService::UNSYNCABLE_PREF); 853 PrefService::UNSYNCABLE_PREF);
633 prefs->RegisterStringPref(prefs::kDefaultSearchProviderIconURL, 854 prefs->RegisterStringPref(prefs::kDefaultSearchProviderIconURL,
634 std::string(), 855 std::string(),
635 PrefService::UNSYNCABLE_PREF); 856 PrefService::UNSYNCABLE_PREF);
636 prefs->RegisterStringPref(prefs::kDefaultSearchProviderEncodings, 857 prefs->RegisterStringPref(prefs::kDefaultSearchProviderEncodings,
637 std::string(), 858 std::string(),
638 PrefService::UNSYNCABLE_PREF); 859 PrefService::UNSYNCABLE_PREF);
639 } 860 }
640 861
862 // static
863 SyncData TemplateURLService::CreateSyncDataFromTemplateURL(
864 const TemplateURL& turl) {
865 sync_pb::EntitySpecifics specifics;
866 sync_pb::SearchEngineSpecifics* se_specifics = specifics.MutableExtension(
867 sync_pb::search_engine);
868 se_specifics->set_short_name(UTF16ToUTF8(turl.short_name()));
869 se_specifics->set_keyword(UTF16ToUTF8(turl.keyword()));
870 se_specifics->set_favicon_url(turl.GetFaviconURL().spec());
871 se_specifics->set_url(turl.url() ? turl.url()->url() : std::string());
872 se_specifics->set_safe_for_autoreplace(turl.safe_for_autoreplace());
873 se_specifics->set_originating_url(turl.originating_url().spec());
874 se_specifics->set_date_created(turl.date_created().ToInternalValue());
875 se_specifics->set_input_encodings(JoinString(turl.input_encodings(), ';'));
876 se_specifics->set_show_in_default_list(turl.show_in_default_list());
877 se_specifics->set_suggestions_url(turl.suggestions_url() ?
878 turl.suggestions_url()->url() : std::string());
879 se_specifics->set_prepopulate_id(turl.prepopulate_id());
880 se_specifics->set_autogenerate_keyword(turl.autogenerate_keyword());
881 se_specifics->set_logo_id(turl.logo_id());
882 se_specifics->set_created_by_policy(turl.created_by_policy());
883 se_specifics->set_instant_url(turl.instant_url() ?
884 turl.instant_url()->url() : std::string());
885 se_specifics->set_id(turl.id());
886 se_specifics->set_last_modified(turl.last_modified().ToInternalValue());
887 se_specifics->set_sync_guid(turl.sync_guid());
888 return SyncData::CreateLocalData(se_specifics->sync_guid(),
889 se_specifics->keyword(),
890 specifics);
891 }
892
893 // static
894 TemplateURL* TemplateURLService::CreateTemplateURLFromSyncData(
895 const SyncData& sync_data) {
896 sync_pb::SearchEngineSpecifics specifics =
897 sync_data.GetSpecifics().GetExtension(sync_pb::search_engine);
898 TemplateURL* turl = new TemplateURL();
899 turl->set_short_name(UTF8ToUTF16(specifics.short_name()));
900 turl->set_keyword(UTF8ToUTF16(specifics.keyword()));
901 turl->SetFaviconURL(GURL(specifics.favicon_url()));
902 turl->SetURL(specifics.url(), 0, 0);
903 turl->set_safe_for_autoreplace(specifics.safe_for_autoreplace());
904 turl->set_originating_url(GURL(specifics.originating_url()));
905 turl->set_date_created(
906 base::Time::FromInternalValue(specifics.date_created()));
907 std::vector<std::string> input_encodings;
908 base::SplitString(specifics.input_encodings(), ';', &input_encodings);
909 turl->set_input_encodings(input_encodings);
910 turl->set_show_in_default_list(specifics.show_in_default_list());
911 turl->SetSuggestionsURL(specifics.suggestions_url(), 0, 0);
912 turl->SetPrepopulateId(specifics.prepopulate_id());
913 turl->set_autogenerate_keyword(specifics.autogenerate_keyword());
914 turl->set_logo_id(specifics.logo_id());
915 turl->set_created_by_policy(specifics.created_by_policy());
916 turl->SetInstantURL(specifics.instant_url(), 0, 0);
917 turl->set_id(specifics.id());
918 turl->set_last_modified(
919 base::Time::FromInternalValue(specifics.last_modified()));
920 turl->set_sync_guid(specifics.sync_guid());
921 return turl;
922 }
923
924 string16 TemplateURLService::UniquifyKeyword(const TemplateURL& turl) const {
925 // Already unique.
926 if (!GetTemplateURLForKeyword(turl.keyword()))
927 return turl.keyword();
928
929 // First, try to return the generated keyword for the TemplateURL.
930 string16 keyword_candidate = GenerateKeyword(
931 turl.url() ? GURL(turl.url()->url()) : GURL(), true);
932 if (!GetTemplateURLForKeyword(keyword_candidate) &&
933 !keyword_candidate.empty()) {
934 return keyword_candidate;
935 }
936
937 // We try to uniquify the keyword by appending a special character to the end.
938 // This is a best-effort approach where we try to preserve the original
939 // keyword and let the user do what they will after our attempt.
940 keyword_candidate = turl.keyword();
941 do {
942 keyword_candidate.append(UTF8ToUTF16("_"));
943 } while (GetTemplateURLForKeyword(keyword_candidate));
944
945 return keyword_candidate;
946 }
947
948 bool TemplateURLService::ResolveSyncKeywordConflict(
949 TemplateURL* sync_turl,
950 SyncChangeList& change_list) {
951 DCHECK(sync_turl);
952
953 const TemplateURL* existing_turl =
954 GetTemplateURLForKeyword(sync_turl->keyword());
955 if (!existing_turl)
956 return false;
957
958 string16 new_keyword;
959 if (existing_turl->last_modified() > sync_turl->last_modified()) {
960 new_keyword = UniquifyKeyword(*sync_turl);
961 DCHECK(!GetTemplateURLForKeyword(new_keyword));
962 sync_turl->set_keyword(new_keyword);
963 // If we update the cloud TURL, we need to push an update back to sync
964 // informing it that something has changed.
965 SyncData sync_data = CreateSyncDataFromTemplateURL(*sync_turl);
966 change_list.push_back(SyncChange(SyncChange::ACTION_UPDATE, sync_data));
967 } else {
968 new_keyword = UniquifyKeyword(*existing_turl);
969 ResetTemplateURL(existing_turl, existing_turl->short_name(), new_keyword,
970 existing_turl->url() ? existing_turl->url()->url() : std::string());
971 }
972 return true;
973 }
974
975 const TemplateURL* TemplateURLService::FindDuplicateOfSyncTemplateURL(
976 const TemplateURL& sync_turl) {
977 const TemplateURL* existing_turl =
978 GetTemplateURLForKeyword(sync_turl.keyword());
979 if (!existing_turl)
980 return NULL;
981
982 if (existing_turl->url() && sync_turl.url() &&
983 existing_turl->url()->url() == sync_turl.url()->url()) {
984 return existing_turl;
985 }
986 return NULL;
987 }
988
989 void TemplateURLService::MergeSyncAndLocalURLDuplicates(
990 TemplateURL* sync_turl,
991 TemplateURL* local_turl,
992 SyncChangeList& change_list) {
993 DCHECK(sync_turl);
994 DCHECK(local_turl);
995
996 if (sync_turl->last_modified() > local_turl->last_modified()) {
997 // Fully replace local_url with Sync's copy. Note that because use Add
998 // rather than ResetTemplateURL, |sync_url| is added with a fresh
999 // TemplateURLID. We don't need to sync the new ID back to the server since
1000 // it's only relevant locally.
1001 Remove(local_turl);
1002 // Force the local ID to 0 so we can add it.
1003 sync_turl->set_id(0);
1004 Add(sync_turl);
1005 } else {
1006 // Change the local TURL's GUID to the server's GUID and push an update to
1007 // Sync. This ensures that the rest of local_url's fields are sync'd up to
1008 // the server, and the next time local_url is synced, it is recognized by
1009 // having the same GUID. We ensure that the local_turl's new GUID is
1010 // persisted to the database by calling ResetTemplateURLGUIDNoNotify.
1011 ResetTemplateURLGUID(local_turl, sync_turl->sync_guid());
1012 ResetTemplateURL(local_turl, local_turl->short_name(),
1013 local_turl->keyword(),
1014 local_turl->url() ? local_turl->url()->url() : std::string());
1015 SyncData sync_data = CreateSyncDataFromTemplateURL(*local_turl);
1016 change_list.push_back(SyncChange(SyncChange::ACTION_UPDATE, sync_data));
1017 }
1018 }
1019
1020 // static
1021 SyncDataMap TemplateURLService::CreateGUIDToSyncDataMap(
1022 const SyncDataList& sync_data) {
1023 SyncDataMap data_map;
1024 SyncDataList::const_iterator iter;
1025 for (iter = sync_data.begin(); iter != sync_data.end(); ++iter) {
1026 data_map[iter->GetSpecifics().GetExtension(
1027 sync_pb::search_engine).sync_guid()] = *iter;
1028 }
1029 return data_map;
1030 }
1031
641 void TemplateURLService::SetKeywordSearchTermsForURL(const TemplateURL* t_url, 1032 void TemplateURLService::SetKeywordSearchTermsForURL(const TemplateURL* t_url,
642 const GURL& url, 1033 const GURL& url,
643 const string16& term) { 1034 const string16& term) {
644 HistoryService* history = profile_ ? 1035 HistoryService* history = profile_ ?
645 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS) : NULL; 1036 profile_->GetHistoryService(Profile::EXPLICIT_ACCESS) : NULL;
646 if (!history) 1037 if (!history)
647 return; 1038 return;
648 history->SetKeywordSearchTermsForURL(url, t_url->id(), term); 1039 history->SetKeywordSearchTermsForURL(url, t_url->id(), term);
649 } 1040 }
650 1041
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
706 if (!env->HasVar(env_vars::kHeadless) && 1097 if (!env->HasVar(env_vars::kHeadless) &&
707 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kChromeFrame)) 1098 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kChromeFrame))
708 GoogleURLTracker::RequestServerCheck(); 1099 GoogleURLTracker::RequestServerCheck();
709 } 1100 }
710 } 1101 }
711 } 1102 }
712 1103
713 void TemplateURLService::RemoveFromMaps(const TemplateURL* template_url) { 1104 void TemplateURLService::RemoveFromMaps(const TemplateURL* template_url) {
714 if (!template_url->keyword().empty()) 1105 if (!template_url->keyword().empty())
715 keyword_to_template_map_.erase(template_url->keyword()); 1106 keyword_to_template_map_.erase(template_url->keyword());
1107 if (!template_url->sync_guid().empty())
1108 guid_to_template_map_.erase(template_url->sync_guid());
716 if (loaded_) 1109 if (loaded_)
717 provider_map_.Remove(template_url); 1110 provider_map_.Remove(template_url);
718 } 1111 }
719 1112
720 void TemplateURLService::RemoveFromKeywordMapByPointer( 1113 void TemplateURLService::RemoveFromKeywordMapByPointer(
721 const TemplateURL* template_url) { 1114 const TemplateURL* template_url) {
722 DCHECK(template_url); 1115 DCHECK(template_url);
723 for (KeywordToTemplateMap::iterator i = keyword_to_template_map_.begin(); 1116 for (KeywordToTemplateMap::iterator i = keyword_to_template_map_.begin();
724 i != keyword_to_template_map_.end(); ++i) { 1117 i != keyword_to_template_map_.end(); ++i) {
725 if (i->second == template_url) { 1118 if (i->second == template_url) {
726 keyword_to_template_map_.erase(i); 1119 keyword_to_template_map_.erase(i);
727 // A given TemplateURL only occurs once in the map. As soon as we find the 1120 // A given TemplateURL only occurs once in the map. As soon as we find the
728 // entry, stop. 1121 // entry, stop.
729 break; 1122 break;
730 } 1123 }
731 } 1124 }
732 } 1125 }
733 1126
734 void TemplateURLService::AddToMaps(const TemplateURL* template_url) { 1127 void TemplateURLService::AddToMaps(const TemplateURL* template_url) {
735 if (!template_url->keyword().empty()) 1128 if (!template_url->keyword().empty())
736 keyword_to_template_map_[template_url->keyword()] = template_url; 1129 keyword_to_template_map_[template_url->keyword()] = template_url;
1130 if (!template_url->sync_guid().empty())
1131 guid_to_template_map_[template_url->sync_guid()] = template_url;
737 if (loaded_) { 1132 if (loaded_) {
738 UIThreadSearchTermsData search_terms_data; 1133 UIThreadSearchTermsData search_terms_data;
739 provider_map_.Add(template_url, search_terms_data); 1134 provider_map_.Add(template_url, search_terms_data);
740 } 1135 }
741 } 1136 }
742 1137
743 void TemplateURLService::SetTemplateURLs( 1138 void TemplateURLService::SetTemplateURLs(
744 const std::vector<TemplateURL*>& urls) { 1139 const std::vector<TemplateURL*>& urls) {
745 // Add mappings for the new items. 1140 // Add mappings for the new items.
746 1141
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after
926 1321
927 void TemplateURLService::UpdateNoNotify(const TemplateURL* existing_turl, 1322 void TemplateURLService::UpdateNoNotify(const TemplateURL* existing_turl,
928 const TemplateURL& new_values) { 1323 const TemplateURL& new_values) {
929 DCHECK(loaded_); 1324 DCHECK(loaded_);
930 DCHECK(existing_turl); 1325 DCHECK(existing_turl);
931 DCHECK(find(template_urls_.begin(), template_urls_.end(), existing_turl) != 1326 DCHECK(find(template_urls_.begin(), template_urls_.end(), existing_turl) !=
932 template_urls_.end()); 1327 template_urls_.end());
933 1328
934 if (!existing_turl->keyword().empty()) 1329 if (!existing_turl->keyword().empty())
935 keyword_to_template_map_.erase(existing_turl->keyword()); 1330 keyword_to_template_map_.erase(existing_turl->keyword());
1331 if (!existing_turl->sync_guid().empty())
1332 guid_to_template_map_.erase(existing_turl->sync_guid());
936 1333
937 // This call handles copying over the values (while retaining the id). 1334 // This call handles copying over the values (while retaining the id).
938 UIThreadSearchTermsData search_terms_data; 1335 UIThreadSearchTermsData search_terms_data;
939 provider_map_.Update(existing_turl, new_values, search_terms_data); 1336 provider_map_.Update(existing_turl, new_values, search_terms_data);
940 1337
941 if (!existing_turl->keyword().empty()) 1338 if (!existing_turl->keyword().empty())
942 keyword_to_template_map_[existing_turl->keyword()] = existing_turl; 1339 keyword_to_template_map_[existing_turl->keyword()] = existing_turl;
1340 if (!existing_turl->sync_guid().empty())
1341 guid_to_template_map_[existing_turl->sync_guid()] = existing_turl;
943 1342
944 if (service_.get()) 1343 if (service_.get())
945 service_->UpdateKeyword(*existing_turl); 1344 service_->UpdateKeyword(*existing_turl);
946 1345
1346 // Inform sync of the update.
1347 ProcessTemplateURLChange(existing_turl, SyncChange::ACTION_UPDATE);
1348
947 if (default_search_provider_ == existing_turl) 1349 if (default_search_provider_ == existing_turl)
948 SetDefaultSearchProviderNoNotify(existing_turl); 1350 SetDefaultSearchProviderNoNotify(existing_turl);
949 } 1351 }
950 1352
951 PrefService* TemplateURLService::GetPrefs() { 1353 PrefService* TemplateURLService::GetPrefs() {
952 return profile_ ? profile_->GetPrefs() : NULL; 1354 return profile_ ? profile_->GetPrefs() : NULL;
953 } 1355 }
954 1356
955 void TemplateURLService::UpdateKeywordSearchTermsForURL( 1357 void TemplateURLService::UpdateKeywordSearchTermsForURL(
956 const history::URLVisitedDetails& details) { 1358 const history::URLVisitedDetails& details) {
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
1233 DCHECK(template_url); 1635 DCHECK(template_url);
1234 DCHECK(template_url->id() == 0); 1636 DCHECK(template_url->id() == 0);
1235 DCHECK(find(template_urls_.begin(), template_urls_.end(), template_url) == 1637 DCHECK(find(template_urls_.begin(), template_urls_.end(), template_url) ==
1236 template_urls_.end()); 1638 template_urls_.end());
1237 template_url->set_id(++next_id_); 1639 template_url->set_id(++next_id_);
1238 template_urls_.push_back(template_url); 1640 template_urls_.push_back(template_url);
1239 AddToMaps(template_url); 1641 AddToMaps(template_url);
1240 1642
1241 if (service_.get()) 1643 if (service_.get())
1242 service_->AddKeyword(*template_url); 1644 service_->AddKeyword(*template_url);
1645
1646 // Inform sync of the addition. Note that this will assign a GUID to
1647 // template_url and add it to the guid_to_template_map_.
1648 ProcessTemplateURLChange(template_url, SyncChange::ACTION_ADD);
1243 } 1649 }
1244 1650
1245 void TemplateURLService::RemoveNoNotify(const TemplateURL* template_url) { 1651 void TemplateURLService::RemoveNoNotify(const TemplateURL* template_url) {
1246 TemplateURLVector::iterator i = find(template_urls_.begin(), 1652 TemplateURLVector::iterator i = find(template_urls_.begin(),
1247 template_urls_.end(), 1653 template_urls_.end(),
1248 template_url); 1654 template_url);
1249 if (i == template_urls_.end()) 1655 if (i == template_urls_.end())
1250 return; 1656 return;
1251 1657
1252 if (template_url == default_search_provider_) { 1658 if (template_url == default_search_provider_) {
1253 // Should never delete the default search provider. 1659 // Should never delete the default search provider.
1254 NOTREACHED(); 1660 NOTREACHED();
1255 return; 1661 return;
1256 } 1662 }
1257 1663
1258 RemoveFromMaps(template_url); 1664 RemoveFromMaps(template_url);
1259 1665
1260 // Remove it from the vector containing all TemplateURLs. 1666 // Remove it from the vector containing all TemplateURLs.
1261 template_urls_.erase(i); 1667 template_urls_.erase(i);
1262 1668
1263 if (service_.get()) 1669 if (service_.get())
1264 service_->RemoveKeyword(*template_url); 1670 service_->RemoveKeyword(*template_url);
1265 1671
1672 // Inform sync of the deletion.
1673 ProcessTemplateURLChange(template_url, SyncChange::ACTION_DELETE);
1674
1266 if (profile_) { 1675 if (profile_) {
1267 Source<Profile> source(profile_); 1676 Source<Profile> source(profile_);
1268 TemplateURLID id = template_url->id(); 1677 TemplateURLID id = template_url->id();
1269 NotificationService::current()->Notify( 1678 NotificationService::current()->Notify(
1270 chrome::NOTIFICATION_TEMPLATE_URL_REMOVED, 1679 chrome::NOTIFICATION_TEMPLATE_URL_REMOVED,
1271 source, 1680 source,
1272 Details<TemplateURLID>(&id)); 1681 Details<TemplateURLID>(&id));
1273 } 1682 }
1274 1683
1275 // We own the TemplateURL and need to delete it. 1684 // We own the TemplateURL and need to delete it.
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
1323 1732
1324 i = template_urls->erase(i); 1733 i = template_urls->erase(i);
1325 if (service_.get()) 1734 if (service_.get())
1326 service_->RemoveKeyword(*template_url); 1735 service_->RemoveKeyword(*template_url);
1327 delete template_url; 1736 delete template_url;
1328 } else { 1737 } else {
1329 ++i; 1738 ++i;
1330 } 1739 }
1331 } 1740 }
1332 } 1741 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698