Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/auto_reset.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/environment.h" | 9 #include "base/environment.h" |
| 10 #include "base/i18n/case_conversion.h" | 10 #include "base/i18n/case_conversion.h" |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 63 // the rare case the term replaces the URL it's unlikely another keyword would | 63 // the rare case the term replaces the URL it's unlikely another keyword would |
| 64 // have the same url. | 64 // have the same url. |
| 65 const char kReplacementTerm[] = "blah.blah.blah.blah.blah"; | 65 const char kReplacementTerm[] = "blah.blah.blah.blah.blah"; |
| 66 | 66 |
| 67 bool TemplateURLsHaveSamePrefs(const TemplateURL* url1, | 67 bool TemplateURLsHaveSamePrefs(const TemplateURL* url1, |
| 68 const TemplateURL* url2) { | 68 const TemplateURL* url2) { |
| 69 if (url1 == url2) | 69 if (url1 == url2) |
| 70 return true; | 70 return true; |
| 71 return (url1 != NULL) && (url2 != NULL) && | 71 return (url1 != NULL) && (url2 != NULL) && |
| 72 (url1->short_name() == url2->short_name()) && | 72 (url1->short_name() == url2->short_name()) && |
| 73 (url1->keyword() == url2->keyword()) && | 73 ((url1->keyword() == url2->keyword()) || |
|
sky
2012/05/04 23:20:25
Is it worth moving this to a common place for both
Peter Kasting
2012/05/07 17:50:24
Yes, good idea.
| |
| 74 (url1->IsGoogleSearchURLWithReplaceableKeyword() && | |
| 75 url2->IsGoogleSearchURLWithReplaceableKeyword())) && | |
| 74 (url1->url() == url2->url()) && | 76 (url1->url() == url2->url()) && |
| 75 (url1->suggestions_url() == url2->suggestions_url()) && | 77 (url1->suggestions_url() == url2->suggestions_url()) && |
| 76 (url1->instant_url() == url2->instant_url()) && | 78 (url1->instant_url() == url2->instant_url()) && |
| 77 (url1->favicon_url() == url2->favicon_url()) && | 79 (url1->favicon_url() == url2->favicon_url()) && |
| 78 (url1->safe_for_autoreplace() == url2->safe_for_autoreplace()) && | 80 (url1->safe_for_autoreplace() == url2->safe_for_autoreplace()) && |
| 79 (url1->show_in_default_list() == url2->show_in_default_list()) && | 81 (url1->show_in_default_list() == url2->show_in_default_list()) && |
| 80 (url1->input_encodings() == url2->input_encodings()); | 82 (url1->input_encodings() == url2->input_encodings()); |
| 81 } | 83 } |
| 82 | 84 |
| 83 TemplateURL* FirstPotentialDefaultEngine( | 85 TemplateURL* FirstPotentialDefaultEngine( |
| 84 const TemplateURLService::TemplateURLVector& template_urls) { | 86 const TemplateURLService::TemplateURLVector& template_urls) { |
| 85 for (TemplateURLService::TemplateURLVector::const_iterator i( | 87 for (TemplateURLService::TemplateURLVector::const_iterator i( |
| 86 template_urls.begin()); i != template_urls.end(); ++i) { | 88 template_urls.begin()); i != template_urls.end(); ++i) { |
| 87 if (!(*i)->IsExtensionKeyword() && (*i)->SupportsReplacement()) | 89 if (!(*i)->IsExtensionKeyword() && (*i)->SupportsReplacement()) |
| 88 return *i; | 90 return *i; |
| 89 } | 91 } |
| 90 return NULL; | 92 return NULL; |
| 91 } | 93 } |
| 92 | 94 |
| 95 // If |change_list| contains ACTION_UPDATEs followed by more ACTION_UPDATEs or | |
| 96 // ACTION_ADDs for the same GUID, remove all but the last one. | |
| 97 // | |
| 98 // This is necessary because when syncing we may first need to migrate the | |
| 99 // server-provided TemplateURL in some way, then resolve conflicts against a | |
| 100 // local URL, generating two different UPDATEs. If we send up both UPDATEs, and | |
| 101 // the server does not coalesce them before sending to other clients, then the | |
| 102 // first update could cause conflicts on the other clients, resulting in them | |
| 103 // sending back UPDATEs of their own to try to resolve things, thus causing mass | |
| 104 // confusion. Since the second UPDATE obviates the need for the first, removing | |
| 105 // the first locally is safe and avoids any potential for this problem. | |
| 106 // | |
| 107 // REVIEWERS: Should we instead do this uniquing at a lower level, or guarantee | |
| 108 // that the server will coalesce these so the client need not worry? | |
| 109 void PreventDuplicateGUIDUpdates(SyncChangeList* change_list) { | |
| 110 for (size_t i = change_list->size(); i > 1; ) { | |
| 111 --i; // Prevent underflow that could occur if we did this in the loop body. | |
| 112 const SyncChange& change_i = (*change_list)[i]; | |
| 113 if ((change_i.change_type() != SyncChange::ACTION_ADD) && | |
| 114 (change_i.change_type() != SyncChange::ACTION_UPDATE)) | |
| 115 continue; | |
| 116 std::string guid( | |
| 117 change_i.sync_data().GetSpecifics().search_engine().sync_guid()); | |
| 118 for (size_t j = 0; j < i; ) { | |
| 119 const SyncChange& change_j = (*change_list)[j]; | |
| 120 if ((change_j.change_type() == SyncChange::ACTION_UPDATE) && | |
| 121 (change_j.sync_data().GetSpecifics().search_engine().sync_guid() == | |
| 122 guid)) { | |
| 123 change_list->erase(change_list->begin() + j); | |
| 124 --i; | |
| 125 } else { | |
| 126 ++j; | |
| 127 } | |
| 128 } | |
| 129 } | |
| 130 } | |
| 131 | |
| 93 } // namespace | 132 } // namespace |
| 94 | 133 |
| 95 | 134 |
| 96 class TemplateURLService::LessWithPrefix { | 135 class TemplateURLService::LessWithPrefix { |
| 97 public: | 136 public: |
| 98 // We want to find the set of keywords that begin with a prefix. The STL | 137 // We want to find the set of keywords that begin with a prefix. The STL |
| 99 // algorithms will return the set of elements that are "equal to" the | 138 // algorithms will return the set of elements that are "equal to" the |
| 100 // prefix, where "equal(x, y)" means "!(cmp(x, y) || cmp(y, x))". When | 139 // prefix, where "equal(x, y)" means "!(cmp(x, y) || cmp(y, x))". When |
| 101 // cmp() is the typical std::less<>, this results in lexicographic equality; | 140 // cmp() is the typical std::less<>, this results in lexicographic equality; |
| 102 // we need to extend this to mark a prefix as "not less than" a keyword it | 141 // we need to extend this to mark a prefix as "not less than" a keyword it |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 153 TemplateURLService::~TemplateURLService() { | 192 TemplateURLService::~TemplateURLService() { |
| 154 if (load_handle_) { | 193 if (load_handle_) { |
| 155 DCHECK(service_.get()); | 194 DCHECK(service_.get()); |
| 156 service_->CancelRequest(load_handle_); | 195 service_->CancelRequest(load_handle_); |
| 157 } | 196 } |
| 158 | 197 |
| 159 STLDeleteElements(&template_urls_); | 198 STLDeleteElements(&template_urls_); |
| 160 } | 199 } |
| 161 | 200 |
| 162 // static | 201 // static |
| 163 string16 TemplateURLService::GenerateKeyword(const GURL& url, | 202 string16 TemplateURLService::GenerateKeyword(const GURL& url) { |
| 164 bool autodetected) { | 203 DCHECK(url.is_valid()); |
| 165 // Don't autogenerate keywords for referrers that are the result of a form | |
| 166 // submission (TODO: right now we approximate this by checking for the URL | |
| 167 // having a query, but we should replace this with a call to WebCore to see if | |
| 168 // the originating page was actually a form submission), anything other than | |
| 169 // http, or referrers with a path. | |
| 170 // | |
| 171 // If we relax the path constraint, we need to be sure to sanitize the path | |
| 172 // elements and update AutocompletePopup to look for keywords using the path. | |
| 173 // See http://b/issue?id=863583. | |
| 174 if (!url.is_valid() || | |
| 175 (autodetected && (url.has_query() || !url.SchemeIs(chrome::kHttpScheme) || | |
| 176 ((url.path() != "") && (url.path() != "/"))))) | |
| 177 return string16(); | |
| 178 | |
| 179 // Strip "www." off the front of the keyword; otherwise the keyword won't work | 204 // Strip "www." off the front of the keyword; otherwise the keyword won't work |
| 180 // properly. See http://code.google.com/p/chromium/issues/detail?id=6984 . | 205 // properly. See http://code.google.com/p/chromium/issues/detail?id=6984 . |
| 181 // Special case: if the host was exactly "www." (not sure this can happen but | 206 // Special case: if the host was exactly "www." (not sure this can happen but |
| 182 // perhaps with some weird intranet and custom DNS server?), ensure we at | 207 // perhaps with some weird intranet and custom DNS server?), ensure we at |
| 183 // least don't return the empty string. | 208 // least don't return the empty string. |
| 184 string16 keyword(net::StripWWW(UTF8ToUTF16(url.host()))); | 209 string16 keyword(net::StripWWW(UTF8ToUTF16(url.host()))); |
| 185 return keyword.empty() ? ASCIIToUTF16("www") : keyword; | 210 return keyword.empty() ? ASCIIToUTF16("www") : keyword; |
| 186 } | 211 } |
| 187 | 212 |
| 188 // static | 213 // static |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 224 DCHECK(t_url); | 249 DCHECK(t_url); |
| 225 UIThreadSearchTermsData search_terms_data; | 250 UIThreadSearchTermsData search_terms_data; |
| 226 return GenerateSearchURLUsingTermsData(t_url, search_terms_data); | 251 return GenerateSearchURLUsingTermsData(t_url, search_terms_data); |
| 227 } | 252 } |
| 228 | 253 |
| 229 // static | 254 // static |
| 230 GURL TemplateURLService::GenerateSearchURLUsingTermsData( | 255 GURL TemplateURLService::GenerateSearchURLUsingTermsData( |
| 231 const TemplateURL* t_url, | 256 const TemplateURL* t_url, |
| 232 const SearchTermsData& search_terms_data) { | 257 const SearchTermsData& search_terms_data) { |
| 233 DCHECK(t_url); | 258 DCHECK(t_url); |
| 259 DCHECK(!t_url->IsExtensionKeyword()); | |
| 260 | |
| 234 const TemplateURLRef& search_ref = t_url->url_ref(); | 261 const TemplateURLRef& search_ref = t_url->url_ref(); |
| 235 // Extension keywords don't have host-based search URLs. | 262 if (!search_ref.IsValidUsingTermsData(search_terms_data)) |
| 236 if (!search_ref.IsValidUsingTermsData(search_terms_data) || | |
| 237 t_url->IsExtensionKeyword()) | |
| 238 return GURL(); | 263 return GURL(); |
| 239 | 264 |
| 240 if (!search_ref.SupportsReplacementUsingTermsData(search_terms_data)) | 265 if (!search_ref.SupportsReplacementUsingTermsData(search_terms_data)) |
| 241 return GURL(t_url->url()); | 266 return GURL(t_url->url()); |
| 242 | 267 |
| 243 return GURL(search_ref.ReplaceSearchTermsUsingTermsData( | 268 return GURL(search_ref.ReplaceSearchTermsUsingTermsData( |
| 244 ASCIIToUTF16(kReplacementTerm), TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, | 269 ASCIIToUTF16(kReplacementTerm), TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, |
| 245 string16(), search_terms_data)); | 270 string16(), search_terms_data)); |
| 246 } | 271 } |
| 247 | 272 |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 327 const std::string& host) { | 352 const std::string& host) { |
| 328 TemplateURL* t_url = provider_map_->GetTemplateURLForHost(host); | 353 TemplateURL* t_url = provider_map_->GetTemplateURLForHost(host); |
| 329 if (t_url) | 354 if (t_url) |
| 330 return t_url; | 355 return t_url; |
| 331 return (initial_default_search_provider_.get() && | 356 return (initial_default_search_provider_.get() && |
| 332 (GenerateSearchURL(initial_default_search_provider_.get()).host() == | 357 (GenerateSearchURL(initial_default_search_provider_.get()).host() == |
| 333 host)) ? initial_default_search_provider_.get() : NULL; | 358 host)) ? initial_default_search_provider_.get() : NULL; |
| 334 } | 359 } |
| 335 | 360 |
| 336 void TemplateURLService::Add(TemplateURL* template_url) { | 361 void TemplateURLService::Add(TemplateURL* template_url) { |
| 337 AddNoNotify(template_url, true); | 362 if (AddNoNotify(template_url, true)) |
| 338 NotifyObservers(); | 363 NotifyObservers(); |
| 339 } | 364 } |
| 340 | 365 |
| 341 void TemplateURLService::AddAndSetProfile(TemplateURL* template_url, | 366 void TemplateURLService::AddAndSetProfile(TemplateURL* template_url, |
| 342 Profile* profile) { | 367 Profile* profile) { |
| 343 template_url->profile_ = profile; | 368 template_url->profile_ = profile; |
| 344 Add(template_url); | 369 Add(template_url); |
| 345 } | 370 } |
| 346 | 371 |
| 347 void TemplateURLService::AddWithOverrides(TemplateURL* template_url, | 372 void TemplateURLService::AddWithOverrides(TemplateURL* template_url, |
| 348 const string16& short_name, | 373 const string16& short_name, |
| 349 const string16& keyword, | 374 const string16& keyword, |
| 350 const std::string& url) { | 375 const std::string& url) { |
| 376 DCHECK(!keyword.empty()); | |
| 351 DCHECK(!url.empty()); | 377 DCHECK(!url.empty()); |
| 352 template_url->data_.short_name = short_name; | 378 template_url->data_.short_name = short_name; |
| 353 template_url->data_.SetKeyword(keyword); | 379 template_url->data_.SetKeyword(keyword); |
| 354 template_url->SetURL(url); | 380 template_url->SetURL(url); |
| 355 Add(template_url); | 381 Add(template_url); |
| 356 } | 382 } |
| 357 | 383 |
| 358 void TemplateURLService::Remove(TemplateURL* template_url) { | 384 void TemplateURLService::Remove(TemplateURL* template_url) { |
| 359 RemoveNoNotify(template_url); | 385 RemoveNoNotify(template_url); |
| 360 NotifyObservers(); | 386 NotifyObservers(); |
| (...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 447 } | 473 } |
| 448 | 474 |
| 449 void TemplateURLService::IncrementUsageCount(TemplateURL* url) { | 475 void TemplateURLService::IncrementUsageCount(TemplateURL* url) { |
| 450 DCHECK(url && std::find(template_urls_.begin(), template_urls_.end(), url) != | 476 DCHECK(url && std::find(template_urls_.begin(), template_urls_.end(), url) != |
| 451 template_urls_.end()); | 477 template_urls_.end()); |
| 452 ++url->data_.usage_count; | 478 ++url->data_.usage_count; |
| 453 // Extension keywords are not persisted. | 479 // Extension keywords are not persisted. |
| 454 // TODO(mpcomplete): If we allow editing extension keywords, then those should | 480 // TODO(mpcomplete): If we allow editing extension keywords, then those should |
| 455 // be persisted to disk and synced. | 481 // be persisted to disk and synced. |
| 456 if (service_.get() && !url->IsExtensionKeyword()) | 482 if (service_.get() && !url->IsExtensionKeyword()) |
| 457 service_.get()->UpdateKeyword(*url); | 483 service_.get()->UpdateKeyword(url->data()); |
| 458 } | 484 } |
| 459 | 485 |
| 460 void TemplateURLService::ResetTemplateURL(TemplateURL* url, | 486 void TemplateURLService::ResetTemplateURL(TemplateURL* url, |
| 461 const string16& title, | 487 const string16& title, |
| 462 const string16& keyword, | 488 const string16& keyword, |
| 463 const std::string& search_url) { | 489 const std::string& search_url) { |
| 490 DCHECK(!keyword.empty()); | |
| 464 DCHECK(!search_url.empty()); | 491 DCHECK(!search_url.empty()); |
| 465 TemplateURLData data(url->data()); | 492 TemplateURLData data(url->data()); |
| 466 data.short_name = title; | 493 data.short_name = title; |
| 467 data.SetKeyword(keyword); | 494 data.SetKeyword(keyword); |
| 468 if (search_url != data.url()) { | 495 if (search_url != data.url()) { |
| 469 data.SetURL(search_url); | 496 data.SetURL(search_url); |
| 470 // The urls have changed, reset the favicon url. | 497 // The urls have changed, reset the favicon url. |
| 471 data.favicon_url = GURL(); | 498 data.favicon_url = GURL(); |
| 472 } | 499 } |
| 473 data.safe_for_autoreplace = false; | 500 data.safe_for_autoreplace = false; |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 604 // The value from the preferences was previously stored in the database. | 631 // The value from the preferences was previously stored in the database. |
| 605 // Reuse it. | 632 // Reuse it. |
| 606 } else { | 633 } else { |
| 607 // The value from the preferences takes over. | 634 // The value from the preferences takes over. |
| 608 default_search_provider = NULL; | 635 default_search_provider = NULL; |
| 609 if (default_from_prefs.get()) { | 636 if (default_from_prefs.get()) { |
| 610 TemplateURLData data(default_from_prefs->data()); | 637 TemplateURLData data(default_from_prefs->data()); |
| 611 data.created_by_policy = true; | 638 data.created_by_policy = true; |
| 612 data.id = kInvalidTemplateURLID; | 639 data.id = kInvalidTemplateURLID; |
| 613 default_search_provider = new TemplateURL(profile_, data); | 640 default_search_provider = new TemplateURL(profile_, data); |
| 614 AddNoNotify(default_search_provider, true); | 641 if (!AddNoNotify(default_search_provider, true)) |
| 642 default_search_provider = NULL; | |
| 615 } | 643 } |
| 616 } | 644 } |
| 617 // Note that this saves the default search provider to prefs. | 645 // Note that this saves the default search provider to prefs. |
| 618 if (!default_search_provider || | 646 if (!default_search_provider || |
| 619 (!default_search_provider->IsExtensionKeyword() && | 647 (!default_search_provider->IsExtensionKeyword() && |
| 620 default_search_provider->SupportsReplacement())) | 648 default_search_provider->SupportsReplacement())) |
| 621 SetDefaultSearchProviderNoNotify(default_search_provider); | 649 SetDefaultSearchProviderNoNotify(default_search_provider); |
| 622 } else { | 650 } else { |
| 623 // If we had a managed default, replace it with the synced default if | 651 // If we had a managed default, replace it with the synced default if |
| 624 // applicable, or the first provider of the list. | 652 // applicable, or the first provider of the list. |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 802 DCHECK_EQ(syncable::SEARCH_ENGINES, iter->sync_data().GetDataType()); | 830 DCHECK_EQ(syncable::SEARCH_ENGINES, iter->sync_data().GetDataType()); |
| 803 | 831 |
| 804 std::string guid = | 832 std::string guid = |
| 805 iter->sync_data().GetSpecifics().search_engine().sync_guid(); | 833 iter->sync_data().GetSpecifics().search_engine().sync_guid(); |
| 806 TemplateURL* existing_turl = GetTemplateURLForGUID(guid); | 834 TemplateURL* existing_turl = GetTemplateURLForGUID(guid); |
| 807 scoped_ptr<TemplateURL> turl(CreateTemplateURLFromTemplateURLAndSyncData( | 835 scoped_ptr<TemplateURL> turl(CreateTemplateURLFromTemplateURLAndSyncData( |
| 808 profile_, existing_turl, iter->sync_data(), &new_changes)); | 836 profile_, existing_turl, iter->sync_data(), &new_changes)); |
| 809 if (!turl.get()) | 837 if (!turl.get()) |
| 810 continue; | 838 continue; |
| 811 | 839 |
| 840 // Explicitly don't check for conflicts against extension keywords; in this | |
| 841 // case the functions which modify the keyword map know how to handle the | |
| 842 // conflicts. | |
| 843 // TODO(mpcomplete): If we allow editing extension keywords, then those will | |
| 844 // need to undergo conflict resolution. | |
| 812 TemplateURL* existing_keyword_turl = | 845 TemplateURL* existing_keyword_turl = |
| 813 GetTemplateURLForKeyword(turl->keyword()); | 846 FindNonExtensionTemplateURLForKeyword(turl->keyword()); |
| 814 | |
| 815 if (iter->change_type() == SyncChange::ACTION_DELETE && existing_turl) { | 847 if (iter->change_type() == SyncChange::ACTION_DELETE && existing_turl) { |
| 816 bool delete_default = (existing_turl == GetDefaultSearchProvider()); | 848 bool delete_default = (existing_turl == GetDefaultSearchProvider()); |
| 817 | 849 |
| 818 if (delete_default && is_default_search_managed_) { | 850 if (delete_default && is_default_search_managed_) { |
| 819 NOTREACHED() << "Tried to delete managed default search provider"; | 851 NOTREACHED() << "Tried to delete managed default search provider"; |
| 820 } else { | 852 } else { |
| 821 if (delete_default) | 853 if (delete_default) |
| 822 default_search_provider_ = NULL; | 854 default_search_provider_ = NULL; |
| 823 | 855 |
| 824 Remove(existing_turl); | 856 Remove(existing_turl); |
| 825 | 857 |
| 826 if (delete_default) | 858 if (delete_default) |
| 827 SetDefaultSearchProvider(FindNewDefaultSearchProvider()); | 859 SetDefaultSearchProvider(FindNewDefaultSearchProvider()); |
| 828 } | 860 } |
| 829 } else if (iter->change_type() == SyncChange::ACTION_ADD && | 861 } else if (iter->change_type() == SyncChange::ACTION_ADD && |
| 830 !existing_turl) { | 862 !existing_turl) { |
| 831 std::string guid = turl->sync_guid(); | 863 std::string guid = turl->sync_guid(); |
| 832 if (existing_keyword_turl) | 864 if (existing_keyword_turl) { |
| 833 ResolveSyncKeywordConflict(turl.get(), &new_changes); | 865 ResolveSyncKeywordConflict(turl.get(), existing_keyword_turl, |
| 866 &new_changes); | |
| 867 } | |
| 834 // Force the local ID to kInvalidTemplateURLID so we can add it. | 868 // Force the local ID to kInvalidTemplateURLID so we can add it. |
| 835 TemplateURLData data(turl->data()); | 869 TemplateURLData data(turl->data()); |
| 836 data.id = kInvalidTemplateURLID; | 870 data.id = kInvalidTemplateURLID; |
| 837 Add(new TemplateURL(profile_, data)); | 871 Add(new TemplateURL(profile_, data)); |
| 838 | 872 |
| 839 // Possibly set the newly added |turl| as the default search provider. | 873 // Possibly set the newly added |turl| as the default search provider. |
| 840 SetDefaultSearchProviderIfNewlySynced(guid); | 874 SetDefaultSearchProviderIfNewlySynced(guid); |
| 841 } else if (iter->change_type() == SyncChange::ACTION_UPDATE && | 875 } else if (iter->change_type() == SyncChange::ACTION_UPDATE && |
| 842 existing_turl) { | 876 existing_turl) { |
| 843 // Possibly resolve a keyword conflict if they have the same keywords but | 877 // Possibly resolve a keyword conflict if they have the same keywords but |
| 844 // are not the same entry. | 878 // are not the same entry. |
| 845 if (existing_keyword_turl && existing_keyword_turl != existing_turl) | 879 if (existing_keyword_turl && existing_keyword_turl != existing_turl) { |
| 846 ResolveSyncKeywordConflict(turl.get(), &new_changes); | 880 ResolveSyncKeywordConflict(turl.get(), existing_keyword_turl, |
| 881 &new_changes); | |
| 882 } | |
| 847 UpdateNoNotify(existing_turl, *turl); | 883 UpdateNoNotify(existing_turl, *turl); |
| 848 NotifyObservers(); | 884 NotifyObservers(); |
| 849 } else { | 885 } else { |
| 850 // Something really unexpected happened. Either we received an | 886 // Something really unexpected happened. Either we received an |
| 851 // ACTION_INVALID, or Sync is in a crazy state: | 887 // ACTION_INVALID, or Sync is in a crazy state: |
| 852 // . Trying to DELETE or UPDATE a non-existent search engine. | 888 // . Trying to DELETE or UPDATE a non-existent search engine. |
| 853 // . Trying to ADD a search engine that already exists. | 889 // . Trying to ADD a search engine that already exists. |
| 854 NOTREACHED() << "Unexpected sync change state."; | 890 NOTREACHED() << "Unexpected sync change state."; |
| 855 error = sync_error_factory_->CreateAndUploadError( | 891 error = sync_error_factory_->CreateAndUploadError( |
| 856 FROM_HERE, | 892 FROM_HERE, |
| 857 "ProcessSyncChanges failed on ChangeType " + | 893 "ProcessSyncChanges failed on ChangeType " + |
| 858 SyncChange::ChangeTypeToString(iter->change_type())); | 894 SyncChange::ChangeTypeToString(iter->change_type())); |
| 859 } | 895 } |
| 860 } | 896 } |
| 897 PreventDuplicateGUIDUpdates(&new_changes); | |
| 861 | 898 |
| 862 // If something went wrong, we want to prematurely exit to avoid pushing | 899 // If something went wrong, we want to prematurely exit to avoid pushing |
| 863 // inconsistent data to Sync. We return the last error we received. | 900 // inconsistent data to Sync. We return the last error we received. |
| 864 if (error.IsSet()) | 901 if (error.IsSet()) |
| 865 return error; | 902 return error; |
| 866 | 903 |
| 867 error = sync_processor_->ProcessSyncChanges(from_here, new_changes); | 904 error = sync_processor_->ProcessSyncChanges(from_here, new_changes); |
| 868 | 905 |
| 869 return error; | 906 return error; |
| 870 } | 907 } |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 942 // Merge duplicates and remove the processed local TURL from the map. | 979 // Merge duplicates and remove the processed local TURL from the map. |
| 943 std::string old_guid = dupe_turl->sync_guid(); | 980 std::string old_guid = dupe_turl->sync_guid(); |
| 944 MergeSyncAndLocalURLDuplicates(sync_turl.release(), dupe_turl, | 981 MergeSyncAndLocalURLDuplicates(sync_turl.release(), dupe_turl, |
| 945 &new_changes); | 982 &new_changes); |
| 946 local_data_map.erase(old_guid); | 983 local_data_map.erase(old_guid); |
| 947 } else { | 984 } else { |
| 948 std::string guid = sync_turl->sync_guid(); | 985 std::string guid = sync_turl->sync_guid(); |
| 949 // Keyword conflict is possible in this case. Resolve it first before | 986 // Keyword conflict is possible in this case. Resolve it first before |
| 950 // adding the new TemplateURL. Note that we don't remove the local TURL | 987 // adding the new TemplateURL. Note that we don't remove the local TURL |
| 951 // from local_data_map in this case as it may still need to be pushed to | 988 // from local_data_map in this case as it may still need to be pushed to |
| 952 // the cloud. | 989 // the cloud. We also explicitly don't resolve conflicts against |
| 953 ResolveSyncKeywordConflict(sync_turl.get(), &new_changes); | 990 // extension keywords; see comments in ProcessSyncChanges(). |
| 991 TemplateURL* existing_keyword_turl = | |
| 992 FindNonExtensionTemplateURLForKeyword(sync_turl->keyword()); | |
| 993 if (existing_keyword_turl) { | |
| 994 ResolveSyncKeywordConflict(sync_turl.get(), existing_keyword_turl, | |
| 995 &new_changes); | |
| 996 } | |
| 954 // Force the local ID to kInvalidTemplateURLID so we can add it. | 997 // Force the local ID to kInvalidTemplateURLID so we can add it. |
| 955 TemplateURLData data(sync_turl->data()); | 998 TemplateURLData data(sync_turl->data()); |
| 956 data.id = kInvalidTemplateURLID; | 999 data.id = kInvalidTemplateURLID; |
| 957 Add(new TemplateURL(profile_, data)); | 1000 Add(new TemplateURL(profile_, data)); |
| 958 | 1001 |
| 959 // Possibly set the newly added |turl| as the default search provider. | 1002 // Possibly set the newly added |turl| as the default search provider. |
| 960 SetDefaultSearchProviderIfNewlySynced(guid); | 1003 SetDefaultSearchProviderIfNewlySynced(guid); |
| 961 } | 1004 } |
| 962 } | 1005 } |
| 963 } | 1006 } |
| 964 | 1007 |
| 965 // The remaining SyncData in local_data_map should be everything that needs to | 1008 // The remaining SyncData in local_data_map should be everything that needs to |
| 966 // be pushed as ADDs to sync. | 1009 // be pushed as ADDs to sync. |
| 967 for (SyncDataMap::const_iterator iter = local_data_map.begin(); | 1010 for (SyncDataMap::const_iterator iter = local_data_map.begin(); |
| 968 iter != local_data_map.end(); ++iter) { | 1011 iter != local_data_map.end(); ++iter) { |
| 969 new_changes.push_back(SyncChange(SyncChange::ACTION_ADD, iter->second)); | 1012 new_changes.push_back(SyncChange(SyncChange::ACTION_ADD, iter->second)); |
| 970 } | 1013 } |
| 971 | 1014 |
| 1015 PreventDuplicateGUIDUpdates(&new_changes); | |
| 1016 | |
| 972 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes); | 1017 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes); |
| 973 if (error.IsSet()) | 1018 if (error.IsSet()) |
| 974 return error; | 1019 return error; |
| 975 | 1020 |
| 976 models_associated_ = true; | 1021 models_associated_ = true; |
| 977 return SyncError(); | 1022 return SyncError(); |
| 978 } | 1023 } |
| 979 | 1024 |
| 980 void TemplateURLService::StopSyncing(syncable::ModelType type) { | 1025 void TemplateURLService::StopSyncing(syncable::ModelType type) { |
| 981 DCHECK_EQ(type, syncable::SEARCH_ENGINES); | 1026 DCHECK_EQ(type, syncable::SEARCH_ENGINES); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1024 se_specifics->set_keyword(UTF16ToUTF8(turl.keyword())); | 1069 se_specifics->set_keyword(UTF16ToUTF8(turl.keyword())); |
| 1025 se_specifics->set_favicon_url(turl.favicon_url().spec()); | 1070 se_specifics->set_favicon_url(turl.favicon_url().spec()); |
| 1026 se_specifics->set_url(turl.url()); | 1071 se_specifics->set_url(turl.url()); |
| 1027 se_specifics->set_safe_for_autoreplace(turl.safe_for_autoreplace()); | 1072 se_specifics->set_safe_for_autoreplace(turl.safe_for_autoreplace()); |
| 1028 se_specifics->set_originating_url(turl.originating_url().spec()); | 1073 se_specifics->set_originating_url(turl.originating_url().spec()); |
| 1029 se_specifics->set_date_created(turl.date_created().ToInternalValue()); | 1074 se_specifics->set_date_created(turl.date_created().ToInternalValue()); |
| 1030 se_specifics->set_input_encodings(JoinString(turl.input_encodings(), ';')); | 1075 se_specifics->set_input_encodings(JoinString(turl.input_encodings(), ';')); |
| 1031 se_specifics->set_show_in_default_list(turl.show_in_default_list()); | 1076 se_specifics->set_show_in_default_list(turl.show_in_default_list()); |
| 1032 se_specifics->set_suggestions_url(turl.suggestions_url()); | 1077 se_specifics->set_suggestions_url(turl.suggestions_url()); |
| 1033 se_specifics->set_prepopulate_id(turl.prepopulate_id()); | 1078 se_specifics->set_prepopulate_id(turl.prepopulate_id()); |
| 1034 se_specifics->set_autogenerate_keyword(turl.autogenerate_keyword()); | 1079 // REVIEWERS: Should I instead remove this line entirely? |
| 1080 se_specifics->set_autogenerate_keyword(false); | |
| 1035 se_specifics->set_instant_url(turl.instant_url()); | 1081 se_specifics->set_instant_url(turl.instant_url()); |
| 1036 se_specifics->set_last_modified(turl.last_modified().ToInternalValue()); | 1082 se_specifics->set_last_modified(turl.last_modified().ToInternalValue()); |
| 1037 se_specifics->set_sync_guid(turl.sync_guid()); | 1083 se_specifics->set_sync_guid(turl.sync_guid()); |
| 1038 return SyncData::CreateLocalData(se_specifics->sync_guid(), | 1084 return SyncData::CreateLocalData(se_specifics->sync_guid(), |
| 1039 se_specifics->keyword(), | 1085 se_specifics->keyword(), |
| 1040 specifics); | 1086 specifics); |
| 1041 } | 1087 } |
| 1042 | 1088 |
| 1043 // static | 1089 // static |
| 1044 TemplateURL* TemplateURLService::CreateTemplateURLFromTemplateURLAndSyncData( | 1090 TemplateURL* TemplateURLService::CreateTemplateURLFromTemplateURLAndSyncData( |
| 1045 Profile* profile, | 1091 Profile* profile, |
| 1046 TemplateURL* existing_turl, | 1092 TemplateURL* existing_turl, |
| 1047 const SyncData& sync_data, | 1093 const SyncData& sync_data, |
| 1048 SyncChangeList* change_list) { | 1094 SyncChangeList* change_list) { |
| 1049 DCHECK(change_list); | 1095 DCHECK(change_list); |
| 1050 | 1096 |
| 1051 sync_pb::SearchEngineSpecifics specifics = | 1097 sync_pb::SearchEngineSpecifics specifics = |
| 1052 sync_data.GetSpecifics().search_engine(); | 1098 sync_data.GetSpecifics().search_engine(); |
| 1053 | 1099 |
| 1054 // Past bugs might have caused either of these fields to be empty. Just | 1100 // Past bugs might have caused either of these fields to be empty. Just |
| 1055 // delete this data off the server. | 1101 // delete this data off the server. |
| 1056 if (specifics.url().empty() || specifics.sync_guid().empty()) { | 1102 if (specifics.url().empty() || specifics.sync_guid().empty()) { |
| 1057 change_list->push_back(SyncChange(SyncChange::ACTION_DELETE, sync_data)); | 1103 change_list->push_back(SyncChange(SyncChange::ACTION_DELETE, sync_data)); |
| 1058 return NULL; | 1104 return NULL; |
| 1059 } | 1105 } |
| 1060 | 1106 |
| 1061 TemplateURLData data; | 1107 TemplateURLData data; |
| 1062 data.short_name = UTF8ToUTF16(specifics.short_name()); | 1108 data.short_name = UTF8ToUTF16(specifics.short_name()); |
| 1063 data.originating_url = GURL(specifics.originating_url()); | 1109 data.originating_url = GURL(specifics.originating_url()); |
| 1064 data.SetKeyword(UTF8ToUTF16(specifics.keyword())); | 1110 string16 keyword(UTF8ToUTF16(specifics.keyword())); |
| 1065 data.SetAutogenerateKeyword(specifics.autogenerate_keyword()); | 1111 // REVIEWERS: Can we ever get to a state where this migration code can be |
| 1112 // eliminated? | |
| 1113 bool reset_keyword = | |
| 1114 specifics.autogenerate_keyword() || specifics.keyword().empty(); | |
| 1115 if (reset_keyword) | |
| 1116 keyword = ASCIIToUTF16("dummy"); // Will be replaced below. | |
| 1117 DCHECK(!keyword.empty()); | |
| 1118 data.SetKeyword(keyword); | |
| 1066 data.SetURL(specifics.url()); | 1119 data.SetURL(specifics.url()); |
| 1067 data.suggestions_url = specifics.suggestions_url(); | 1120 data.suggestions_url = specifics.suggestions_url(); |
| 1068 data.instant_url = specifics.instant_url(); | 1121 data.instant_url = specifics.instant_url(); |
| 1069 data.favicon_url = GURL(specifics.favicon_url()); | 1122 data.favicon_url = GURL(specifics.favicon_url()); |
| 1070 data.show_in_default_list = specifics.show_in_default_list(); | 1123 data.show_in_default_list = specifics.show_in_default_list(); |
| 1071 data.safe_for_autoreplace = specifics.safe_for_autoreplace(); | 1124 data.safe_for_autoreplace = specifics.safe_for_autoreplace(); |
| 1072 base::SplitString(specifics.input_encodings(), ';', &data.input_encodings); | 1125 base::SplitString(specifics.input_encodings(), ';', &data.input_encodings); |
| 1073 data.date_created = base::Time::FromInternalValue(specifics.date_created()); | 1126 data.date_created = base::Time::FromInternalValue(specifics.date_created()); |
| 1074 data.last_modified = base::Time::FromInternalValue(specifics.last_modified()); | 1127 data.last_modified = base::Time::FromInternalValue(specifics.last_modified()); |
| 1075 data.prepopulate_id = specifics.prepopulate_id(); | 1128 data.prepopulate_id = specifics.prepopulate_id(); |
| 1076 data.sync_guid = specifics.sync_guid(); | 1129 data.sync_guid = specifics.sync_guid(); |
| 1077 if (existing_turl) { | 1130 if (existing_turl) { |
| 1078 data.id = existing_turl->id(); | 1131 data.id = existing_turl->id(); |
| 1079 data.created_by_policy = existing_turl->created_by_policy(); | 1132 data.created_by_policy = existing_turl->created_by_policy(); |
| 1080 data.usage_count = existing_turl->usage_count(); | 1133 data.usage_count = existing_turl->usage_count(); |
| 1081 } | 1134 } |
| 1082 | 1135 |
| 1083 TemplateURL* turl = new TemplateURL(profile, data); | 1136 TemplateURL* turl = new TemplateURL(profile, data); |
| 1084 DCHECK(!turl->IsExtensionKeyword()); | 1137 DCHECK(!turl->IsExtensionKeyword()); |
| 1138 if (reset_keyword) { | |
| 1139 turl->ResetKeywordIfNecessary(true); | |
| 1140 SyncData sync_data = CreateSyncDataFromTemplateURL(*turl); | |
| 1141 change_list->push_back(SyncChange(SyncChange::ACTION_UPDATE, sync_data)); | |
| 1142 } | |
| 1085 return turl; | 1143 return turl; |
| 1086 } | 1144 } |
| 1087 | 1145 |
| 1088 // static | 1146 // static |
| 1089 SyncDataMap TemplateURLService::CreateGUIDToSyncDataMap( | 1147 SyncDataMap TemplateURLService::CreateGUIDToSyncDataMap( |
| 1090 const SyncDataList& sync_data) { | 1148 const SyncDataList& sync_data) { |
| 1091 SyncDataMap data_map; | 1149 SyncDataMap data_map; |
| 1092 for (SyncDataList::const_iterator i(sync_data.begin()); i != sync_data.end(); | 1150 for (SyncDataList::const_iterator i(sync_data.begin()); i != sync_data.end(); |
| 1093 ++i) | 1151 ++i) |
| 1094 data_map[i->GetSpecifics().search_engine().sync_guid()] = *i; | 1152 data_map[i->GetSpecifics().search_engine().sync_guid()] = *i; |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1160 if (initial_default_search_provider_.get() && | 1218 if (initial_default_search_provider_.get() && |
| 1161 initial_default_search_provider_->url_ref().HasGoogleBaseURLs()) { | 1219 initial_default_search_provider_->url_ref().HasGoogleBaseURLs()) { |
| 1162 scoped_ptr<base::Environment> env(base::Environment::Create()); | 1220 scoped_ptr<base::Environment> env(base::Environment::Create()); |
| 1163 if (!env->HasVar(env_vars::kHeadless) && | 1221 if (!env->HasVar(env_vars::kHeadless) && |
| 1164 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kChromeFrame)) | 1222 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kChromeFrame)) |
| 1165 GoogleURLTracker::RequestServerCheck(); | 1223 GoogleURLTracker::RequestServerCheck(); |
| 1166 } | 1224 } |
| 1167 } | 1225 } |
| 1168 | 1226 |
| 1169 void TemplateURLService::RemoveFromMaps(TemplateURL* template_url) { | 1227 void TemplateURLService::RemoveFromMaps(TemplateURL* template_url) { |
| 1170 if (!template_url->keyword().empty()) | 1228 const string16& keyword = template_url->keyword(); |
| 1171 keyword_to_template_map_.erase(template_url->keyword()); | 1229 DCHECK_NE(0U, keyword_to_template_map_.count(keyword)); |
| 1230 if (keyword_to_template_map_[keyword] == template_url) { | |
| 1231 // We need to check whether the keyword can now be provided by another | |
| 1232 // TemplateURL. See the comments in AddToMaps() for more information on | |
| 1233 // extension keywords and how they can coexist with non-extension keywords. | |
| 1234 // In the case of more than one extension, we use the most recently | |
| 1235 // installed (which will be the most recently added, which will have the | |
| 1236 // highest ID). | |
| 1237 TemplateURL* best_fallback = NULL; | |
| 1238 for (TemplateURLVector::const_iterator i(template_urls_.begin()); | |
| 1239 i != template_urls_.end(); ++i) { | |
| 1240 TemplateURL* turl = *i; | |
| 1241 // This next statement relies on the fact that there can only be one | |
| 1242 // non-extension TemplateURL with a given keyword. | |
| 1243 if ((turl != template_url) && (turl->keyword() == keyword) && | |
| 1244 (!best_fallback || !best_fallback->IsExtensionKeyword() || | |
| 1245 (turl->IsExtensionKeyword() && (turl->id() > best_fallback->id())))) | |
| 1246 best_fallback = turl; | |
| 1247 } | |
| 1248 if (best_fallback) | |
| 1249 keyword_to_template_map_[keyword] = best_fallback; | |
| 1250 else | |
| 1251 keyword_to_template_map_.erase(keyword); | |
| 1252 } | |
| 1172 | 1253 |
| 1173 // If the keyword we're removing is from an extension, we're now done, since | 1254 // If the keyword we're removing is from an extension, we're now done, since |
| 1174 // it won't be synced or stored in the provider map. | 1255 // it won't be synced or stored in the provider map. |
| 1175 // TODO(mpcomplete): If we allow editing extension keywords, then those should | 1256 // TODO(mpcomplete): If we allow editing extension keywords, then those should |
| 1176 // be synced. | 1257 // be synced. |
| 1177 if (template_url->IsExtensionKeyword()) | 1258 if (template_url->IsExtensionKeyword()) |
| 1178 return; | 1259 return; |
| 1179 | 1260 |
| 1180 if (!template_url->sync_guid().empty()) | 1261 if (!template_url->sync_guid().empty()) |
| 1181 guid_to_template_map_.erase(template_url->sync_guid()); | 1262 guid_to_template_map_.erase(template_url->sync_guid()); |
| 1182 if (loaded_) | 1263 if (loaded_) |
| 1183 provider_map_->Remove(template_url); | 1264 provider_map_->Remove(template_url); |
| 1184 } | 1265 } |
| 1185 | 1266 |
| 1186 void TemplateURLService::RemoveFromKeywordMapByPointer( | 1267 void TemplateURLService::RemoveFromKeywordMapByPointer( |
| 1187 TemplateURL* template_url) { | 1268 TemplateURL* template_url) { |
| 1188 DCHECK(template_url); | 1269 DCHECK(template_url); |
| 1189 for (KeywordToTemplateMap::iterator i = keyword_to_template_map_.begin(); | 1270 for (KeywordToTemplateMap::iterator i = keyword_to_template_map_.begin(); |
| 1190 i != keyword_to_template_map_.end(); ++i) { | 1271 i != keyword_to_template_map_.end(); ++i) { |
| 1191 if (i->second == template_url) { | 1272 if (i->second == template_url) { |
| 1192 keyword_to_template_map_.erase(i); | 1273 keyword_to_template_map_.erase(i); |
| 1193 // A given TemplateURL only occurs once in the map. As soon as we find the | 1274 // A given TemplateURL only occurs once in the map. As soon as we find the |
| 1194 // entry, stop. | 1275 // entry, stop. |
| 1195 break; | 1276 break; |
| 1196 } | 1277 } |
| 1197 } | 1278 } |
| 1198 } | 1279 } |
| 1199 | 1280 |
| 1200 void TemplateURLService::AddToMaps(TemplateURL* template_url) { | 1281 void TemplateURLService::AddToMaps(TemplateURL* template_url) { |
| 1201 if (!template_url->keyword().empty()) | 1282 bool template_extension = template_url->IsExtensionKeyword(); |
| 1202 keyword_to_template_map_[template_url->keyword()] = template_url; | 1283 const string16& keyword = template_url->keyword(); |
| 1284 KeywordToTemplateMap::const_iterator i = | |
| 1285 keyword_to_template_map_.find(keyword); | |
| 1286 if (i == keyword_to_template_map_.end()) { | |
| 1287 keyword_to_template_map_[keyword] = template_url; | |
| 1288 } else { | |
| 1289 const TemplateURL* existing_url = i->second; | |
| 1290 // We should only have overlapping keywords when at least one comes from | |
| 1291 // an extension. In that case, the ranking order is: | |
| 1292 // Manually-modified keywords > extension keywords > replaceable keywords | |
| 1293 // When there are multiple extensions, the last-added wins. | |
| 1294 bool existing_extension = existing_url->IsExtensionKeyword(); | |
| 1295 DCHECK(existing_extension || template_extension); | |
| 1296 if (existing_extension ? | |
| 1297 !CanReplace(template_url) : CanReplace(existing_url)) | |
| 1298 keyword_to_template_map_[keyword] = template_url; | |
| 1299 } | |
| 1203 | 1300 |
| 1204 // Extension keywords are not synced, so they don't go into the GUID map, | 1301 // Extension keywords are not synced, so they don't go into the GUID map, |
| 1205 // and do not use host-based search URLs, so they don't go into the provider | 1302 // and do not use host-based search URLs, so they don't go into the provider |
| 1206 // map, so at this point we're done. | 1303 // map, so at this point we're done. |
| 1207 // TODO(mpcomplete): If we allow editing extension keywords, then those should | 1304 // TODO(mpcomplete): If we allow editing extension keywords, then those should |
| 1208 // be persisted to disk and synced. | 1305 // be persisted to disk and synced. |
| 1209 if (template_url->IsExtensionKeyword()) | 1306 if (template_extension) |
| 1210 return; | 1307 return; |
| 1211 | 1308 |
| 1212 if (!template_url->sync_guid().empty()) | 1309 if (!template_url->sync_guid().empty()) |
| 1213 guid_to_template_map_[template_url->sync_guid()] = template_url; | 1310 guid_to_template_map_[template_url->sync_guid()] = template_url; |
| 1214 if (loaded_) { | 1311 if (loaded_) { |
| 1215 UIThreadSearchTermsData search_terms_data; | 1312 UIThreadSearchTermsData search_terms_data; |
| 1216 provider_map_->Add(template_url, search_terms_data); | 1313 provider_map_->Add(template_url, search_terms_data); |
| 1217 } | 1314 } |
| 1218 } | 1315 } |
| 1219 | 1316 |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1319 if (!prefs->GetBoolean(prefs::kDefaultSearchProviderEnabled)) { | 1416 if (!prefs->GetBoolean(prefs::kDefaultSearchProviderEnabled)) { |
| 1320 // The user doesn't want a default search provider. | 1417 // The user doesn't want a default search provider. |
| 1321 default_provider->reset(NULL); | 1418 default_provider->reset(NULL); |
| 1322 return true; | 1419 return true; |
| 1323 } | 1420 } |
| 1324 | 1421 |
| 1325 string16 name = | 1422 string16 name = |
| 1326 UTF8ToUTF16(prefs->GetString(prefs::kDefaultSearchProviderName)); | 1423 UTF8ToUTF16(prefs->GetString(prefs::kDefaultSearchProviderName)); |
| 1327 string16 keyword = | 1424 string16 keyword = |
| 1328 UTF8ToUTF16(prefs->GetString(prefs::kDefaultSearchProviderKeyword)); | 1425 UTF8ToUTF16(prefs->GetString(prefs::kDefaultSearchProviderKeyword)); |
| 1426 // Force keyword to be non-empty. | |
| 1427 // TODO(pkasting): This is only necessary as long as we're potentially loading | |
| 1428 // older prefs where empty keywords are theoretically possible. Eventually | |
| 1429 // this code can be replaced with a DCHECK(!keyword.empty());. | |
| 1430 bool update_keyword = keyword.empty(); | |
| 1431 if (update_keyword) | |
| 1432 keyword = ASCIIToUTF16("dummy"); | |
| 1329 std::string search_url = | 1433 std::string search_url = |
| 1330 prefs->GetString(prefs::kDefaultSearchProviderSearchURL); | 1434 prefs->GetString(prefs::kDefaultSearchProviderSearchURL); |
| 1331 // Force URL to be non-empty. We've never supported this case, but past bugs | 1435 // Force URL to be non-empty. We've never supported this case, but past bugs |
| 1332 // might have resulted in it slipping through; eventually this code can be | 1436 // might have resulted in it slipping through; eventually this code can be |
| 1333 // replaced with a DCHECK(!search_url.empty());. | 1437 // replaced with a DCHECK(!search_url.empty());. |
| 1334 if (search_url.empty()) | 1438 if (search_url.empty()) |
| 1335 return false; | 1439 return false; |
| 1336 std::string suggest_url = | 1440 std::string suggest_url = |
| 1337 prefs->GetString(prefs::kDefaultSearchProviderSuggestURL); | 1441 prefs->GetString(prefs::kDefaultSearchProviderSuggestURL); |
| 1338 std::string instant_url = | 1442 std::string instant_url = |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 1359 base::StringToInt64(id_string, &value); | 1463 base::StringToInt64(id_string, &value); |
| 1360 data.id = value; | 1464 data.id = value; |
| 1361 } | 1465 } |
| 1362 if (!prepopulate_id.empty() && !*is_managed) { | 1466 if (!prepopulate_id.empty() && !*is_managed) { |
| 1363 int value; | 1467 int value; |
| 1364 base::StringToInt(prepopulate_id, &value); | 1468 base::StringToInt(prepopulate_id, &value); |
| 1365 data.prepopulate_id = value; | 1469 data.prepopulate_id = value; |
| 1366 } | 1470 } |
| 1367 default_provider->reset(new TemplateURL(profile_, data)); | 1471 default_provider->reset(new TemplateURL(profile_, data)); |
| 1368 DCHECK(!(*default_provider)->IsExtensionKeyword()); | 1472 DCHECK(!(*default_provider)->IsExtensionKeyword()); |
| 1473 if (update_keyword) | |
| 1474 (*default_provider)->ResetKeywordIfNecessary(true); | |
| 1369 return true; | 1475 return true; |
| 1370 } | 1476 } |
| 1371 | 1477 |
| 1372 bool TemplateURLService::CanReplaceKeywordForHost( | 1478 bool TemplateURLService::CanReplaceKeywordForHost( |
| 1373 const std::string& host, | 1479 const std::string& host, |
| 1374 TemplateURL** to_replace) { | 1480 TemplateURL** to_replace) { |
| 1375 DCHECK(!to_replace || !*to_replace); | 1481 DCHECK(!to_replace || !*to_replace); |
| 1376 const TemplateURLSet* urls = provider_map_->GetURLsForHost(host); | 1482 const TemplateURLSet* urls = provider_map_->GetURLsForHost(host); |
| 1377 if (!urls) | 1483 if (!urls) |
| 1378 return true; | 1484 return true; |
| 1379 for (TemplateURLSet::const_iterator i(urls->begin()); i != urls->end(); ++i) { | 1485 for (TemplateURLSet::const_iterator i(urls->begin()); i != urls->end(); ++i) { |
| 1380 if (CanReplace(*i)) { | 1486 if (CanReplace(*i)) { |
| 1381 if (to_replace) | 1487 if (to_replace) |
| 1382 *to_replace = *i; | 1488 *to_replace = *i; |
| 1383 return true; | 1489 return true; |
| 1384 } | 1490 } |
| 1385 } | 1491 } |
| 1386 return false; | 1492 return false; |
| 1387 } | 1493 } |
| 1388 | 1494 |
| 1389 bool TemplateURLService::CanReplace(const TemplateURL* t_url) { | 1495 bool TemplateURLService::CanReplace(const TemplateURL* t_url) { |
| 1390 return (t_url != default_search_provider_ && !t_url->show_in_default_list() && | 1496 return (t_url != default_search_provider_ && !t_url->show_in_default_list() && |
| 1391 t_url->safe_for_autoreplace()); | 1497 t_url->safe_for_autoreplace()); |
| 1392 } | 1498 } |
| 1393 | 1499 |
| 1500 TemplateURL* TemplateURLService::FindNonExtensionTemplateURLForKeyword( | |
| 1501 const string16& keyword) { | |
| 1502 TemplateURL* keyword_turl = GetTemplateURLForKeyword(keyword); | |
| 1503 if (!keyword_turl || !keyword_turl->IsExtensionKeyword()) | |
| 1504 return keyword_turl; | |
| 1505 // The extension keyword in the model may be hiding a replaceable | |
| 1506 // non-extension keyword. Look for it. | |
| 1507 for (TemplateURLVector::const_iterator i(template_urls_.begin()); | |
| 1508 i != template_urls_.end(); ++i) { | |
| 1509 if (!(*i)->IsExtensionKeyword() && ((*i)->keyword() == keyword)) | |
| 1510 return *i; | |
| 1511 } | |
| 1512 return NULL; | |
| 1513 } | |
| 1514 | |
| 1394 void TemplateURLService::UpdateNoNotify(TemplateURL* existing_turl, | 1515 void TemplateURLService::UpdateNoNotify(TemplateURL* existing_turl, |
| 1395 const TemplateURL& new_values) { | 1516 const TemplateURL& new_values) { |
| 1396 DCHECK(loaded_); | 1517 DCHECK(loaded_); |
| 1397 DCHECK(existing_turl); | 1518 DCHECK(existing_turl); |
| 1398 DCHECK(std::find(template_urls_.begin(), template_urls_.end(), | 1519 DCHECK(std::find(template_urls_.begin(), template_urls_.end(), |
| 1399 existing_turl) != template_urls_.end()); | 1520 existing_turl) != template_urls_.end()); |
| 1400 | 1521 |
| 1401 // TODO(mpcomplete): If we allow editing extension keywords, then those should | 1522 // TODO(mpcomplete): If we allow editing extension keywords, then those should |
| 1402 // be persisted to disk and synced. In this case this DCHECK should be | 1523 // be persisted to disk and synced. In this case this DCHECK should be |
| 1403 // removed. | 1524 // removed. |
| 1404 DCHECK(!existing_turl->IsExtensionKeyword()); | 1525 DCHECK(!existing_turl->IsExtensionKeyword()); |
| 1405 | 1526 |
| 1406 string16 old_keyword(existing_turl->keyword()); | 1527 string16 old_keyword(existing_turl->keyword()); |
| 1407 if (!old_keyword.empty()) | 1528 keyword_to_template_map_.erase(old_keyword); |
| 1408 keyword_to_template_map_.erase(old_keyword); | |
| 1409 if (!existing_turl->sync_guid().empty()) | 1529 if (!existing_turl->sync_guid().empty()) |
| 1410 guid_to_template_map_.erase(existing_turl->sync_guid()); | 1530 guid_to_template_map_.erase(existing_turl->sync_guid()); |
| 1411 | 1531 |
| 1412 provider_map_->Remove(existing_turl); | 1532 provider_map_->Remove(existing_turl); |
| 1413 TemplateURLID previous_id = existing_turl->id(); | 1533 TemplateURLID previous_id = existing_turl->id(); |
| 1414 *existing_turl = new_values; | 1534 *existing_turl = new_values; |
| 1415 existing_turl->data_.id = previous_id; | 1535 existing_turl->data_.id = previous_id; |
| 1416 UIThreadSearchTermsData search_terms_data; | 1536 UIThreadSearchTermsData search_terms_data; |
| 1417 provider_map_->Add(existing_turl, search_terms_data); | 1537 provider_map_->Add(existing_turl, search_terms_data); |
| 1418 | 1538 |
| 1419 const string16& keyword = existing_turl->keyword(); | 1539 const string16& keyword = existing_turl->keyword(); |
| 1420 if (!keyword.empty()) | 1540 KeywordToTemplateMap::const_iterator i = |
| 1541 keyword_to_template_map_.find(keyword); | |
| 1542 if (i == keyword_to_template_map_.end()) { | |
| 1421 keyword_to_template_map_[keyword] = existing_turl; | 1543 keyword_to_template_map_[keyword] = existing_turl; |
| 1544 } else { | |
| 1545 // We can theoretically reach here in two cases: | |
| 1546 // * There is an existing extension keyword and sync brings in a rename of | |
| 1547 // a non-extension keyword to match. In this case we just need to pick | |
| 1548 // which keyword has priority to update the keyword map. | |
| 1549 // * Autogeneration of the keyword for a Google default search provider | |
| 1550 // at load time causes it to conflict with an existing keyword. In this | |
| 1551 // case we delete the existing keyword if it's replaceable, or else undo | |
| 1552 // the change in keyword for |existing_turl|. | |
| 1553 DCHECK(!existing_turl->IsExtensionKeyword()); | |
| 1554 TemplateURL* existing_keyword_turl = i->second; | |
| 1555 if (existing_keyword_turl->IsExtensionKeyword()) { | |
| 1556 if (!CanReplace(existing_turl)) | |
| 1557 keyword_to_template_map_[keyword] = existing_turl; | |
| 1558 } else { | |
| 1559 if (CanReplace(existing_keyword_turl)) { | |
| 1560 RemoveNoNotify(existing_keyword_turl); | |
| 1561 } else { | |
| 1562 existing_turl->data_.SetKeyword(old_keyword); | |
| 1563 keyword_to_template_map_[old_keyword] = existing_turl; | |
| 1564 } | |
| 1565 } | |
| 1566 } | |
| 1422 if (!existing_turl->sync_guid().empty()) | 1567 if (!existing_turl->sync_guid().empty()) |
| 1423 guid_to_template_map_[existing_turl->sync_guid()] = existing_turl; | 1568 guid_to_template_map_[existing_turl->sync_guid()] = existing_turl; |
| 1424 | 1569 |
| 1425 if (service_.get()) | 1570 if (service_.get()) |
| 1426 service_->UpdateKeyword(*existing_turl); | 1571 service_->UpdateKeyword(existing_turl->data()); |
| 1427 | 1572 |
| 1428 // Inform sync of the update. | 1573 // Inform sync of the update. |
| 1429 ProcessTemplateURLChange(existing_turl, SyncChange::ACTION_UPDATE); | 1574 ProcessTemplateURLChange(existing_turl, SyncChange::ACTION_UPDATE); |
| 1430 | 1575 |
| 1431 if (default_search_provider_ == existing_turl) | 1576 if (default_search_provider_ == existing_turl) |
| 1432 SetDefaultSearchProviderNoNotify(existing_turl); | 1577 SetDefaultSearchProviderNoNotify(existing_turl); |
| 1433 } | 1578 } |
| 1434 | 1579 |
| 1435 PrefService* TemplateURLService::GetPrefs() { | 1580 PrefService* TemplateURLService::GetPrefs() { |
| 1436 return profile_ ? profile_->GetPrefs() : NULL; | 1581 return profile_ ? profile_->GetPrefs() : NULL; |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1557 bool something_changed = false; | 1702 bool something_changed = false; |
| 1558 for (TemplateURLVector::iterator i(template_urls_.begin()); | 1703 for (TemplateURLVector::iterator i(template_urls_.begin()); |
| 1559 i != template_urls_.end(); ++i) { | 1704 i != template_urls_.end(); ++i) { |
| 1560 TemplateURL* t_url = *i; | 1705 TemplateURL* t_url = *i; |
| 1561 if (t_url->url_ref().HasGoogleBaseURLs() || | 1706 if (t_url->url_ref().HasGoogleBaseURLs() || |
| 1562 t_url->suggestions_url_ref().HasGoogleBaseURLs()) { | 1707 t_url->suggestions_url_ref().HasGoogleBaseURLs()) { |
| 1563 something_changed = true; | 1708 something_changed = true; |
| 1564 string16 original_keyword(t_url->keyword()); | 1709 string16 original_keyword(t_url->keyword()); |
| 1565 t_url->InvalidateCachedValues(); | 1710 t_url->InvalidateCachedValues(); |
| 1566 const string16& new_keyword(t_url->keyword()); | 1711 const string16& new_keyword(t_url->keyword()); |
| 1712 KeywordToTemplateMap::const_iterator i = | |
| 1713 keyword_to_template_map_.find(new_keyword); | |
| 1714 if ((i != keyword_to_template_map_.end()) && (i->second != t_url)) { | |
| 1715 // The new autogenerated keyword conflicts with another TemplateURL. | |
| 1716 // Overwrite it if it's replaceable; otherwise just reset |t_url|'s | |
| 1717 // keyword. (This will not prevent |t_url| from auto-updating the | |
| 1718 // keyword in the future if the conflicting TemplateURL disappears.) | |
| 1719 if (!CanReplace(i->second)) { | |
| 1720 t_url->data_.SetKeyword(original_keyword); | |
| 1721 continue; | |
| 1722 } | |
| 1723 RemoveNoNotify(i->second); | |
| 1724 } | |
| 1567 RemoveFromKeywordMapByPointer(t_url); | 1725 RemoveFromKeywordMapByPointer(t_url); |
| 1568 if (!new_keyword.empty()) | 1726 keyword_to_template_map_[new_keyword] = t_url; |
| 1569 keyword_to_template_map_[new_keyword] = t_url; | |
| 1570 } | 1727 } |
| 1571 } | 1728 } |
| 1572 | 1729 |
| 1573 if (something_changed && loaded_) { | 1730 if (something_changed && loaded_) { |
| 1574 UIThreadSearchTermsData search_terms_data; | 1731 UIThreadSearchTermsData search_terms_data; |
| 1575 provider_map_->UpdateGoogleBaseURLs(search_terms_data); | 1732 provider_map_->UpdateGoogleBaseURLs(search_terms_data); |
| 1576 NotifyObservers(); | 1733 NotifyObservers(); |
| 1577 } | 1734 } |
| 1578 } | 1735 } |
| 1579 | 1736 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1624 TemplateURLData data(new_default_from_prefs->data()); | 1781 TemplateURLData data(new_default_from_prefs->data()); |
| 1625 data.created_by_policy = true; | 1782 data.created_by_policy = true; |
| 1626 TemplateURL new_values(profile_, data); | 1783 TemplateURL new_values(profile_, data); |
| 1627 UpdateNoNotify(default_search_provider_, new_values); | 1784 UpdateNoNotify(default_search_provider_, new_values); |
| 1628 } else { | 1785 } else { |
| 1629 TemplateURL* new_template = NULL; | 1786 TemplateURL* new_template = NULL; |
| 1630 if (new_default_from_prefs.get()) { | 1787 if (new_default_from_prefs.get()) { |
| 1631 TemplateURLData data(new_default_from_prefs->data()); | 1788 TemplateURLData data(new_default_from_prefs->data()); |
| 1632 data.created_by_policy = true; | 1789 data.created_by_policy = true; |
| 1633 new_template = new TemplateURL(profile_, data); | 1790 new_template = new TemplateURL(profile_, data); |
| 1634 AddNoNotify(new_template, true); | 1791 if (!AddNoNotify(new_template, true)) |
| 1792 return; | |
| 1635 } | 1793 } |
| 1636 SetDefaultSearchProviderNoNotify(new_template); | 1794 SetDefaultSearchProviderNoNotify(new_template); |
| 1637 } | 1795 } |
| 1638 } else if (!is_default_search_managed_ && new_is_default_managed) { | 1796 } else if (!is_default_search_managed_ && new_is_default_managed) { |
| 1639 // The default used to be unmanaged and is now managed. Add the new | 1797 // The default used to be unmanaged and is now managed. Add the new |
| 1640 // managed default to the list of URLs and set it as default. | 1798 // managed default to the list of URLs and set it as default. |
| 1641 is_default_search_managed_ = new_is_default_managed; | 1799 is_default_search_managed_ = new_is_default_managed; |
| 1642 TemplateURL* new_template = NULL; | 1800 TemplateURL* new_template = NULL; |
| 1643 if (new_default_from_prefs.get()) { | 1801 if (new_default_from_prefs.get()) { |
| 1644 TemplateURLData data(new_default_from_prefs->data()); | 1802 TemplateURLData data(new_default_from_prefs->data()); |
| 1645 data.created_by_policy = true; | 1803 data.created_by_policy = true; |
| 1646 new_template = new TemplateURL(profile_, data); | 1804 new_template = new TemplateURL(profile_, data); |
| 1647 AddNoNotify(new_template, true); | 1805 if (!AddNoNotify(new_template, true)) |
| 1806 return; | |
| 1648 } | 1807 } |
| 1649 SetDefaultSearchProviderNoNotify(new_template); | 1808 SetDefaultSearchProviderNoNotify(new_template); |
| 1650 } else { | 1809 } else { |
| 1651 // The default was managed and is no longer. | 1810 // The default was managed and is no longer. |
| 1652 DCHECK(is_default_search_managed_ && !new_is_default_managed); | 1811 DCHECK(is_default_search_managed_ && !new_is_default_managed); |
| 1653 is_default_search_managed_ = new_is_default_managed; | 1812 is_default_search_managed_ = new_is_default_managed; |
| 1654 // If we had a default, delete the previous default if created by policy | 1813 // If we had a default, delete the previous default if created by policy |
| 1655 // and set a likely default. | 1814 // and set a likely default. |
| 1656 if ((default_search_provider_ != NULL) && | 1815 if ((default_search_provider_ != NULL) && |
| 1657 default_search_provider_->created_by_policy()) { | 1816 default_search_provider_->created_by_policy()) { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 1679 DCHECK(!url->IsExtensionKeyword()); | 1838 DCHECK(!url->IsExtensionKeyword()); |
| 1680 } | 1839 } |
| 1681 | 1840 |
| 1682 default_search_provider_ = url; | 1841 default_search_provider_ = url; |
| 1683 | 1842 |
| 1684 if (url) { | 1843 if (url) { |
| 1685 // Don't mark the url as edited, otherwise we won't be able to rev the | 1844 // Don't mark the url as edited, otherwise we won't be able to rev the |
| 1686 // template urls we ship with. | 1845 // template urls we ship with. |
| 1687 url->data_.show_in_default_list = true; | 1846 url->data_.show_in_default_list = true; |
| 1688 if (service_.get()) | 1847 if (service_.get()) |
| 1689 service_->UpdateKeyword(*url); | 1848 service_->UpdateKeyword(url->data()); |
| 1690 | 1849 |
| 1691 if (url->url_ref().HasGoogleBaseURLs()) { | 1850 if (url->url_ref().HasGoogleBaseURLs()) { |
| 1692 GoogleURLTracker::RequestServerCheck(); | 1851 GoogleURLTracker::RequestServerCheck(); |
| 1693 #if defined(ENABLE_RLZ) | 1852 #if defined(ENABLE_RLZ) |
| 1694 // Needs to be evaluated. See http://crbug.com/62328. | 1853 // Needs to be evaluated. See http://crbug.com/62328. |
| 1695 base::ThreadRestrictions::ScopedAllowIO allow_io; | 1854 base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 1696 RLZTracker::RecordProductEvent(rlz_lib::CHROME, | 1855 RLZTracker::RecordProductEvent(rlz_lib::CHROME, |
| 1697 rlz_lib::CHROME_OMNIBOX, | 1856 rlz_lib::CHROME_OMNIBOX, |
| 1698 rlz_lib::SET_TO_GOOGLE); | 1857 rlz_lib::SET_TO_GOOGLE); |
| 1699 #endif | 1858 #endif |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1713 } | 1872 } |
| 1714 | 1873 |
| 1715 if (service_.get()) | 1874 if (service_.get()) |
| 1716 service_->SetDefaultSearchProvider(url); | 1875 service_->SetDefaultSearchProvider(url); |
| 1717 | 1876 |
| 1718 // Inform sync the change to the show_in_default_list flag. | 1877 // Inform sync the change to the show_in_default_list flag. |
| 1719 if (url) | 1878 if (url) |
| 1720 ProcessTemplateURLChange(url, SyncChange::ACTION_UPDATE); | 1879 ProcessTemplateURLChange(url, SyncChange::ACTION_UPDATE); |
| 1721 } | 1880 } |
| 1722 | 1881 |
| 1723 void TemplateURLService::AddNoNotify(TemplateURL* template_url, | 1882 bool TemplateURLService::AddNoNotify(TemplateURL* template_url, |
| 1724 bool newly_adding) { | 1883 bool newly_adding) { |
| 1725 DCHECK(template_url); | 1884 DCHECK(template_url); |
| 1726 | 1885 |
| 1727 if (newly_adding) { | 1886 if (newly_adding) { |
| 1728 DCHECK_EQ(kInvalidTemplateURLID, template_url->id()); | 1887 DCHECK_EQ(kInvalidTemplateURLID, template_url->id()); |
| 1729 DCHECK(std::find(template_urls_.begin(), template_urls_.end(), | 1888 DCHECK(std::find(template_urls_.begin(), template_urls_.end(), |
| 1730 template_url) == template_urls_.end()); | 1889 template_url) == template_urls_.end()); |
| 1731 template_url->data_.id = ++next_id_; | 1890 template_url->data_.id = ++next_id_; |
| 1732 } | 1891 } |
| 1733 | 1892 |
| 1893 template_url->ResetKeywordIfNecessary(false); | |
| 1894 if (!template_url->IsExtensionKeyword()) { | |
| 1895 // Check whether |template_url|'s keyword conflicts with any already in the | |
| 1896 // model. | |
| 1897 TemplateURL* existing_keyword_turl = | |
| 1898 FindNonExtensionTemplateURLForKeyword(template_url->keyword()); | |
| 1899 if (existing_keyword_turl != NULL) { | |
| 1900 DCHECK_NE(existing_keyword_turl, template_url); | |
| 1901 if (CanReplace(existing_keyword_turl)) { | |
| 1902 RemoveNoNotify(existing_keyword_turl); | |
| 1903 } else if (CanReplace(template_url)) { | |
| 1904 delete template_url; | |
| 1905 return false; | |
| 1906 } else { | |
| 1907 string16 new_keyword = UniquifyKeyword(*existing_keyword_turl); | |
| 1908 ResetTemplateURL(existing_keyword_turl, | |
| 1909 existing_keyword_turl->short_name(), new_keyword, | |
| 1910 existing_keyword_turl->url()); | |
| 1911 } | |
| 1912 } | |
| 1913 } | |
| 1734 template_urls_.push_back(template_url); | 1914 template_urls_.push_back(template_url); |
| 1735 AddToMaps(template_url); | 1915 AddToMaps(template_url); |
| 1736 | 1916 |
| 1737 if (newly_adding) { | 1917 if (newly_adding) { |
| 1738 // Don't persist extension keywords to disk. They'll get re-added on each | 1918 // Don't persist extension keywords to disk. They'll get re-added on each |
| 1739 // launch as the extensions are loaded. | 1919 // launch as the extensions are loaded. |
| 1740 // TODO(mpcomplete): If we allow editing extension keywords, then those | 1920 // TODO(mpcomplete): If we allow editing extension keywords, then those |
| 1741 // should be persisted to disk and synced. | 1921 // should be persisted to disk and synced. |
| 1742 if (service_.get() && !template_url->IsExtensionKeyword()) | 1922 if (service_.get() && !template_url->IsExtensionKeyword()) |
| 1743 service_->AddKeyword(*template_url); | 1923 service_->AddKeyword(template_url->data()); |
| 1744 | 1924 |
| 1745 // Inform sync of the addition. Note that this will assign a GUID to | 1925 // Inform sync of the addition. Note that this will assign a GUID to |
| 1746 // template_url and add it to the guid_to_template_map_. | 1926 // template_url and add it to the guid_to_template_map_. |
| 1747 ProcessTemplateURLChange(template_url, SyncChange::ACTION_ADD); | 1927 ProcessTemplateURLChange(template_url, SyncChange::ACTION_ADD); |
| 1748 } | 1928 } |
| 1929 | |
| 1930 return true; | |
| 1749 } | 1931 } |
| 1750 | 1932 |
| 1751 void TemplateURLService::RemoveNoNotify(TemplateURL* template_url) { | 1933 void TemplateURLService::RemoveNoNotify(TemplateURL* template_url) { |
| 1752 TemplateURLVector::iterator i = | 1934 TemplateURLVector::iterator i = |
| 1753 std::find(template_urls_.begin(), template_urls_.end(), template_url); | 1935 std::find(template_urls_.begin(), template_urls_.end(), template_url); |
| 1754 if (i == template_urls_.end()) | 1936 if (i == template_urls_.end()) |
| 1755 return; | 1937 return; |
| 1756 | 1938 |
| 1757 if (template_url == default_search_provider_) { | 1939 if (template_url == default_search_provider_) { |
| 1758 // Should never delete the default search provider. | 1940 // Should never delete the default search provider. |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1856 } | 2038 } |
| 1857 | 2039 |
| 1858 string16 TemplateURLService::UniquifyKeyword(const TemplateURL& turl) { | 2040 string16 TemplateURLService::UniquifyKeyword(const TemplateURL& turl) { |
| 1859 // Already unique. | 2041 // Already unique. |
| 1860 if (!GetTemplateURLForKeyword(turl.keyword())) | 2042 if (!GetTemplateURLForKeyword(turl.keyword())) |
| 1861 return turl.keyword(); | 2043 return turl.keyword(); |
| 1862 | 2044 |
| 1863 // First, try to return the generated keyword for the TemplateURL. | 2045 // First, try to return the generated keyword for the TemplateURL. |
| 1864 GURL gurl(turl.url()); | 2046 GURL gurl(turl.url()); |
| 1865 if (gurl.is_valid()) { | 2047 if (gurl.is_valid()) { |
| 1866 string16 keyword_candidate = GenerateKeyword(gurl, true); | 2048 string16 keyword_candidate = GenerateKeyword(gurl); |
| 1867 if (!GetTemplateURLForKeyword(keyword_candidate) && | 2049 if (!GetTemplateURLForKeyword(keyword_candidate)) |
| 1868 !keyword_candidate.empty()) | |
| 1869 return keyword_candidate; | 2050 return keyword_candidate; |
| 1870 } | 2051 } |
| 1871 | 2052 |
| 1872 // We try to uniquify the keyword by appending a special character to the end. | 2053 // We try to uniquify the keyword by appending a special character to the end. |
| 1873 // This is a best-effort approach where we try to preserve the original | 2054 // This is a best-effort approach where we try to preserve the original |
| 1874 // keyword and let the user do what they will after our attempt. | 2055 // keyword and let the user do what they will after our attempt. |
| 1875 string16 keyword_candidate(turl.keyword()); | 2056 string16 keyword_candidate(turl.keyword()); |
| 1876 do { | 2057 do { |
| 1877 keyword_candidate.append(ASCIIToUTF16("_")); | 2058 keyword_candidate.append(ASCIIToUTF16("_")); |
| 1878 } while (GetTemplateURLForKeyword(keyword_candidate)); | 2059 } while (GetTemplateURLForKeyword(keyword_candidate)); |
| 1879 | 2060 |
| 1880 return keyword_candidate; | 2061 return keyword_candidate; |
| 1881 } | 2062 } |
| 1882 | 2063 |
| 1883 bool TemplateURLService::ResolveSyncKeywordConflict( | 2064 void TemplateURLService::ResolveSyncKeywordConflict( |
| 1884 TemplateURL* sync_turl, | 2065 TemplateURL* sync_turl, |
| 2066 TemplateURL* local_turl, | |
| 1885 SyncChangeList* change_list) { | 2067 SyncChangeList* change_list) { |
| 1886 DCHECK(sync_turl); | 2068 DCHECK(sync_turl); |
| 2069 DCHECK(local_turl); | |
| 2070 DCHECK(sync_turl->sync_guid() != local_turl->sync_guid()); | |
| 2071 DCHECK(!local_turl->IsExtensionKeyword()); | |
| 1887 DCHECK(change_list); | 2072 DCHECK(change_list); |
| 1888 | 2073 |
| 1889 TemplateURL* existing_turl = | 2074 if (local_turl->last_modified() > sync_turl->last_modified() || |
| 1890 GetTemplateURLForKeyword(sync_turl->keyword()); | 2075 local_turl->created_by_policy()) { |
| 1891 // If there is no conflict, or it's just conflicting with itself, return. | |
| 1892 if (!existing_turl || existing_turl->sync_guid() == sync_turl->sync_guid()) | |
| 1893 return false; | |
| 1894 | |
| 1895 if (existing_turl->last_modified() > sync_turl->last_modified() || | |
| 1896 existing_turl->created_by_policy()) { | |
| 1897 string16 new_keyword = UniquifyKeyword(*sync_turl); | 2076 string16 new_keyword = UniquifyKeyword(*sync_turl); |
| 1898 DCHECK(!GetTemplateURLForKeyword(new_keyword)); | 2077 DCHECK(!GetTemplateURLForKeyword(new_keyword)); |
| 1899 sync_turl->data_.SetKeyword(new_keyword); | 2078 sync_turl->data_.SetKeyword(new_keyword); |
| 1900 // If we update the cloud TURL, we need to push an update back to sync | 2079 // If we update the cloud TURL, we need to push an update back to sync |
| 1901 // informing it that something has changed. | 2080 // informing it that something has changed. |
| 1902 SyncData sync_data = CreateSyncDataFromTemplateURL(*sync_turl); | 2081 SyncData sync_data = CreateSyncDataFromTemplateURL(*sync_turl); |
| 1903 change_list->push_back(SyncChange(SyncChange::ACTION_UPDATE, sync_data)); | 2082 change_list->push_back(SyncChange(SyncChange::ACTION_UPDATE, sync_data)); |
| 1904 } else { | 2083 } else { |
| 1905 string16 new_keyword = UniquifyKeyword(*existing_turl); | 2084 string16 new_keyword = UniquifyKeyword(*local_turl); |
| 1906 TemplateURLData data(existing_turl->data()); | 2085 TemplateURLData data(local_turl->data()); |
| 1907 data.SetKeyword(new_keyword); | 2086 data.SetKeyword(new_keyword); |
| 1908 TemplateURL new_turl(existing_turl->profile(), data); | 2087 TemplateURL new_turl(local_turl->profile(), data); |
| 1909 UpdateNoNotify(existing_turl, new_turl); | 2088 UpdateNoNotify(local_turl, new_turl); |
| 1910 NotifyObservers(); | 2089 NotifyObservers(); |
| 2090 if (!models_associated_) { | |
| 2091 // We're doing our initial sync, so UpdateNoNotify() won't have generated | |
| 2092 // an ACTION_UPDATE. If this local URL is one that was just newly brought | |
| 2093 // down from the sync server, we need to go ahead and generate an update | |
| 2094 // for it. If it was pre-existing, then this is unnecessary (and in fact | |
| 2095 // wrong) because MergeDataAndStartSyncing() will later add an ACTION_ADD | |
| 2096 // for this URL; but in this case, PreventDuplicateGUIDUpdates() will | |
| 2097 // prune out the ACTION_UPDATE we create here. | |
| 2098 SyncData sync_data = CreateSyncDataFromTemplateURL(*local_turl); | |
| 2099 change_list->push_back(SyncChange(SyncChange::ACTION_UPDATE, sync_data)); | |
| 2100 } | |
| 1911 } | 2101 } |
| 1912 return true; | |
| 1913 } | 2102 } |
| 1914 | 2103 |
| 1915 TemplateURL* TemplateURLService::FindDuplicateOfSyncTemplateURL( | 2104 TemplateURL* TemplateURLService::FindDuplicateOfSyncTemplateURL( |
| 1916 const TemplateURL& sync_turl) { | 2105 const TemplateURL& sync_turl) { |
| 1917 TemplateURL* existing_turl = GetTemplateURLForKeyword(sync_turl.keyword()); | 2106 TemplateURL* existing_turl = GetTemplateURLForKeyword(sync_turl.keyword()); |
| 1918 return existing_turl && (existing_turl->url() == sync_turl.url()) ? | 2107 return existing_turl && (existing_turl->url() == sync_turl.url()) ? |
| 1919 existing_turl : NULL; | 2108 existing_turl : NULL; |
| 1920 } | 2109 } |
| 1921 | 2110 |
| 1922 void TemplateURLService::MergeSyncAndLocalURLDuplicates( | 2111 void TemplateURLService::MergeSyncAndLocalURLDuplicates( |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1990 i != template_urls->end(); ++i) { | 2179 i != template_urls->end(); ++i) { |
| 1991 TemplateURL* template_url = *i; | 2180 TemplateURL* template_url = *i; |
| 1992 DCHECK(template_url); | 2181 DCHECK(template_url); |
| 1993 // Extension keywords are never synced. | 2182 // Extension keywords are never synced. |
| 1994 // TODO(mpcomplete): If we allow editing extension keywords, then those | 2183 // TODO(mpcomplete): If we allow editing extension keywords, then those |
| 1995 // should be persisted to disk and synced. | 2184 // should be persisted to disk and synced. |
| 1996 if (template_url->sync_guid().empty() && | 2185 if (template_url->sync_guid().empty() && |
| 1997 !template_url->IsExtensionKeyword()) { | 2186 !template_url->IsExtensionKeyword()) { |
| 1998 template_url->data_.sync_guid = guid::GenerateGUID(); | 2187 template_url->data_.sync_guid = guid::GenerateGUID(); |
| 1999 if (service_.get()) | 2188 if (service_.get()) |
| 2000 service_->UpdateKeyword(*template_url); | 2189 service_->UpdateKeyword(template_url->data()); |
| 2001 } | 2190 } |
| 2002 } | 2191 } |
| 2003 } | 2192 } |
| OLD | NEW |