1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/search_engines/default_search_pref_migration.h"
6
7#include "base/bind.h"
8#include "base/bind_helpers.h"
9#include "base/logging.h"
10#include "base/memory/scoped_ptr.h"
11#include "base/metrics/histogram.h"
12#include "base/prefs/pref_service.h"
13#include "components/search_engines/default_search_manager.h"
14#include "components/search_engines/search_engines_pref_names.h"
15#include "components/search_engines/template_url_data.h"
16#include "components/search_engines/template_url_service.h"
17
18namespace {
19
20// Loads the user-selected DSE (if there is one, and it's not masked by policy
21// or an extension) from legacy preferences.
22scoped_ptr<TemplateURLData> LoadDefaultSearchProviderFromPrefs(
23    PrefService* pref_service) {
24  scoped_ptr<TemplateURLData> legacy_dse_from_prefs;
25  bool legacy_is_managed = false;
26  TemplateURLService::LoadDefaultSearchProviderFromPrefs(
27      pref_service, &legacy_dse_from_prefs, &legacy_is_managed);
28  return legacy_is_managed ?
29      scoped_ptr<TemplateURLData>() : legacy_dse_from_prefs.Pass();
30}
31
32void ClearDefaultSearchProviderFromLegacyPrefs(PrefService* prefs) {
33  prefs->ClearPref(prefs::kDefaultSearchProviderName);
34  prefs->ClearPref(prefs::kDefaultSearchProviderKeyword);
35  prefs->ClearPref(prefs::kDefaultSearchProviderSearchURL);
36  prefs->ClearPref(prefs::kDefaultSearchProviderSuggestURL);
37  prefs->ClearPref(prefs::kDefaultSearchProviderInstantURL);
38  prefs->ClearPref(prefs::kDefaultSearchProviderImageURL);
39  prefs->ClearPref(prefs::kDefaultSearchProviderNewTabURL);
40  prefs->ClearPref(prefs::kDefaultSearchProviderSearchURLPostParams);
41  prefs->ClearPref(prefs::kDefaultSearchProviderSuggestURLPostParams);
42  prefs->ClearPref(prefs::kDefaultSearchProviderInstantURLPostParams);
43  prefs->ClearPref(prefs::kDefaultSearchProviderImageURLPostParams);
44  prefs->ClearPref(prefs::kDefaultSearchProviderIconURL);
45  prefs->ClearPref(prefs::kDefaultSearchProviderEncodings);
46  prefs->ClearPref(prefs::kDefaultSearchProviderPrepopulateID);
47  prefs->ClearPref(prefs::kDefaultSearchProviderAlternateURLs);
48  prefs->ClearPref(prefs::kDefaultSearchProviderSearchTermsReplacementKey);
49}
50
51void MigrateDefaultSearchPref(PrefService* pref_service) {
52  DCHECK(pref_service);
53
54  scoped_ptr<TemplateURLData> legacy_dse_from_prefs =
55      LoadDefaultSearchProviderFromPrefs(pref_service);
56  if (!legacy_dse_from_prefs)
57    return;
58
59  DefaultSearchManager default_search_manager(
60      pref_service, DefaultSearchManager::ObserverCallback());
61  DefaultSearchManager::Source modern_source;
62  TemplateURLData* modern_value =
63      default_search_manager.GetDefaultSearchEngine(&modern_source);
64  if (modern_source == DefaultSearchManager::FROM_FALLBACK) {
65    // |modern_value| is the prepopulated default. If it matches the legacy DSE
66    // we assume it is not a user-selected value.
67    if (!modern_value ||
68        legacy_dse_from_prefs->prepopulate_id != modern_value->prepopulate_id) {
69      // This looks like a user-selected value, so let's migrate it.
70      // TODO(erikwright): Remove this migration logic when this stat approaches
71      // zero.
72      UMA_HISTOGRAM_BOOLEAN("Search.MigratedPrefToDictionaryValue", true);
73      default_search_manager.SetUserSelectedDefaultSearchEngine(
74          *legacy_dse_from_prefs);
75    }
76  }
77
78  ClearDefaultSearchProviderFromLegacyPrefs(pref_service);
79}
80
81void OnPrefsInitialized(PrefService* pref_service,
82                        bool pref_service_initialization_success) {
83  MigrateDefaultSearchPref(pref_service);
84}
85
86}  // namespace
87
88void ConfigureDefaultSearchPrefMigrationToDictionaryValue(
89    PrefService* pref_service) {
90  if (pref_service->GetInitializationStatus() ==
91      PrefService::INITIALIZATION_STATUS_WAITING) {
92    pref_service->AddPrefInitObserver(
93        base::Bind(&OnPrefsInitialized, base::Unretained(pref_service)));
94  } else {
95    MigrateDefaultSearchPref(pref_service);
96  }
97}
98