| 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->HasSameKeywordAs(*url2) && |
| 74 (url1->url() == url2->url()) && | 74 (url1->url() == url2->url()) && |
| 75 (url1->suggestions_url() == url2->suggestions_url()) && | 75 (url1->suggestions_url() == url2->suggestions_url()) && |
| 76 (url1->instant_url() == url2->instant_url()) && | 76 (url1->instant_url() == url2->instant_url()) && |
| 77 (url1->favicon_url() == url2->favicon_url()) && | 77 (url1->favicon_url() == url2->favicon_url()) && |
| 78 (url1->safe_for_autoreplace() == url2->safe_for_autoreplace()) && | 78 (url1->safe_for_autoreplace() == url2->safe_for_autoreplace()) && |
| 79 (url1->show_in_default_list() == url2->show_in_default_list()) && | 79 (url1->show_in_default_list() == url2->show_in_default_list()) && |
| 80 (url1->input_encodings() == url2->input_encodings()); | 80 (url1->input_encodings() == url2->input_encodings()); |
| 81 } | 81 } |
| 82 | 82 |
| 83 TemplateURL* FirstPotentialDefaultEngine( | 83 TemplateURL* FirstPotentialDefaultEngine( |
| 84 const TemplateURLService::TemplateURLVector& template_urls) { | 84 const TemplateURLService::TemplateURLVector& template_urls) { |
| 85 for (TemplateURLService::TemplateURLVector::const_iterator i( | 85 for (TemplateURLService::TemplateURLVector::const_iterator i( |
| 86 template_urls.begin()); i != template_urls.end(); ++i) { | 86 template_urls.begin()); i != template_urls.end(); ++i) { |
| 87 if (!(*i)->IsExtensionKeyword() && (*i)->SupportsReplacement()) | 87 if (!(*i)->IsExtensionKeyword() && (*i)->SupportsReplacement()) |
| 88 return *i; | 88 return *i; |
| 89 } | 89 } |
| 90 return NULL; | 90 return NULL; |
| 91 } | 91 } |
| 92 | 92 |
| 93 // If |change_list| contains ACTION_UPDATEs followed by more ACTION_UPDATEs or |
| 94 // ACTION_ADDs for the same GUID, remove all but the last one. |
| 95 // |
| 96 // Removing UPDATE before ADD is important. This can happen if |
| 97 // ResolveSyncKeywordConflict() changes a local TemplateURL that hasn't actually |
| 98 // been seen by the server yet. In this case sending the UPDATE first might |
| 99 // confuse the sync server. |
| 100 // |
| 101 // Removing UPDATE before UPDATE, OTOH, is not really necessary as the server |
| 102 // will coalesce these before other clients see them; however it's easy to do in |
| 103 // conjunction with the filtering for UPDATE-before-ADD and saves bandwidth. |
| 104 void PreventDuplicateGUIDUpdates(SyncChangeList* change_list) { |
| 105 for (size_t i = change_list->size(); i > 1; ) { |
| 106 --i; // Prevent underflow that could occur if we did this in the loop body. |
| 107 const SyncChange& change_i = (*change_list)[i]; |
| 108 if ((change_i.change_type() != SyncChange::ACTION_ADD) && |
| 109 (change_i.change_type() != SyncChange::ACTION_UPDATE)) |
| 110 continue; |
| 111 std::string guid( |
| 112 change_i.sync_data().GetSpecifics().search_engine().sync_guid()); |
| 113 for (size_t j = 0; j < i; ) { |
| 114 const SyncChange& change_j = (*change_list)[j]; |
| 115 if ((change_j.change_type() == SyncChange::ACTION_UPDATE) && |
| 116 (change_j.sync_data().GetSpecifics().search_engine().sync_guid() == |
| 117 guid)) { |
| 118 change_list->erase(change_list->begin() + j); |
| 119 --i; |
| 120 } else { |
| 121 ++j; |
| 122 } |
| 123 } |
| 124 } |
| 125 } |
| 126 |
| 93 } // namespace | 127 } // namespace |
| 94 | 128 |
| 95 | 129 |
| 96 class TemplateURLService::LessWithPrefix { | 130 class TemplateURLService::LessWithPrefix { |
| 97 public: | 131 public: |
| 98 // We want to find the set of keywords that begin with a prefix. The STL | 132 // 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 | 133 // 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 | 134 // 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; | 135 // 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 | 136 // 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() { | 187 TemplateURLService::~TemplateURLService() { |
| 154 if (load_handle_) { | 188 if (load_handle_) { |
| 155 DCHECK(service_.get()); | 189 DCHECK(service_.get()); |
| 156 service_->CancelRequest(load_handle_); | 190 service_->CancelRequest(load_handle_); |
| 157 } | 191 } |
| 158 | 192 |
| 159 STLDeleteElements(&template_urls_); | 193 STLDeleteElements(&template_urls_); |
| 160 } | 194 } |
| 161 | 195 |
| 162 // static | 196 // static |
| 163 string16 TemplateURLService::GenerateKeyword(const GURL& url, | 197 string16 TemplateURLService::GenerateKeyword(const GURL& url) { |
| 164 bool autodetected) { | 198 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 | 199 // 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 . | 200 // 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 | 201 // 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 | 202 // perhaps with some weird intranet and custom DNS server?), ensure we at |
| 183 // least don't return the empty string. | 203 // least don't return the empty string. |
| 184 string16 keyword(net::StripWWW(UTF8ToUTF16(url.host()))); | 204 string16 keyword(net::StripWWW(UTF8ToUTF16(url.host()))); |
| 185 return keyword.empty() ? ASCIIToUTF16("www") : keyword; | 205 return keyword.empty() ? ASCIIToUTF16("www") : keyword; |
| 186 } | 206 } |
| 187 | 207 |
| 188 // static | 208 // static |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 DCHECK(t_url); | 244 DCHECK(t_url); |
| 225 UIThreadSearchTermsData search_terms_data; | 245 UIThreadSearchTermsData search_terms_data; |
| 226 return GenerateSearchURLUsingTermsData(t_url, search_terms_data); | 246 return GenerateSearchURLUsingTermsData(t_url, search_terms_data); |
| 227 } | 247 } |
| 228 | 248 |
| 229 // static | 249 // static |
| 230 GURL TemplateURLService::GenerateSearchURLUsingTermsData( | 250 GURL TemplateURLService::GenerateSearchURLUsingTermsData( |
| 231 const TemplateURL* t_url, | 251 const TemplateURL* t_url, |
| 232 const SearchTermsData& search_terms_data) { | 252 const SearchTermsData& search_terms_data) { |
| 233 DCHECK(t_url); | 253 DCHECK(t_url); |
| 254 DCHECK(!t_url->IsExtensionKeyword()); |
| 255 |
| 234 const TemplateURLRef& search_ref = t_url->url_ref(); | 256 const TemplateURLRef& search_ref = t_url->url_ref(); |
| 235 // Extension keywords don't have host-based search URLs. | 257 if (!search_ref.IsValidUsingTermsData(search_terms_data)) |
| 236 if (!search_ref.IsValidUsingTermsData(search_terms_data) || | |
| 237 t_url->IsExtensionKeyword()) | |
| 238 return GURL(); | 258 return GURL(); |
| 239 | 259 |
| 240 if (!search_ref.SupportsReplacementUsingTermsData(search_terms_data)) | 260 if (!search_ref.SupportsReplacementUsingTermsData(search_terms_data)) |
| 241 return GURL(t_url->url()); | 261 return GURL(t_url->url()); |
| 242 | 262 |
| 243 return GURL(search_ref.ReplaceSearchTermsUsingTermsData( | 263 return GURL(search_ref.ReplaceSearchTermsUsingTermsData( |
| 244 ASCIIToUTF16(kReplacementTerm), TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, | 264 ASCIIToUTF16(kReplacementTerm), TemplateURLRef::NO_SUGGESTIONS_AVAILABLE, |
| 245 string16(), search_terms_data)); | 265 string16(), search_terms_data)); |
| 246 } | 266 } |
| 247 | 267 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 matches->push_back(i->first); | 320 matches->push_back(i->first); |
| 301 } | 321 } |
| 302 } | 322 } |
| 303 | 323 |
| 304 TemplateURL* TemplateURLService::GetTemplateURLForKeyword( | 324 TemplateURL* TemplateURLService::GetTemplateURLForKeyword( |
| 305 const string16& keyword) { | 325 const string16& keyword) { |
| 306 KeywordToTemplateMap::const_iterator elem( | 326 KeywordToTemplateMap::const_iterator elem( |
| 307 keyword_to_template_map_.find(keyword)); | 327 keyword_to_template_map_.find(keyword)); |
| 308 if (elem != keyword_to_template_map_.end()) | 328 if (elem != keyword_to_template_map_.end()) |
| 309 return elem->second; | 329 return elem->second; |
| 310 return (initial_default_search_provider_.get() && | 330 return ((!loaded_ || load_failed_) && |
| 331 initial_default_search_provider_.get() && |
| 311 (initial_default_search_provider_->keyword() == keyword)) ? | 332 (initial_default_search_provider_->keyword() == keyword)) ? |
| 312 initial_default_search_provider_.get() : NULL; | 333 initial_default_search_provider_.get() : NULL; |
| 313 } | 334 } |
| 314 | 335 |
| 315 TemplateURL* TemplateURLService::GetTemplateURLForGUID( | 336 TemplateURL* TemplateURLService::GetTemplateURLForGUID( |
| 316 const std::string& sync_guid) { | 337 const std::string& sync_guid) { |
| 317 GUIDToTemplateMap::const_iterator elem( | 338 GUIDToTemplateMap::const_iterator elem(guid_to_template_map_.find(sync_guid)); |
| 318 guid_to_template_map_.find(sync_guid)); | |
| 319 if (elem != guid_to_template_map_.end()) | 339 if (elem != guid_to_template_map_.end()) |
| 320 return elem->second; | 340 return elem->second; |
| 321 return (initial_default_search_provider_.get() && | 341 return ((!loaded_ || load_failed_) && |
| 342 initial_default_search_provider_.get() && |
| 322 (initial_default_search_provider_->sync_guid() == sync_guid)) ? | 343 (initial_default_search_provider_->sync_guid() == sync_guid)) ? |
| 323 initial_default_search_provider_.get() : NULL; | 344 initial_default_search_provider_.get() : NULL; |
| 324 } | 345 } |
| 325 | 346 |
| 326 TemplateURL* TemplateURLService::GetTemplateURLForHost( | 347 TemplateURL* TemplateURLService::GetTemplateURLForHost( |
| 327 const std::string& host) { | 348 const std::string& host) { |
| 328 TemplateURL* t_url = provider_map_->GetTemplateURLForHost(host); | 349 TemplateURL* t_url = provider_map_->GetTemplateURLForHost(host); |
| 329 if (t_url) | 350 if (t_url) |
| 330 return t_url; | 351 return t_url; |
| 331 return (initial_default_search_provider_.get() && | 352 return ((!loaded_ || load_failed_) && |
| 353 initial_default_search_provider_.get() && |
| 332 (GenerateSearchURL(initial_default_search_provider_.get()).host() == | 354 (GenerateSearchURL(initial_default_search_provider_.get()).host() == |
| 333 host)) ? initial_default_search_provider_.get() : NULL; | 355 host)) ? initial_default_search_provider_.get() : NULL; |
| 334 } | 356 } |
| 335 | 357 |
| 336 void TemplateURLService::Add(TemplateURL* template_url) { | 358 void TemplateURLService::Add(TemplateURL* template_url) { |
| 337 AddNoNotify(template_url, true); | 359 if (AddNoNotify(template_url, true)) |
| 338 NotifyObservers(); | 360 NotifyObservers(); |
| 339 } | 361 } |
| 340 | 362 |
| 341 void TemplateURLService::AddAndSetProfile(TemplateURL* template_url, | 363 void TemplateURLService::AddAndSetProfile(TemplateURL* template_url, |
| 342 Profile* profile) { | 364 Profile* profile) { |
| 343 template_url->profile_ = profile; | 365 template_url->profile_ = profile; |
| 344 Add(template_url); | 366 Add(template_url); |
| 345 } | 367 } |
| 346 | 368 |
| 347 void TemplateURLService::AddWithOverrides(TemplateURL* template_url, | 369 void TemplateURLService::AddWithOverrides(TemplateURL* template_url, |
| 348 const string16& short_name, | 370 const string16& short_name, |
| 349 const string16& keyword, | 371 const string16& keyword, |
| 350 const std::string& url) { | 372 const std::string& url) { |
| 373 DCHECK(!keyword.empty()); |
| 351 DCHECK(!url.empty()); | 374 DCHECK(!url.empty()); |
| 352 template_url->data_.short_name = short_name; | 375 template_url->data_.short_name = short_name; |
| 353 template_url->data_.SetKeyword(keyword); | 376 template_url->data_.SetKeyword(keyword); |
| 354 template_url->SetURL(url); | 377 template_url->SetURL(url); |
| 355 Add(template_url); | 378 Add(template_url); |
| 356 } | 379 } |
| 357 | 380 |
| 358 void TemplateURLService::Remove(TemplateURL* template_url) { | 381 void TemplateURLService::Remove(TemplateURL* template_url) { |
| 359 RemoveNoNotify(template_url); | 382 RemoveNoNotify(template_url); |
| 360 NotifyObservers(); | 383 NotifyObservers(); |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 440 } | 463 } |
| 441 | 464 |
| 442 return NULL; | 465 return NULL; |
| 443 } | 466 } |
| 444 | 467 |
| 445 TemplateURLService::TemplateURLVector TemplateURLService::GetTemplateURLs() { | 468 TemplateURLService::TemplateURLVector TemplateURLService::GetTemplateURLs() { |
| 446 return template_urls_; | 469 return template_urls_; |
| 447 } | 470 } |
| 448 | 471 |
| 449 void TemplateURLService::IncrementUsageCount(TemplateURL* url) { | 472 void TemplateURLService::IncrementUsageCount(TemplateURL* url) { |
| 450 DCHECK(url && std::find(template_urls_.begin(), template_urls_.end(), url) != | 473 DCHECK(url); |
| 451 template_urls_.end()); | 474 if (std::find(template_urls_.begin(), template_urls_.end(), url) == |
| 475 template_urls_.end()) |
| 476 return; |
| 452 ++url->data_.usage_count; | 477 ++url->data_.usage_count; |
| 453 // Extension keywords are not persisted. | 478 // Extension keywords are not persisted. |
| 454 // TODO(mpcomplete): If we allow editing extension keywords, then those should | 479 // TODO(mpcomplete): If we allow editing extension keywords, then those should |
| 455 // be persisted to disk and synced. | 480 // be persisted to disk and synced. |
| 456 if (service_.get() && !url->IsExtensionKeyword()) | 481 if (service_.get() && !url->IsExtensionKeyword()) |
| 457 service_.get()->UpdateKeyword(*url); | 482 service_.get()->UpdateKeyword(url->data()); |
| 458 } | 483 } |
| 459 | 484 |
| 460 void TemplateURLService::ResetTemplateURL(TemplateURL* url, | 485 void TemplateURLService::ResetTemplateURL(TemplateURL* url, |
| 461 const string16& title, | 486 const string16& title, |
| 462 const string16& keyword, | 487 const string16& keyword, |
| 463 const std::string& search_url) { | 488 const std::string& search_url) { |
| 489 if (!loaded_) |
| 490 return; |
| 491 DCHECK(!keyword.empty()); |
| 464 DCHECK(!search_url.empty()); | 492 DCHECK(!search_url.empty()); |
| 465 TemplateURLData data(url->data()); | 493 TemplateURLData data(url->data()); |
| 466 data.short_name = title; | 494 data.short_name = title; |
| 467 data.SetKeyword(keyword); | 495 data.SetKeyword(keyword); |
| 468 if (search_url != data.url()) { | 496 if (search_url != data.url()) { |
| 469 data.SetURL(search_url); | 497 data.SetURL(search_url); |
| 470 // The urls have changed, reset the favicon url. | 498 // The urls have changed, reset the favicon url. |
| 471 data.favicon_url = GURL(); | 499 data.favicon_url = GURL(); |
| 472 } | 500 } |
| 473 data.safe_for_autoreplace = false; | 501 data.safe_for_autoreplace = false; |
| 474 data.last_modified = time_provider_(); | 502 data.last_modified = time_provider_(); |
| 475 TemplateURL new_url(url->profile(), data); | 503 TemplateURL new_url(url->profile(), data); |
| 476 UpdateNoNotify(url, new_url); | 504 if (UpdateNoNotify(url, new_url)) |
| 477 NotifyObservers(); | 505 NotifyObservers(); |
| 478 } | 506 } |
| 479 | 507 |
| 480 bool TemplateURLService::CanMakeDefault(const TemplateURL* url) { | 508 bool TemplateURLService::CanMakeDefault(const TemplateURL* url) { |
| 481 return url != GetDefaultSearchProvider() && | 509 return url != GetDefaultSearchProvider() && |
| 482 url->url_ref().SupportsReplacement() && !is_default_search_managed(); | 510 url->url_ref().SupportsReplacement() && !is_default_search_managed(); |
| 483 } | 511 } |
| 484 | 512 |
| 485 void TemplateURLService::SetDefaultSearchProvider(TemplateURL* url) { | 513 void TemplateURLService::SetDefaultSearchProvider(TemplateURL* url) { |
| 486 DCHECK(!is_default_search_managed_); | 514 DCHECK(!is_default_search_managed_); |
| 487 // Extension keywords cannot be made default, as they are inherently async. | 515 // Extension keywords cannot be made default, as they are inherently async. |
| 488 DCHECK(!url || !url->IsExtensionKeyword()); | 516 DCHECK(!url || !url->IsExtensionKeyword()); |
| 489 | 517 |
| 490 // Always persist the setting in the database, that way if the backup | 518 // Always persist the setting in the database, that way if the backup |
| 491 // signature has changed out from under us it gets reset correctly. | 519 // signature has changed out from under us it gets reset correctly. |
| 492 SetDefaultSearchProviderNoNotify(url); | 520 if (SetDefaultSearchProviderNoNotify(url)) |
| 493 NotifyObservers(); | 521 NotifyObservers(); |
| 494 } | 522 } |
| 495 | 523 |
| 496 TemplateURL* TemplateURLService::GetDefaultSearchProvider() { | 524 TemplateURL* TemplateURLService::GetDefaultSearchProvider() { |
| 497 if (loaded_ && !load_failed_) | 525 if (loaded_ && !load_failed_) |
| 498 return default_search_provider_; | 526 return default_search_provider_; |
| 499 | 527 |
| 500 // We're not loaded, rely on the default search provider stored in prefs. | 528 // We're not loaded, rely on the default search provider stored in prefs. |
| 501 return initial_default_search_provider_.get(); | 529 return initial_default_search_provider_.get(); |
| 502 } | 530 } |
| 503 | 531 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 604 // The value from the preferences was previously stored in the database. | 632 // The value from the preferences was previously stored in the database. |
| 605 // Reuse it. | 633 // Reuse it. |
| 606 } else { | 634 } else { |
| 607 // The value from the preferences takes over. | 635 // The value from the preferences takes over. |
| 608 default_search_provider = NULL; | 636 default_search_provider = NULL; |
| 609 if (default_from_prefs.get()) { | 637 if (default_from_prefs.get()) { |
| 610 TemplateURLData data(default_from_prefs->data()); | 638 TemplateURLData data(default_from_prefs->data()); |
| 611 data.created_by_policy = true; | 639 data.created_by_policy = true; |
| 612 data.id = kInvalidTemplateURLID; | 640 data.id = kInvalidTemplateURLID; |
| 613 default_search_provider = new TemplateURL(profile_, data); | 641 default_search_provider = new TemplateURL(profile_, data); |
| 614 AddNoNotify(default_search_provider, true); | 642 if (!AddNoNotify(default_search_provider, true)) |
| 643 default_search_provider = NULL; |
| 615 } | 644 } |
| 616 } | 645 } |
| 617 // Note that this saves the default search provider to prefs. | 646 // Note that this saves the default search provider to prefs. |
| 618 if (!default_search_provider || | 647 if (!default_search_provider || |
| 619 (!default_search_provider->IsExtensionKeyword() && | 648 (!default_search_provider->IsExtensionKeyword() && |
| 620 default_search_provider->SupportsReplacement())) | 649 default_search_provider->SupportsReplacement())) { |
| 621 SetDefaultSearchProviderNoNotify(default_search_provider); | 650 bool success = SetDefaultSearchProviderNoNotify(default_search_provider); |
| 651 DCHECK(success); |
| 652 } |
| 622 } else { | 653 } else { |
| 623 // If we had a managed default, replace it with the synced default if | 654 // If we had a managed default, replace it with the synced default if |
| 624 // applicable, or the first provider of the list. | 655 // applicable, or the first provider of the list. |
| 625 TemplateURL* synced_default = GetPendingSyncedDefaultSearchProvider(); | 656 TemplateURL* synced_default = GetPendingSyncedDefaultSearchProvider(); |
| 626 if (synced_default) { | 657 if (synced_default) { |
| 627 default_search_provider = synced_default; | 658 default_search_provider = synced_default; |
| 628 pending_synced_default_search_ = false; | 659 pending_synced_default_search_ = false; |
| 629 } else if (database_specified_a_default && | 660 } else if (database_specified_a_default && |
| 630 default_search_provider == NULL) { | 661 default_search_provider == NULL) { |
| 631 default_search_provider = FirstPotentialDefaultEngine(template_urls); | 662 default_search_provider = FirstPotentialDefaultEngine(template_urls); |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 692 check_if_default_search_valid = false; | 723 check_if_default_search_valid = false; |
| 693 } | 724 } |
| 694 #endif | 725 #endif |
| 695 | 726 |
| 696 if (check_if_default_search_valid) { | 727 if (check_if_default_search_valid) { |
| 697 bool has_default_search_provider = default_search_provider_ != NULL && | 728 bool has_default_search_provider = default_search_provider_ != NULL && |
| 698 default_search_provider_->SupportsReplacement(); | 729 default_search_provider_->SupportsReplacement(); |
| 699 UMA_HISTOGRAM_BOOLEAN("Search.HasDefaultSearchProvider", | 730 UMA_HISTOGRAM_BOOLEAN("Search.HasDefaultSearchProvider", |
| 700 has_default_search_provider); | 731 has_default_search_provider); |
| 701 // Ensure that default search provider exists. See http://crbug.com/116952. | 732 // Ensure that default search provider exists. See http://crbug.com/116952. |
| 702 if (!has_default_search_provider) | 733 if (!has_default_search_provider) { |
| 703 SetDefaultSearchProviderNoNotify(FindNewDefaultSearchProvider()); | 734 bool success = |
| 735 SetDefaultSearchProviderNoNotify(FindNewDefaultSearchProvider()); |
| 736 DCHECK(success); |
| 737 } |
| 704 } | 738 } |
| 705 | 739 |
| 706 NotifyObservers(); | 740 NotifyObservers(); |
| 707 NotifyLoaded(); | 741 NotifyLoaded(); |
| 708 } | 742 } |
| 709 | 743 |
| 710 string16 TemplateURLService::GetKeywordShortName(const string16& keyword, | 744 string16 TemplateURLService::GetKeywordShortName(const string16& keyword, |
| 711 bool* is_extension_keyword) { | 745 bool* is_extension_keyword) { |
| 712 const TemplateURL* template_url = GetTemplateURLForKeyword(keyword); | 746 const TemplateURL* template_url = GetTemplateURLForKeyword(keyword); |
| 713 | 747 |
| 714 // TODO(sky): Once LocationBarView adds a listener to the TemplateURLService | 748 // TODO(sky): Once LocationBarView adds a listener to the TemplateURLService |
| 715 // to track changes to the model, this should become a DCHECK. | 749 // to track changes to the model, this should become a DCHECK. |
| 716 if (template_url) { | 750 if (template_url) { |
| 717 *is_extension_keyword = template_url->IsExtensionKeyword(); | 751 *is_extension_keyword = template_url->IsExtensionKeyword(); |
| 718 return template_url->AdjustedShortNameForLocaleDirection(); | 752 return template_url->AdjustedShortNameForLocaleDirection(); |
| 719 } | 753 } |
| 720 *is_extension_keyword = false; | 754 *is_extension_keyword = false; |
| 721 return string16(); | 755 return string16(); |
| 722 } | 756 } |
| 723 | 757 |
| 724 void TemplateURLService::Observe(int type, | 758 void TemplateURLService::Observe(int type, |
| 725 const content::NotificationSource& source, | 759 const content::NotificationSource& source, |
| 726 const content::NotificationDetails& details) { | 760 const content::NotificationDetails& details) { |
| 727 if (type == chrome::NOTIFICATION_HISTORY_URL_VISITED) { | 761 if (type == chrome::NOTIFICATION_HISTORY_URL_VISITED) { |
| 728 content::Details<history::URLVisitedDetails> visit_details(details); | 762 content::Details<history::URLVisitedDetails> visit_details(details); |
| 729 if (!loaded()) | 763 if (!loaded_) |
| 730 visits_to_add_.push_back(*visit_details.ptr()); | 764 visits_to_add_.push_back(*visit_details.ptr()); |
| 731 else | 765 else |
| 732 UpdateKeywordSearchTermsForURL(*visit_details.ptr()); | 766 UpdateKeywordSearchTermsForURL(*visit_details.ptr()); |
| 733 } else if (type == chrome::NOTIFICATION_DEFAULT_SEARCH_POLICY_CHANGED) { | 767 } else if (type == chrome::NOTIFICATION_DEFAULT_SEARCH_POLICY_CHANGED) { |
| 734 // Policy has been updated, so the default search prefs may be different. | 768 // Policy has been updated, so the default search prefs may be different. |
| 735 // Reload the default search provider from them. | 769 // Reload the default search provider from them. |
| 736 // TODO(pkasting): Rather than communicating via prefs, we should eventually | 770 // TODO(pkasting): Rather than communicating via prefs, we should eventually |
| 737 // observe policy changes directly. | 771 // observe policy changes directly. |
| 738 UpdateDefaultSearch(); | 772 UpdateDefaultSearch(); |
| 739 } else if (type == chrome::NOTIFICATION_GOOGLE_URL_UPDATED) { | 773 } else if (type == chrome::NOTIFICATION_GOOGLE_URL_UPDATED) { |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 785 } | 819 } |
| 786 | 820 |
| 787 SyncError TemplateURLService::ProcessSyncChanges( | 821 SyncError TemplateURLService::ProcessSyncChanges( |
| 788 const tracked_objects::Location& from_here, | 822 const tracked_objects::Location& from_here, |
| 789 const SyncChangeList& change_list) { | 823 const SyncChangeList& change_list) { |
| 790 if (!models_associated_) { | 824 if (!models_associated_) { |
| 791 SyncError error(FROM_HERE, "Models not yet associated.", | 825 SyncError error(FROM_HERE, "Models not yet associated.", |
| 792 syncable::SEARCH_ENGINES); | 826 syncable::SEARCH_ENGINES); |
| 793 return error; | 827 return error; |
| 794 } | 828 } |
| 829 DCHECK(loaded_); |
| 795 | 830 |
| 796 AutoReset<bool> processing_changes(&processing_syncer_changes_, true); | 831 AutoReset<bool> processing_changes(&processing_syncer_changes_, true); |
| 797 | 832 |
| 798 SyncChangeList new_changes; | 833 SyncChangeList new_changes; |
| 799 SyncError error; | 834 SyncError error; |
| 800 for (SyncChangeList::const_iterator iter = change_list.begin(); | 835 for (SyncChangeList::const_iterator iter = change_list.begin(); |
| 801 iter != change_list.end(); ++iter) { | 836 iter != change_list.end(); ++iter) { |
| 802 DCHECK_EQ(syncable::SEARCH_ENGINES, iter->sync_data().GetDataType()); | 837 DCHECK_EQ(syncable::SEARCH_ENGINES, iter->sync_data().GetDataType()); |
| 803 | 838 |
| 804 std::string guid = | 839 std::string guid = |
| 805 iter->sync_data().GetSpecifics().search_engine().sync_guid(); | 840 iter->sync_data().GetSpecifics().search_engine().sync_guid(); |
| 806 TemplateURL* existing_turl = GetTemplateURLForGUID(guid); | 841 TemplateURL* existing_turl = GetTemplateURLForGUID(guid); |
| 807 scoped_ptr<TemplateURL> turl(CreateTemplateURLFromTemplateURLAndSyncData( | 842 scoped_ptr<TemplateURL> turl(CreateTemplateURLFromTemplateURLAndSyncData( |
| 808 profile_, existing_turl, iter->sync_data(), &new_changes)); | 843 profile_, existing_turl, iter->sync_data(), &new_changes)); |
| 809 if (!turl.get()) | 844 if (!turl.get()) |
| 810 continue; | 845 continue; |
| 811 | 846 |
| 847 // Explicitly don't check for conflicts against extension keywords; in this |
| 848 // case the functions which modify the keyword map know how to handle the |
| 849 // conflicts. |
| 850 // TODO(mpcomplete): If we allow editing extension keywords, then those will |
| 851 // need to undergo conflict resolution. |
| 812 TemplateURL* existing_keyword_turl = | 852 TemplateURL* existing_keyword_turl = |
| 813 GetTemplateURLForKeyword(turl->keyword()); | 853 FindNonExtensionTemplateURLForKeyword(turl->keyword()); |
| 814 | |
| 815 if (iter->change_type() == SyncChange::ACTION_DELETE && existing_turl) { | 854 if (iter->change_type() == SyncChange::ACTION_DELETE && existing_turl) { |
| 816 bool delete_default = (existing_turl == GetDefaultSearchProvider()); | 855 bool delete_default = (existing_turl == GetDefaultSearchProvider()); |
| 817 | 856 |
| 818 if (delete_default && is_default_search_managed_) { | 857 if (delete_default && is_default_search_managed_) { |
| 819 NOTREACHED() << "Tried to delete managed default search provider"; | 858 NOTREACHED() << "Tried to delete managed default search provider"; |
| 820 } else { | 859 } else { |
| 821 if (delete_default) | 860 if (delete_default) |
| 822 default_search_provider_ = NULL; | 861 default_search_provider_ = NULL; |
| 823 | 862 |
| 824 Remove(existing_turl); | 863 Remove(existing_turl); |
| 825 | 864 |
| 826 if (delete_default) | 865 if (delete_default) |
| 827 SetDefaultSearchProvider(FindNewDefaultSearchProvider()); | 866 SetDefaultSearchProvider(FindNewDefaultSearchProvider()); |
| 828 } | 867 } |
| 829 } else if (iter->change_type() == SyncChange::ACTION_ADD && | 868 } else if (iter->change_type() == SyncChange::ACTION_ADD && |
| 830 !existing_turl) { | 869 !existing_turl) { |
| 831 std::string guid = turl->sync_guid(); | 870 std::string guid = turl->sync_guid(); |
| 832 if (existing_keyword_turl) | 871 if (existing_keyword_turl) { |
| 833 ResolveSyncKeywordConflict(turl.get(), &new_changes); | 872 ResolveSyncKeywordConflict(turl.get(), existing_keyword_turl, |
| 873 &new_changes); |
| 874 } |
| 834 // Force the local ID to kInvalidTemplateURLID so we can add it. | 875 // Force the local ID to kInvalidTemplateURLID so we can add it. |
| 835 TemplateURLData data(turl->data()); | 876 TemplateURLData data(turl->data()); |
| 836 data.id = kInvalidTemplateURLID; | 877 data.id = kInvalidTemplateURLID; |
| 837 Add(new TemplateURL(profile_, data)); | 878 Add(new TemplateURL(profile_, data)); |
| 838 | 879 |
| 839 // Possibly set the newly added |turl| as the default search provider. | 880 // Possibly set the newly added |turl| as the default search provider. |
| 840 SetDefaultSearchProviderIfNewlySynced(guid); | 881 SetDefaultSearchProviderIfNewlySynced(guid); |
| 841 } else if (iter->change_type() == SyncChange::ACTION_UPDATE && | 882 } else if (iter->change_type() == SyncChange::ACTION_UPDATE && |
| 842 existing_turl) { | 883 existing_turl) { |
| 843 // Possibly resolve a keyword conflict if they have the same keywords but | 884 // Possibly resolve a keyword conflict if they have the same keywords but |
| 844 // are not the same entry. | 885 // are not the same entry. |
| 845 if (existing_keyword_turl && existing_keyword_turl != existing_turl) | 886 if (existing_keyword_turl && existing_keyword_turl != existing_turl) { |
| 846 ResolveSyncKeywordConflict(turl.get(), &new_changes); | 887 ResolveSyncKeywordConflict(turl.get(), existing_keyword_turl, |
| 847 UpdateNoNotify(existing_turl, *turl); | 888 &new_changes); |
| 848 NotifyObservers(); | 889 } |
| 890 if (UpdateNoNotify(existing_turl, *turl)) |
| 891 NotifyObservers(); |
| 849 } else { | 892 } else { |
| 850 // Something really unexpected happened. Either we received an | 893 // Something really unexpected happened. Either we received an |
| 851 // ACTION_INVALID, or Sync is in a crazy state: | 894 // ACTION_INVALID, or Sync is in a crazy state: |
| 852 // . Trying to DELETE or UPDATE a non-existent search engine. | 895 // . Trying to DELETE or UPDATE a non-existent search engine. |
| 853 // . Trying to ADD a search engine that already exists. | 896 // . Trying to ADD a search engine that already exists. |
| 854 NOTREACHED() << "Unexpected sync change state."; | 897 NOTREACHED() << "Unexpected sync change state."; |
| 855 error = sync_error_factory_->CreateAndUploadError( | 898 error = sync_error_factory_->CreateAndUploadError( |
| 856 FROM_HERE, | 899 FROM_HERE, |
| 857 "ProcessSyncChanges failed on ChangeType " + | 900 "ProcessSyncChanges failed on ChangeType " + |
| 858 SyncChange::ChangeTypeToString(iter->change_type())); | 901 SyncChange::ChangeTypeToString(iter->change_type())); |
| 859 } | 902 } |
| 860 } | 903 } |
| 904 PreventDuplicateGUIDUpdates(&new_changes); |
| 861 | 905 |
| 862 // If something went wrong, we want to prematurely exit to avoid pushing | 906 // If something went wrong, we want to prematurely exit to avoid pushing |
| 863 // inconsistent data to Sync. We return the last error we received. | 907 // inconsistent data to Sync. We return the last error we received. |
| 864 if (error.IsSet()) | 908 if (error.IsSet()) |
| 865 return error; | 909 return error; |
| 866 | 910 |
| 867 error = sync_processor_->ProcessSyncChanges(from_here, new_changes); | 911 error = sync_processor_->ProcessSyncChanges(from_here, new_changes); |
| 868 | 912 |
| 869 return error; | 913 return error; |
| 870 } | 914 } |
| 871 | 915 |
| 872 SyncError TemplateURLService::MergeDataAndStartSyncing( | 916 SyncError TemplateURLService::MergeDataAndStartSyncing( |
| 873 syncable::ModelType type, | 917 syncable::ModelType type, |
| 874 const SyncDataList& initial_sync_data, | 918 const SyncDataList& initial_sync_data, |
| 875 scoped_ptr<SyncChangeProcessor> sync_processor, | 919 scoped_ptr<SyncChangeProcessor> sync_processor, |
| 876 scoped_ptr<SyncErrorFactory> sync_error_factory) { | 920 scoped_ptr<SyncErrorFactory> sync_error_factory) { |
| 877 DCHECK(loaded()); | 921 DCHECK(loaded_); |
| 878 DCHECK_EQ(type, syncable::SEARCH_ENGINES); | 922 DCHECK_EQ(type, syncable::SEARCH_ENGINES); |
| 879 DCHECK(!sync_processor_.get()); | 923 DCHECK(!sync_processor_.get()); |
| 880 DCHECK(sync_processor.get()); | 924 DCHECK(sync_processor.get()); |
| 881 DCHECK(sync_error_factory.get()); | 925 DCHECK(sync_error_factory.get()); |
| 882 sync_processor_ = sync_processor.Pass(); | 926 sync_processor_ = sync_processor.Pass(); |
| 883 sync_error_factory_ = sync_error_factory.Pass(); | 927 sync_error_factory_ = sync_error_factory.Pass(); |
| 884 | 928 |
| 885 // We just started syncing, so set our wait-for-default flag if we are | 929 // We just started syncing, so set our wait-for-default flag if we are |
| 886 // expecting a default from Sync. | 930 // expecting a default from Sync. |
| 887 if (GetPrefs()) { | 931 if (GetPrefs()) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 917 if (local_turl) { | 961 if (local_turl) { |
| 918 // This local search engine is already synced. If the timestamp differs | 962 // This local search engine is already synced. If the timestamp differs |
| 919 // from Sync, we need to update locally or to the cloud. Note that if the | 963 // from Sync, we need to update locally or to the cloud. Note that if the |
| 920 // timestamps are equal, we touch neither. | 964 // timestamps are equal, we touch neither. |
| 921 if (sync_turl->last_modified() > local_turl->last_modified()) { | 965 if (sync_turl->last_modified() > local_turl->last_modified()) { |
| 922 // We've received an update from Sync. We should replace all synced | 966 // We've received an update from Sync. We should replace all synced |
| 923 // fields in the local TemplateURL. Note that this includes the | 967 // fields in the local TemplateURL. Note that this includes the |
| 924 // TemplateURLID and the TemplateURL may have to be reparsed. This | 968 // TemplateURLID and the TemplateURL may have to be reparsed. This |
| 925 // also makes the local data's last_modified timestamp equal to Sync's, | 969 // also makes the local data's last_modified timestamp equal to Sync's, |
| 926 // avoiding an Update on the next MergeData call. | 970 // avoiding an Update on the next MergeData call. |
| 927 UpdateNoNotify(local_turl, *sync_turl); | 971 if (UpdateNoNotify(local_turl, *sync_turl)) |
| 928 NotifyObservers(); | 972 NotifyObservers(); |
| 929 } else if (sync_turl->last_modified() < local_turl->last_modified()) { | 973 } else if (sync_turl->last_modified() < local_turl->last_modified()) { |
| 930 // Otherwise, we know we have newer data, so update Sync with our | 974 // Otherwise, we know we have newer data, so update Sync with our |
| 931 // data fields. | 975 // data fields. |
| 932 new_changes.push_back(SyncChange(SyncChange::ACTION_UPDATE, | 976 new_changes.push_back(SyncChange(SyncChange::ACTION_UPDATE, |
| 933 local_data_map[local_turl->sync_guid()])); | 977 local_data_map[local_turl->sync_guid()])); |
| 934 } | 978 } |
| 935 local_data_map.erase(iter->first); | 979 local_data_map.erase(iter->first); |
| 936 } else { | 980 } else { |
| 937 // The search engine from the cloud has not been synced locally, but there | 981 // The search engine from the cloud has not been synced locally, but there |
| 938 // might be a local search engine that is a duplicate that needs to be | 982 // might be a local search engine that is a duplicate that needs to be |
| 939 // merged. | 983 // merged. |
| 940 TemplateURL* dupe_turl = FindDuplicateOfSyncTemplateURL(*sync_turl); | 984 TemplateURL* dupe_turl = FindDuplicateOfSyncTemplateURL(*sync_turl); |
| 941 if (dupe_turl) { | 985 if (dupe_turl) { |
| 942 // Merge duplicates and remove the processed local TURL from the map. | 986 // Merge duplicates and remove the processed local TURL from the map. |
| 943 std::string old_guid = dupe_turl->sync_guid(); | 987 std::string old_guid = dupe_turl->sync_guid(); |
| 944 MergeSyncAndLocalURLDuplicates(sync_turl.release(), dupe_turl, | 988 MergeSyncAndLocalURLDuplicates(sync_turl.release(), dupe_turl, |
| 945 &new_changes); | 989 &new_changes); |
| 946 local_data_map.erase(old_guid); | 990 local_data_map.erase(old_guid); |
| 947 } else { | 991 } else { |
| 948 std::string guid = sync_turl->sync_guid(); | 992 std::string guid = sync_turl->sync_guid(); |
| 949 // Keyword conflict is possible in this case. Resolve it first before | 993 // 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 | 994 // 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 | 995 // from local_data_map in this case as it may still need to be pushed to |
| 952 // the cloud. | 996 // the cloud. We also explicitly don't resolve conflicts against |
| 953 ResolveSyncKeywordConflict(sync_turl.get(), &new_changes); | 997 // extension keywords; see comments in ProcessSyncChanges(). |
| 998 TemplateURL* existing_keyword_turl = |
| 999 FindNonExtensionTemplateURLForKeyword(sync_turl->keyword()); |
| 1000 if (existing_keyword_turl) { |
| 1001 ResolveSyncKeywordConflict(sync_turl.get(), existing_keyword_turl, |
| 1002 &new_changes); |
| 1003 } |
| 954 // Force the local ID to kInvalidTemplateURLID so we can add it. | 1004 // Force the local ID to kInvalidTemplateURLID so we can add it. |
| 955 TemplateURLData data(sync_turl->data()); | 1005 TemplateURLData data(sync_turl->data()); |
| 956 data.id = kInvalidTemplateURLID; | 1006 data.id = kInvalidTemplateURLID; |
| 957 Add(new TemplateURL(profile_, data)); | 1007 Add(new TemplateURL(profile_, data)); |
| 958 | 1008 |
| 959 // Possibly set the newly added |turl| as the default search provider. | 1009 // Possibly set the newly added |turl| as the default search provider. |
| 960 SetDefaultSearchProviderIfNewlySynced(guid); | 1010 SetDefaultSearchProviderIfNewlySynced(guid); |
| 961 } | 1011 } |
| 962 } | 1012 } |
| 963 } | 1013 } |
| 964 | 1014 |
| 965 // The remaining SyncData in local_data_map should be everything that needs to | 1015 // The remaining SyncData in local_data_map should be everything that needs to |
| 966 // be pushed as ADDs to sync. | 1016 // be pushed as ADDs to sync. |
| 967 for (SyncDataMap::const_iterator iter = local_data_map.begin(); | 1017 for (SyncDataMap::const_iterator iter = local_data_map.begin(); |
| 968 iter != local_data_map.end(); ++iter) { | 1018 iter != local_data_map.end(); ++iter) { |
| 969 new_changes.push_back(SyncChange(SyncChange::ACTION_ADD, iter->second)); | 1019 new_changes.push_back(SyncChange(SyncChange::ACTION_ADD, iter->second)); |
| 970 } | 1020 } |
| 971 | 1021 |
| 1022 PreventDuplicateGUIDUpdates(&new_changes); |
| 1023 |
| 972 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes); | 1024 SyncError error = sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes); |
| 973 if (error.IsSet()) | 1025 if (error.IsSet()) |
| 974 return error; | 1026 return error; |
| 975 | 1027 |
| 976 models_associated_ = true; | 1028 models_associated_ = true; |
| 977 return SyncError(); | 1029 return SyncError(); |
| 978 } | 1030 } |
| 979 | 1031 |
| 980 void TemplateURLService::StopSyncing(syncable::ModelType type) { | 1032 void TemplateURLService::StopSyncing(syncable::ModelType type) { |
| 981 DCHECK_EQ(type, syncable::SEARCH_ENGINES); | 1033 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())); | 1076 se_specifics->set_keyword(UTF16ToUTF8(turl.keyword())); |
| 1025 se_specifics->set_favicon_url(turl.favicon_url().spec()); | 1077 se_specifics->set_favicon_url(turl.favicon_url().spec()); |
| 1026 se_specifics->set_url(turl.url()); | 1078 se_specifics->set_url(turl.url()); |
| 1027 se_specifics->set_safe_for_autoreplace(turl.safe_for_autoreplace()); | 1079 se_specifics->set_safe_for_autoreplace(turl.safe_for_autoreplace()); |
| 1028 se_specifics->set_originating_url(turl.originating_url().spec()); | 1080 se_specifics->set_originating_url(turl.originating_url().spec()); |
| 1029 se_specifics->set_date_created(turl.date_created().ToInternalValue()); | 1081 se_specifics->set_date_created(turl.date_created().ToInternalValue()); |
| 1030 se_specifics->set_input_encodings(JoinString(turl.input_encodings(), ';')); | 1082 se_specifics->set_input_encodings(JoinString(turl.input_encodings(), ';')); |
| 1031 se_specifics->set_show_in_default_list(turl.show_in_default_list()); | 1083 se_specifics->set_show_in_default_list(turl.show_in_default_list()); |
| 1032 se_specifics->set_suggestions_url(turl.suggestions_url()); | 1084 se_specifics->set_suggestions_url(turl.suggestions_url()); |
| 1033 se_specifics->set_prepopulate_id(turl.prepopulate_id()); | 1085 se_specifics->set_prepopulate_id(turl.prepopulate_id()); |
| 1034 se_specifics->set_autogenerate_keyword(turl.autogenerate_keyword()); | |
| 1035 se_specifics->set_instant_url(turl.instant_url()); | 1086 se_specifics->set_instant_url(turl.instant_url()); |
| 1036 se_specifics->set_last_modified(turl.last_modified().ToInternalValue()); | 1087 se_specifics->set_last_modified(turl.last_modified().ToInternalValue()); |
| 1037 se_specifics->set_sync_guid(turl.sync_guid()); | 1088 se_specifics->set_sync_guid(turl.sync_guid()); |
| 1038 return SyncData::CreateLocalData(se_specifics->sync_guid(), | 1089 return SyncData::CreateLocalData(se_specifics->sync_guid(), |
| 1039 se_specifics->keyword(), | 1090 se_specifics->keyword(), |
| 1040 specifics); | 1091 specifics); |
| 1041 } | 1092 } |
| 1042 | 1093 |
| 1043 // static | 1094 // static |
| 1044 TemplateURL* TemplateURLService::CreateTemplateURLFromTemplateURLAndSyncData( | 1095 TemplateURL* TemplateURLService::CreateTemplateURLFromTemplateURLAndSyncData( |
| 1045 Profile* profile, | 1096 Profile* profile, |
| 1046 TemplateURL* existing_turl, | 1097 TemplateURL* existing_turl, |
| 1047 const SyncData& sync_data, | 1098 const SyncData& sync_data, |
| 1048 SyncChangeList* change_list) { | 1099 SyncChangeList* change_list) { |
| 1049 DCHECK(change_list); | 1100 DCHECK(change_list); |
| 1050 | 1101 |
| 1051 sync_pb::SearchEngineSpecifics specifics = | 1102 sync_pb::SearchEngineSpecifics specifics = |
| 1052 sync_data.GetSpecifics().search_engine(); | 1103 sync_data.GetSpecifics().search_engine(); |
| 1053 | 1104 |
| 1054 // Past bugs might have caused either of these fields to be empty. Just | 1105 // Past bugs might have caused either of these fields to be empty. Just |
| 1055 // delete this data off the server. | 1106 // delete this data off the server. |
| 1056 if (specifics.url().empty() || specifics.sync_guid().empty()) { | 1107 if (specifics.url().empty() || specifics.sync_guid().empty()) { |
| 1057 change_list->push_back(SyncChange(SyncChange::ACTION_DELETE, sync_data)); | 1108 change_list->push_back(SyncChange(SyncChange::ACTION_DELETE, sync_data)); |
| 1058 return NULL; | 1109 return NULL; |
| 1059 } | 1110 } |
| 1060 | 1111 |
| 1061 TemplateURLData data; | 1112 TemplateURLData data; |
| 1062 data.short_name = UTF8ToUTF16(specifics.short_name()); | 1113 data.short_name = UTF8ToUTF16(specifics.short_name()); |
| 1063 data.originating_url = GURL(specifics.originating_url()); | 1114 data.originating_url = GURL(specifics.originating_url()); |
| 1064 data.SetKeyword(UTF8ToUTF16(specifics.keyword())); | 1115 string16 keyword(UTF8ToUTF16(specifics.keyword())); |
| 1065 data.SetAutogenerateKeyword(specifics.autogenerate_keyword()); | 1116 // NOTE: Once this code has shipped in a couple of stable releases, we can |
| 1117 // probably remove the migration portion, comment out the |
| 1118 // "autogenerate_keyword" field entirely in the .proto file, and fold the |
| 1119 // empty keyword case into the "delete data" block above. |
| 1120 bool reset_keyword = |
| 1121 specifics.autogenerate_keyword() || specifics.keyword().empty(); |
| 1122 if (reset_keyword) |
| 1123 keyword = ASCIIToUTF16("dummy"); // Will be replaced below. |
| 1124 DCHECK(!keyword.empty()); |
| 1125 data.SetKeyword(keyword); |
| 1066 data.SetURL(specifics.url()); | 1126 data.SetURL(specifics.url()); |
| 1067 data.suggestions_url = specifics.suggestions_url(); | 1127 data.suggestions_url = specifics.suggestions_url(); |
| 1068 data.instant_url = specifics.instant_url(); | 1128 data.instant_url = specifics.instant_url(); |
| 1069 data.favicon_url = GURL(specifics.favicon_url()); | 1129 data.favicon_url = GURL(specifics.favicon_url()); |
| 1070 data.show_in_default_list = specifics.show_in_default_list(); | 1130 data.show_in_default_list = specifics.show_in_default_list(); |
| 1071 data.safe_for_autoreplace = specifics.safe_for_autoreplace(); | 1131 data.safe_for_autoreplace = specifics.safe_for_autoreplace(); |
| 1072 base::SplitString(specifics.input_encodings(), ';', &data.input_encodings); | 1132 base::SplitString(specifics.input_encodings(), ';', &data.input_encodings); |
| 1073 data.date_created = base::Time::FromInternalValue(specifics.date_created()); | 1133 data.date_created = base::Time::FromInternalValue(specifics.date_created()); |
| 1074 data.last_modified = base::Time::FromInternalValue(specifics.last_modified()); | 1134 data.last_modified = base::Time::FromInternalValue(specifics.last_modified()); |
| 1075 data.prepopulate_id = specifics.prepopulate_id(); | 1135 data.prepopulate_id = specifics.prepopulate_id(); |
| 1076 data.sync_guid = specifics.sync_guid(); | 1136 data.sync_guid = specifics.sync_guid(); |
| 1077 if (existing_turl) { | 1137 if (existing_turl) { |
| 1078 data.id = existing_turl->id(); | 1138 data.id = existing_turl->id(); |
| 1079 data.created_by_policy = existing_turl->created_by_policy(); | 1139 data.created_by_policy = existing_turl->created_by_policy(); |
| 1080 data.usage_count = existing_turl->usage_count(); | 1140 data.usage_count = existing_turl->usage_count(); |
| 1081 } | 1141 } |
| 1082 | 1142 |
| 1083 TemplateURL* turl = new TemplateURL(profile, data); | 1143 TemplateURL* turl = new TemplateURL(profile, data); |
| 1084 DCHECK(!turl->IsExtensionKeyword()); | 1144 DCHECK(!turl->IsExtensionKeyword()); |
| 1145 if (reset_keyword) { |
| 1146 turl->ResetKeywordIfNecessary(true); |
| 1147 SyncData sync_data = CreateSyncDataFromTemplateURL(*turl); |
| 1148 change_list->push_back(SyncChange(SyncChange::ACTION_UPDATE, sync_data)); |
| 1149 } |
| 1085 return turl; | 1150 return turl; |
| 1086 } | 1151 } |
| 1087 | 1152 |
| 1088 // static | 1153 // static |
| 1089 SyncDataMap TemplateURLService::CreateGUIDToSyncDataMap( | 1154 SyncDataMap TemplateURLService::CreateGUIDToSyncDataMap( |
| 1090 const SyncDataList& sync_data) { | 1155 const SyncDataList& sync_data) { |
| 1091 SyncDataMap data_map; | 1156 SyncDataMap data_map; |
| 1092 for (SyncDataList::const_iterator i(sync_data.begin()); i != sync_data.end(); | 1157 for (SyncDataList::const_iterator i(sync_data.begin()); i != sync_data.end(); |
| 1093 ++i) | 1158 ++i) |
| 1094 data_map[i->GetSpecifics().search_engine().sync_guid()] = *i; | 1159 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() && | 1225 if (initial_default_search_provider_.get() && |
| 1161 initial_default_search_provider_->url_ref().HasGoogleBaseURLs()) { | 1226 initial_default_search_provider_->url_ref().HasGoogleBaseURLs()) { |
| 1162 scoped_ptr<base::Environment> env(base::Environment::Create()); | 1227 scoped_ptr<base::Environment> env(base::Environment::Create()); |
| 1163 if (!env->HasVar(env_vars::kHeadless) && | 1228 if (!env->HasVar(env_vars::kHeadless) && |
| 1164 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kChromeFrame)) | 1229 !CommandLine::ForCurrentProcess()->HasSwitch(switches::kChromeFrame)) |
| 1165 GoogleURLTracker::RequestServerCheck(); | 1230 GoogleURLTracker::RequestServerCheck(); |
| 1166 } | 1231 } |
| 1167 } | 1232 } |
| 1168 | 1233 |
| 1169 void TemplateURLService::RemoveFromMaps(TemplateURL* template_url) { | 1234 void TemplateURLService::RemoveFromMaps(TemplateURL* template_url) { |
| 1170 if (!template_url->keyword().empty()) | 1235 const string16& keyword = template_url->keyword(); |
| 1171 keyword_to_template_map_.erase(template_url->keyword()); | 1236 DCHECK_NE(0U, keyword_to_template_map_.count(keyword)); |
| 1237 if (keyword_to_template_map_[keyword] == template_url) { |
| 1238 // We need to check whether the keyword can now be provided by another |
| 1239 // TemplateURL. See the comments in AddToMaps() for more information on |
| 1240 // extension keywords and how they can coexist with non-extension keywords. |
| 1241 // In the case of more than one extension, we use the most recently |
| 1242 // installed (which will be the most recently added, which will have the |
| 1243 // highest ID). |
| 1244 TemplateURL* best_fallback = NULL; |
| 1245 for (TemplateURLVector::const_iterator i(template_urls_.begin()); |
| 1246 i != template_urls_.end(); ++i) { |
| 1247 TemplateURL* turl = *i; |
| 1248 // This next statement relies on the fact that there can only be one |
| 1249 // non-extension TemplateURL with a given keyword. |
| 1250 if ((turl != template_url) && (turl->keyword() == keyword) && |
| 1251 (!best_fallback || !best_fallback->IsExtensionKeyword() || |
| 1252 (turl->IsExtensionKeyword() && (turl->id() > best_fallback->id())))) |
| 1253 best_fallback = turl; |
| 1254 } |
| 1255 if (best_fallback) |
| 1256 keyword_to_template_map_[keyword] = best_fallback; |
| 1257 else |
| 1258 keyword_to_template_map_.erase(keyword); |
| 1259 } |
| 1172 | 1260 |
| 1173 // If the keyword we're removing is from an extension, we're now done, since | 1261 // 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. | 1262 // it won't be synced or stored in the provider map. |
| 1175 // TODO(mpcomplete): If we allow editing extension keywords, then those should | 1263 // TODO(mpcomplete): If we allow editing extension keywords, then those should |
| 1176 // be synced. | 1264 // be synced. |
| 1177 if (template_url->IsExtensionKeyword()) | 1265 if (template_url->IsExtensionKeyword()) |
| 1178 return; | 1266 return; |
| 1179 | 1267 |
| 1180 if (!template_url->sync_guid().empty()) | 1268 if (!template_url->sync_guid().empty()) |
| 1181 guid_to_template_map_.erase(template_url->sync_guid()); | 1269 guid_to_template_map_.erase(template_url->sync_guid()); |
| 1182 if (loaded_) | 1270 if (loaded_) |
| 1183 provider_map_->Remove(template_url); | 1271 provider_map_->Remove(template_url); |
| 1184 } | 1272 } |
| 1185 | 1273 |
| 1186 void TemplateURLService::RemoveFromKeywordMapByPointer( | 1274 void TemplateURLService::RemoveFromKeywordMapByPointer( |
| 1187 TemplateURL* template_url) { | 1275 TemplateURL* template_url) { |
| 1188 DCHECK(template_url); | 1276 DCHECK(template_url); |
| 1189 for (KeywordToTemplateMap::iterator i = keyword_to_template_map_.begin(); | 1277 for (KeywordToTemplateMap::iterator i = keyword_to_template_map_.begin(); |
| 1190 i != keyword_to_template_map_.end(); ++i) { | 1278 i != keyword_to_template_map_.end(); ++i) { |
| 1191 if (i->second == template_url) { | 1279 if (i->second == template_url) { |
| 1192 keyword_to_template_map_.erase(i); | 1280 keyword_to_template_map_.erase(i); |
| 1193 // A given TemplateURL only occurs once in the map. As soon as we find the | 1281 // A given TemplateURL only occurs once in the map. As soon as we find the |
| 1194 // entry, stop. | 1282 // entry, stop. |
| 1195 break; | 1283 break; |
| 1196 } | 1284 } |
| 1197 } | 1285 } |
| 1198 } | 1286 } |
| 1199 | 1287 |
| 1200 void TemplateURLService::AddToMaps(TemplateURL* template_url) { | 1288 void TemplateURLService::AddToMaps(TemplateURL* template_url) { |
| 1201 if (!template_url->keyword().empty()) | 1289 bool template_extension = template_url->IsExtensionKeyword(); |
| 1202 keyword_to_template_map_[template_url->keyword()] = template_url; | 1290 const string16& keyword = template_url->keyword(); |
| 1291 KeywordToTemplateMap::const_iterator i = |
| 1292 keyword_to_template_map_.find(keyword); |
| 1293 if (i == keyword_to_template_map_.end()) { |
| 1294 keyword_to_template_map_[keyword] = template_url; |
| 1295 } else { |
| 1296 const TemplateURL* existing_url = i->second; |
| 1297 // We should only have overlapping keywords when at least one comes from |
| 1298 // an extension. In that case, the ranking order is: |
| 1299 // Manually-modified keywords > extension keywords > replaceable keywords |
| 1300 // When there are multiple extensions, the last-added wins. |
| 1301 bool existing_extension = existing_url->IsExtensionKeyword(); |
| 1302 DCHECK(existing_extension || template_extension); |
| 1303 if (existing_extension ? |
| 1304 !CanReplace(template_url) : CanReplace(existing_url)) |
| 1305 keyword_to_template_map_[keyword] = template_url; |
| 1306 } |
| 1203 | 1307 |
| 1204 // Extension keywords are not synced, so they don't go into the GUID map, | 1308 // 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 | 1309 // 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. | 1310 // map, so at this point we're done. |
| 1207 // TODO(mpcomplete): If we allow editing extension keywords, then those should | 1311 // TODO(mpcomplete): If we allow editing extension keywords, then those should |
| 1208 // be persisted to disk and synced. | 1312 // be persisted to disk and synced. |
| 1209 if (template_url->IsExtensionKeyword()) | 1313 if (template_extension) |
| 1210 return; | 1314 return; |
| 1211 | 1315 |
| 1212 if (!template_url->sync_guid().empty()) | 1316 if (!template_url->sync_guid().empty()) |
| 1213 guid_to_template_map_[template_url->sync_guid()] = template_url; | 1317 guid_to_template_map_[template_url->sync_guid()] = template_url; |
| 1214 if (loaded_) { | 1318 if (loaded_) { |
| 1215 UIThreadSearchTermsData search_terms_data; | 1319 UIThreadSearchTermsData search_terms_data; |
| 1216 provider_map_->Add(template_url, search_terms_data); | 1320 provider_map_->Add(template_url, search_terms_data); |
| 1217 } | 1321 } |
| 1218 } | 1322 } |
| 1219 | 1323 |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1319 if (!prefs->GetBoolean(prefs::kDefaultSearchProviderEnabled)) { | 1423 if (!prefs->GetBoolean(prefs::kDefaultSearchProviderEnabled)) { |
| 1320 // The user doesn't want a default search provider. | 1424 // The user doesn't want a default search provider. |
| 1321 default_provider->reset(NULL); | 1425 default_provider->reset(NULL); |
| 1322 return true; | 1426 return true; |
| 1323 } | 1427 } |
| 1324 | 1428 |
| 1325 string16 name = | 1429 string16 name = |
| 1326 UTF8ToUTF16(prefs->GetString(prefs::kDefaultSearchProviderName)); | 1430 UTF8ToUTF16(prefs->GetString(prefs::kDefaultSearchProviderName)); |
| 1327 string16 keyword = | 1431 string16 keyword = |
| 1328 UTF8ToUTF16(prefs->GetString(prefs::kDefaultSearchProviderKeyword)); | 1432 UTF8ToUTF16(prefs->GetString(prefs::kDefaultSearchProviderKeyword)); |
| 1433 // Force keyword to be non-empty. |
| 1434 // TODO(pkasting): This is only necessary as long as we're potentially loading |
| 1435 // older prefs where empty keywords are theoretically possible. Eventually |
| 1436 // this code can be replaced with a DCHECK(!keyword.empty());. |
| 1437 bool update_keyword = keyword.empty(); |
| 1438 if (update_keyword) |
| 1439 keyword = ASCIIToUTF16("dummy"); |
| 1329 std::string search_url = | 1440 std::string search_url = |
| 1330 prefs->GetString(prefs::kDefaultSearchProviderSearchURL); | 1441 prefs->GetString(prefs::kDefaultSearchProviderSearchURL); |
| 1331 // Force URL to be non-empty. We've never supported this case, but past bugs | 1442 // 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 | 1443 // might have resulted in it slipping through; eventually this code can be |
| 1333 // replaced with a DCHECK(!search_url.empty());. | 1444 // replaced with a DCHECK(!search_url.empty());. |
| 1334 if (search_url.empty()) | 1445 if (search_url.empty()) |
| 1335 return false; | 1446 return false; |
| 1336 std::string suggest_url = | 1447 std::string suggest_url = |
| 1337 prefs->GetString(prefs::kDefaultSearchProviderSuggestURL); | 1448 prefs->GetString(prefs::kDefaultSearchProviderSuggestURL); |
| 1338 std::string instant_url = | 1449 std::string instant_url = |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1359 base::StringToInt64(id_string, &value); | 1470 base::StringToInt64(id_string, &value); |
| 1360 data.id = value; | 1471 data.id = value; |
| 1361 } | 1472 } |
| 1362 if (!prepopulate_id.empty() && !*is_managed) { | 1473 if (!prepopulate_id.empty() && !*is_managed) { |
| 1363 int value; | 1474 int value; |
| 1364 base::StringToInt(prepopulate_id, &value); | 1475 base::StringToInt(prepopulate_id, &value); |
| 1365 data.prepopulate_id = value; | 1476 data.prepopulate_id = value; |
| 1366 } | 1477 } |
| 1367 default_provider->reset(new TemplateURL(profile_, data)); | 1478 default_provider->reset(new TemplateURL(profile_, data)); |
| 1368 DCHECK(!(*default_provider)->IsExtensionKeyword()); | 1479 DCHECK(!(*default_provider)->IsExtensionKeyword()); |
| 1480 if (update_keyword) |
| 1481 (*default_provider)->ResetKeywordIfNecessary(true); |
| 1369 return true; | 1482 return true; |
| 1370 } | 1483 } |
| 1371 | 1484 |
| 1372 bool TemplateURLService::CanReplaceKeywordForHost( | 1485 bool TemplateURLService::CanReplaceKeywordForHost( |
| 1373 const std::string& host, | 1486 const std::string& host, |
| 1374 TemplateURL** to_replace) { | 1487 TemplateURL** to_replace) { |
| 1375 DCHECK(!to_replace || !*to_replace); | 1488 DCHECK(!to_replace || !*to_replace); |
| 1376 const TemplateURLSet* urls = provider_map_->GetURLsForHost(host); | 1489 const TemplateURLSet* urls = provider_map_->GetURLsForHost(host); |
| 1377 if (!urls) | 1490 if (!urls) |
| 1378 return true; | 1491 return true; |
| 1379 for (TemplateURLSet::const_iterator i(urls->begin()); i != urls->end(); ++i) { | 1492 for (TemplateURLSet::const_iterator i(urls->begin()); i != urls->end(); ++i) { |
| 1380 if (CanReplace(*i)) { | 1493 if (CanReplace(*i)) { |
| 1381 if (to_replace) | 1494 if (to_replace) |
| 1382 *to_replace = *i; | 1495 *to_replace = *i; |
| 1383 return true; | 1496 return true; |
| 1384 } | 1497 } |
| 1385 } | 1498 } |
| 1386 return false; | 1499 return false; |
| 1387 } | 1500 } |
| 1388 | 1501 |
| 1389 bool TemplateURLService::CanReplace(const TemplateURL* t_url) { | 1502 bool TemplateURLService::CanReplace(const TemplateURL* t_url) { |
| 1390 return (t_url != default_search_provider_ && !t_url->show_in_default_list() && | 1503 return (t_url != default_search_provider_ && !t_url->show_in_default_list() && |
| 1391 t_url->safe_for_autoreplace()); | 1504 t_url->safe_for_autoreplace()); |
| 1392 } | 1505 } |
| 1393 | 1506 |
| 1394 void TemplateURLService::UpdateNoNotify(TemplateURL* existing_turl, | 1507 TemplateURL* TemplateURLService::FindNonExtensionTemplateURLForKeyword( |
| 1508 const string16& keyword) { |
| 1509 TemplateURL* keyword_turl = GetTemplateURLForKeyword(keyword); |
| 1510 if (!keyword_turl || !keyword_turl->IsExtensionKeyword()) |
| 1511 return keyword_turl; |
| 1512 // The extension keyword in the model may be hiding a replaceable |
| 1513 // non-extension keyword. Look for it. |
| 1514 for (TemplateURLVector::const_iterator i(template_urls_.begin()); |
| 1515 i != template_urls_.end(); ++i) { |
| 1516 if (!(*i)->IsExtensionKeyword() && ((*i)->keyword() == keyword)) |
| 1517 return *i; |
| 1518 } |
| 1519 return NULL; |
| 1520 } |
| 1521 |
| 1522 bool TemplateURLService::UpdateNoNotify(TemplateURL* existing_turl, |
| 1395 const TemplateURL& new_values) { | 1523 const TemplateURL& new_values) { |
| 1396 DCHECK(loaded_); | 1524 DCHECK(loaded_); |
| 1397 DCHECK(existing_turl); | 1525 DCHECK(existing_turl); |
| 1398 DCHECK(std::find(template_urls_.begin(), template_urls_.end(), | 1526 if (std::find(template_urls_.begin(), template_urls_.end(), existing_turl) == |
| 1399 existing_turl) != template_urls_.end()); | 1527 template_urls_.end()) |
| 1528 return false; |
| 1400 | 1529 |
| 1401 // TODO(mpcomplete): If we allow editing extension keywords, then those should | 1530 // 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 | 1531 // be persisted to disk and synced. In this case this DCHECK should be |
| 1403 // removed. | 1532 // removed. |
| 1404 DCHECK(!existing_turl->IsExtensionKeyword()); | 1533 DCHECK(!existing_turl->IsExtensionKeyword()); |
| 1405 | 1534 |
| 1406 string16 old_keyword(existing_turl->keyword()); | 1535 string16 old_keyword(existing_turl->keyword()); |
| 1407 if (!old_keyword.empty()) | 1536 keyword_to_template_map_.erase(old_keyword); |
| 1408 keyword_to_template_map_.erase(old_keyword); | |
| 1409 if (!existing_turl->sync_guid().empty()) | 1537 if (!existing_turl->sync_guid().empty()) |
| 1410 guid_to_template_map_.erase(existing_turl->sync_guid()); | 1538 guid_to_template_map_.erase(existing_turl->sync_guid()); |
| 1411 | 1539 |
| 1412 provider_map_->Remove(existing_turl); | 1540 provider_map_->Remove(existing_turl); |
| 1413 TemplateURLID previous_id = existing_turl->id(); | 1541 TemplateURLID previous_id = existing_turl->id(); |
| 1414 *existing_turl = new_values; | 1542 *existing_turl = new_values; |
| 1415 existing_turl->data_.id = previous_id; | 1543 existing_turl->data_.id = previous_id; |
| 1416 UIThreadSearchTermsData search_terms_data; | 1544 UIThreadSearchTermsData search_terms_data; |
| 1417 provider_map_->Add(existing_turl, search_terms_data); | 1545 provider_map_->Add(existing_turl, search_terms_data); |
| 1418 | 1546 |
| 1419 const string16& keyword = existing_turl->keyword(); | 1547 const string16& keyword = existing_turl->keyword(); |
| 1420 if (!keyword.empty()) | 1548 KeywordToTemplateMap::const_iterator i = |
| 1549 keyword_to_template_map_.find(keyword); |
| 1550 if (i == keyword_to_template_map_.end()) { |
| 1421 keyword_to_template_map_[keyword] = existing_turl; | 1551 keyword_to_template_map_[keyword] = existing_turl; |
| 1552 } else { |
| 1553 // We can theoretically reach here in two cases: |
| 1554 // * There is an existing extension keyword and sync brings in a rename of |
| 1555 // a non-extension keyword to match. In this case we just need to pick |
| 1556 // which keyword has priority to update the keyword map. |
| 1557 // * Autogeneration of the keyword for a Google default search provider |
| 1558 // at load time causes it to conflict with an existing keyword. In this |
| 1559 // case we delete the existing keyword if it's replaceable, or else undo |
| 1560 // the change in keyword for |existing_turl|. |
| 1561 DCHECK(!existing_turl->IsExtensionKeyword()); |
| 1562 TemplateURL* existing_keyword_turl = i->second; |
| 1563 if (existing_keyword_turl->IsExtensionKeyword()) { |
| 1564 if (!CanReplace(existing_turl)) |
| 1565 keyword_to_template_map_[keyword] = existing_turl; |
| 1566 } else { |
| 1567 if (CanReplace(existing_keyword_turl)) { |
| 1568 RemoveNoNotify(existing_keyword_turl); |
| 1569 } else { |
| 1570 existing_turl->data_.SetKeyword(old_keyword); |
| 1571 keyword_to_template_map_[old_keyword] = existing_turl; |
| 1572 } |
| 1573 } |
| 1574 } |
| 1422 if (!existing_turl->sync_guid().empty()) | 1575 if (!existing_turl->sync_guid().empty()) |
| 1423 guid_to_template_map_[existing_turl->sync_guid()] = existing_turl; | 1576 guid_to_template_map_[existing_turl->sync_guid()] = existing_turl; |
| 1424 | 1577 |
| 1425 if (service_.get()) | 1578 if (service_.get()) |
| 1426 service_->UpdateKeyword(*existing_turl); | 1579 service_->UpdateKeyword(existing_turl->data()); |
| 1427 | 1580 |
| 1428 // Inform sync of the update. | 1581 // Inform sync of the update. |
| 1429 ProcessTemplateURLChange(existing_turl, SyncChange::ACTION_UPDATE); | 1582 ProcessTemplateURLChange(existing_turl, SyncChange::ACTION_UPDATE); |
| 1430 | 1583 |
| 1431 if (default_search_provider_ == existing_turl) | 1584 if (default_search_provider_ == existing_turl) { |
| 1432 SetDefaultSearchProviderNoNotify(existing_turl); | 1585 bool success = SetDefaultSearchProviderNoNotify(existing_turl); |
| 1586 DCHECK(success); |
| 1587 } |
| 1588 return true; |
| 1433 } | 1589 } |
| 1434 | 1590 |
| 1435 PrefService* TemplateURLService::GetPrefs() { | 1591 PrefService* TemplateURLService::GetPrefs() { |
| 1436 return profile_ ? profile_->GetPrefs() : NULL; | 1592 return profile_ ? profile_->GetPrefs() : NULL; |
| 1437 } | 1593 } |
| 1438 | 1594 |
| 1439 void TemplateURLService::UpdateKeywordSearchTermsForURL( | 1595 void TemplateURLService::UpdateKeywordSearchTermsForURL( |
| 1440 const history::URLVisitedDetails& details) { | 1596 const history::URLVisitedDetails& details) { |
| 1441 const history::URLRow& row = details.row; | 1597 const history::URLRow& row = details.row; |
| 1442 if (!row.url().is_valid() || | 1598 if (!row.url().is_valid() || |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1557 bool something_changed = false; | 1713 bool something_changed = false; |
| 1558 for (TemplateURLVector::iterator i(template_urls_.begin()); | 1714 for (TemplateURLVector::iterator i(template_urls_.begin()); |
| 1559 i != template_urls_.end(); ++i) { | 1715 i != template_urls_.end(); ++i) { |
| 1560 TemplateURL* t_url = *i; | 1716 TemplateURL* t_url = *i; |
| 1561 if (t_url->url_ref().HasGoogleBaseURLs() || | 1717 if (t_url->url_ref().HasGoogleBaseURLs() || |
| 1562 t_url->suggestions_url_ref().HasGoogleBaseURLs()) { | 1718 t_url->suggestions_url_ref().HasGoogleBaseURLs()) { |
| 1563 something_changed = true; | 1719 something_changed = true; |
| 1564 string16 original_keyword(t_url->keyword()); | 1720 string16 original_keyword(t_url->keyword()); |
| 1565 t_url->InvalidateCachedValues(); | 1721 t_url->InvalidateCachedValues(); |
| 1566 const string16& new_keyword(t_url->keyword()); | 1722 const string16& new_keyword(t_url->keyword()); |
| 1723 KeywordToTemplateMap::const_iterator i = |
| 1724 keyword_to_template_map_.find(new_keyword); |
| 1725 if ((i != keyword_to_template_map_.end()) && (i->second != t_url)) { |
| 1726 // The new autogenerated keyword conflicts with another TemplateURL. |
| 1727 // Overwrite it if it's replaceable; otherwise just reset |t_url|'s |
| 1728 // keyword. (This will not prevent |t_url| from auto-updating the |
| 1729 // keyword in the future if the conflicting TemplateURL disappears.) |
| 1730 if (!CanReplace(i->second)) { |
| 1731 t_url->data_.SetKeyword(original_keyword); |
| 1732 continue; |
| 1733 } |
| 1734 RemoveNoNotify(i->second); |
| 1735 } |
| 1567 RemoveFromKeywordMapByPointer(t_url); | 1736 RemoveFromKeywordMapByPointer(t_url); |
| 1568 if (!new_keyword.empty()) | 1737 keyword_to_template_map_[new_keyword] = t_url; |
| 1569 keyword_to_template_map_[new_keyword] = t_url; | |
| 1570 } | 1738 } |
| 1571 } | 1739 } |
| 1572 | 1740 |
| 1573 if (something_changed && loaded_) { | 1741 if (something_changed && loaded_) { |
| 1574 UIThreadSearchTermsData search_terms_data; | 1742 UIThreadSearchTermsData search_terms_data; |
| 1575 provider_map_->UpdateGoogleBaseURLs(search_terms_data); | 1743 provider_map_->UpdateGoogleBaseURLs(search_terms_data); |
| 1576 NotifyObservers(); | 1744 NotifyObservers(); |
| 1577 } | 1745 } |
| 1578 } | 1746 } |
| 1579 | 1747 |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1611 // if it has changed; we don't want to respond to changes triggered by | 1779 // if it has changed; we don't want to respond to changes triggered by |
| 1612 // SaveDefaultSearchProviderToPrefs. | 1780 // SaveDefaultSearchProviderToPrefs. |
| 1613 if (TemplateURLsHaveSamePrefs(default_search_provider_, | 1781 if (TemplateURLsHaveSamePrefs(default_search_provider_, |
| 1614 new_default_from_prefs.get())) | 1782 new_default_from_prefs.get())) |
| 1615 return; | 1783 return; |
| 1616 if (new_default_from_prefs.get() == NULL) { | 1784 if (new_default_from_prefs.get() == NULL) { |
| 1617 // default_search_provider_ can't be NULL otherwise | 1785 // default_search_provider_ can't be NULL otherwise |
| 1618 // TemplateURLsHaveSamePrefs would have returned true. Remove this now | 1786 // TemplateURLsHaveSamePrefs would have returned true. Remove this now |
| 1619 // invalid value. | 1787 // invalid value. |
| 1620 TemplateURL* old_default = default_search_provider_; | 1788 TemplateURL* old_default = default_search_provider_; |
| 1621 SetDefaultSearchProviderNoNotify(NULL); | 1789 bool success = SetDefaultSearchProviderNoNotify(NULL); |
| 1790 DCHECK(success); |
| 1622 RemoveNoNotify(old_default); | 1791 RemoveNoNotify(old_default); |
| 1623 } else if (default_search_provider_) { | 1792 } else if (default_search_provider_) { |
| 1624 TemplateURLData data(new_default_from_prefs->data()); | 1793 TemplateURLData data(new_default_from_prefs->data()); |
| 1625 data.created_by_policy = true; | 1794 data.created_by_policy = true; |
| 1626 TemplateURL new_values(profile_, data); | 1795 TemplateURL new_values(profile_, data); |
| 1627 UpdateNoNotify(default_search_provider_, new_values); | 1796 UpdateNoNotify(default_search_provider_, new_values); |
| 1628 } else { | 1797 } else { |
| 1629 TemplateURL* new_template = NULL; | 1798 TemplateURL* new_template = NULL; |
| 1630 if (new_default_from_prefs.get()) { | 1799 if (new_default_from_prefs.get()) { |
| 1631 TemplateURLData data(new_default_from_prefs->data()); | 1800 TemplateURLData data(new_default_from_prefs->data()); |
| 1632 data.created_by_policy = true; | 1801 data.created_by_policy = true; |
| 1633 new_template = new TemplateURL(profile_, data); | 1802 new_template = new TemplateURL(profile_, data); |
| 1634 AddNoNotify(new_template, true); | 1803 if (!AddNoNotify(new_template, true)) |
| 1804 return; |
| 1635 } | 1805 } |
| 1636 SetDefaultSearchProviderNoNotify(new_template); | 1806 bool success = SetDefaultSearchProviderNoNotify(new_template); |
| 1807 DCHECK(success); |
| 1637 } | 1808 } |
| 1638 } else if (!is_default_search_managed_ && new_is_default_managed) { | 1809 } else if (!is_default_search_managed_ && new_is_default_managed) { |
| 1639 // The default used to be unmanaged and is now managed. Add the new | 1810 // 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. | 1811 // managed default to the list of URLs and set it as default. |
| 1641 is_default_search_managed_ = new_is_default_managed; | 1812 is_default_search_managed_ = new_is_default_managed; |
| 1642 TemplateURL* new_template = NULL; | 1813 TemplateURL* new_template = NULL; |
| 1643 if (new_default_from_prefs.get()) { | 1814 if (new_default_from_prefs.get()) { |
| 1644 TemplateURLData data(new_default_from_prefs->data()); | 1815 TemplateURLData data(new_default_from_prefs->data()); |
| 1645 data.created_by_policy = true; | 1816 data.created_by_policy = true; |
| 1646 new_template = new TemplateURL(profile_, data); | 1817 new_template = new TemplateURL(profile_, data); |
| 1647 AddNoNotify(new_template, true); | 1818 if (!AddNoNotify(new_template, true)) |
| 1819 return; |
| 1648 } | 1820 } |
| 1649 SetDefaultSearchProviderNoNotify(new_template); | 1821 bool success = SetDefaultSearchProviderNoNotify(new_template); |
| 1822 DCHECK(success); |
| 1650 } else { | 1823 } else { |
| 1651 // The default was managed and is no longer. | 1824 // The default was managed and is no longer. |
| 1652 DCHECK(is_default_search_managed_ && !new_is_default_managed); | 1825 DCHECK(is_default_search_managed_ && !new_is_default_managed); |
| 1653 is_default_search_managed_ = new_is_default_managed; | 1826 is_default_search_managed_ = new_is_default_managed; |
| 1654 // If we had a default, delete the previous default if created by policy | 1827 // If we had a default, delete the previous default if created by policy |
| 1655 // and set a likely default. | 1828 // and set a likely default. |
| 1656 if ((default_search_provider_ != NULL) && | 1829 if ((default_search_provider_ != NULL) && |
| 1657 default_search_provider_->created_by_policy()) { | 1830 default_search_provider_->created_by_policy()) { |
| 1658 TemplateURL* old_default = default_search_provider_; | 1831 TemplateURL* old_default = default_search_provider_; |
| 1659 default_search_provider_ = NULL; | 1832 default_search_provider_ = NULL; |
| 1660 RemoveNoNotify(old_default); | 1833 RemoveNoNotify(old_default); |
| 1661 } | 1834 } |
| 1662 | 1835 |
| 1663 // The likely default should be from Sync if we were waiting on Sync. | 1836 // The likely default should be from Sync if we were waiting on Sync. |
| 1664 // Otherwise, it should be FindNewDefaultSearchProvider. | 1837 // Otherwise, it should be FindNewDefaultSearchProvider. |
| 1665 TemplateURL* synced_default = GetPendingSyncedDefaultSearchProvider(); | 1838 TemplateURL* synced_default = GetPendingSyncedDefaultSearchProvider(); |
| 1666 if (synced_default) | 1839 if (synced_default) |
| 1667 pending_synced_default_search_ = false; | 1840 pending_synced_default_search_ = false; |
| 1668 SetDefaultSearchProviderNoNotify(synced_default ? synced_default : | 1841 SetDefaultSearchProviderNoNotify(synced_default ? synced_default : |
| 1669 FindNewDefaultSearchProvider()); | 1842 FindNewDefaultSearchProvider()); |
| 1670 } | 1843 } |
| 1671 NotifyObservers(); | 1844 NotifyObservers(); |
| 1672 } | 1845 } |
| 1673 | 1846 |
| 1674 void TemplateURLService::SetDefaultSearchProviderNoNotify(TemplateURL* url) { | 1847 bool TemplateURLService::SetDefaultSearchProviderNoNotify(TemplateURL* url) { |
| 1675 if (url) { | 1848 if (url) { |
| 1676 DCHECK(std::find(template_urls_.begin(), template_urls_.end(), url) != | 1849 if (std::find(template_urls_.begin(), template_urls_.end(), url) == |
| 1677 template_urls_.end()); | 1850 template_urls_.end()) |
| 1851 return false; |
| 1678 // Extension keywords cannot be made default, as they're inherently async. | 1852 // Extension keywords cannot be made default, as they're inherently async. |
| 1679 DCHECK(!url->IsExtensionKeyword()); | 1853 DCHECK(!url->IsExtensionKeyword()); |
| 1680 } | 1854 } |
| 1681 | 1855 |
| 1682 default_search_provider_ = url; | 1856 default_search_provider_ = url; |
| 1683 | 1857 |
| 1684 if (url) { | 1858 if (url) { |
| 1685 // Don't mark the url as edited, otherwise we won't be able to rev the | 1859 // Don't mark the url as edited, otherwise we won't be able to rev the |
| 1686 // template urls we ship with. | 1860 // template urls we ship with. |
| 1687 url->data_.show_in_default_list = true; | 1861 url->data_.show_in_default_list = true; |
| 1688 if (service_.get()) | 1862 if (service_.get()) |
| 1689 service_->UpdateKeyword(*url); | 1863 service_->UpdateKeyword(url->data()); |
| 1690 | 1864 |
| 1691 if (url->url_ref().HasGoogleBaseURLs()) { | 1865 if (url->url_ref().HasGoogleBaseURLs()) { |
| 1692 GoogleURLTracker::RequestServerCheck(); | 1866 GoogleURLTracker::RequestServerCheck(); |
| 1693 #if defined(ENABLE_RLZ) | 1867 #if defined(ENABLE_RLZ) |
| 1694 // Needs to be evaluated. See http://crbug.com/62328. | 1868 // Needs to be evaluated. See http://crbug.com/62328. |
| 1695 base::ThreadRestrictions::ScopedAllowIO allow_io; | 1869 base::ThreadRestrictions::ScopedAllowIO allow_io; |
| 1696 RLZTracker::RecordProductEvent(rlz_lib::CHROME, | 1870 RLZTracker::RecordProductEvent(rlz_lib::CHROME, |
| 1697 rlz_lib::CHROME_OMNIBOX, | 1871 rlz_lib::CHROME_OMNIBOX, |
| 1698 rlz_lib::SET_TO_GOOGLE); | 1872 rlz_lib::SET_TO_GOOGLE); |
| 1699 #endif | 1873 #endif |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1711 url->sync_guid()); | 1885 url->sync_guid()); |
| 1712 } | 1886 } |
| 1713 } | 1887 } |
| 1714 | 1888 |
| 1715 if (service_.get()) | 1889 if (service_.get()) |
| 1716 service_->SetDefaultSearchProvider(url); | 1890 service_->SetDefaultSearchProvider(url); |
| 1717 | 1891 |
| 1718 // Inform sync the change to the show_in_default_list flag. | 1892 // Inform sync the change to the show_in_default_list flag. |
| 1719 if (url) | 1893 if (url) |
| 1720 ProcessTemplateURLChange(url, SyncChange::ACTION_UPDATE); | 1894 ProcessTemplateURLChange(url, SyncChange::ACTION_UPDATE); |
| 1895 return true; |
| 1721 } | 1896 } |
| 1722 | 1897 |
| 1723 void TemplateURLService::AddNoNotify(TemplateURL* template_url, | 1898 bool TemplateURLService::AddNoNotify(TemplateURL* template_url, |
| 1724 bool newly_adding) { | 1899 bool newly_adding) { |
| 1725 DCHECK(template_url); | 1900 DCHECK(template_url); |
| 1726 | 1901 |
| 1727 if (newly_adding) { | 1902 if (newly_adding) { |
| 1728 DCHECK_EQ(kInvalidTemplateURLID, template_url->id()); | 1903 DCHECK_EQ(kInvalidTemplateURLID, template_url->id()); |
| 1729 DCHECK(std::find(template_urls_.begin(), template_urls_.end(), | 1904 DCHECK(std::find(template_urls_.begin(), template_urls_.end(), |
| 1730 template_url) == template_urls_.end()); | 1905 template_url) == template_urls_.end()); |
| 1731 template_url->data_.id = ++next_id_; | 1906 template_url->data_.id = ++next_id_; |
| 1732 } | 1907 } |
| 1733 | 1908 |
| 1909 template_url->ResetKeywordIfNecessary(false); |
| 1910 if (!template_url->IsExtensionKeyword()) { |
| 1911 // Check whether |template_url|'s keyword conflicts with any already in the |
| 1912 // model. |
| 1913 TemplateURL* existing_keyword_turl = |
| 1914 FindNonExtensionTemplateURLForKeyword(template_url->keyword()); |
| 1915 if (existing_keyword_turl != NULL) { |
| 1916 DCHECK_NE(existing_keyword_turl, template_url); |
| 1917 if (CanReplace(existing_keyword_turl)) { |
| 1918 RemoveNoNotify(existing_keyword_turl); |
| 1919 } else if (CanReplace(template_url)) { |
| 1920 delete template_url; |
| 1921 return false; |
| 1922 } else { |
| 1923 string16 new_keyword = UniquifyKeyword(*existing_keyword_turl); |
| 1924 ResetTemplateURL(existing_keyword_turl, |
| 1925 existing_keyword_turl->short_name(), new_keyword, |
| 1926 existing_keyword_turl->url()); |
| 1927 } |
| 1928 } |
| 1929 } |
| 1734 template_urls_.push_back(template_url); | 1930 template_urls_.push_back(template_url); |
| 1735 AddToMaps(template_url); | 1931 AddToMaps(template_url); |
| 1736 | 1932 |
| 1737 if (newly_adding) { | 1933 if (newly_adding) { |
| 1738 // Don't persist extension keywords to disk. They'll get re-added on each | 1934 // Don't persist extension keywords to disk. They'll get re-added on each |
| 1739 // launch as the extensions are loaded. | 1935 // launch as the extensions are loaded. |
| 1740 // TODO(mpcomplete): If we allow editing extension keywords, then those | 1936 // TODO(mpcomplete): If we allow editing extension keywords, then those |
| 1741 // should be persisted to disk and synced. | 1937 // should be persisted to disk and synced. |
| 1742 if (service_.get() && !template_url->IsExtensionKeyword()) | 1938 if (service_.get() && !template_url->IsExtensionKeyword()) |
| 1743 service_->AddKeyword(*template_url); | 1939 service_->AddKeyword(template_url->data()); |
| 1744 | 1940 |
| 1745 // Inform sync of the addition. Note that this will assign a GUID to | 1941 // 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_. | 1942 // template_url and add it to the guid_to_template_map_. |
| 1747 ProcessTemplateURLChange(template_url, SyncChange::ACTION_ADD); | 1943 ProcessTemplateURLChange(template_url, SyncChange::ACTION_ADD); |
| 1748 } | 1944 } |
| 1945 |
| 1946 return true; |
| 1749 } | 1947 } |
| 1750 | 1948 |
| 1751 void TemplateURLService::RemoveNoNotify(TemplateURL* template_url) { | 1949 void TemplateURLService::RemoveNoNotify(TemplateURL* template_url) { |
| 1752 TemplateURLVector::iterator i = | 1950 TemplateURLVector::iterator i = |
| 1753 std::find(template_urls_.begin(), template_urls_.end(), template_url); | 1951 std::find(template_urls_.begin(), template_urls_.end(), template_url); |
| 1754 if (i == template_urls_.end()) | 1952 if (i == template_urls_.end()) |
| 1755 return; | 1953 return; |
| 1756 | 1954 |
| 1757 if (template_url == default_search_provider_) { | 1955 if (template_url == default_search_provider_) { |
| 1758 // Should never delete the default search provider. | 1956 // Should never delete the default search provider. |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1840 service_->RemoveKeyword(template_url->id()); | 2038 service_->RemoveKeyword(template_url->id()); |
| 1841 delete template_url; | 2039 delete template_url; |
| 1842 } else { | 2040 } else { |
| 1843 ++i; | 2041 ++i; |
| 1844 } | 2042 } |
| 1845 } | 2043 } |
| 1846 } | 2044 } |
| 1847 | 2045 |
| 1848 void TemplateURLService::ResetTemplateURLGUID(TemplateURL* url, | 2046 void TemplateURLService::ResetTemplateURLGUID(TemplateURL* url, |
| 1849 const std::string& guid) { | 2047 const std::string& guid) { |
| 2048 DCHECK(loaded_); |
| 1850 DCHECK(!guid.empty()); | 2049 DCHECK(!guid.empty()); |
| 1851 | 2050 |
| 1852 TemplateURLData data(url->data()); | 2051 TemplateURLData data(url->data()); |
| 1853 data.sync_guid = guid; | 2052 data.sync_guid = guid; |
| 1854 TemplateURL new_url(url->profile(), data); | 2053 TemplateURL new_url(url->profile(), data); |
| 1855 UpdateNoNotify(url, new_url); | 2054 UpdateNoNotify(url, new_url); |
| 1856 } | 2055 } |
| 1857 | 2056 |
| 1858 string16 TemplateURLService::UniquifyKeyword(const TemplateURL& turl) { | 2057 string16 TemplateURLService::UniquifyKeyword(const TemplateURL& turl) { |
| 1859 // Already unique. | 2058 // Already unique. |
| 1860 if (!GetTemplateURLForKeyword(turl.keyword())) | 2059 if (!GetTemplateURLForKeyword(turl.keyword())) |
| 1861 return turl.keyword(); | 2060 return turl.keyword(); |
| 1862 | 2061 |
| 1863 // First, try to return the generated keyword for the TemplateURL. | 2062 // First, try to return the generated keyword for the TemplateURL. |
| 1864 GURL gurl(turl.url()); | 2063 GURL gurl(turl.url()); |
| 1865 if (gurl.is_valid()) { | 2064 if (gurl.is_valid()) { |
| 1866 string16 keyword_candidate = GenerateKeyword(gurl, true); | 2065 string16 keyword_candidate = GenerateKeyword(gurl); |
| 1867 if (!GetTemplateURLForKeyword(keyword_candidate) && | 2066 if (!GetTemplateURLForKeyword(keyword_candidate)) |
| 1868 !keyword_candidate.empty()) | |
| 1869 return keyword_candidate; | 2067 return keyword_candidate; |
| 1870 } | 2068 } |
| 1871 | 2069 |
| 1872 // We try to uniquify the keyword by appending a special character to the end. | 2070 // 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 | 2071 // 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. | 2072 // keyword and let the user do what they will after our attempt. |
| 1875 string16 keyword_candidate(turl.keyword()); | 2073 string16 keyword_candidate(turl.keyword()); |
| 1876 do { | 2074 do { |
| 1877 keyword_candidate.append(ASCIIToUTF16("_")); | 2075 keyword_candidate.append(ASCIIToUTF16("_")); |
| 1878 } while (GetTemplateURLForKeyword(keyword_candidate)); | 2076 } while (GetTemplateURLForKeyword(keyword_candidate)); |
| 1879 | 2077 |
| 1880 return keyword_candidate; | 2078 return keyword_candidate; |
| 1881 } | 2079 } |
| 1882 | 2080 |
| 1883 bool TemplateURLService::ResolveSyncKeywordConflict( | 2081 void TemplateURLService::ResolveSyncKeywordConflict( |
| 1884 TemplateURL* sync_turl, | 2082 TemplateURL* sync_turl, |
| 2083 TemplateURL* local_turl, |
| 1885 SyncChangeList* change_list) { | 2084 SyncChangeList* change_list) { |
| 2085 DCHECK(loaded_); |
| 1886 DCHECK(sync_turl); | 2086 DCHECK(sync_turl); |
| 2087 DCHECK(local_turl); |
| 2088 DCHECK(sync_turl->sync_guid() != local_turl->sync_guid()); |
| 2089 DCHECK(!local_turl->IsExtensionKeyword()); |
| 1887 DCHECK(change_list); | 2090 DCHECK(change_list); |
| 1888 | 2091 |
| 1889 TemplateURL* existing_turl = | 2092 if (local_turl->last_modified() > sync_turl->last_modified() || |
| 1890 GetTemplateURLForKeyword(sync_turl->keyword()); | 2093 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); | 2094 string16 new_keyword = UniquifyKeyword(*sync_turl); |
| 1898 DCHECK(!GetTemplateURLForKeyword(new_keyword)); | 2095 DCHECK(!GetTemplateURLForKeyword(new_keyword)); |
| 1899 sync_turl->data_.SetKeyword(new_keyword); | 2096 sync_turl->data_.SetKeyword(new_keyword); |
| 1900 // If we update the cloud TURL, we need to push an update back to sync | 2097 // If we update the cloud TURL, we need to push an update back to sync |
| 1901 // informing it that something has changed. | 2098 // informing it that something has changed. |
| 1902 SyncData sync_data = CreateSyncDataFromTemplateURL(*sync_turl); | 2099 SyncData sync_data = CreateSyncDataFromTemplateURL(*sync_turl); |
| 1903 change_list->push_back(SyncChange(SyncChange::ACTION_UPDATE, sync_data)); | 2100 change_list->push_back(SyncChange(SyncChange::ACTION_UPDATE, sync_data)); |
| 1904 } else { | 2101 } else { |
| 1905 string16 new_keyword = UniquifyKeyword(*existing_turl); | 2102 string16 new_keyword = UniquifyKeyword(*local_turl); |
| 1906 TemplateURLData data(existing_turl->data()); | 2103 TemplateURLData data(local_turl->data()); |
| 1907 data.SetKeyword(new_keyword); | 2104 data.SetKeyword(new_keyword); |
| 1908 TemplateURL new_turl(existing_turl->profile(), data); | 2105 TemplateURL new_turl(local_turl->profile(), data); |
| 1909 UpdateNoNotify(existing_turl, new_turl); | 2106 if (UpdateNoNotify(local_turl, new_turl)) |
| 1910 NotifyObservers(); | 2107 NotifyObservers(); |
| 2108 if (!models_associated_) { |
| 2109 // We're doing our initial sync, so UpdateNoNotify() won't have generated |
| 2110 // an ACTION_UPDATE. If this local URL is one that was just newly brought |
| 2111 // down from the sync server, we need to go ahead and generate an update |
| 2112 // for it. If it was pre-existing, then this is unnecessary (and in fact |
| 2113 // wrong) because MergeDataAndStartSyncing() will later add an ACTION_ADD |
| 2114 // for this URL; but in this case, PreventDuplicateGUIDUpdates() will |
| 2115 // prune out the ACTION_UPDATE we create here. |
| 2116 SyncData sync_data = CreateSyncDataFromTemplateURL(*local_turl); |
| 2117 change_list->push_back(SyncChange(SyncChange::ACTION_UPDATE, sync_data)); |
| 2118 } |
| 1911 } | 2119 } |
| 1912 return true; | |
| 1913 } | 2120 } |
| 1914 | 2121 |
| 1915 TemplateURL* TemplateURLService::FindDuplicateOfSyncTemplateURL( | 2122 TemplateURL* TemplateURLService::FindDuplicateOfSyncTemplateURL( |
| 1916 const TemplateURL& sync_turl) { | 2123 const TemplateURL& sync_turl) { |
| 1917 TemplateURL* existing_turl = GetTemplateURLForKeyword(sync_turl.keyword()); | 2124 TemplateURL* existing_turl = GetTemplateURLForKeyword(sync_turl.keyword()); |
| 1918 return existing_turl && (existing_turl->url() == sync_turl.url()) ? | 2125 return existing_turl && (existing_turl->url() == sync_turl.url()) ? |
| 1919 existing_turl : NULL; | 2126 existing_turl : NULL; |
| 1920 } | 2127 } |
| 1921 | 2128 |
| 1922 void TemplateURLService::MergeSyncAndLocalURLDuplicates( | 2129 void TemplateURLService::MergeSyncAndLocalURLDuplicates( |
| 1923 TemplateURL* sync_turl, | 2130 TemplateURL* sync_turl, |
| 1924 TemplateURL* local_turl, | 2131 TemplateURL* local_turl, |
| 1925 SyncChangeList* change_list) { | 2132 SyncChangeList* change_list) { |
| 2133 DCHECK(loaded_); |
| 1926 DCHECK(sync_turl); | 2134 DCHECK(sync_turl); |
| 1927 DCHECK(local_turl); | 2135 DCHECK(local_turl); |
| 1928 DCHECK(change_list); | 2136 DCHECK(change_list); |
| 1929 scoped_ptr<TemplateURL> scoped_sync_turl(sync_turl); | 2137 scoped_ptr<TemplateURL> scoped_sync_turl(sync_turl); |
| 1930 if (sync_turl->last_modified() > local_turl->last_modified()) { | 2138 if (sync_turl->last_modified() > local_turl->last_modified()) { |
| 1931 // Fully replace local_url with Sync's copy. Note that because use Add | 2139 // Fully replace local_url with Sync's copy. Note that because use Add |
| 1932 // rather than ResetTemplateURL, |sync_url| is added with a fresh | 2140 // rather than ResetTemplateURL, |sync_url| is added with a fresh |
| 1933 // TemplateURLID. We don't need to sync the new ID back to the server since | 2141 // TemplateURLID. We don't need to sync the new ID back to the server since |
| 1934 // it's only relevant locally. | 2142 // it's only relevant locally. |
| 1935 bool delete_default = (local_turl == GetDefaultSearchProvider()); | 2143 bool delete_default = (local_turl == GetDefaultSearchProvider()); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1990 i != template_urls->end(); ++i) { | 2198 i != template_urls->end(); ++i) { |
| 1991 TemplateURL* template_url = *i; | 2199 TemplateURL* template_url = *i; |
| 1992 DCHECK(template_url); | 2200 DCHECK(template_url); |
| 1993 // Extension keywords are never synced. | 2201 // Extension keywords are never synced. |
| 1994 // TODO(mpcomplete): If we allow editing extension keywords, then those | 2202 // TODO(mpcomplete): If we allow editing extension keywords, then those |
| 1995 // should be persisted to disk and synced. | 2203 // should be persisted to disk and synced. |
| 1996 if (template_url->sync_guid().empty() && | 2204 if (template_url->sync_guid().empty() && |
| 1997 !template_url->IsExtensionKeyword()) { | 2205 !template_url->IsExtensionKeyword()) { |
| 1998 template_url->data_.sync_guid = guid::GenerateGUID(); | 2206 template_url->data_.sync_guid = guid::GenerateGUID(); |
| 1999 if (service_.get()) | 2207 if (service_.get()) |
| 2000 service_->UpdateKeyword(*template_url); | 2208 service_->UpdateKeyword(template_url->data()); |
| 2001 } | 2209 } |
| 2002 } | 2210 } |
| 2003 } | 2211 } |
| OLD | NEW |