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

Side by Side Diff: chrome/browser/search_engines/template_url_service.cc

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

Powered by Google App Engine
This is Rietveld 408576698