15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/search_engines/template_url_service.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include <algorithm>
8a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include <utility>
9a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/auto_reset.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/environment.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/guid.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/i18n/case_conversion.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/memory/scoped_vector.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/stl_util.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
22868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h"
23868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
24eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "chrome/browser/chrome_notification_types.h"
26ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "chrome/browser/extensions/extension_service.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/google/google_url_tracker.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_notifications.h"
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/history/history_service.h"
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/history/history_service_factory.h"
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h"
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/rlz/rlz.h"
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/search_engines/search_host_to_urls_map.h"
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/search_engines/search_terms_data.h"
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/search_engines/template_url.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/search_engines/template_url_prepopulate_data.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/search_engines/template_url_service_observer.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/search_engines/util.h"
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/webdata/web_data_service.h"
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h"
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/env_vars.h"
42ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "chrome/common/extensions/api/omnibox/omnibox_handler.h"
43558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "chrome/common/net/url_fixer_upper.h"
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/url_constants.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/notification_service.h"
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "extensions/common/constants.h"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/api/sync_change.h"
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/api/sync_error_factory.h"
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/protocol/search_engine_specifics.pb.h"
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sync/protocol/sync.pb.h"
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef SearchHostToURLsMap::TemplateURLSet TemplateURLSet;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef TemplateURLService::SyncDataMap SyncDataMap;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TemplateURLsHaveSamePrefs(const TemplateURL* url1,
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               const TemplateURL* url2) {
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (url1 == url2)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (url1 != NULL) && (url2 != NULL) &&
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (url1->short_name() == url2->short_name()) &&
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url1->HasSameKeywordAs(*url2) &&
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (url1->url() == url2->url()) &&
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (url1->suggestions_url() == url2->suggestions_url()) &&
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (url1->instant_url() == url2->instant_url()) &&
70a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      (url1->image_url() == url2->image_url()) &&
71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      (url1->search_url_post_params() == url2->search_url_post_params()) &&
72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      (url1->suggestions_url_post_params() ==
73a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)          url2->suggestions_url_post_params()) &&
74a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      (url1->instant_url_post_params() == url2->instant_url_post_params()) &&
75a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      (url1->image_url_post_params() == url2->image_url_post_params()) &&
76a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      (url1->image_url() == url2->image_url()) &&
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (url1->favicon_url() == url2->favicon_url()) &&
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (url1->safe_for_autoreplace() == url2->safe_for_autoreplace()) &&
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (url1->show_in_default_list() == url2->show_in_default_list()) &&
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (url1->input_encodings() == url2->input_encodings()) &&
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (url1->alternate_urls() == url2->alternate_urls()) &&
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (url1->search_terms_replacement_key() ==
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          url2->search_terms_replacement_key());
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kFirstPotentialEngineHistogramName[] =
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Search.FirstPotentialEngineCalled";
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Values for an enumerated histogram used to track whenever
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FirstPotentialDefaultEngine is called, and from where.
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum FirstPotentialEngineCaller {
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FIRST_POTENTIAL_CALLSITE_FIND_NEW_DSP,
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FIRST_POTENTIAL_CALLSITE_FIND_NEW_DSP_PROCESSING_SYNC_CHANGES,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FIRST_POTENTIAL_CALLSITE_ON_LOAD,
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FIRST_POTENTIAL_CALLSITE_FIND_NEW_DSP_SYNCING,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FIRST_POTENTIAL_CALLSITE_FIND_NEW_DSP_NOT_SYNCING,
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FIRST_POTENTIAL_CALLSITE_MAX,
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kDeleteSyncedEngineHistogramName[] =
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "Search.DeleteSyncedSearchEngine";
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Values for an enumerated histogram used to track whenever an ACTION_DELETE is
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sent to the server for search engines.
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum DeleteSyncedSearchEngineEvent {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DELETE_ENGINE_USER_ACTION,
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DELETE_ENGINE_PRE_SYNC,
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DELETE_ENGINE_EMPTY_FIELD,
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DELETE_ENGINE_MAX,
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURL* FirstPotentialDefaultEngine(
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TemplateURLService::TemplateURLVector& template_urls) {
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (TemplateURLService::TemplateURLVector::const_iterator i(
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       template_urls.begin()); i != template_urls.end(); ++i) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*i)->ShowInDefaultList()) {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(!(*i)->IsExtensionKeyword());
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return *i;
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true iff the change in |change_list| at index |i| should not be sent
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// up to the server based on its GUIDs presence in |sync_data| or when compared
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to changes after it in |change_list|.
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The criteria is:
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  1) It is an ACTION_UPDATE or ACTION_DELETE and the sync_guid associated
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     with it is NOT found in |sync_data|. We can only update and remove
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     entries that were originally from the Sync server.
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  2) It is an ACTION_ADD and the sync_guid associated with it is found in
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     |sync_data|. We cannot re-add entries that Sync already knew about.
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//  3) There is an update after an update for the same GUID. We prune earlier
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     ones just to save bandwidth (Sync would normally coalesce them).
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ShouldRemoveSyncChange(size_t index,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            syncer::SyncChangeList* change_list,
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const SyncDataMap* sync_data) {
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(index < change_list->size());
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const syncer::SyncChange& change_i = (*change_list)[index];
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string guid = change_i.sync_data().GetSpecifics()
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .search_engine().sync_guid();
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::SyncChange::SyncChangeType type = change_i.change_type();
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((type == syncer::SyncChange::ACTION_UPDATE ||
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       type == syncer::SyncChange::ACTION_DELETE) &&
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       sync_data->find(guid) == sync_data->end())
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == syncer::SyncChange::ACTION_ADD &&
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sync_data->find(guid) != sync_data->end())
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == syncer::SyncChange::ACTION_UPDATE) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t j = index + 1; j < change_list->size(); j++) {
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const syncer::SyncChange& change_j = (*change_list)[j];
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((syncer::SyncChange::ACTION_UPDATE == change_j.change_type()) &&
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (change_j.sync_data().GetSpecifics().search_engine().sync_guid() ==
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              guid))
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Remove SyncChanges that should not be sent to the server from |change_list|.
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This is done to eliminate incorrect SyncChanges added by the merge and
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// conflict resolution logic when it is unsure of whether or not an entry is new
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// from Sync or originally from the local model. This also removes changes that
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// would be otherwise be coalesced by Sync in order to save bandwidth.
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PruneSyncChanges(const SyncDataMap* sync_data,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      syncer::SyncChangeList* change_list) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < change_list->size(); ) {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ShouldRemoveSyncChange(i, change_list, sync_data))
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      change_list->erase(change_list->begin() + i);
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++i;
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Helper class that reports a specific string as the Google base URL.  We use
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this so that code can calculate a TemplateURL's previous search URL after a
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// change to the global base URL.
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class OldBaseURLSearchTermsData : public UIThreadSearchTermsData {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  OldBaseURLSearchTermsData(Profile* profile, const std::string& old_base_url);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~OldBaseURLSearchTermsData();
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual std::string GoogleBaseURLValue() const OVERRIDE;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string old_base_url;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OldBaseURLSearchTermsData::OldBaseURLSearchTermsData(
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile,
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& old_base_url)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : UIThreadSearchTermsData(profile),
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      old_base_url(old_base_url) {
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)OldBaseURLSearchTermsData::~OldBaseURLSearchTermsData() {
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string OldBaseURLSearchTermsData::GoogleBaseURLValue() const {
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return old_base_url;
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if |turl|'s GUID is not found inside |sync_data|. This is to be
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// used in MergeDataAndStartSyncing to differentiate between TemplateURLs from
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Sync and TemplateURLs that were initially local, assuming |sync_data| is the
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |initial_sync_data| parameter.
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsFromSync(const TemplateURL* turl, const SyncDataMap& sync_data) {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !!sync_data.count(turl->sync_guid());
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Log the number of instances of a keyword that exist, with zero or more
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// underscores, which could occur as the result of conflict resolution.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void LogDuplicatesHistogram(
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TemplateURLService::TemplateURLVector& template_urls) {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::map<std::string, int> duplicates;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (TemplateURLService::TemplateURLVector::const_iterator it =
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      template_urls.begin(); it != template_urls.end(); ++it) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string keyword = UTF16ToASCII((*it)->keyword());
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TrimString(keyword, "_", &keyword);
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    duplicates[keyword]++;
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Count the keywords with duplicates.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_dupes = 0;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::map<std::string, int>::const_iterator it = duplicates.begin();
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      it != duplicates.end(); ++it) {
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (it->second > 1)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      num_dupes++;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_COUNTS_100("Search.SearchEngineDuplicateCounts", num_dupes);
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
236ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochtypedef std::vector<TemplateURLService::ExtensionKeyword> ExtensionKeywords;
237ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
238ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#if !defined(OS_ANDROID)
239ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Extract all installed Omnibox Extensions.
240ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochExtensionKeywords GetExtensionKeywords(Profile* profile) {
241ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(profile);
242ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ExtensionService* extension_service = profile->GetExtensionService();
243ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(extension_service);
244ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  const ExtensionSet* extensions = extension_service->extensions();
245ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  ExtensionKeywords extension_keywords;
246ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  for (ExtensionSet::const_iterator it = extensions->begin();
247ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch       it != extensions->end(); ++it) {
248ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::string& keyword = extensions::OmniboxInfo::GetKeyword(*it);
249ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    if (!keyword.empty()) {
250ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      extension_keywords.push_back(TemplateURLService::ExtensionKeyword(
251ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch          (*it)->id(), (*it)->name(), keyword));
252ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    }
253ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
254ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return extension_keywords;
255ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
256ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#else
257ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Extensions are not supported.
258ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochExtensionKeywords GetExtensionKeywords(Profile* profile) {
259ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return ExtensionKeywords();
260ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
261ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#endif
262ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
266ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// TemplateURLService::ExtensionKeyword ---------------------------------------
267ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
268ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTemplateURLService::ExtensionKeyword::ExtensionKeyword(
269ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::string& id,
270ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::string& name,
271ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const std::string& keyword)
272ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    : extension_id(id),
273ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      extension_name(name),
274ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      extension_keyword(keyword) {
275ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
276ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
277ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTemplateURLService::ExtensionKeyword::~ExtensionKeyword() {}
278ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
279ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
280ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// TemplateURLService::LessWithPrefix -----------------------------------------
281ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TemplateURLService::LessWithPrefix {
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We want to find the set of keywords that begin with a prefix.  The STL
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // algorithms will return the set of elements that are "equal to" the
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // prefix, where "equal(x, y)" means "!(cmp(x, y) || cmp(y, x))".  When
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // cmp() is the typical std::less<>, this results in lexicographic equality;
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we need to extend this to mark a prefix as "not less than" a keyword it
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // begins, which will cause the desired elements to be considered "equal to"
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the prefix.  Note: this is still a strict weak ordering, as required by
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // equal_range() (though I will not prove that here).
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Unfortunately the calling convention is not "prefix and element" but
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // rather "two elements", so we pass the prefix as a fake "element" which has
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a NULL KeywordDataElement pointer.
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool operator()(const KeywordToTemplateMap::value_type& elem1,
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  const KeywordToTemplateMap::value_type& elem2) const {
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (elem1.second == NULL) ?
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (elem2.first.compare(0, elem1.first.length(), elem1.first) > 0) :
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (elem1.first < elem2.first);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
304ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
305ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// TemplateURLService ---------------------------------------------------------
306ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURLService::TemplateURLService(Profile* profile)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : provider_map_(new SearchHostToURLsMap),
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_(profile),
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      loaded_(false),
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      load_failed_(false),
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      load_handle_(0),
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default_search_provider_(NULL),
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_default_search_managed_(false),
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_id_(kInvalidTemplateURLID + 1),
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      time_provider_(&base::Time::Now),
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      models_associated_(false),
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      processing_syncer_changes_(false),
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_synced_default_search_(false),
3207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      dsp_change_origin_(DSP_CHANGE_OTHER) {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(profile_);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Init(NULL, 0);
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURLService::TemplateURLService(const Initializer* initializers,
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       const int count)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : provider_map_(new SearchHostToURLsMap),
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      profile_(NULL),
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      loaded_(false),
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      load_failed_(false),
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      load_handle_(0),
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service_(NULL),
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default_search_provider_(NULL),
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_default_search_managed_(false),
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      next_id_(kInvalidTemplateURLID + 1),
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      time_provider_(&base::Time::Now),
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      models_associated_(false),
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      processing_syncer_changes_(false),
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_synced_default_search_(false),
3407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      dsp_change_origin_(DSP_CHANGE_OTHER) {
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Init(initializers, count);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURLService::~TemplateURLService() {
345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (service_.get())
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Shutdown();
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  STLDeleteElements(&template_urls_);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 TemplateURLService::GenerateKeyword(const GURL& url) {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(url.is_valid());
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Strip "www." off the front of the keyword; otherwise the keyword won't work
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // properly.  See http://code.google.com/p/chromium/issues/detail?id=6984 .
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Special case: if the host was exactly "www." (not sure this can happen but
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // perhaps with some weird intranet and custom DNS server?), ensure we at
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // least don't return the empty string.
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string16 keyword(net::StripWWWFromHost(url));
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return keyword.empty() ? ASCIIToUTF16("www") : keyword;
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 TemplateURLService::CleanUserInputKeyword(const string16& keyword) {
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove the scheme.
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string16 result(base::i18n::ToLower(keyword));
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TrimWhitespace(result, TRIM_ALL, &result);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_parse::Component scheme_component;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (url_parse::ExtractScheme(UTF16ToUTF8(keyword).c_str(),
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               static_cast<int>(keyword.length()),
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               &scheme_component)) {
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the scheme isn't "http" or "https", bail.  The user isn't trying to
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // type a web address, but rather an FTP, file:, or other scheme URL, or a
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // search query with some sort of initial operator (e.g. "site:").
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result.compare(0, scheme_component.end(),
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       ASCIIToUTF16(chrome::kHttpScheme)) &&
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        result.compare(0, scheme_component.end(),
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       ASCIIToUTF16(chrome::kHttpsScheme)))
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return string16();
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Include trailing ':'.
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.erase(0, scheme_component.end() + 1);
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Many schemes usually have "//" after them, so strip it too.
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string16 after_scheme(ASCIIToUTF16("//"));
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (result.compare(0, after_scheme.length(), after_scheme) == 0)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result.erase(0, after_scheme.length());
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove leading "www.".
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result = net::StripWWW(result);
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove trailing "/".
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (result.length() > 0 && result[result.length() - 1] == '/') ?
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      result.substr(0, result.length() - 1) : result;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL TemplateURLService::GenerateSearchURL(TemplateURL* t_url) {
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(t_url);
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UIThreadSearchTermsData search_terms_data(t_url->profile());
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GenerateSearchURLUsingTermsData(t_url, search_terms_data);
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL TemplateURLService::GenerateSearchURLUsingTermsData(
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TemplateURL* t_url,
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SearchTermsData& search_terms_data) {
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(t_url);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const TemplateURLRef& search_ref = t_url->url_ref();
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!search_ref.IsValidUsingTermsData(search_terms_data))
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GURL();
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!search_ref.SupportsReplacementUsingTermsData(search_terms_data))
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return GURL(t_url->url());
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
416f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles)  // Use something obscure for the search terms argument so that in the rare
417f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles)  // case the term replaces the URL it's unlikely another keyword would have the
418f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles)  // same url.
419f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles)  // TODO(jnd): Add additional parameters to get post data when the search URL
4207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  // has post parameters.
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GURL(search_ref.ReplaceSearchTermsUsingTermsData(
422f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles)      TemplateURLRef::SearchTermsArgs(ASCIIToUTF16("blah.blah.blah.blah.blah")),
423f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles)      search_terms_data, NULL));
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TemplateURLService::CanReplaceKeyword(
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string16& keyword,
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& url,
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL** template_url_to_replace) {
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!keyword.empty());  // This should only be called for non-empty
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             // keywords. If we need to support empty kewords
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             // the code needs to change slightly.
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TemplateURL* existing_url = GetTemplateURLForKeyword(keyword);
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (template_url_to_replace)
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *template_url_to_replace = existing_url;
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (existing_url) {
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We already have a TemplateURL for this keyword. Only allow it to be
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // replaced if the TemplateURL can be replaced.
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return CanReplace(existing_url);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We don't have a TemplateURL with keyword. Only allow a new one if there
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // isn't a TemplateURL for the specified host, or there is one but it can
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be replaced. We do this to ensure that if the user assigns a different
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // keyword to a generated TemplateURL, we won't regenerate another keyword for
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the same host.
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !url.is_valid() || url.host().empty() ||
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CanReplaceKeywordForHost(url.host(), template_url_to_replace);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::FindMatchingKeywords(
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string16& prefix,
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool support_replacement_only,
454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    TemplateURLVector* matches) const {
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sanity check args.
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (prefix.empty())
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(matches != NULL);
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(matches->empty());  // The code for exact matches assumes this.
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Required for VS2010: http://connect.microsoft.com/VisualStudio/feedback/details/520043/error-converting-from-null-to-a-pointer-type-in-std-pair
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TemplateURL* const kNullTemplateURL = NULL;
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Find matching keyword range.  Searches the element map for keywords
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // beginning with |prefix| and stores the endpoints of the resulting set in
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |match_range|.
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::pair<KeywordToTemplateMap::const_iterator,
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  KeywordToTemplateMap::const_iterator> match_range(
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::equal_range(
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          keyword_to_template_map_.begin(), keyword_to_template_map_.end(),
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          KeywordToTemplateMap::value_type(prefix, kNullTemplateURL),
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          LessWithPrefix()));
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return vector of matching keywords.
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (KeywordToTemplateMap::const_iterator i(match_range.first);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != match_range.second; ++i) {
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!support_replacement_only || i->second->url_ref().SupportsReplacement())
478eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      matches->push_back(i->second);
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURL* TemplateURLService::GetTemplateURLForKeyword(
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string16& keyword) {
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  KeywordToTemplateMap::const_iterator elem(
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      keyword_to_template_map_.find(keyword));
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (elem != keyword_to_template_map_.end())
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return elem->second;
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ((!loaded_ || load_failed_) &&
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      initial_default_search_provider_.get() &&
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (initial_default_search_provider_->keyword() == keyword)) ?
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      initial_default_search_provider_.get() : NULL;
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURL* TemplateURLService::GetTemplateURLForGUID(
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& sync_guid) {
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GUIDToTemplateMap::const_iterator elem(guid_to_template_map_.find(sync_guid));
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (elem != guid_to_template_map_.end())
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return elem->second;
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ((!loaded_ || load_failed_) &&
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      initial_default_search_provider_.get() &&
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (initial_default_search_provider_->sync_guid() == sync_guid)) ?
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      initial_default_search_provider_.get() : NULL;
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURL* TemplateURLService::GetTemplateURLForHost(
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& host) {
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (loaded_) {
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL* t_url = provider_map_->GetTemplateURLForHost(host);
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (t_url)
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return t_url;
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ((!loaded_ || load_failed_) &&
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      initial_default_search_provider_.get() &&
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      (GenerateSearchURL(initial_default_search_provider_.get()).host() ==
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          host)) ? initial_default_search_provider_.get() : NULL;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::Add(TemplateURL* template_url) {
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (AddNoNotify(template_url, true))
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyObservers();
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::AddAndSetProfile(TemplateURL* template_url,
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          Profile* profile) {
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template_url->profile_ = profile;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Add(template_url);
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::AddWithOverrides(TemplateURL* template_url,
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const string16& short_name,
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const string16& keyword,
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const std::string& url) {
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!keyword.empty());
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!url.empty());
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template_url->data_.short_name = short_name;
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template_url->data_.SetKeyword(keyword);
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template_url->SetURL(url);
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Add(template_url);
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::Remove(TemplateURL* template_url) {
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RemoveNoNotify(template_url);
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotifyObservers();
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::RemoveAutoGeneratedSince(base::Time created_after) {
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RemoveAutoGeneratedBetween(created_after, base::Time());
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::RemoveAutoGeneratedBetween(base::Time created_after,
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                    base::Time created_before) {
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RemoveAutoGeneratedForOriginBetween(GURL(), created_after, created_before);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::RemoveAutoGeneratedForOriginBetween(
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& origin,
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Time created_after,
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::Time created_before) {
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL o(origin.GetOrigin());
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool should_notify = false;
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < template_urls_.size();) {
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (template_urls_[i]->date_created() >= created_after &&
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (created_before.is_null() ||
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         template_urls_[i]->date_created() < created_before) &&
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CanReplace(template_urls_[i]) &&
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (o.is_empty() ||
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         GenerateSearchURL(template_urls_[i]).GetOrigin() == o)) {
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RemoveNoNotify(template_urls_[i]);
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      should_notify = true;
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++i;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (should_notify)
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyObservers();
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::RegisterExtensionKeyword(
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& extension_id,
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& extension_name,
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& keyword) {
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(loaded_);
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!GetTemplateURLForExtension(extension_id)) {
586ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    ExtensionKeyword extension_url(extension_id, extension_name, keyword);
587ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    Add(CreateTemplateURLForExtension(extension_url));
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::UnregisterExtensionKeyword(
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& extension_id) {
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(loaded_);
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TemplateURL* url = GetTemplateURLForExtension(extension_id);
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (url)
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Remove(url);
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURL* TemplateURLService::GetTemplateURLForExtension(
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& extension_id) {
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (TemplateURLVector::const_iterator i = template_urls_.begin();
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != template_urls_.end(); ++i) {
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*i)->IsExtensionKeyword() &&
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        ((*i)->url_ref().GetHost() == extension_id))
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return *i;
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURLService::TemplateURLVector TemplateURLService::GetTemplateURLs() {
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return template_urls_;
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::IncrementUsageCount(TemplateURL* url) {
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(url);
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (std::find(template_urls_.begin(), template_urls_.end(), url) ==
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      template_urls_.end())
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++url->data_.usage_count;
621868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (service_.get())
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_.get()->UpdateKeyword(url->data());
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::ResetTemplateURL(TemplateURL* url,
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const string16& title,
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const string16& keyword,
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          const std::string& search_url) {
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!loaded_)
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!keyword.empty());
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!search_url.empty());
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TemplateURLData data(url->data());
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.short_name = title;
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.SetKeyword(keyword);
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (search_url != data.url()) {
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data.SetURL(search_url);
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The urls have changed, reset the favicon url.
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data.favicon_url = GURL();
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.safe_for_autoreplace = false;
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.last_modified = time_provider_();
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TemplateURL new_url(url->profile(), data);
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UIThreadSearchTermsData search_terms_data(url->profile());
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (UpdateNoNotify(url, new_url, search_terms_data))
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyObservers();
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TemplateURLService::CanMakeDefault(const TemplateURL* url) {
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return url != GetDefaultSearchProvider() &&
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      url->url_ref().SupportsReplacement() && !is_default_search_managed();
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::SetDefaultSearchProvider(TemplateURL* url) {
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!is_default_search_managed_);
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Extension keywords cannot be made default, as they are inherently async.
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!url || !url->IsExtensionKeyword());
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Always persist the setting in the database, that way if the backup
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // signature has changed out from under us it gets reset correctly.
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (SetDefaultSearchProviderNoNotify(url))
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyObservers();
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURL* TemplateURLService::GetDefaultSearchProvider() {
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (loaded_ && !load_failed_)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return default_search_provider_;
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We're not loaded, rely on the default search provider stored in prefs.
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return initial_default_search_provider_.get();
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6724311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdochbool TemplateURLService::IsSearchResultsPageFromDefaultSearchProvider(
6734311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch    const GURL& url) {
6744311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  TemplateURL* default_provider = GetDefaultSearchProvider();
6754311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch  return default_provider && default_provider->IsSearchURL(url);
6764311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch}
6774311e82a78ceafbe0585f51d4c8a86df9f21aa0dBen Murdoch
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURL* TemplateURLService::FindNewDefaultSearchProvider() {
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // See if the prepopulated default still exists.
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<TemplateURL> prepopulated_default(
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(profile_));
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (TemplateURLVector::iterator i = template_urls_.begin();
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != template_urls_.end(); ++i) {
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*i)->prepopulate_id() == prepopulated_default->prepopulate_id())
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return *i;
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If not, use the first non-extension keyword of the templates that supports
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // search term replacement.
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (processing_syncer_changes_) {
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION(
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kFirstPotentialEngineHistogramName,
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FIRST_POTENTIAL_CALLSITE_FIND_NEW_DSP_PROCESSING_SYNC_CHANGES,
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FIRST_POTENTIAL_CALLSITE_MAX);
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sync_processor_.get()) {
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We're not currently in a sync cycle, but we're syncing.
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_ENUMERATION(kFirstPotentialEngineHistogramName,
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                FIRST_POTENTIAL_CALLSITE_FIND_NEW_DSP_SYNCING,
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                FIRST_POTENTIAL_CALLSITE_MAX);
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We're not syncing at all.
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_ENUMERATION(
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          kFirstPotentialEngineHistogramName,
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FIRST_POTENTIAL_CALLSITE_FIND_NEW_DSP_NOT_SYNCING,
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FIRST_POTENTIAL_CALLSITE_MAX);
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return FirstPotentialDefaultEngine(template_urls_);
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
711ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid TemplateURLService::ResetURLs() {
712868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Can't clean DB if it hasn't been loaded.
713868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(loaded());
714ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  DCHECK(service_);
715868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ClearDefaultProviderFromPrefs();
716868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
717ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  TemplateURLVector entries_to_process = template_urls_;
718868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Clear default provider to be able to delete it.
719868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  default_search_provider_ = NULL;
720868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  for (TemplateURLVector::const_iterator i = entries_to_process.begin();
721868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)       i != entries_to_process.end(); ++i)
722868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    RemoveNoNotify(*i);
723868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
724868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  entries_to_process.clear();
725868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  provider_map_.reset(new SearchHostToURLsMap);
726868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  UIThreadSearchTermsData search_terms_data(profile_);
727868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  provider_map_->Init(TemplateURLVector(), search_terms_data);
728868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
729868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TemplateURL* default_search_provider = NULL;
730868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Force GetSearchProvidersUsingLoadedEngines() to include the prepopulated
731868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // engines in the list by claiming we are currently on version 0, ensuring
732868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // that the prepopulate data version will be newer.
733868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int new_resource_keyword_version = 0;
734868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  GetSearchProvidersUsingLoadedEngines(service_.get(), profile_,
735868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                       &entries_to_process,
736868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                       &default_search_provider,
737868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                       &new_resource_keyword_version,
738868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                       &pre_sync_deletes_);
739868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Setup search engines and a default one.
7407dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  base::AutoReset<DefaultSearchChangeOrigin> change_origin(
7417dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      &dsp_change_origin_, DSP_CHANGE_PROFILE_RESET);
742868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddTemplateURLsAndSetupDefaultEngine(&entries_to_process,
743868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                       default_search_provider);
744868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
745ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // Repopulate extension keywords.
746ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  std::vector<ExtensionKeyword> extension_keywords =
747ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      GetExtensionKeywords(profile());
748ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  for (size_t i = 0; i < extension_keywords.size(); ++i) {
749ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    TemplateURL* extension_url =
750ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch        CreateTemplateURLForExtension(extension_keywords[i]);
751ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    AddNoNotify(extension_url, true);
752ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  }
753ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
754868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (new_resource_keyword_version)
755868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    service_->SetBuiltinKeywordVersion(new_resource_keyword_version);
756868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
757868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EnsureDefaultSearchProviderExists();
758868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  NotifyObservers();
759868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
760868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::AddObserver(TemplateURLServiceObserver* observer) {
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  model_observers_.AddObserver(observer);
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::RemoveObserver(TemplateURLServiceObserver* observer) {
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  model_observers_.RemoveObserver(observer);
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::Load() {
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (loaded_ || load_handle_)
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!service_.get()) {
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    service_ = WebDataService::FromBrowserContext(profile_);
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service_.get()) {
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    load_handle_ = service_->GetKeywords(this);
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ChangeToLoadedState();
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyLoaded();
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::OnWebDataServiceRequestDone(
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WebDataService::Handle h,
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const WDTypedResult* result) {
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Reset the load_handle so that we don't try and cancel the load in
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the destructor.
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  load_handle_ = 0;
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!result) {
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Results are null if the database went away or (most likely) wasn't
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // loaded.
7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    load_failed_ = true;
7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ChangeToLoadedState();
7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyLoaded();
7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // initial_default_search_provider_ is only needed before we've finished
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // loading. Now that we've loaded we can nuke it.
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  initial_default_search_provider_.reset();
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TemplateURLVector template_urls;
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TemplateURL* default_search_provider = NULL;
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int new_resource_keyword_version = 0;
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetSearchProvidersUsingKeywordResult(*result, service_.get(), profile_,
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &template_urls, &default_search_provider, &new_resource_keyword_version,
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &pre_sync_deletes_);
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
812868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  AddTemplateURLsAndSetupDefaultEngine(&template_urls, default_search_provider);
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This initializes provider_map_ which should be done before
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // calling UpdateKeywordSearchTermsForURL.
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ChangeToLoadedState();
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Index any visits that occurred before we finished loading.
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < visits_to_add_.size(); ++i)
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateKeywordSearchTermsForURL(visits_to_add_[i]);
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  visits_to_add_.clear();
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_resource_keyword_version)
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_->SetBuiltinKeywordVersion(new_resource_keyword_version);
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
826868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EnsureDefaultSearchProviderExists();
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotifyObservers();
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotifyLoaded();
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 TemplateURLService::GetKeywordShortName(const string16& keyword,
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 bool* is_extension_keyword) {
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const TemplateURL* template_url = GetTemplateURLForKeyword(keyword);
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(sky): Once LocationBarView adds a listener to the TemplateURLService
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to track changes to the model, this should become a DCHECK.
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (template_url) {
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *is_extension_keyword = template_url->IsExtensionKeyword();
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return template_url->AdjustedShortNameForLocaleDirection();
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *is_extension_keyword = false;
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return string16();
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::Observe(int type,
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const content::NotificationSource& source,
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 const content::NotificationDetails& details) {
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type == chrome::NOTIFICATION_HISTORY_URL_VISITED) {
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::Details<history::URLVisitedDetails> visit_details(details);
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!loaded_)
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      visits_to_add_.push_back(*visit_details.ptr());
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateKeywordSearchTermsForURL(*visit_details.ptr());
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (type == chrome::NOTIFICATION_DEFAULT_SEARCH_POLICY_CHANGED) {
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Policy has been updated, so the default search prefs may be different.
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Reload the default search provider from them.
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(pkasting): Rather than communicating via prefs, we should eventually
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // observe policy changes directly.
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UpdateDefaultSearch();
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (type == chrome::NOTIFICATION_GOOGLE_URL_UPDATED) {
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (loaded_) {
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GoogleBaseURLChanged(
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::Details<GoogleURLTracker::UpdatedDetails>(details)->first);
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
871c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void TemplateURLService::Shutdown() {
872c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // This check has to be done at Shutdown() instead of in the dtor to ensure
873c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // that no clients of WebDataService are holding ptrs to it after the first
87490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  // phase of the BrowserContextKeyedService Shutdown() process.
875c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (load_handle_) {
876c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DCHECK(service_.get());
877c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    service_->CancelRequest(load_handle_);
878c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
879c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  service_ = NULL;
880c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
881c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TemplateURLService::OnSyncedDefaultSearchProviderGUIDChanged() {
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Listen for changes to the default search from Sync.
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrefService* prefs = GetPrefs();
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TemplateURL* new_default_search = GetTemplateURLForGUID(
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prefs->GetString(prefs::kSyncedDefaultSearchProviderGUID));
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (new_default_search && !is_default_search_managed_) {
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (new_default_search != GetDefaultSearchProvider()) {
8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::AutoReset<DefaultSearchChangeOrigin> change_origin(
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &dsp_change_origin_, DSP_CHANGE_SYNC_PREF);
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetDefaultSearchProvider(new_default_search);
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_synced_default_search_ = false;
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If it's not there, or if default search is currently managed, set a
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // flag to indicate that we waiting on the search engine entry to come
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // in through Sync.
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_synced_default_search_ = true;
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateDefaultSearch();
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)syncer::SyncDataList TemplateURLService::GetAllSyncData(
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::ModelType type) const {
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(syncer::SEARCH_ENGINES, type);
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::SyncDataList current_data;
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (TemplateURLVector::const_iterator iter = template_urls_.begin();
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iter != template_urls_.end(); ++iter) {
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We don't sync keywords managed by policy.
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((*iter)->created_by_policy())
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    current_data.push_back(CreateSyncDataFromTemplateURL(**iter));
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return current_data;
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)syncer::SyncError TemplateURLService::ProcessSyncChanges(
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const tracked_objects::Location& from_here,
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const syncer::SyncChangeList& change_list) {
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!models_associated_) {
923eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    syncer::SyncError error(FROM_HERE,
924eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            syncer::SyncError::DATATYPE_ERROR,
925eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            "Models not yet associated.",
926eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch                            syncer::SEARCH_ENGINES);
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return error;
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(loaded_);
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AutoReset<bool> processing_changes(&processing_syncer_changes_, true);
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We've started syncing, so set our origin member to the base Sync value.
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // As we move through Sync Code, we may set this to increasingly specific
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // origins so we can tell what exactly caused a DSP change.
9362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AutoReset<DefaultSearchChangeOrigin> change_origin(&dsp_change_origin_,
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DSP_CHANGE_SYNC_UNINTENTIONAL);
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::SyncChangeList new_changes;
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::SyncError error;
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (syncer::SyncChangeList::const_iterator iter = change_list.begin();
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iter != change_list.end(); ++iter) {
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(syncer::SEARCH_ENGINES, iter->sync_data().GetDataType());
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string guid =
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        iter->sync_data().GetSpecifics().search_engine().sync_guid();
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL* existing_turl = GetTemplateURLForGUID(guid);
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<TemplateURL> turl(CreateTemplateURLFromTemplateURLAndSyncData(
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        profile_, existing_turl, iter->sync_data(), &new_changes));
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!turl.get())
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Explicitly don't check for conflicts against extension keywords; in this
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // case the functions which modify the keyword map know how to handle the
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // conflicts.
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(mpcomplete): If we allow editing extension keywords, then those will
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // need to undergo conflict resolution.
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL* existing_keyword_turl =
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        FindNonExtensionTemplateURLForKeyword(turl->keyword());
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (iter->change_type() == syncer::SyncChange::ACTION_DELETE) {
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!existing_turl) {
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED() << "Unexpected sync change state.";
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        error = sync_error_factory_->CreateAndUploadError(
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            FROM_HERE,
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "ProcessSyncChanges failed on ChangeType ACTION_DELETE");
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(ERROR) << "Trying to delete a non-existent TemplateURL.";
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (existing_turl == GetDefaultSearchProvider()) {
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The only way Sync can attempt to delete the default search provider
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // is if we had changed the kSyncedDefaultSearchProviderGUID
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // preference, but perhaps it has not yet been received. To avoid
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // situations where this has come in erroneously, we will un-delete
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // the current default search from the Sync data. If the pref really
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // does arrive later, then default search will change to the correct
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // entry, but we'll have this extra entry sitting around. The result is
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // not ideal, but it prevents a far more severe bug where the default is
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // unexpectedly swapped to something else. The user can safely delete
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // the extra entry again later, if they choose. Most users who do not
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // look at the search engines UI will not notice this.
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Note that we append a special character to the end of the keyword in
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // an attempt to avoid a ping-poinging situation where receiving clients
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // may try to continually delete the resurrected entry.
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        string16 updated_keyword = UniquifyKeyword(*existing_turl, true);
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TemplateURLData data(existing_turl->data());
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data.SetKeyword(updated_keyword);
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TemplateURL new_turl(existing_turl->profile(), data);
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UIThreadSearchTermsData search_terms_data(existing_turl->profile());
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (UpdateNoNotify(existing_turl, new_turl, search_terms_data))
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NotifyObservers();
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        syncer::SyncData sync_data = CreateSyncDataFromTemplateURL(new_turl);
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new_changes.push_back(syncer::SyncChange(FROM_HERE,
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 syncer::SyncChange::ACTION_ADD,
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 sync_data));
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Ignore the delete attempt. This means we never end up reseting the
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // default search provider due to an ACTION_DELETE from sync.
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Remove(existing_turl);
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (iter->change_type() == syncer::SyncChange::ACTION_ADD) {
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (existing_turl) {
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED() << "Unexpected sync change state.";
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        error = sync_error_factory_->CreateAndUploadError(
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            FROM_HERE,
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "ProcessSyncChanges failed on ChangeType ACTION_ADD");
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(ERROR) << "Trying to add an existing TemplateURL.";
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string guid = turl->sync_guid();
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (existing_keyword_turl) {
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Resolve any conflicts so we can safely add the new entry.
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ResolveSyncKeywordConflict(turl.get(), existing_keyword_turl,
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   &new_changes);
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Force the local ID to kInvalidTemplateURLID so we can add it.
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TemplateURLData data(turl->data());
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data.id = kInvalidTemplateURLID;
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Add(new TemplateURL(profile_, data));
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Possibly set the newly added |turl| as the default search provider.
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetDefaultSearchProviderIfNewlySynced(guid);
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (iter->change_type() == syncer::SyncChange::ACTION_UPDATE) {
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!existing_turl) {
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED() << "Unexpected sync change state.";
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        error = sync_error_factory_->CreateAndUploadError(
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            FROM_HERE,
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            "ProcessSyncChanges failed on ChangeType ACTION_UPDATE");
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        LOG(ERROR) << "Trying to update a non-existent TemplateURL.";
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (existing_keyword_turl && (existing_keyword_turl != existing_turl)) {
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Resolve any conflicts with other entries so we can safely update the
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // keyword.
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ResolveSyncKeywordConflict(turl.get(), existing_keyword_turl,
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   &new_changes);
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UIThreadSearchTermsData search_terms_data(existing_turl->profile());
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (UpdateNoNotify(existing_turl, *turl, search_terms_data))
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NotifyObservers();
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We've unexpectedly received an ACTION_INVALID.
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED() << "Unexpected sync change state.";
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      error = sync_error_factory_->CreateAndUploadError(
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          FROM_HERE,
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          "ProcessSyncChanges received an ACTION_INVALID");
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If something went wrong, we want to prematurely exit to avoid pushing
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // inconsistent data to Sync. We return the last error we received.
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (error.IsSet())
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return error;
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  error = sync_processor_->ProcessSyncChanges(from_here, new_changes);
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return error;
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)syncer::SyncMergeResult TemplateURLService::MergeDataAndStartSyncing(
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::ModelType type,
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const syncer::SyncDataList& initial_sync_data,
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<syncer::SyncChangeProcessor> sync_processor,
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<syncer::SyncErrorFactory> sync_error_factory) {
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(loaded_);
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(type, syncer::SEARCH_ENGINES);
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!sync_processor_.get());
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(sync_processor.get());
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(sync_error_factory.get());
10712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  syncer::SyncMergeResult merge_result(type);
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_processor_ = sync_processor.Pass();
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_error_factory_ = sync_error_factory.Pass();
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We just started syncing, so set our wait-for-default flag if we are
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // expecting a default from Sync.
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetPrefs()) {
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string default_guid = GetPrefs()->GetString(
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        prefs::kSyncedDefaultSearchProviderGUID);
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TemplateURL* current_default = GetDefaultSearchProvider();
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!default_guid.empty() &&
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (!current_default || current_default->sync_guid() != default_guid))
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      pending_synced_default_search_ = true;
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We do a lot of calls to Add/Remove/ResetTemplateURL here, so ensure we
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // don't step on our own toes.
10892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AutoReset<bool> processing_changes(&processing_syncer_changes_, true);
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We've started syncing, so set our origin member to the base Sync value.
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // As we move through Sync Code, we may set this to increasingly specific
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // origins so we can tell what exactly caused a DSP change.
10942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::AutoReset<DefaultSearchChangeOrigin> change_origin(&dsp_change_origin_,
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DSP_CHANGE_SYNC_UNINTENTIONAL);
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::SyncChangeList new_changes;
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Build maps of our sync GUIDs to syncer::SyncData.
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyncDataMap local_data_map = CreateGUIDToSyncDataMap(
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetAllSyncData(syncer::SEARCH_ENGINES));
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyncDataMap sync_data_map = CreateGUIDToSyncDataMap(initial_sync_data);
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  merge_result.set_num_items_before_association(local_data_map.size());
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (SyncDataMap::const_iterator iter = sync_data_map.begin();
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iter != sync_data_map.end(); ++iter) {
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL* local_turl = GetTemplateURLForGUID(iter->first);
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<TemplateURL> sync_turl(
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        CreateTemplateURLFromTemplateURLAndSyncData(profile_, local_turl,
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            iter->second, &new_changes));
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!sync_turl.get())
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (pre_sync_deletes_.find(sync_turl->sync_guid()) !=
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        pre_sync_deletes_.end()) {
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This entry was deleted before the initial sync began (possibly through
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // preprocessing in TemplateURLService's loading code). Ignore it and send
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // an ACTION_DELETE up to the server.
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_changes.push_back(
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          syncer::SyncChange(FROM_HERE,
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             syncer::SyncChange::ACTION_DELETE,
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             iter->second));
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UMA_HISTOGRAM_ENUMERATION(kDeleteSyncedEngineHistogramName,
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          DELETE_ENGINE_PRE_SYNC, DELETE_ENGINE_MAX);
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (local_turl) {
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(IsFromSync(local_turl, sync_data_map));
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This local search engine is already synced. If the timestamp differs
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // from Sync, we need to update locally or to the cloud. Note that if the
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // timestamps are equal, we touch neither.
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (sync_turl->last_modified() > local_turl->last_modified()) {
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We've received an update from Sync. We should replace all synced
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // fields in the local TemplateURL. Note that this includes the
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // TemplateURLID and the TemplateURL may have to be reparsed. This
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // also makes the local data's last_modified timestamp equal to Sync's,
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // avoiding an Update on the next MergeData call.
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        UIThreadSearchTermsData search_terms_data(local_turl->profile());
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (UpdateNoNotify(local_turl, *sync_turl, search_terms_data))
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          NotifyObservers();
11422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        merge_result.set_num_items_modified(
11432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            merge_result.num_items_modified() + 1);
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (sync_turl->last_modified() < local_turl->last_modified()) {
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Otherwise, we know we have newer data, so update Sync with our
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // data fields.
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new_changes.push_back(
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            syncer::SyncChange(FROM_HERE,
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               syncer::SyncChange::ACTION_UPDATE,
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               local_data_map[local_turl->sync_guid()]));
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      local_data_map.erase(iter->first);
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The search engine from the cloud has not been synced locally. Merge it
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // into our local model. This will handle any conflicts with local (and
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // already-synced) TemplateURLs. It will prefer to keep entries from Sync
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // over not-yet-synced TemplateURLs.
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MergeInSyncTemplateURL(sync_turl.get(), sync_data_map, &new_changes,
11592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             &local_data_map, &merge_result);
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If there is a pending synced default search provider that was processed
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // above, set it now.
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TemplateURL* pending_default = GetPendingSyncedDefaultSearchProvider();
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pending_default) {
11672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::AutoReset<DefaultSearchChangeOrigin> change_origin(
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        &dsp_change_origin_, DSP_CHANGE_SYNC_ADD);
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SetDefaultSearchProvider(pending_default);
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The remaining SyncData in local_data_map should be everything that needs to
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be pushed as ADDs to sync.
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (SyncDataMap::const_iterator iter = local_data_map.begin();
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iter != local_data_map.end(); ++iter) {
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_changes.push_back(
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        syncer::SyncChange(FROM_HERE,
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           syncer::SyncChange::ACTION_ADD,
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           iter->second));
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Do some post-processing on the change list to ensure that we are sending
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // valid changes to sync_processor_.
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PruneSyncChanges(&sync_data_map, &new_changes);
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LogDuplicatesHistogram(GetTemplateURLs());
11872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  merge_result.set_num_items_after_association(
11882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetAllSyncData(syncer::SEARCH_ENGINES).size());
11892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  merge_result.set_error(
11902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      sync_processor_->ProcessSyncChanges(FROM_HERE, new_changes));
11912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (merge_result.error().IsSet())
11922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return merge_result;
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The ACTION_DELETEs from this set are processed. Empty it so we don't try to
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // reuse them on the next call to MergeDataAndStartSyncing.
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pre_sync_deletes_.clear();
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  models_associated_ = true;
11992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return merge_result;
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::StopSyncing(syncer::ModelType type) {
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(type, syncer::SEARCH_ENGINES);
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  models_associated_ = false;
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_processor_.reset();
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_error_factory_.reset();
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::ProcessTemplateURLChange(
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const tracked_objects::Location& from_here,
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TemplateURL* turl,
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::SyncChange::SyncChangeType type) {
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(type, syncer::SyncChange::ACTION_INVALID);
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(turl);
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!models_associated_)
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Not syncing.
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (processing_syncer_changes_)
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // These are changes originating from us. Ignore.
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Avoid syncing keywords managed by policy.
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (turl->created_by_policy())
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::SyncChangeList changes;
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::SyncData sync_data = CreateSyncDataFromTemplateURL(*turl);
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  changes.push_back(syncer::SyncChange(from_here,
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       type,
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       sync_data));
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_processor_->ProcessSyncChanges(FROM_HERE, changes);
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)syncer::SyncData TemplateURLService::CreateSyncDataFromTemplateURL(
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TemplateURL& turl) {
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_pb::EntitySpecifics specifics;
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_pb::SearchEngineSpecifics* se_specifics =
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      specifics.mutable_search_engine();
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  se_specifics->set_short_name(UTF16ToUTF8(turl.short_name()));
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  se_specifics->set_keyword(UTF16ToUTF8(turl.keyword()));
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  se_specifics->set_favicon_url(turl.favicon_url().spec());
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  se_specifics->set_url(turl.url());
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  se_specifics->set_safe_for_autoreplace(turl.safe_for_autoreplace());
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  se_specifics->set_originating_url(turl.originating_url().spec());
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  se_specifics->set_date_created(turl.date_created().ToInternalValue());
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  se_specifics->set_input_encodings(JoinString(turl.input_encodings(), ';'));
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  se_specifics->set_show_in_default_list(turl.show_in_default_list());
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  se_specifics->set_suggestions_url(turl.suggestions_url());
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  se_specifics->set_prepopulate_id(turl.prepopulate_id());
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  se_specifics->set_instant_url(turl.instant_url());
1254a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!turl.image_url().empty())
1255a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    se_specifics->set_image_url(turl.image_url());
1256a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!turl.search_url_post_params().empty())
1257a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    se_specifics->set_search_url_post_params(turl.search_url_post_params());
1258a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!turl.suggestions_url_post_params().empty()) {
1259a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    se_specifics->set_suggestions_url_post_params(
1260a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)        turl.suggestions_url_post_params());
1261a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
1262a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!turl.instant_url_post_params().empty())
1263a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    se_specifics->set_instant_url_post_params(turl.instant_url_post_params());
1264a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (!turl.image_url_post_params().empty())
1265a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    se_specifics->set_image_url_post_params(turl.image_url_post_params());
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  se_specifics->set_last_modified(turl.last_modified().ToInternalValue());
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  se_specifics->set_sync_guid(turl.sync_guid());
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < turl.alternate_urls().size(); ++i)
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    se_specifics->add_alternate_urls(turl.alternate_urls()[i]);
12702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  se_specifics->set_search_terms_replacement_key(
12712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      turl.search_terms_replacement_key());
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return syncer::SyncData::CreateLocalData(se_specifics->sync_guid(),
12742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           se_specifics->keyword(),
12752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           specifics);
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURL* TemplateURLService::CreateTemplateURLFromTemplateURLAndSyncData(
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Profile* profile,
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL* existing_turl,
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const syncer::SyncData& sync_data,
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::SyncChangeList* change_list) {
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(change_list);
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sync_pb::SearchEngineSpecifics specifics =
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sync_data.GetSpecifics().search_engine();
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Past bugs might have caused either of these fields to be empty.  Just
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // delete this data off the server.
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (specifics.url().empty() || specifics.sync_guid().empty()) {
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    change_list->push_back(
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        syncer::SyncChange(FROM_HERE,
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           syncer::SyncChange::ACTION_DELETE,
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           sync_data));
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION(kDeleteSyncedEngineHistogramName,
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DELETE_ENGINE_EMPTY_FIELD, DELETE_ENGINE_MAX);
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TemplateURLData data(existing_turl ?
13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      existing_turl->data() : TemplateURLData());
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.short_name = UTF8ToUTF16(specifics.short_name());
13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.originating_url = GURL(specifics.originating_url());
13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string16 keyword(UTF8ToUTF16(specifics.keyword()));
13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: Once this code has shipped in a couple of stable releases, we can
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // probably remove the migration portion, comment out the
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "autogenerate_keyword" field entirely in the .proto file, and fold the
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // empty keyword case into the "delete data" block above.
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool reset_keyword =
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      specifics.autogenerate_keyword() || specifics.keyword().empty();
13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (reset_keyword)
13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    keyword = ASCIIToUTF16("dummy");  // Will be replaced below.
13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!keyword.empty());
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.SetKeyword(keyword);
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.SetURL(specifics.url());
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.suggestions_url = specifics.suggestions_url();
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.instant_url = specifics.instant_url();
1319a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  data.image_url = specifics.image_url();
1320a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  data.search_url_post_params = specifics.search_url_post_params();
1321a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  data.suggestions_url_post_params = specifics.suggestions_url_post_params();
1322a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  data.instant_url_post_params = specifics.instant_url_post_params();
1323a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  data.image_url_post_params = specifics.image_url_post_params();
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.favicon_url = GURL(specifics.favicon_url());
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.show_in_default_list = specifics.show_in_default_list();
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.safe_for_autoreplace = specifics.safe_for_autoreplace();
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SplitString(specifics.input_encodings(), ';', &data.input_encodings);
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the server data has duplicate encodings, we'll want to push an update
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // below to correct it.  Note that we also fix this in
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GetSearchProvidersUsingKeywordResult(), since otherwise we'd never correct
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // local problems for clients which have disabled search engine sync.
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool deduped = DeDupeEncodings(&data.input_encodings);
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.date_created = base::Time::FromInternalValue(specifics.date_created());
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.last_modified = base::Time::FromInternalValue(specifics.last_modified());
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.prepopulate_id = specifics.prepopulate_id();
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.sync_guid = specifics.sync_guid();
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.alternate_urls.clear();
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < specifics.alternate_urls_size(); ++i)
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data.alternate_urls.push_back(specifics.alternate_urls(i));
13402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.search_terms_replacement_key = specifics.search_terms_replacement_key();
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TemplateURL* turl = new TemplateURL(profile, data);
13432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If this TemplateURL matches a built-in prepopulated template URL, it's
13442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // possible that sync is trying to modify fields that should not be touched.
13452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Revert these fields to the built-in values.
13462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  UpdateTemplateURLIfPrepopulated(turl, profile);
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (reset_keyword || deduped) {
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (reset_keyword)
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      turl->ResetKeywordIfNecessary(true);
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::SyncData sync_data = CreateSyncDataFromTemplateURL(*turl);
13512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    change_list->push_back(syncer::SyncChange(FROM_HERE,
13522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                              syncer::SyncChange::ACTION_UPDATE,
13532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                              sync_data));
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (turl->IsGoogleSearchURLWithReplaceableKeyword()) {
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!existing_turl) {
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // We're adding a new TemplateURL that uses the Google base URL, so set
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // its keyword appropriately for the local environment.
13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      turl->ResetKeywordIfNecessary(false);
13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (existing_turl->IsGoogleSearchURLWithReplaceableKeyword()) {
13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Ignore keyword changes triggered by the Google base URL changing on
13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // another client.  If the base URL changes in this client as well, we'll
13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // pick that up separately at the appropriate time.  Otherwise, changing
13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // the keyword here could result in having the wrong keyword for the local
13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // environment.
13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      turl->data_.SetKeyword(existing_turl->keyword());
13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return turl;
13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SyncDataMap TemplateURLService::CreateGUIDToSyncDataMap(
13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const syncer::SyncDataList& sync_data) {
13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SyncDataMap data_map;
13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (syncer::SyncDataList::const_iterator i(sync_data.begin());
13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != sync_data.end();
13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++i)
13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_map[i->GetSpecifics().search_engine().sync_guid()] = *i;
13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return data_map;
13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::SetKeywordSearchTermsForURL(const TemplateURL* t_url,
13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     const GURL& url,
13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                     const string16& term) {
13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HistoryService* history = profile_  ?
13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HistoryServiceFactory::GetForProfile(profile_,
13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           Profile::EXPLICIT_ACCESS) :
13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NULL;
13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!history)
13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  history->SetKeywordSearchTermsForURL(url, t_url->id(), term);
13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::Init(const Initializer* initializers,
13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              int num_initializers) {
13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Register for notifications.
13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (profile_) {
13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(sky): bug 1166191. The keywords should be moved into the history
14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // db, which will mean we no longer need this notification and the history
14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // backend can handle automatically adding the search terms as the user
14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // navigates.
14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::Source<Profile> profile_source(profile_->GetOriginalProfile());
14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    notification_registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URL_VISITED,
14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                profile_source);
14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    notification_registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_URL_UPDATED,
14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                profile_source);
14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pref_change_registrar_.Init(GetPrefs());
14092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pref_change_registrar_.Add(
14102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        prefs::kSyncedDefaultSearchProviderGUID,
14112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(
14122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            &TemplateURLService::OnSyncedDefaultSearchProviderGUIDChanged,
14132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            base::Unretained(this)));
14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  notification_registrar_.Add(this,
14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::NOTIFICATION_DEFAULT_SEARCH_POLICY_CHANGED,
14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NotificationService::AllSources());
14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (num_initializers > 0) {
14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // This path is only hit by test code and is used to simulate a loaded
14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TemplateURLService.
14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ChangeToLoadedState();
14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Add specific initializers, if any.
14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (int i(0); i < num_initializers; ++i) {
14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(initializers[i].keyword);
14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(initializers[i].url);
14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(initializers[i].content);
14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TemplateURLService ends up owning the TemplateURL, don't try and free
14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // it.
14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TemplateURLData data;
14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data.short_name = UTF8ToUTF16(initializers[i].content);
14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data.SetKeyword(UTF8ToUTF16(initializers[i].keyword));
1435f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles)      data.SetURL(initializers[i].url);
1436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      TemplateURL* template_url = new TemplateURL(profile_, data);
1437eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      AddNoNotify(template_url, true);
1438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      // Set the first provided identifier to be the default.
1440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch      if (i == 0)
1441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch        SetDefaultSearchProviderNoNotify(template_url);
14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Initialize default search.
14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateDefaultSearch();
14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Request a server check for the correct Google URL if Google is the
14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // default search engine, not in headless mode and not in Chrome Frame.
14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (profile_ && initial_default_search_provider_.get() &&
14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      initial_default_search_provider_->url_ref().HasGoogleBaseURLs()) {
14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<base::Environment> env(base::Environment::Create());
14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!env->HasVar(env_vars::kHeadless) &&
14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !CommandLine::ForCurrentProcess()->HasSwitch(switches::kChromeFrame))
14557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      GoogleURLTracker::RequestServerCheck(profile_, false);
14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::RemoveFromMaps(TemplateURL* template_url) {
14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string16& keyword = template_url->keyword();
14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_NE(0U, keyword_to_template_map_.count(keyword));
14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (keyword_to_template_map_[keyword] == template_url) {
14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We need to check whether the keyword can now be provided by another
14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TemplateURL.  See the comments in AddToMaps() for more information on
14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // extension keywords and how they can coexist with non-extension keywords.
14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // In the case of more than one extension, we use the most recently
14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // installed (which will be the most recently added, which will have the
14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // highest ID).
14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL* best_fallback = NULL;
14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (TemplateURLVector::const_iterator i(template_urls_.begin());
14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         i != template_urls_.end(); ++i) {
14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TemplateURL* turl = *i;
14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This next statement relies on the fact that there can only be one
14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // non-extension TemplateURL with a given keyword.
14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((turl != template_url) && (turl->keyword() == keyword) &&
14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (!best_fallback || !best_fallback->IsExtensionKeyword() ||
14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)           (turl->IsExtensionKeyword() && (turl->id() > best_fallback->id()))))
14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        best_fallback = turl;
14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (best_fallback)
14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      keyword_to_template_map_[keyword] = best_fallback;
14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else
14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      keyword_to_template_map_.erase(keyword);
14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!template_url->sync_guid().empty())
14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    guid_to_template_map_.erase(template_url->sync_guid());
14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (loaded_) {
14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UIThreadSearchTermsData search_terms_data(template_url->profile());
14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    provider_map_->Remove(template_url, search_terms_data);
14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::RemoveFromKeywordMapByPointer(
14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL* template_url) {
14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(template_url);
14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (KeywordToTemplateMap::iterator i = keyword_to_template_map_.begin();
14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != keyword_to_template_map_.end(); ++i) {
14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i->second == template_url) {
15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      keyword_to_template_map_.erase(i);
15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // A given TemplateURL only occurs once in the map. As soon as we find the
15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // entry, stop.
15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::AddToMaps(TemplateURL* template_url) {
15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool template_extension = template_url->IsExtensionKeyword();
15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string16& keyword = template_url->keyword();
15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  KeywordToTemplateMap::const_iterator i =
15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      keyword_to_template_map_.find(keyword);
15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i == keyword_to_template_map_.end()) {
15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    keyword_to_template_map_[keyword] = template_url;
15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TemplateURL* existing_url = i->second;
15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We should only have overlapping keywords when at least one comes from
15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // an extension.  In that case, the ranking order is:
15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //   Manually-modified keywords > extension keywords > replaceable keywords
15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // When there are multiple extensions, the last-added wins.
15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool existing_extension = existing_url->IsExtensionKeyword();
15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(existing_extension || template_extension);
15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (existing_extension ?
15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        !CanReplace(template_url) : CanReplace(existing_url))
15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      keyword_to_template_map_[keyword] = template_url;
15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!template_url->sync_guid().empty())
15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    guid_to_template_map_[template_url->sync_guid()] = template_url;
15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (loaded_) {
15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UIThreadSearchTermsData search_terms_data(profile_);
15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    provider_map_->Add(template_url, search_terms_data);
15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1536810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)// Helper for partition() call in next function.
1537810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)bool HasValidID(TemplateURL* t_url) {
1538810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)  return t_url->id() != kInvalidTemplateURLID;
1539810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)}
1540810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)
1541810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)void TemplateURLService::SetTemplateURLs(TemplateURLVector* urls) {
1542810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)  // Partition the URLs first, instead of implementing the loops below by simply
1543810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)  // scanning the input twice.  While it's not supposed to happen normally, it's
1544810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)  // possible for corrupt databases to return multiple entries with the same
1545810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)  // keyword.  In this case, the first loop may delete the first entry when
1546810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)  // adding the second.  If this happens, the second loop must not attempt to
1547810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)  // access the deleted entry.  Partitioning ensures this constraint.
1548810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)  TemplateURLVector::iterator first_invalid(
1549810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)      std::partition(urls->begin(), urls->end(), HasValidID));
1550810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)
1551810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)  // First, add the items that already have id's, so that the next_id_ gets
1552810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)  // properly set.
1553810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)  for (TemplateURLVector::const_iterator i = urls->begin(); i != first_invalid;
15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++i) {
1555810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)    next_id_ = std::max(next_id_, (*i)->id());
1556810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)    AddNoNotify(*i, false);
15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Next add the new items that don't have id's.
1560810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)  for (TemplateURLVector::const_iterator i = first_invalid; i != urls->end();
1561810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)       ++i)
1562810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)    AddNoNotify(*i, true);
1563810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)
1564810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)  // Clear the input vector to reduce the chance callers will try to use a
1565810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)  // (possibly deleted) entry.
1566810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)  urls->clear();
15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::ChangeToLoadedState() {
15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!loaded_);
15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UIThreadSearchTermsData search_terms_data(profile_);
15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  provider_map_->Init(template_urls_, search_terms_data);
15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  loaded_ = true;
15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::NotifyLoaded() {
15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::NotificationService::current()->Notify(
15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      chrome::NOTIFICATION_TEMPLATE_URL_SERVICE_LOADED,
15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::Source<TemplateURLService>(this),
15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content::NotificationService::NoDetails());
15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::SaveDefaultSearchProviderToPrefs(
15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TemplateURL* t_url) {
15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrefService* prefs = GetPrefs();
15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!prefs)
15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool enabled = false;
15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string search_url;
15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string suggest_url;
15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string instant_url;
1594a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::string image_url;
1595a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::string search_url_post_params;
1596a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::string suggest_url_post_params;
1597a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::string instant_url_post_params;
1598a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::string image_url_post_params;
15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string icon_url;
16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string encodings;
16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string short_name;
16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string keyword;
16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string id_string;
16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string prepopulate_id;
16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ListValue alternate_urls;
16062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string search_terms_replacement_key;
16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (t_url) {
16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!t_url->IsExtensionKeyword());
16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    enabled = true;
16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    search_url = t_url->url();
16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    suggest_url = t_url->suggestions_url();
16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    instant_url = t_url->instant_url();
1613a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    image_url = t_url->image_url();
1614a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    search_url_post_params = t_url->search_url_post_params();
1615a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    suggest_url_post_params = t_url->suggestions_url_post_params();
1616a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    instant_url_post_params = t_url->instant_url_post_params();
1617a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    image_url_post_params = t_url->image_url_post_params();
16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL icon_gurl = t_url->favicon_url();
16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!icon_gurl.is_empty())
16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      icon_url = icon_gurl.spec();
16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    encodings = JoinString(t_url->input_encodings(), ';');
16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    short_name = UTF16ToUTF8(t_url->short_name());
16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    keyword = UTF16ToUTF8(t_url->keyword());
16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    id_string = base::Int64ToString(t_url->id());
16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prepopulate_id = base::Int64ToString(t_url->prepopulate_id());
16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (size_t i = 0; i < t_url->alternate_urls().size(); ++i)
16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      alternate_urls.AppendString(t_url->alternate_urls()[i]);
16282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    search_terms_replacement_key = t_url->search_terms_replacement_key();
16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefs->SetBoolean(prefs::kDefaultSearchProviderEnabled, enabled);
16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefs->SetString(prefs::kDefaultSearchProviderSearchURL, search_url);
16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefs->SetString(prefs::kDefaultSearchProviderSuggestURL, suggest_url);
16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefs->SetString(prefs::kDefaultSearchProviderInstantURL, instant_url);
1634a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  prefs->SetString(prefs::kDefaultSearchProviderImageURL, image_url);
1635a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  prefs->SetString(prefs::kDefaultSearchProviderSearchURLPostParams,
1636a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                   search_url_post_params);
1637a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  prefs->SetString(prefs::kDefaultSearchProviderSuggestURLPostParams,
1638a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                   suggest_url_post_params);
1639a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  prefs->SetString(prefs::kDefaultSearchProviderInstantURLPostParams,
1640a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                   instant_url_post_params);
1641a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  prefs->SetString(prefs::kDefaultSearchProviderImageURLPostParams,
1642a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                   image_url_post_params);
16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefs->SetString(prefs::kDefaultSearchProviderIconURL, icon_url);
16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefs->SetString(prefs::kDefaultSearchProviderEncodings, encodings);
16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefs->SetString(prefs::kDefaultSearchProviderName, short_name);
16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefs->SetString(prefs::kDefaultSearchProviderKeyword, keyword);
16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefs->SetString(prefs::kDefaultSearchProviderID, id_string);
16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefs->SetString(prefs::kDefaultSearchProviderPrepopulateID, prepopulate_id);
16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  prefs->Set(prefs::kDefaultSearchProviderAlternateURLs, alternate_urls);
16502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  prefs->SetString(prefs::kDefaultSearchProviderSearchTermsReplacementKey,
16512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      search_terms_replacement_key);
16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TemplateURLService::LoadDefaultSearchProviderFromPrefs(
16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_ptr<TemplateURL>* default_provider,
16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool* is_managed) {
16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrefService* prefs = GetPrefs();
16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!prefs || !prefs->HasPrefPath(prefs::kDefaultSearchProviderSearchURL))
16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const PrefService::Preference* pref =
16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prefs->FindPreference(prefs::kDefaultSearchProviderSearchURL);
16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *is_managed = pref && pref->IsManaged();
16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!prefs->GetBoolean(prefs::kDefaultSearchProviderEnabled)) {
16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The user doesn't want a default search provider.
16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default_provider->reset(NULL);
16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string16 name =
16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UTF8ToUTF16(prefs->GetString(prefs::kDefaultSearchProviderName));
16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string16 keyword =
16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UTF8ToUTF16(prefs->GetString(prefs::kDefaultSearchProviderKeyword));
16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Force keyword to be non-empty.
16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(pkasting): This is only necessary as long as we're potentially loading
16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // older prefs where empty keywords are theoretically possible.  Eventually
16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this code can be replaced with a DCHECK(!keyword.empty());.
16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool update_keyword = keyword.empty();
16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (update_keyword)
16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    keyword = ASCIIToUTF16("dummy");
16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string search_url =
16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prefs->GetString(prefs::kDefaultSearchProviderSearchURL);
16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Force URL to be non-empty.  We've never supported this case, but past bugs
16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // might have resulted in it slipping through; eventually this code can be
16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // replaced with a DCHECK(!search_url.empty());.
16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (search_url.empty())
16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string suggest_url =
16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prefs->GetString(prefs::kDefaultSearchProviderSuggestURL);
16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string instant_url =
16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prefs->GetString(prefs::kDefaultSearchProviderInstantURL);
1693a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::string image_url =
1694a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      prefs->GetString(prefs::kDefaultSearchProviderImageURL);
1695a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::string search_url_post_params =
1696a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      prefs->GetString(prefs::kDefaultSearchProviderSearchURLPostParams);
1697a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::string suggest_url_post_params =
1698a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      prefs->GetString(prefs::kDefaultSearchProviderSuggestURLPostParams);
1699a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::string instant_url_post_params =
1700a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      prefs->GetString(prefs::kDefaultSearchProviderInstantURLPostParams);
1701a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::string image_url_post_params =
1702a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      prefs->GetString(prefs::kDefaultSearchProviderImageURLPostParams);
17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string icon_url =
17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prefs->GetString(prefs::kDefaultSearchProviderIconURL);
17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string encodings =
17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prefs->GetString(prefs::kDefaultSearchProviderEncodings);
17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string id_string = prefs->GetString(prefs::kDefaultSearchProviderID);
17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string prepopulate_id =
17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prefs->GetString(prefs::kDefaultSearchProviderPrepopulateID);
17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ListValue* alternate_urls =
17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prefs->GetList(prefs::kDefaultSearchProviderAlternateURLs);
17122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string search_terms_replacement_key = prefs->GetString(
17132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      prefs::kDefaultSearchProviderSearchTermsReplacementKey);
17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TemplateURLData data;
17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.short_name = name;
17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.SetKeyword(keyword);
17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.SetURL(search_url);
17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.suggestions_url = suggest_url;
17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.instant_url = instant_url;
1721a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  data.image_url = image_url;
1722a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  data.search_url_post_params = search_url_post_params;
1723a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  data.suggestions_url_post_params = suggest_url_post_params;
1724a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  data.instant_url_post_params = instant_url_post_params;
1725a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  data.image_url_post_params = image_url_post_params;
17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.favicon_url = GURL(icon_url);
17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.show_in_default_list = true;
17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.alternate_urls.clear();
17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < alternate_urls->GetSize(); ++i) {
17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string alternate_url;
17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (alternate_urls->GetString(i, &alternate_url))
17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data.alternate_urls.push_back(alternate_url);
17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  data.search_terms_replacement_key = search_terms_replacement_key;
17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SplitString(encodings, ';', &data.input_encodings);
17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!id_string.empty() && !*is_managed) {
17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int64 value;
17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringToInt64(id_string, &value);
17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data.id = value;
17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!prepopulate_id.empty() && !*is_managed) {
17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int value;
17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    base::StringToInt(prepopulate_id, &value);
17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data.prepopulate_id = value;
17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  default_provider->reset(new TemplateURL(profile_, data));
17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!(*default_provider)->IsExtensionKeyword());
17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (update_keyword)
17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*default_provider)->ResetKeywordIfNecessary(true);
17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1753868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void TemplateURLService::ClearDefaultProviderFromPrefs() {
1754868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // We overwrite user preferences. If the default search engine is managed,
1755868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // there is no effect.
1756868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  SaveDefaultSearchProviderToPrefs(NULL);
1757868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Default value for kDefaultSearchProviderEnabled is true.
1758868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PrefService* prefs = GetPrefs();
1759868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (prefs)
1760868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    prefs->SetBoolean(prefs::kDefaultSearchProviderEnabled, true);
1761868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
1762868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TemplateURLService::CanReplaceKeywordForHost(
17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& host,
17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL** to_replace) {
17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!to_replace || !*to_replace);
17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const TemplateURLSet* urls = provider_map_->GetURLsForHost(host);
17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!urls)
17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (TemplateURLSet::const_iterator i(urls->begin()); i != urls->end(); ++i) {
17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (CanReplace(*i)) {
17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (to_replace)
17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *to_replace = *i;
17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TemplateURLService::CanReplace(const TemplateURL* t_url) {
17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (t_url != default_search_provider_ && !t_url->show_in_default_list() &&
17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          t_url->safe_for_autoreplace());
17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURL* TemplateURLService::FindNonExtensionTemplateURLForKeyword(
17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const string16& keyword) {
17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TemplateURL* keyword_turl = GetTemplateURLForKeyword(keyword);
17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!keyword_turl || !keyword_turl->IsExtensionKeyword())
17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return keyword_turl;
17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The extension keyword in the model may be hiding a replaceable
17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // non-extension keyword.  Look for it.
17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (TemplateURLVector::const_iterator i(template_urls_.begin());
17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != template_urls_.end(); ++i) {
17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(*i)->IsExtensionKeyword() && ((*i)->keyword() == keyword))
17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return *i;
17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return NULL;
17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TemplateURLService::UpdateNoNotify(
18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL* existing_turl,
18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TemplateURL& new_values,
18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SearchTermsData& old_search_terms_data) {
18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(loaded_);
18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(existing_turl);
18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (std::find(template_urls_.begin(), template_urls_.end(), existing_turl) ==
18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      template_urls_.end())
18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string16 old_keyword(existing_turl->keyword());
18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  keyword_to_template_map_.erase(old_keyword);
18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!existing_turl->sync_guid().empty())
18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    guid_to_template_map_.erase(existing_turl->sync_guid());
18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  provider_map_->Remove(existing_turl, old_search_terms_data);
18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TemplateURLID previous_id = existing_turl->id();
18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  existing_turl->CopyFrom(new_values);
18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  existing_turl->data_.id = previous_id;
18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UIThreadSearchTermsData new_search_terms_data(profile_);
18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  provider_map_->Add(existing_turl, new_search_terms_data);
18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const string16& keyword = existing_turl->keyword();
18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  KeywordToTemplateMap::const_iterator i =
18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      keyword_to_template_map_.find(keyword);
18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i == keyword_to_template_map_.end()) {
18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    keyword_to_template_map_[keyword] = existing_turl;
18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We can theoretically reach here in two cases:
18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //   * There is an existing extension keyword and sync brings in a rename of
18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //     a non-extension keyword to match.  In this case we just need to pick
18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //     which keyword has priority to update the keyword map.
18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //   * Autogeneration of the keyword for a Google default search provider
18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //     at load time causes it to conflict with an existing keyword.  In this
18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //     case we delete the existing keyword if it's replaceable, or else undo
18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    //     the change in keyword for |existing_turl|.
18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL* existing_keyword_turl = i->second;
18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (existing_keyword_turl->IsExtensionKeyword()) {
18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!CanReplace(existing_turl))
18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        keyword_to_template_map_[keyword] = existing_turl;
18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (CanReplace(existing_keyword_turl)) {
18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        RemoveNoNotify(existing_keyword_turl);
18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        existing_turl->data_.SetKeyword(old_keyword);
18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        keyword_to_template_map_[old_keyword] = existing_turl;
18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!existing_turl->sync_guid().empty())
18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    guid_to_template_map_[existing_turl->sync_guid()] = existing_turl;
18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service_.get())
18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_->UpdateKeyword(existing_turl->data());
18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Inform sync of the update.
18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProcessTemplateURLChange(FROM_HERE,
18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           existing_turl,
18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           syncer::SyncChange::ACTION_UPDATE);
18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (default_search_provider_ == existing_turl) {
18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool success = SetDefaultSearchProviderNoNotify(existing_turl);
18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(success);
18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
18682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void TemplateURLService::UpdateTemplateURLIfPrepopulated(
18692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    TemplateURL* template_url,
18702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    Profile* profile) {
18712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int prepopulate_id = template_url->prepopulate_id();
18722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (template_url->prepopulate_id() == 0)
18732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
18742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ScopedVector<TemplateURL> prepopulated_urls;
18762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t default_search_index;
18772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  TemplateURLPrepopulateData::GetPrepopulatedEngines(profile,
18782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &prepopulated_urls.get(), &default_search_index);
18792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < prepopulated_urls.size(); ++i) {
18812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (prepopulated_urls[i]->prepopulate_id() == prepopulate_id) {
18822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MergeIntoPrepopulatedEngineData(&prepopulated_urls[i]->data_,
18832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      template_url);
18842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      template_url->CopyFrom(*prepopulated_urls[i]);
18852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
18862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
18872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
18882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)PrefService* TemplateURLService::GetPrefs() {
18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return profile_ ? profile_->GetPrefs() : NULL;
18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::UpdateKeywordSearchTermsForURL(
18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const history::URLVisitedDetails& details) {
18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const history::URLRow& row = details.row;
1896c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!row.url().is_valid())
18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const TemplateURLSet* urls_for_host =
19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      provider_map_->GetURLsForHost(row.url().host());
19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!urls_for_host)
19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QueryTerms query_terms;
19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string path = row.url().path();
19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (TemplateURLSet::const_iterator i = urls_for_host->begin();
19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != urls_for_host->end(); ++i) {
1909c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    string16 search_terms;
1910c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if ((*i)->ExtractSearchTermsFromURL(row.url(), &search_terms) &&
1911c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        !search_terms.empty()) {
19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (content::PageTransitionStripQualifier(details.transition) ==
19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          content::PAGE_TRANSITION_KEYWORD) {
19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The visit is the result of the user entering a keyword, generate a
19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // KEYWORD_GENERATED visit for the KEYWORD so that the keyword typed
19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // count is boosted.
19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        AddTabToSearchVisit(**i);
19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1919c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      SetKeywordSearchTermsForURL(*i, row.url(), search_terms);
19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::AddTabToSearchVisit(const TemplateURL& t_url) {
19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only add visits for entries the user hasn't modified. If the user modified
19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the entry the keyword may no longer correspond to the host name. It may be
19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // possible to do something more sophisticated here, but it's so rare as to
19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not be worth it.
19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!t_url.safe_for_autoreplace())
19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!profile_)
19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HistoryService* history =
19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HistoryServiceFactory::GetForProfile(profile_, Profile::EXPLICIT_ACCESS);
19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!history)
19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL url(URLFixerUpper::FixupURL(UTF16ToUTF8(t_url.keyword()),
19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   std::string()));
19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!url.is_valid())
19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Synthesize a visit for the keyword. This ensures the url for the keyword is
19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // autocompleted even if the user doesn't type the url in directly.
19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  history->AddPage(url, base::Time::Now(), NULL, 0, GURL(),
19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   history::RedirectList(),
19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   content::PAGE_TRANSITION_KEYWORD_GENERATED,
19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   history::SOURCE_BROWSED, false);
19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::GoogleBaseURLChanged(const GURL& old_base_url) {
19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool something_changed = false;
19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (TemplateURLVector::iterator i(template_urls_.begin());
19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != template_urls_.end(); ++i) {
19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL* t_url = *i;
19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (t_url->url_ref().HasGoogleBaseURLs() ||
19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        t_url->suggestions_url_ref().HasGoogleBaseURLs()) {
19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TemplateURL updated_turl(t_url->profile(), t_url->data());
19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      updated_turl.ResetKeywordIfNecessary(false);
19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      KeywordToTemplateMap::const_iterator existing_entry =
19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          keyword_to_template_map_.find(updated_turl.keyword());
19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if ((existing_entry != keyword_to_template_map_.end()) &&
19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (existing_entry->second != t_url)) {
19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // The new autogenerated keyword conflicts with another TemplateURL.
19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Overwrite it if it's replaceable; otherwise, leave |t_url| using its
19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // current keyword.  (This will not prevent |t_url| from auto-updating
19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // the keyword in the future if the conflicting TemplateURL disappears.)
19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Note that we must still update |t_url| in this case, or the
19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // |provider_map_| will not be updated correctly.
19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (CanReplace(existing_entry->second))
19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          RemoveNoNotify(existing_entry->second);
19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else
19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          updated_turl.data_.SetKeyword(t_url->keyword());
19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      something_changed = true;
19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This will send the keyword change to sync.  Note that other clients
19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // need to reset the keyword to an appropriate local value when this
19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // change arrives; see CreateTemplateURLFromTemplateURLAndSyncData().
19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateNoNotify(t_url, updated_turl,
19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          OldBaseURLSearchTermsData(t_url->profile(), old_base_url.spec()));
19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (something_changed)
19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NotifyObservers();
19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::UpdateDefaultSearch() {
19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!loaded_) {
19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Set |initial_default_search_provider_| from the preferences.  We use this
19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // value for default search provider until the database has been loaded.
19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!LoadDefaultSearchProviderFromPrefs(&initial_default_search_provider_,
19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            &is_default_search_managed_)) {
19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Prefs does not specify, so rely on the prepopulated engines.  This
19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // should happen only the first time Chrome is started.
19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      initial_default_search_provider_.reset(
19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(profile_));
19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      is_default_search_managed_ = false;
20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load the default search specified in prefs.
20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<TemplateURL> new_default_from_prefs;
20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool new_is_default_managed = false;
20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Load the default from prefs.  It's possible that it won't succeed
20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // because we are in the middle of doing SaveDefaultSearchProviderToPrefs()
20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // and all the preference items have not been saved.  In that case, we
20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // don't have yet a default.  It would be much better if we could save
20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // preferences in batches and trigger notifications at the end.
20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LoadDefaultSearchProviderFromPrefs(&new_default_from_prefs,
20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     &new_is_default_managed);
20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_default_search_managed_ && !new_is_default_managed) {
20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We're not interested in cases where the default was and remains
20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // unmanaged.  In that case, preferences have no impact on the default.
20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (is_default_search_managed_ && new_is_default_managed) {
20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The default was managed and remains managed.  Update the default only
20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // if it has changed; we don't want to respond to changes triggered by
20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // SaveDefaultSearchProviderToPrefs.
20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (TemplateURLsHaveSamePrefs(default_search_provider_,
20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  new_default_from_prefs.get()))
20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (new_default_from_prefs.get() == NULL) {
20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // default_search_provider_ can't be NULL otherwise
20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TemplateURLsHaveSamePrefs would have returned true.  Remove this now
20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // invalid value.
20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TemplateURL* old_default = default_search_provider_;
20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool success = SetDefaultSearchProviderNoNotify(NULL);
20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(success);
20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RemoveNoNotify(old_default);
20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (default_search_provider_) {
20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TemplateURLData data(new_default_from_prefs->data());
20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data.created_by_policy = true;
20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TemplateURL new_values(new_default_from_prefs->profile(), data);
20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UIThreadSearchTermsData search_terms_data(
20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          default_search_provider_->profile());
20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UpdateNoNotify(default_search_provider_, new_values, search_terms_data);
20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TemplateURL* new_template = NULL;
20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (new_default_from_prefs.get()) {
20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TemplateURLData data(new_default_from_prefs->data());
20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data.created_by_policy = true;
20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        new_template = new TemplateURL(profile_, data);
20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (!AddNoNotify(new_template, true))
20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return;
20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool success = SetDefaultSearchProviderNoNotify(new_template);
20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DCHECK(success);
20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (!is_default_search_managed_ && new_is_default_managed) {
20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The default used to be unmanaged and is now managed.  Add the new
20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // managed default to the list of URLs and set it as default.
20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_default_search_managed_ = new_is_default_managed;
20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL* new_template = NULL;
20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (new_default_from_prefs.get()) {
20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TemplateURLData data(new_default_from_prefs->data());
20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data.created_by_policy = true;
20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_template = new TemplateURL(profile_, data);
20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!AddNoNotify(new_template, true))
20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return;
20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool success = SetDefaultSearchProviderNoNotify(new_template);
20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(success);
20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The default was managed and is no longer.
20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(is_default_search_managed_ && !new_is_default_managed);
20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    is_default_search_managed_ = new_is_default_managed;
20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we had a default, delete the previous default if created by policy
20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // and set a likely default.
20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if ((default_search_provider_ != NULL) &&
20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        default_search_provider_->created_by_policy()) {
20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      TemplateURL* old_default = default_search_provider_;
20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default_search_provider_ = NULL;
20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RemoveNoNotify(old_default);
20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The likely default should be from Sync if we were waiting on Sync.
20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Otherwise, it should be FindNewDefaultSearchProvider.
20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL* synced_default = GetPendingSyncedDefaultSearchProvider();
20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (synced_default) {
2083a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      pending_synced_default_search_ = false;
2084a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
20852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::AutoReset<DefaultSearchChangeOrigin> change_origin(
20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &dsp_change_origin_, DSP_CHANGE_SYNC_NOT_MANAGED);
20877dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      SetDefaultSearchProviderNoNotify(synced_default);
20887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    } else {
20897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      SetDefaultSearchProviderNoNotify(FindNewDefaultSearchProvider());
20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NotifyObservers();
20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TemplateURLService::SetDefaultSearchProviderNoNotify(TemplateURL* url) {
20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (url) {
20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (std::find(template_urls_.begin(), template_urls_.end(), url) ==
20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        template_urls_.end())
20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Extension keywords cannot be made default, as they're inherently async.
21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!url->IsExtensionKeyword());
21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Only bother reassigning |url| if it has changed. Notice that we don't just
21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // early exit if they are equal, because |url| may have had its fields
21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // changed, and needs to be persisted below (for example, when this is called
21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // from UpdateNoNotify).
21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (default_search_provider_ != url) {
2109f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles)    UMA_HISTOGRAM_ENUMERATION("Search.DefaultSearchChangeOrigin",
2110f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles)                              dsp_change_origin_, DSP_CHANGE_MAX);
21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default_search_provider_ = url;
21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (url) {
21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Don't mark the url as edited, otherwise we won't be able to rev the
21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // template urls we ship with.
21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    url->data_.show_in_default_list = true;
21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (service_.get())
21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service_->UpdateKeyword(url->data());
21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (url->url_ref().HasGoogleBaseURLs()) {
21227d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      GoogleURLTracker::RequestServerCheck(profile_, false);
21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(ENABLE_RLZ)
21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      RLZTracker::RecordProductEvent(rlz_lib::CHROME,
21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     RLZTracker::CHROME_OMNIBOX,
21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     rlz_lib::SET_TO_GOOGLE);
21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!is_default_search_managed_) {
21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SaveDefaultSearchProviderToPrefs(url);
21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If we are syncing, we want to set the synced pref that will notify other
21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // instances to change their default to this new search provider.
21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note: we don't update the pref if we're currently in the middle of
21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // handling a sync operation. Sync operations from other clients are not
21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // guaranteed to arrive together, and any client that deletes the default
21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // needs to set a new default as well. If we update the default here, we're
21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // likely to race with the update from the other client, resulting in
21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // a possibly random default search provider.
21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sync_processor_.get() && url && !url->sync_guid().empty() &&
21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        GetPrefs() && !processing_syncer_changes_) {
21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetPrefs()->SetString(prefs::kSyncedDefaultSearchProviderGUID,
21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            url->sync_guid());
21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (service_.get())
21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_->SetDefaultSearchProvider(url);
21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Inform sync the change to the show_in_default_list flag.
21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (url)
21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProcessTemplateURLChange(FROM_HERE,
21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             url,
21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             syncer::SyncChange::ACTION_UPDATE);
21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TemplateURLService::AddNoNotify(TemplateURL* template_url,
21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                     bool newly_adding) {
21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(template_url);
21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (newly_adding) {
21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(kInvalidTemplateURLID, template_url->id());
21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(std::find(template_urls_.begin(), template_urls_.end(),
21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     template_url) == template_urls_.end());
21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    template_url->data_.id = ++next_id_;
21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template_url->ResetKeywordIfNecessary(false);
2172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Check whether |template_url|'s keyword conflicts with any already in the
2173868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // model.
2174868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  TemplateURL* existing_keyword_turl =
2175868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      GetTemplateURLForKeyword(template_url->keyword());
2176868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (existing_keyword_turl != NULL) {
2177868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DCHECK_NE(existing_keyword_turl, template_url);
2178868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Only replace one of the TemplateURLs if they are either both extensions,
2179868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // or both not extensions.
2180868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool are_same_type = existing_keyword_turl->IsExtensionKeyword() ==
2181868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        template_url->IsExtensionKeyword();
2182868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (CanReplace(existing_keyword_turl) && are_same_type) {
2183868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      RemoveNoNotify(existing_keyword_turl);
2184868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else if (CanReplace(template_url) && are_same_type) {
2185868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      delete template_url;
2186868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return false;
2187868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
2188868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      string16 new_keyword = UniquifyKeyword(*existing_keyword_turl, false);
2189868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ResetTemplateURL(existing_keyword_turl,
2190868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       existing_keyword_turl->short_name(), new_keyword,
2191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                       existing_keyword_turl->url());
21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template_urls_.push_back(template_url);
21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  AddToMaps(template_url);
21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (newly_adding) {
2198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (service_.get())
21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      service_->AddKeyword(template_url->data());
22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Inform sync of the addition. Note that this will assign a GUID to
22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // template_url and add it to the guid_to_template_map_.
22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ProcessTemplateURLChange(FROM_HERE,
22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             template_url,
22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             syncer::SyncChange::ACTION_ADD);
22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::RemoveNoNotify(TemplateURL* template_url) {
22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TemplateURLVector::iterator i =
22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::find(template_urls_.begin(), template_urls_.end(), template_url);
22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i == template_urls_.end())
22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (template_url == default_search_provider_) {
22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Should never delete the default search provider.
22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RemoveFromMaps(template_url);
22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Remove it from the vector containing all TemplateURLs.
22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template_urls_.erase(i);
22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (service_.get())
22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    service_->RemoveKeyword(template_url->id());
22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Inform sync of the deletion.
22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ProcessTemplateURLChange(FROM_HERE,
22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           template_url,
22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           syncer::SyncChange::ACTION_DELETE);
22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_ENUMERATION(kDeleteSyncedEngineHistogramName,
22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DELETE_ENGINE_USER_ACTION, DELETE_ENGINE_MAX);
22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (profile_) {
22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::Source<Profile> source(profile_);
22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURLID id = template_url->id();
22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    content::NotificationService::current()->Notify(
22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        chrome::NOTIFICATION_TEMPLATE_URL_REMOVED,
22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        source,
22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        content::Details<TemplateURLID>(&id));
22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We own the TemplateURL and need to delete it.
22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete template_url;
22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::NotifyObservers() {
22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!loaded_)
22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FOR_EACH_OBSERVER(TemplateURLServiceObserver, model_observers_,
22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    OnTemplateURLServiceChanged());
22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |template_urls| are the TemplateURLs loaded from the database.
22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |default_search_provider| points to one of them, if it was set in the db.
22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |default_from_prefs| is the default search provider from the preferences.
22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Check |is_default_search_managed_| to determine if it was set by policy.
22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This function removes from the vector and the database all the TemplateURLs
22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that were set by policy, unless it is the current default search provider
22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and matches what is set by a managed preference.
22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::RemoveProvidersCreatedByPolicy(
22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURLVector* template_urls,
22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL** default_search_provider,
22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL* default_from_prefs) {
22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(template_urls);
22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(default_search_provider);
22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (TemplateURLVector::iterator i = template_urls->begin();
22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != template_urls->end(); ) {
22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL* template_url = *i;
22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (template_url->created_by_policy()) {
22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (template_url == *default_search_provider &&
22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          is_default_search_managed_ &&
22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          TemplateURLsHaveSamePrefs(template_url,
22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    default_from_prefs)) {
22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // If the database specified a default search provider that was set
22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // by policy, and the default search provider from the preferences
22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // is also set by policy and they are the same, keep the entry in the
22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // database and the |default_search_provider|.
22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ++i;
22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The database loaded a managed |default_search_provider|, but it has
22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // been updated in the prefs. Remove it from the database, and update the
22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // |default_search_provider| pointer here.
22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (*default_search_provider &&
22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (*default_search_provider)->id() == template_url->id())
22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *default_search_provider = NULL;
22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i = template_urls->erase(i);
2297868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (service_.get())
22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        service_->RemoveKeyword(template_url->id());
22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      delete template_url;
23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ++i;
23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::ResetTemplateURLGUID(TemplateURL* url,
23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              const std::string& guid) {
23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(loaded_);
23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!guid.empty());
23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TemplateURLData data(url->data());
23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  data.sync_guid = guid;
23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TemplateURL new_url(url->profile(), data);
23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UIThreadSearchTermsData search_terms_data(url->profile());
23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UpdateNoNotify(url, new_url, search_terms_data);
23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)string16 TemplateURLService::UniquifyKeyword(const TemplateURL& turl,
23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             bool force) {
23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!force) {
23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Already unique.
23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!GetTemplateURLForKeyword(turl.keyword()))
23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return turl.keyword();
23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2325868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // First, try to return the generated keyword for the TemplateURL (except
2326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // for extensions, as their keywords are not associated with their URLs).
23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    GURL gurl(turl.url());
2328868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (gurl.is_valid() && !turl.IsExtensionKeyword()) {
23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      string16 keyword_candidate = GenerateKeyword(gurl);
23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!GetTemplateURLForKeyword(keyword_candidate))
23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return keyword_candidate;
23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We try to uniquify the keyword by appending a special character to the end.
23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is a best-effort approach where we try to preserve the original
23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // keyword and let the user do what they will after our attempt.
23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string16 keyword_candidate(turl.keyword());
23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    keyword_candidate.append(ASCIIToUTF16("_"));
23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (GetTemplateURLForKeyword(keyword_candidate));
23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return keyword_candidate;
23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool TemplateURLService::IsLocalTemplateURLBetter(
23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TemplateURL* local_turl,
23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const TemplateURL* sync_turl) {
23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(GetTemplateURLForGUID(local_turl->sync_guid()));
23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return local_turl->last_modified() > sync_turl->last_modified() ||
23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         local_turl->created_by_policy() ||
23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         local_turl== GetDefaultSearchProvider();
23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::ResolveSyncKeywordConflict(
23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL* unapplied_sync_turl,
23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL* applied_sync_turl,
23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::SyncChangeList* change_list) {
23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(loaded_);
23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(unapplied_sync_turl);
23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(applied_sync_turl);
23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(change_list);
23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ(applied_sync_turl->keyword(), unapplied_sync_turl->keyword());
23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Both |unapplied_sync_turl| and |applied_sync_turl| are known to Sync, so
23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // don't delete either of them. Instead, determine which is "better" and
23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // uniquify the other one, sending an update to the server for the updated
23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // entry.
23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const bool applied_turl_is_better =
23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      IsLocalTemplateURLBetter(applied_sync_turl, unapplied_sync_turl);
23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TemplateURL* loser = applied_turl_is_better ?
23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      unapplied_sync_turl : applied_sync_turl;
23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  string16 new_keyword = UniquifyKeyword(*loser, false);
23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!GetTemplateURLForKeyword(new_keyword));
23755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (applied_turl_is_better) {
23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Just set the keyword of |unapplied_sync_turl|. The caller is responsible
23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // for adding or updating unapplied_sync_turl in the local model.
23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    unapplied_sync_turl->data_.SetKeyword(new_keyword);
23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Update |applied_sync_turl| in the local model with the new keyword.
23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURLData data(applied_sync_turl->data());
23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data.SetKeyword(new_keyword);
23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL new_turl(applied_sync_turl->profile(), data);
23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    UIThreadSearchTermsData search_terms_data(applied_sync_turl->profile());
23855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (UpdateNoNotify(applied_sync_turl, new_turl, search_terms_data))
23865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NotifyObservers();
23875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
23885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The losing TemplateURL should have their keyword updated. Send a change to
23895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the server to reflect this change.
23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  syncer::SyncData sync_data = CreateSyncDataFromTemplateURL(*loser);
23915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  change_list->push_back(syncer::SyncChange(FROM_HERE,
23925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      syncer::SyncChange::ACTION_UPDATE,
23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      sync_data));
23945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
23965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::MergeInSyncTemplateURL(
23975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL* sync_turl,
23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const SyncDataMap& sync_data,
23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    syncer::SyncChangeList* change_list,
24002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SyncDataMap* local_data,
24012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    syncer::SyncMergeResult* merge_result) {
24025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(sync_turl);
24035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!GetTemplateURLForGUID(sync_turl->sync_guid()));
24045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsFromSync(sync_turl, sync_data));
24055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TemplateURL* conflicting_turl =
24075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FindNonExtensionTemplateURLForKeyword(sync_turl->keyword());
24085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool should_add_sync_turl = true;
24095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If there was no TemplateURL in the local model that conflicts with
24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |sync_turl|, skip the following preparation steps and just add |sync_turl|
24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // directly. Otherwise, modify |conflicting_turl| to make room for
24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |sync_turl|.
24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (conflicting_turl) {
24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IsFromSync(conflicting_turl, sync_data)) {
24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // |conflicting_turl| is already known to Sync, so we're not allowed to
24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // remove it. In this case, we want to uniquify the worse one and send an
24185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // update for the changed keyword to sync. We can reuse the logic from
24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // ResolveSyncKeywordConflict for this.
24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ResolveSyncKeywordConflict(sync_turl, conflicting_turl, change_list);
24212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      merge_result->set_num_items_modified(
24222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          merge_result->num_items_modified() + 1);
24235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
24245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // |conflicting_turl| is not yet known to Sync. If it is better, then we
24255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // want to transfer its values up to sync. Otherwise, we remove it and
24265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // allow the entry from Sync to overtake it in the model.
24275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const std::string guid = conflicting_turl->sync_guid();
24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (IsLocalTemplateURLBetter(conflicting_turl, sync_turl)) {
24295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ResetTemplateURLGUID(conflicting_turl, sync_turl->sync_guid());
24305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        syncer::SyncData sync_data =
24315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            CreateSyncDataFromTemplateURL(*conflicting_turl);
24325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        change_list->push_back(syncer::SyncChange(
24335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            FROM_HERE, syncer::SyncChange::ACTION_UPDATE, sync_data));
24345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (conflicting_turl == GetDefaultSearchProvider() &&
24355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            !pending_synced_default_search_) {
24365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // If we're not waiting for the Synced default to come in, we should
24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // override the pref with our new GUID. If we are waiting for the
24385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // arrival of a synced default, setting the pref here would cause us
24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          // to lose the GUID we are waiting on.
24405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          PrefService* prefs = GetPrefs();
24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          if (prefs) {
24425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            prefs->SetString(prefs::kSyncedDefaultSearchProviderGUID,
24435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             conflicting_turl->sync_guid());
24445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          }
24455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
24465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // Note that in this case we do not add the Sync TemplateURL to the
24475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // local model, since we've effectively "merged" it in by updating the
24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // local conflicting entry with its sync_guid.
24495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        should_add_sync_turl = false;
24502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        merge_result->set_num_items_modified(
24512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            merge_result->num_items_modified() + 1);
24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // We guarantee that this isn't the local search provider. Otherwise,
24545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        // local would have won.
24555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        DCHECK(conflicting_turl != GetDefaultSearchProvider());
24565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Remove(conflicting_turl);
24572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        merge_result->set_num_items_deleted(
24582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)            merge_result->num_items_deleted() + 1);
24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // This TemplateURL was either removed or overwritten in the local model.
24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Remove the entry from the local data so it isn't pushed up to Sync.
24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      local_data->erase(guid);
24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (should_add_sync_turl) {
24675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string guid = sync_turl->sync_guid();
24685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Force the local ID to kInvalidTemplateURLID so we can add it.
24695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURLData data(sync_turl->data());
24705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data.id = kInvalidTemplateURLID;
24715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Add(new TemplateURL(profile_, data));
24722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    merge_result->set_num_items_added(
24732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        merge_result->num_items_added() + 1);
24745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::SetDefaultSearchProviderIfNewlySynced(
24785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& guid) {
24795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we're not syncing or if default search is managed by policy, ignore.
24805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!sync_processor_.get() || is_default_search_managed_)
24815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
24825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrefService* prefs = GetPrefs();
24845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (prefs && pending_synced_default_search_ &&
24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prefs->GetString(prefs::kSyncedDefaultSearchProviderGUID) == guid) {
24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Make sure this actually exists. We should not be calling this unless we
24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // really just added this TemplateURL.
24885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL* turl_from_sync = GetTemplateURLForGUID(guid);
24895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (turl_from_sync && turl_from_sync->SupportsReplacement()) {
24902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::AutoReset<DefaultSearchChangeOrigin> change_origin(
24915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          &dsp_change_origin_, DSP_CHANGE_SYNC_ADD);
24925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      SetDefaultSearchProvider(turl_from_sync);
24935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
24945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pending_synced_default_search_ = false;
24955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
24965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
24975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
24985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TemplateURL* TemplateURLService::GetPendingSyncedDefaultSearchProvider() {
24995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PrefService* prefs = GetPrefs();
25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!prefs || !pending_synced_default_search_)
25015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
25025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Could be NULL if no such thing exists.
25045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetTemplateURLForGUID(
25055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      prefs->GetString(prefs::kSyncedDefaultSearchProviderGUID));
25065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
25075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void TemplateURLService::PatchMissingSyncGUIDs(
25095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURLVector* template_urls) {
25105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(template_urls);
25115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (TemplateURLVector::iterator i = template_urls->begin();
25125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       i != template_urls->end(); ++i) {
25135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    TemplateURL* template_url = *i;
25145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(template_url);
2515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (template_url->sync_guid().empty()) {
25165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      template_url->data_.sync_guid = base::GenerateGUID();
25175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (service_.get())
25185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        service_->UpdateKeyword(template_url->data());
25195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
25205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
25215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2522868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2523868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void TemplateURLService::AddTemplateURLsAndSetupDefaultEngine(
2524868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TemplateURLVector* template_urls,
2525868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TemplateURL* default_search_provider) {
2526868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(template_urls);
2527868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  is_default_search_managed_ = false;
2528868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  bool database_specified_a_default = (default_search_provider != NULL);
2529868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2530868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Check if default search provider is now managed.
2531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<TemplateURL> default_from_prefs;
2532868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  LoadDefaultSearchProviderFromPrefs(&default_from_prefs,
2533868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                     &is_default_search_managed_);
2534868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2535868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Remove entries that were created because of policy as they may have
2536868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // changed since the database was saved.
2537868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  RemoveProvidersCreatedByPolicy(template_urls,
2538868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 &default_search_provider,
2539868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                 default_from_prefs.get());
2540868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2541868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  PatchMissingSyncGUIDs(template_urls);
2542868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2543868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (is_default_search_managed_) {
2544810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)    SetTemplateURLs(template_urls);
2545868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2546868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (TemplateURLsHaveSamePrefs(default_search_provider,
2547868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                  default_from_prefs.get())) {
2548868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // The value from the preferences was previously stored in the database.
2549868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Reuse it.
2550868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
2551868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // The value from the preferences takes over.
2552868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      default_search_provider = NULL;
2553868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (default_from_prefs.get()) {
2554868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        TemplateURLData data(default_from_prefs->data());
2555868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        data.created_by_policy = true;
2556868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        data.id = kInvalidTemplateURLID;
2557868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        default_search_provider = new TemplateURL(profile_, data);
2558868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        if (!AddNoNotify(default_search_provider, true))
2559868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          default_search_provider = NULL;
2560868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      }
2561868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
2562868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Note that this saves the default search provider to prefs.
2563868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!default_search_provider ||
2564868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        (!default_search_provider->IsExtensionKeyword() &&
2565868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)            default_search_provider->SupportsReplacement())) {
2566868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      bool success = SetDefaultSearchProviderNoNotify(default_search_provider);
2567868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      DCHECK(success);
2568868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
2569868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
2570868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // If we had a managed default, replace it with the synced default if
2571868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // applicable, or the first provider of the list.
2572868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    TemplateURL* synced_default = GetPendingSyncedDefaultSearchProvider();
2573868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (synced_default) {
2574868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      default_search_provider = synced_default;
2575868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      pending_synced_default_search_ = false;
2576868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else if (database_specified_a_default &&
2577868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        default_search_provider == NULL) {
2578868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      UMA_HISTOGRAM_ENUMERATION(kFirstPotentialEngineHistogramName,
2579868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                FIRST_POTENTIAL_CALLSITE_ON_LOAD,
2580868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                FIRST_POTENTIAL_CALLSITE_MAX);
2581868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      default_search_provider = FirstPotentialDefaultEngine(*template_urls);
2582868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
2583868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2584868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // If the default search provider existed previously, then just
2585868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // set the member variable. Otherwise, we'll set it using the method
2586868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // to ensure that it is saved properly after its id is set.
2587868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (default_search_provider &&
2588868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        (default_search_provider->id() != kInvalidTemplateURLID)) {
2589868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      default_search_provider_ = default_search_provider;
2590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      default_search_provider = NULL;
2591868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
2592810e1ddbe56b57afdcdf66369cbed8e1ec967838Torne (Richard Coles)    SetTemplateURLs(template_urls);
2593868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2594868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (default_search_provider) {
2595868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Note that this saves the default search provider to prefs.
2596868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      SetDefaultSearchProvider(default_search_provider);
2597868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    } else {
2598868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // Always save the default search provider to prefs. That way we don't
2599868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      // have to worry about it being out of sync.
2600868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      if (default_search_provider_)
2601868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        SaveDefaultSearchProviderToPrefs(default_search_provider_);
2602868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
2603868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2604868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
2605868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
2606868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)void TemplateURLService::EnsureDefaultSearchProviderExists() {
2607868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!is_default_search_managed_) {
2608868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    bool has_default_search_provider = default_search_provider_ &&
2609868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        default_search_provider_->SupportsReplacement();
2610f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles)    UMA_HISTOGRAM_BOOLEAN("Search.HasDefaultSearchProvider",
2611868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                          has_default_search_provider);
2612868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    // Ensure that default search provider exists. See http://crbug.com/116952.
2613868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!has_default_search_provider) {
2614868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      bool success =
2615868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          SetDefaultSearchProviderNoNotify(FindNewDefaultSearchProvider());
2616868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      DCHECK(success);
2617868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
2618f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles)    // Don't log anything if the user has a NULL default search provider.
2619868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (default_search_provider_) {
2620f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles)      // TODO(pkasting): This histogram obsoletes the next one.  Remove the next
2621f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles)      // one in Chrome 32 or later.
2622f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles)      UMA_HISTOGRAM_ENUMERATION("Search.DefaultSearchProviderType",
2623f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles)          TemplateURLPrepopulateData::GetEngineType(*default_search_provider_),
2624f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles)          SEARCH_ENGINE_MAX);
2625868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      UMA_HISTOGRAM_ENUMERATION(
2626f3ce491c3623b9924dccab3703a43e03157e988aTorne (Richard Coles)          "Search.DefaultSearchProvider",
2627868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          default_search_provider_->prepopulate_id(),
2628868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          TemplateURLPrepopulateData::kMaxPrepopulatedEngineID);
2629868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
2630868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
2631868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
2632ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
2633ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTemplateURL* TemplateURLService::CreateTemplateURLForExtension(
2634ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch    const ExtensionKeyword& extension_keyword) const {
2635ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  TemplateURLData data;
2636ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.short_name = UTF8ToUTF16(extension_keyword.extension_name);
2637ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.SetKeyword(UTF8ToUTF16(extension_keyword.extension_keyword));
2638ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // This URL is not actually used for navigation. It holds the extension's
2639ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // ID, as well as forcing the TemplateURL to be treated as a search keyword.
2640ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  data.SetURL(std::string(extensions::kExtensionScheme) + "://" +
2641ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch      extension_keyword.extension_id + "/?q={searchTerms}");
2642ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  return new TemplateURL(profile_, data);
2643ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}
2644