OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |