summaryrefslogtreecommitdiffstats
path: root/chrome/browser/search_engines
diff options
context:
space:
mode:
authorcaitkp@chromium.org <caitkp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-06 07:12:49 +0000
committercaitkp@chromium.org <caitkp@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-05-06 07:12:49 +0000
commit95d064c8127e3c5c92dfb789337b03d35d1fc066 (patch)
tree07f98e2840428ef40d60d370026beb40784b82e1 /chrome/browser/search_engines
parentda2efe9d3c35968a486584a61cc862dfc9a19d8a (diff)
downloadchromium_src-95d064c8127e3c5c92dfb789337b03d35d1fc066.zip
chromium_src-95d064c8127e3c5c92dfb789337b03d35d1fc066.tar.gz
chromium_src-95d064c8127e3c5c92dfb789337b03d35d1fc066.tar.bz2
Add overrides and fallback values to DefaultSearchManager
This patch adds support for extensions (via Settings override API) and Policy to override Default search. As well as a fallback value if none of these (or prefs) are available, and logic to determine which one should be used. BUG=365762 Review URL: https://codereview.chromium.org/255313002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@268454 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/search_engines')
-rw-r--r--chrome/browser/search_engines/default_search_manager.cc357
-rw-r--r--chrome/browser/search_engines/default_search_manager.h86
-rw-r--r--chrome/browser/search_engines/default_search_manager_unittest.cc260
-rw-r--r--chrome/browser/search_engines/default_search_pref_migration.cc8
-rw-r--r--chrome/browser/search_engines/default_search_pref_migration_unittest.cc47
-rw-r--r--chrome/browser/search_engines/template_url_service.cc4
6 files changed, 630 insertions, 132 deletions
diff --git a/chrome/browser/search_engines/default_search_manager.cc b/chrome/browser/search_engines/default_search_manager.cc
index cd763d7..42deedc 100644
--- a/chrome/browser/search_engines/default_search_manager.cc
+++ b/chrome/browser/search_engines/default_search_manager.cc
@@ -7,8 +7,11 @@
#include <algorithm>
#include <utility>
+#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
#include "base/i18n/case_conversion.h"
+#include "base/logging.h"
#include "base/prefs/pref_service.h"
#include "base/prefs/pref_value_map.h"
#include "base/stl_util.h"
@@ -19,21 +22,18 @@
#include "base/time/time.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/search_engines/template_url_prepopulate_data.h"
#include "chrome/browser/search_engines/template_url_service.h"
#include "chrome/browser/search_engines/util.h"
#include "chrome/common/pref_names.h"
#include "components/user_prefs/pref_registry_syncable.h"
-namespace {
-
// A dictionary to hold all data related to the Default Search Engine.
// Eventually, this should replace all the data stored in the
// default_search_provider.* prefs.
-const char kDefaultSearchProviderData[] =
+const char DefaultSearchManager::kDefaultSearchProviderDataPrefName[] =
"default_search_provider_data.template_url_data";
-} // namespace
-
const char DefaultSearchManager::kID[] = "id";
const char DefaultSearchManager::kShortName[] = "short_name";
const char DefaultSearchManager::kKeyword[] = "keyword";
@@ -70,9 +70,25 @@ const char DefaultSearchManager::kSearchTermsReplacementKey[] =
const char DefaultSearchManager::kCreatedByPolicy[] = "created_by_policy";
const char DefaultSearchManager::kDisabledByPolicy[] = "disabled_by_policy";
-DefaultSearchManager::DefaultSearchManager(PrefService* pref_service)
- : pref_service_(pref_service) {
- DCHECK(pref_service_);
+DefaultSearchManager::DefaultSearchManager(
+ PrefService* pref_service,
+ const ObserverCallback& change_observer)
+ : pref_service_(pref_service),
+ change_observer_(change_observer),
+ default_search_controlled_by_policy_(false) {
+ if (pref_service_) {
+ pref_change_registrar_.Init(pref_service_);
+ pref_change_registrar_.Add(
+ kDefaultSearchProviderDataPrefName,
+ base::Bind(&DefaultSearchManager::OnDefaultSearchPrefChanged,
+ base::Unretained(this)));
+ pref_change_registrar_.Add(
+ prefs::kSearchProviderOverrides,
+ base::Bind(&DefaultSearchManager::OnOverridesPrefChanged,
+ base::Unretained(this)));
+ }
+ LoadPrepopulatedDefaultSearch();
+ LoadDefaultSearchEngineFromPrefs();
}
DefaultSearchManager::~DefaultSearchManager() {
@@ -82,102 +98,55 @@ DefaultSearchManager::~DefaultSearchManager() {
void DefaultSearchManager::RegisterProfilePrefs(
user_prefs::PrefRegistrySyncable* registry) {
registry->RegisterDictionaryPref(
- kDefaultSearchProviderData,
- user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
+ kDefaultSearchProviderDataPrefName,
+ user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
}
// static
void DefaultSearchManager::AddPrefValueToMap(base::DictionaryValue* value,
PrefValueMap* pref_value_map) {
- pref_value_map->SetValue(kDefaultSearchProviderData, value);
+ pref_value_map->SetValue(kDefaultSearchProviderDataPrefName, value);
}
-bool DefaultSearchManager::GetDefaultSearchEngine(TemplateURLData* data) {
- const base::DictionaryValue* url_dict =
- pref_service_->GetDictionary(kDefaultSearchProviderData);
-
- if (url_dict->empty())
- return false;
-
- std::string search_url;
- base::string16 keyword;
- url_dict->GetString(kURL, &search_url);
- url_dict->GetString(kKeyword, &keyword);
- if (search_url.empty())
- return false;
- if (keyword.empty())
- keyword = TemplateURLService::GenerateKeyword(GURL(search_url));
- data->SetKeyword(keyword);
- data->SetURL(search_url);
-
- std::string id;
- url_dict->GetString(kID, &id);
- base::StringToInt64(id, &data->id);
- url_dict->GetString(kShortName, &data->short_name);
- url_dict->GetInteger(kPrepopulateID, &data->prepopulate_id);
- url_dict->GetString(kSyncGUID, &data->sync_guid);
-
- url_dict->GetString(kSuggestionsURL, &data->suggestions_url);
- url_dict->GetString(kInstantURL, &data->instant_url);
- url_dict->GetString(kImageURL, &data->image_url);
- url_dict->GetString(kNewTabURL, &data->new_tab_url);
-
- std::string favicon_url;
- std::string originating_url;
- url_dict->GetString(kFaviconURL, &favicon_url);
- url_dict->GetString(kOriginatingURL, &originating_url);
- data->favicon_url = GURL(favicon_url);
- data->originating_url = GURL(originating_url);
-
- url_dict->GetString(kSearchURLPostParams, &data->search_url_post_params);
- url_dict->GetString(kSuggestionsURLPostParams,
- &data->suggestions_url_post_params);
- url_dict->GetString(kInstantURLPostParams, &data->instant_url_post_params);
- url_dict->GetString(kImageURLPostParams, &data->image_url_post_params);
-
- url_dict->GetBoolean(kSafeForAutoReplace, &data->safe_for_autoreplace);
-
- double date_created = 0.0;
- double last_modified = 0.0;
- url_dict->GetDouble(kDateCreated, &date_created);
- url_dict->GetDouble(kLastModified, &last_modified);
- data->date_created = base::Time::FromInternalValue(date_created);
- data->last_modified = base::Time::FromInternalValue(last_modified);
-
- url_dict->GetInteger(kUsageCount, &data->usage_count);
-
- const base::ListValue* alternate_urls;
- url_dict->GetList(kAlternateURLs, &alternate_urls);
- data->alternate_urls.clear();
- for (base::ListValue::const_iterator it = alternate_urls->begin();
- it != alternate_urls->end(); ++it) {
- std::string alternate_url;
- if ((*it)->GetAsString(&alternate_url))
- data->alternate_urls.push_back(alternate_url);
+TemplateURLData* DefaultSearchManager::GetDefaultSearchEngine(
+ Source* source) const {
+ if (default_search_controlled_by_policy_) {
+ if (source)
+ *source = FROM_POLICY;
+ return prefs_default_search_.get();
}
-
- const base::ListValue* encodings;
- url_dict->GetList(kInputEncodings, &encodings);
- data->input_encodings.clear();
- for (base::ListValue::const_iterator it = encodings->begin();
- it != encodings->end(); ++it) {
- std::string encoding;
- if ((*it)->GetAsString(&encoding))
- data->input_encodings.push_back(encoding);
+ if (extension_default_search_) {
+ if (source)
+ *source = FROM_EXTENSION;
+ return extension_default_search_.get();
+ }
+ if (prefs_default_search_) {
+ if (source)
+ *source = FROM_USER;
+ return prefs_default_search_.get();
}
- url_dict->GetString(kSearchTermsReplacementKey,
- &data->search_terms_replacement_key);
-
- url_dict->GetBoolean(kCreatedByPolicy, &data->created_by_policy);
-
- data->show_in_default_list = true;
+ if (source)
+ *source = FROM_FALLBACK;
+ return fallback_default_search_.get();
+}
- return true;
+DefaultSearchManager::Source
+DefaultSearchManager::GetDefaultSearchEngineSource() const {
+ Source source;
+ GetDefaultSearchEngine(&source);
+ return source;
}
void DefaultSearchManager::SetUserSelectedDefaultSearchEngine(
const TemplateURLData& data) {
+ if (!pref_service_) {
+ prefs_default_search_.reset(new TemplateURLData(data));
+ MergePrefsDataWithPrepopulated();
+ NotifyObserver();
+ return;
+ }
+
base::DictionaryValue url_dict;
url_dict.SetString(kID, base::Int64ToString(data.id));
url_dict.SetString(kShortName, data.short_name);
@@ -201,8 +170,10 @@ void DefaultSearchManager::SetUserSelectedDefaultSearchEngine(
url_dict.SetBoolean(kSafeForAutoReplace, data.safe_for_autoreplace);
- url_dict.SetDouble(kDateCreated, data.date_created.ToInternalValue());
- url_dict.SetDouble(kLastModified, data.last_modified.ToInternalValue());
+ url_dict.SetString(kDateCreated,
+ base::Int64ToString(data.date_created.ToInternalValue()));
+ url_dict.SetString(kLastModified,
+ base::Int64ToString(data.last_modified.ToInternalValue()));
url_dict.SetInteger(kUsageCount, data.usage_count);
scoped_ptr<base::ListValue> alternate_urls(new base::ListValue);
@@ -226,9 +197,209 @@ void DefaultSearchManager::SetUserSelectedDefaultSearchEngine(
url_dict.SetBoolean(kCreatedByPolicy, data.created_by_policy);
- pref_service_->Set(kDefaultSearchProviderData, url_dict);
+ pref_service_->Set(kDefaultSearchProviderDataPrefName, url_dict);
+}
+
+void DefaultSearchManager::SetExtensionControlledDefaultSearchEngine(
+ const TemplateURLData& data) {
+ extension_default_search_.reset(new TemplateURLData(data));
+ if (GetDefaultSearchEngineSource() == FROM_EXTENSION)
+ NotifyObserver();
+}
+
+void DefaultSearchManager::ClearExtensionControlledDefaultSearchEngine() {
+ Source old_source = GetDefaultSearchEngineSource();
+ extension_default_search_.reset();
+ if (old_source == FROM_EXTENSION)
+ NotifyObserver();
}
void DefaultSearchManager::ClearUserSelectedDefaultSearchEngine() {
- pref_service_->ClearPref(kDefaultSearchProviderData);
+ if (pref_service_) {
+ pref_service_->ClearPref(kDefaultSearchProviderDataPrefName);
+ } else {
+ prefs_default_search_.reset();
+ NotifyObserver();
+ }
+}
+
+void DefaultSearchManager::OnDefaultSearchPrefChanged() {
+ Source source = GetDefaultSearchEngineSource();
+ LoadDefaultSearchEngineFromPrefs();
+
+ // If we were/are FROM_USER or FROM_POLICY the effective DSE may have changed.
+ if (source != FROM_USER && source != FROM_POLICY)
+ source = GetDefaultSearchEngineSource();
+ if (source == FROM_USER || source == FROM_POLICY)
+ NotifyObserver();
+}
+
+void DefaultSearchManager::OnOverridesPrefChanged() {
+ LoadPrepopulatedDefaultSearch();
+
+ TemplateURLData* effective_data = GetDefaultSearchEngine(NULL);
+ if (effective_data && effective_data->prepopulate_id) {
+ // A user-selected, policy-selected or fallback pre-populated engine is
+ // active and may have changed with this event.
+ NotifyObserver();
+ }
+}
+
+void DefaultSearchManager::MergePrefsDataWithPrepopulated() {
+ if (!prefs_default_search_ || !prefs_default_search_->prepopulate_id)
+ return;
+
+ size_t default_search_index;
+ ScopedVector<TemplateURLData> prepopulated_urls =
+ TemplateURLPrepopulateData::GetPrepopulatedEngines(pref_service_,
+ &default_search_index);
+
+ for (size_t i = 0; i < prepopulated_urls.size(); ++i) {
+ if (prepopulated_urls[i]->prepopulate_id ==
+ prefs_default_search_->prepopulate_id) {
+ if (!prefs_default_search_->safe_for_autoreplace) {
+ prepopulated_urls[i]->safe_for_autoreplace = false;
+ prepopulated_urls[i]->SetKeyword(prefs_default_search_->keyword());
+ prepopulated_urls[i]->short_name = prefs_default_search_->short_name;
+ }
+ prepopulated_urls[i]->id = prefs_default_search_->id;
+ prepopulated_urls[i]->sync_guid = prefs_default_search_->sync_guid;
+ prepopulated_urls[i]->date_created = prefs_default_search_->date_created;
+ prepopulated_urls[i]->last_modified =
+ prefs_default_search_->last_modified;
+ prefs_default_search_.reset(prepopulated_urls[i]);
+ prepopulated_urls.weak_erase(prepopulated_urls.begin() + i);
+ return;
+ }
+ }
+}
+
+void DefaultSearchManager::LoadDefaultSearchEngineFromPrefs() {
+ if (!pref_service_)
+ return;
+
+ prefs_default_search_.reset();
+ const PrefService::Preference* pref =
+ pref_service_->FindPreference(kDefaultSearchProviderDataPrefName);
+ DCHECK(pref);
+ default_search_controlled_by_policy_ = pref->IsManaged();
+
+ const base::DictionaryValue* url_dict =
+ pref_service_->GetDictionary(kDefaultSearchProviderDataPrefName);
+ if (url_dict->empty())
+ return;
+
+ if (default_search_controlled_by_policy_) {
+ bool disabled_by_policy = false;
+ if (url_dict->GetBoolean(kDisabledByPolicy, &disabled_by_policy) &&
+ disabled_by_policy)
+ return;
+ }
+
+ std::string search_url;
+ base::string16 keyword;
+ url_dict->GetString(kURL, &search_url);
+ url_dict->GetString(kKeyword, &keyword);
+ if (search_url.empty() || keyword.empty())
+ return;
+
+ prefs_default_search_.reset(new TemplateURLData);
+ prefs_default_search_->SetKeyword(keyword);
+ prefs_default_search_->SetURL(search_url);
+
+ std::string id;
+ url_dict->GetString(kID, &id);
+ base::StringToInt64(id, &prefs_default_search_->id);
+ url_dict->GetString(kShortName, &prefs_default_search_->short_name);
+ url_dict->GetInteger(kPrepopulateID, &prefs_default_search_->prepopulate_id);
+ url_dict->GetString(kSyncGUID, &prefs_default_search_->sync_guid);
+
+ url_dict->GetString(kSuggestionsURL, &prefs_default_search_->suggestions_url);
+ url_dict->GetString(kInstantURL, &prefs_default_search_->instant_url);
+ url_dict->GetString(kImageURL, &prefs_default_search_->image_url);
+ url_dict->GetString(kNewTabURL, &prefs_default_search_->new_tab_url);
+
+ std::string favicon_url;
+ std::string originating_url;
+ url_dict->GetString(kFaviconURL, &favicon_url);
+ url_dict->GetString(kOriginatingURL, &originating_url);
+ prefs_default_search_->favicon_url = GURL(favicon_url);
+ prefs_default_search_->originating_url = GURL(originating_url);
+
+ url_dict->GetString(kSearchURLPostParams,
+ &prefs_default_search_->search_url_post_params);
+ url_dict->GetString(kSuggestionsURLPostParams,
+ &prefs_default_search_->suggestions_url_post_params);
+ url_dict->GetString(kInstantURLPostParams,
+ &prefs_default_search_->instant_url_post_params);
+ url_dict->GetString(kImageURLPostParams,
+ &prefs_default_search_->image_url_post_params);
+
+ url_dict->GetBoolean(kSafeForAutoReplace,
+ &prefs_default_search_->safe_for_autoreplace);
+
+ std::string date_created_str;
+ std::string last_modified_str;
+ url_dict->GetString(kDateCreated, &date_created_str);
+ url_dict->GetString(kLastModified, &last_modified_str);
+
+ int64 date_created = 0;
+ if (base::StringToInt64(date_created_str, &date_created)) {
+ prefs_default_search_->date_created =
+ base::Time::FromInternalValue(date_created);
+ }
+
+ int64 last_modified = 0;
+ if (base::StringToInt64(date_created_str, &last_modified)) {
+ prefs_default_search_->last_modified =
+ base::Time::FromInternalValue(last_modified);
+ }
+
+ url_dict->GetInteger(kUsageCount, &prefs_default_search_->usage_count);
+
+ const base::ListValue* alternate_urls = NULL;
+ if (url_dict->GetList(kAlternateURLs, &alternate_urls)) {
+ for (base::ListValue::const_iterator it = alternate_urls->begin();
+ it != alternate_urls->end();
+ ++it) {
+ std::string alternate_url;
+ if ((*it)->GetAsString(&alternate_url))
+ prefs_default_search_->alternate_urls.push_back(alternate_url);
+ }
+ }
+
+ const base::ListValue* encodings = NULL;
+ if (url_dict->GetList(kInputEncodings, &encodings)) {
+ for (base::ListValue::const_iterator it = encodings->begin();
+ it != encodings->end();
+ ++it) {
+ std::string encoding;
+ if ((*it)->GetAsString(&encoding))
+ prefs_default_search_->input_encodings.push_back(encoding);
+ }
+ }
+
+ url_dict->GetString(kSearchTermsReplacementKey,
+ &prefs_default_search_->search_terms_replacement_key);
+
+ url_dict->GetBoolean(kCreatedByPolicy,
+ &prefs_default_search_->created_by_policy);
+
+ prefs_default_search_->show_in_default_list = true;
+ MergePrefsDataWithPrepopulated();
+}
+
+void DefaultSearchManager::LoadPrepopulatedDefaultSearch() {
+ scoped_ptr<TemplateURLData> data =
+ TemplateURLPrepopulateData::GetPrepopulatedDefaultSearch(pref_service_);
+ fallback_default_search_ = data.Pass();
+ MergePrefsDataWithPrepopulated();
+}
+
+void DefaultSearchManager::NotifyObserver() {
+ if (!change_observer_.is_null()) {
+ Source source = FROM_FALLBACK;
+ TemplateURLData* data = GetDefaultSearchEngine(&source);
+ change_observer_.Run(data, source);
+ }
}
diff --git a/chrome/browser/search_engines/default_search_manager.h b/chrome/browser/search_engines/default_search_manager.h
index 9035564..95a5bfb 100644
--- a/chrome/browser/search_engines/default_search_manager.h
+++ b/chrome/browser/search_engines/default_search_manager.h
@@ -5,7 +5,10 @@
#ifndef CHROME_BROWSER_SEARCH_ENGINES_DEFAULT_SEARCH_MANAGER_H_
#define CHROME_BROWSER_SEARCH_ENGINES_DEFAULT_SEARCH_MANAGER_H_
+#include "base/callback.h"
#include "base/macros.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/prefs/pref_change_registrar.h"
namespace base {
class DictionaryValue;
@@ -21,9 +24,10 @@ struct TemplateURLData;
// DefaultSearchManager handles the loading and writing of the user's default
// search engine selection to and from prefs.
-
class DefaultSearchManager {
public:
+ static const char kDefaultSearchProviderDataPrefName[];
+
static const char kID[];
static const char kShortName[];
static const char kKeyword[];
@@ -55,7 +59,18 @@ class DefaultSearchManager {
static const char kCreatedByPolicy[];
static const char kDisabledByPolicy[];
- explicit DefaultSearchManager(PrefService* pref_service);
+ enum Source {
+ FROM_FALLBACK = 0,
+ FROM_USER,
+ FROM_EXTENSION,
+ FROM_POLICY,
+ };
+
+ typedef base::Callback<void(const TemplateURLData*, Source)> ObserverCallback;
+
+ DefaultSearchManager(PrefService* pref_service,
+ const ObserverCallback& change_observer);
+
~DefaultSearchManager();
// Register prefs needed for tracking the default search provider.
@@ -65,17 +80,78 @@ class DefaultSearchManager {
static void AddPrefValueToMap(base::DictionaryValue* value,
PrefValueMap* pref_value_map);
- // Read default search provider data from |pref_service_|.
- bool GetDefaultSearchEngine(TemplateURLData* url);
+ // Gets a pointer to the current Default Search Engine. If NULL, indicates
+ // that Default Search is explicitly disabled. |source|, if not NULL, will be
+ // filled in with the source of the result.
+ TemplateURLData* GetDefaultSearchEngine(Source* source) const;
+
+ // Gets the source of the current Default Search Engine value.
+ Source GetDefaultSearchEngineSource() const;
// Write default search provider data to |pref_service_|.
void SetUserSelectedDefaultSearchEngine(const TemplateURLData& data);
- // Clear the user's default search provider choice from |pref_service_|.
+ // Override the default search provider with an extension.
+ void SetExtensionControlledDefaultSearchEngine(const TemplateURLData& data);
+
+ // Clear the extension-provided default search engine. Does not explicitly
+ // disable Default Search. The new current default search engine will be
+ // defined by policy, extensions, or pre-populated data.
+ void ClearExtensionControlledDefaultSearchEngine();
+
+ // Clear the user's default search provider choice from |pref_service_|. Does
+ // not explicitly disable Default Search. The new default search
+ // engine will be defined by policy, extensions, or pre-populated data.
void ClearUserSelectedDefaultSearchEngine();
private:
+ // Handles changes to kDefaultSearchProviderData pref. This includes sync and
+ // policy changes. Calls LoadDefaultSearchEngineFromPrefs() and
+ // NotifyObserver() if the effective DSE might have changed.
+ void OnDefaultSearchPrefChanged();
+
+ // Handles changes to kSearchProviderOverrides pref. Calls
+ // LoadPrepopulatedDefaultSearch() and NotifyObserver() if the effective DSE
+ // might have changed.
+ void OnOverridesPrefChanged();
+
+ // Updates |prefs_default_search_| with values from its corresponding
+ // pre-populated search provider record, if any.
+ void MergePrefsDataWithPrepopulated();
+
+ // Reads default search provider data from |pref_service_|, updating
+ // |prefs_default_search_| and |default_search_controlled_by_policy_|.
+ // Invokes MergePrefsDataWithPrepopulated().
+ void LoadDefaultSearchEngineFromPrefs();
+
+ // Reads pre-populated search providers, which will be built-in or overridden
+ // by kSearchProviderOverrides. Updates |fallback_default_search_|. Invoke
+ // MergePrefsDataWithPrepopulated().
+ void LoadPrepopulatedDefaultSearch();
+
+ // Invokes |change_observer_| if it is not NULL.
+ void NotifyObserver();
+
PrefService* pref_service_;
+ const ObserverCallback change_observer_;
+ PrefChangeRegistrar pref_change_registrar_;
+
+ // Default search engine provided by pre-populated data or by the
+ // |kSearchProviderOverrides| pref. This will be used when no other default
+ // search engine has been selected.
+ scoped_ptr<TemplateURLData> fallback_default_search_;
+
+ // Default search engine provided by prefs (either user prefs or policy
+ // prefs). This will be null if no value was set in the pref store.
+ scoped_ptr<TemplateURLData> extension_default_search_;
+
+ // Default search engine provided by extension (usings Settings Override API).
+ // This will be null if there are no extensions installed which provide
+ // default search engines.
+ scoped_ptr<TemplateURLData> prefs_default_search_;
+
+ // True if the default search is currently enforced by policy.
+ bool default_search_controlled_by_policy_;
DISALLOW_COPY_AND_ASSIGN(DefaultSearchManager);
};
diff --git a/chrome/browser/search_engines/default_search_manager_unittest.cc b/chrome/browser/search_engines/default_search_manager_unittest.cc
index 9dd2cb5..fd6f99f 100644
--- a/chrome/browser/search_engines/default_search_manager_unittest.cc
+++ b/chrome/browser/search_engines/default_search_manager_unittest.cc
@@ -3,19 +3,27 @@
// found in the LICENSE file.
#include "base/files/scoped_temp_dir.h"
+#include "base/memory/scoped_ptr.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "chrome/browser/search_engines/default_search_manager.h"
#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/search_engines/template_url_prepopulate_data.h"
+#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_pref_service_syncable.h"
#include "components/user_prefs/pref_registry_syncable.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
+// A dictionary to hold all data related to the Default Search Engine.
+// Eventually, this should replace all the data stored in the
+// default_search_provider.* prefs.
+const char kDefaultSearchProviderData[] =
+ "default_search_provider_data.template_url_data";
-// Checks that the two TemplateURLs are similar. It does not check the id, the
+// Checks that the two TemplateURLs are similar. Does not check the id, the
// date_created or the last_modified time. Neither pointer should be NULL.
void ExpectSimilar(const TemplateURLData* expected,
const TemplateURLData* actual) {
@@ -35,6 +43,98 @@ void ExpectSimilar(const TemplateURLData* expected,
actual->search_terms_replacement_key);
}
+// TODO(caitkp): TemplateURLData-ify this.
+void SetOverrides(TestingPrefServiceSyncable* prefs, bool update) {
+ prefs->SetUserPref(prefs::kSearchProviderOverridesVersion,
+ base::Value::CreateIntegerValue(1));
+ base::ListValue* overrides = new base::ListValue;
+ scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue);
+
+ entry->SetString("name", update ? "new_foo" : "foo");
+ entry->SetString("keyword", update ? "new_fook" : "fook");
+ entry->SetString("search_url", "http://foo.com/s?q={searchTerms}");
+ entry->SetString("favicon_url", "http://foi.com/favicon.ico");
+ entry->SetString("encoding", "UTF-8");
+ entry->SetInteger("id", 1001);
+ entry->SetString("suggest_url", "http://foo.com/suggest?q={searchTerms}");
+ entry->SetString("instant_url", "http://foo.com/instant?q={searchTerms}");
+ base::ListValue* alternate_urls = new base::ListValue;
+ alternate_urls->AppendString("http://foo.com/alternate?q={searchTerms}");
+ entry->Set("alternate_urls", alternate_urls);
+ entry->SetString("search_terms_replacement_key", "espv");
+ overrides->Append(entry->DeepCopy());
+
+ entry.reset(new base::DictionaryValue);
+ entry->SetInteger("id", 1002);
+ entry->SetString("name", update ? "new_bar" : "bar");
+ entry->SetString("keyword", update ? "new_bark" : "bark");
+ entry->SetString("encoding", std::string());
+ overrides->Append(entry->DeepCopy());
+ entry->SetInteger("id", 1003);
+ entry->SetString("name", "baz");
+ entry->SetString("keyword", "bazk");
+ entry->SetString("encoding", "UTF-8");
+ overrides->Append(entry->DeepCopy());
+ prefs->SetUserPref(prefs::kSearchProviderOverrides, overrides);
+}
+
+void SetPolicy(TestingPrefServiceSyncable* prefs,
+ bool enabled,
+ TemplateURLData* data) {
+ if (enabled) {
+ EXPECT_FALSE(data->keyword().empty());
+ EXPECT_FALSE(data->url().empty());
+ }
+ scoped_ptr<base::DictionaryValue> entry(new base::DictionaryValue);
+ entry->SetString(DefaultSearchManager::kShortName, data->short_name);
+ entry->SetString(DefaultSearchManager::kKeyword, data->keyword());
+ entry->SetString(DefaultSearchManager::kURL, data->url());
+ entry->SetString(DefaultSearchManager::kFaviconURL, data->favicon_url.spec());
+ entry->SetString(DefaultSearchManager::kSuggestionsURL,
+ data->suggestions_url);
+ entry->SetBoolean(DefaultSearchManager::kSafeForAutoReplace,
+ data->safe_for_autoreplace);
+ scoped_ptr<base::ListValue> alternate_urls(new base::ListValue);
+ for (std::vector<std::string>::const_iterator it =
+ data->alternate_urls.begin();
+ it != data->alternate_urls.end();
+ ++it) {
+ alternate_urls->AppendString(*it);
+ }
+ entry->Set(DefaultSearchManager::kAlternateURLs, alternate_urls.release());
+
+ scoped_ptr<base::ListValue> encodings(new base::ListValue);
+ for (std::vector<std::string>::const_iterator it =
+ data->input_encodings.begin();
+ it != data->input_encodings.end();
+ ++it) {
+ encodings->AppendString(*it);
+ }
+ entry->Set(DefaultSearchManager::kInputEncodings, encodings.release());
+
+ entry->SetString(DefaultSearchManager::kSearchTermsReplacementKey,
+ data->search_terms_replacement_key);
+ entry->SetBoolean(DefaultSearchManager::kDisabledByPolicy, !enabled);
+ prefs->SetManagedPref(kDefaultSearchProviderData, entry.release());
+}
+
+scoped_ptr<TemplateURLData> GenerateDummyTemplateURLData(std::string type) {
+ scoped_ptr<TemplateURLData> data(new TemplateURLData());
+ data->short_name = base::UTF8ToUTF16(std::string(type).append("name"));
+ data->SetKeyword(base::UTF8ToUTF16(std::string(type).append("key")));
+ data->SetURL(std::string("http://").append(type).append("foo/{searchTerms}"));
+ data->suggestions_url = std::string("http://").append(type).append("sugg");
+ data->alternate_urls.push_back(
+ std::string("http://").append(type).append("foo/alt"));
+ data->favicon_url = GURL("http://icon1");
+ data->safe_for_autoreplace = true;
+ data->show_in_default_list = true;
+ base::SplitString("UTF-8;UTF-16", ';', &data->input_encodings);
+ data->date_created = base::Time();
+ data->last_modified = base::Time();
+ return data.Pass();
+}
+
} // namespace
class DefaultSearchManagerTest : public testing::Test {
@@ -44,9 +144,10 @@ class DefaultSearchManagerTest : public testing::Test {
virtual void SetUp() OVERRIDE {
pref_service_.reset(new TestingPrefServiceSyncable);
DefaultSearchManager::RegisterProfilePrefs(pref_service_->registry());
+ TemplateURLPrepopulateData::RegisterProfilePrefs(pref_service_->registry());
}
- PrefService* pref_service() { return pref_service_.get(); }
+ TestingPrefServiceSyncable* pref_service() { return pref_service_.get(); }
private:
scoped_ptr<TestingPrefServiceSyncable> pref_service_;
@@ -56,7 +157,8 @@ class DefaultSearchManagerTest : public testing::Test {
// Test that a TemplateURLData object is properly written and read from Prefs.
TEST_F(DefaultSearchManagerTest, ReadAndWritePref) {
- DefaultSearchManager manager(pref_service());
+ DefaultSearchManager manager(pref_service(),
+ DefaultSearchManager::ObserverCallback());
TemplateURLData data;
data.short_name = base::UTF8ToUTF16("name1");
data.SetKeyword(base::UTF8ToUTF16("key1"));
@@ -71,14 +173,150 @@ TEST_F(DefaultSearchManagerTest, ReadAndWritePref) {
data.last_modified = base::Time();
manager.SetUserSelectedDefaultSearchEngine(data);
- TemplateURLData read_data;
- manager.GetDefaultSearchEngine(&read_data);
- ExpectSimilar(&data, &read_data);
+ TemplateURLData* read_data = manager.GetDefaultSearchEngine(NULL);
+ ExpectSimilar(&data, read_data);
+}
+
+// Test DefaultSearchmanager handles user-selected DSEs correctly.
+TEST_F(DefaultSearchManagerTest, DefaultSearchSetByUserPref) {
+ size_t default_search_index = 0;
+ DefaultSearchManager manager(pref_service(),
+ DefaultSearchManager::ObserverCallback());
+ ScopedVector<TemplateURLData> prepopulated_urls =
+ TemplateURLPrepopulateData::GetPrepopulatedEngines(pref_service(),
+ &default_search_index);
+ DefaultSearchManager::Source source = DefaultSearchManager::FROM_POLICY;
+ // If no user pref is set, we should use the pre-populated values.
+ ExpectSimilar(prepopulated_urls[default_search_index],
+ manager.GetDefaultSearchEngine(&source));
+ EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, source);
+
+ // Setting a user pref overrides the pre-populated values.
+ scoped_ptr<TemplateURLData> data = GenerateDummyTemplateURLData("user");
+ manager.SetUserSelectedDefaultSearchEngine(*data.get());
+
+ ExpectSimilar(data.get(), manager.GetDefaultSearchEngine(&source));
+ EXPECT_EQ(DefaultSearchManager::FROM_USER, source);
+
+ // Updating the user pref (externally to this instance of
+ // DefaultSearchManager) triggers an update.
+ scoped_ptr<TemplateURLData> new_data = GenerateDummyTemplateURLData("user2");
+ DefaultSearchManager other_manager(pref_service(),
+ DefaultSearchManager::ObserverCallback());
+ other_manager.SetUserSelectedDefaultSearchEngine(*new_data.get());
+
+ ExpectSimilar(new_data.get(), manager.GetDefaultSearchEngine(&source));
+ EXPECT_EQ(DefaultSearchManager::FROM_USER, source);
+
+ // Clearing the user pref should cause the default search to revert to the
+ // prepopulated vlaues.
+ manager.ClearUserSelectedDefaultSearchEngine();
+ ExpectSimilar(prepopulated_urls[default_search_index],
+ manager.GetDefaultSearchEngine(&source));
+ EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, source);
}
-// Test that there is no default value set in the pref.
-TEST_F(DefaultSearchManagerTest, ReadDefaultPref) {
- DefaultSearchManager manager(pref_service());
- TemplateURLData read_data;
- EXPECT_FALSE(manager.GetDefaultSearchEngine(&read_data));
+// Test that DefaultSearch manager detects changes to kSearchProviderOverrides.
+TEST_F(DefaultSearchManagerTest, DefaultSearchSetByOverrides) {
+ SetOverrides(pref_service(), false);
+ size_t default_search_index = 0;
+ DefaultSearchManager manager(pref_service(),
+ DefaultSearchManager::ObserverCallback());
+ ScopedVector<TemplateURLData> prepopulated_urls =
+ TemplateURLPrepopulateData::GetPrepopulatedEngines(pref_service(),
+ &default_search_index);
+
+ DefaultSearchManager::Source source = DefaultSearchManager::FROM_POLICY;
+ TemplateURLData first_default(*manager.GetDefaultSearchEngine(&source));
+ ExpectSimilar(prepopulated_urls[default_search_index], &first_default);
+ EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, source);
+
+ // Update the overrides:
+ SetOverrides(pref_service(), true);
+ prepopulated_urls = TemplateURLPrepopulateData::GetPrepopulatedEngines(
+ pref_service(), &default_search_index);
+
+ // Make sure DefaultSearchManager updated:
+ ExpectSimilar(prepopulated_urls[default_search_index],
+ manager.GetDefaultSearchEngine(&source));
+ EXPECT_EQ(DefaultSearchManager::FROM_FALLBACK, source);
+ EXPECT_NE(manager.GetDefaultSearchEngine(NULL)->short_name,
+ first_default.short_name);
+ EXPECT_NE(manager.GetDefaultSearchEngine(NULL)->keyword(),
+ first_default.keyword());
+}
+
+// Test DefaultSearchManager handles policy-enforced DSEs correctly.
+TEST_F(DefaultSearchManagerTest, DefaultSearchSetByPolicy) {
+ DefaultSearchManager manager(pref_service(),
+ DefaultSearchManager::ObserverCallback());
+ scoped_ptr<TemplateURLData> data = GenerateDummyTemplateURLData("user");
+ manager.SetUserSelectedDefaultSearchEngine(*data.get());
+
+ DefaultSearchManager::Source source = DefaultSearchManager::FROM_FALLBACK;
+ ExpectSimilar(data.get(), manager.GetDefaultSearchEngine(&source));
+ EXPECT_EQ(DefaultSearchManager::FROM_USER, source);
+
+ scoped_ptr<TemplateURLData> policy_data =
+ GenerateDummyTemplateURLData("policy");
+ SetPolicy(pref_service(), true, policy_data.get());
+
+ ExpectSimilar(policy_data.get(), manager.GetDefaultSearchEngine(&source));
+ EXPECT_EQ(DefaultSearchManager::FROM_POLICY, source);
+
+ TemplateURLData null_policy_data;
+ SetPolicy(pref_service(), false, &null_policy_data);
+ EXPECT_EQ(NULL, manager.GetDefaultSearchEngine(&source));
+ EXPECT_EQ(DefaultSearchManager::FROM_POLICY, source);
+
+ pref_service()->RemoveManagedPref(kDefaultSearchProviderData);
+ ExpectSimilar(data.get(), manager.GetDefaultSearchEngine(&source));
+ EXPECT_EQ(DefaultSearchManager::FROM_USER, source);
+}
+
+// Test DefaultSearchManager handles extension-controlled DSEs correctly.
+TEST_F(DefaultSearchManagerTest, DefaultSearchSetByExtension) {
+ DefaultSearchManager manager(pref_service(),
+ DefaultSearchManager::ObserverCallback());
+ scoped_ptr<TemplateURLData> data = GenerateDummyTemplateURLData("user");
+ manager.SetUserSelectedDefaultSearchEngine(*data);
+
+ DefaultSearchManager::Source source = DefaultSearchManager::FROM_FALLBACK;
+ ExpectSimilar(data.get(), manager.GetDefaultSearchEngine(&source));
+ EXPECT_EQ(DefaultSearchManager::FROM_USER, source);
+
+ // Extension trumps prefs:
+ scoped_ptr<TemplateURLData> extension_data_1 =
+ GenerateDummyTemplateURLData("ext1");
+ manager.SetExtensionControlledDefaultSearchEngine(*extension_data_1);
+
+ ExpectSimilar(extension_data_1.get(),
+ manager.GetDefaultSearchEngine(&source));
+ EXPECT_EQ(DefaultSearchManager::FROM_EXTENSION, source);
+
+ // Policy trumps extension:
+ scoped_ptr<TemplateURLData> policy_data =
+ GenerateDummyTemplateURLData("policy");
+ SetPolicy(pref_service(), true, policy_data.get());
+
+ ExpectSimilar(policy_data.get(), manager.GetDefaultSearchEngine(&source));
+ EXPECT_EQ(DefaultSearchManager::FROM_POLICY, source);
+ pref_service()->RemoveManagedPref(kDefaultSearchProviderData);
+
+ // Extensions trump each other:
+ scoped_ptr<TemplateURLData> extension_data_2 =
+ GenerateDummyTemplateURLData("ext2");
+ scoped_ptr<TemplateURLData> extension_data_3 =
+ GenerateDummyTemplateURLData("ext3");
+ manager.SetExtensionControlledDefaultSearchEngine(*extension_data_2);
+ manager.SetExtensionControlledDefaultSearchEngine(*extension_data_3);
+
+ ExpectSimilar(extension_data_3.get(),
+ manager.GetDefaultSearchEngine(&source));
+ EXPECT_EQ(DefaultSearchManager::FROM_EXTENSION, source);
+
+ manager.ClearExtensionControlledDefaultSearchEngine();
+
+ ExpectSimilar(data.get(), manager.GetDefaultSearchEngine(&source));
+ EXPECT_EQ(DefaultSearchManager::FROM_USER, source);
}
diff --git a/chrome/browser/search_engines/default_search_pref_migration.cc b/chrome/browser/search_engines/default_search_pref_migration.cc
index 4d7625e..7516bfc 100644
--- a/chrome/browser/search_engines/default_search_pref_migration.cc
+++ b/chrome/browser/search_engines/default_search_pref_migration.cc
@@ -17,11 +17,13 @@
namespace {
void MigrateDefaultSearchPref(PrefService* pref_service) {
- DefaultSearchManager default_search_manager(pref_service);
+ DefaultSearchManager default_search_manager(
+ pref_service, DefaultSearchManager::ObserverCallback());
- TemplateURLData modern_user_dse;
- if (default_search_manager.GetDefaultSearchEngine(&modern_user_dse))
+ if (default_search_manager.GetDefaultSearchEngineSource() ==
+ DefaultSearchManager::FROM_USER) {
return;
+ }
scoped_ptr<TemplateURLData> legacy_dse_from_prefs;
bool legacy_is_managed = false;
diff --git a/chrome/browser/search_engines/default_search_pref_migration_unittest.cc b/chrome/browser/search_engines/default_search_pref_migration_unittest.cc
index 9d85c0e..5a1fa35 100644
--- a/chrome/browser/search_engines/default_search_pref_migration_unittest.cc
+++ b/chrome/browser/search_engines/default_search_pref_migration_unittest.cc
@@ -72,12 +72,13 @@ TEST_F(DefaultSearchPrefMigrationTest, MigrateUserSelectedValue) {
test_util()->profile()->GetPrefs());
// Test that it was migrated.
- TemplateURLData modern_default;
- ASSERT_TRUE(DefaultSearchManager(test_util()->profile()->GetPrefs())
- .GetDefaultSearchEngine(&modern_default));
- EXPECT_EQ(t_url->short_name(), modern_default.short_name);
- EXPECT_EQ(t_url->keyword(), modern_default.keyword());
- EXPECT_EQ(t_url->url(), modern_default.url());
+ DefaultSearchManager manager(test_util()->profile()->GetPrefs(),
+ DefaultSearchManager::ObserverCallback());
+ TemplateURLData* modern_default = manager.GetDefaultSearchEngine(NULL);
+ ASSERT_TRUE(modern_default);
+ EXPECT_EQ(t_url->short_name(), modern_default->short_name);
+ EXPECT_EQ(t_url->keyword(), modern_default->keyword());
+ EXPECT_EQ(t_url->url(), modern_default->url());
}
TEST_F(DefaultSearchPrefMigrationTest, ModernValuePresent) {
@@ -90,7 +91,8 @@ TEST_F(DefaultSearchPrefMigrationTest, ModernValuePresent) {
t_url.get(), test_util()->profile()->GetPrefs());
// Store another value in the modern location.
- DefaultSearchManager(test_util()->profile()->GetPrefs())
+ DefaultSearchManager(test_util()->profile()->GetPrefs(),
+ DefaultSearchManager::ObserverCallback())
.SetUserSelectedDefaultSearchEngine(t_url2->data());
// Run the migration.
@@ -98,12 +100,13 @@ TEST_F(DefaultSearchPrefMigrationTest, ModernValuePresent) {
test_util()->profile()->GetPrefs());
// Test that no migration occurred. The modern value is left intact.
- TemplateURLData modern_default;
- ASSERT_TRUE(DefaultSearchManager(test_util()->profile()->GetPrefs())
- .GetDefaultSearchEngine(&modern_default));
- EXPECT_EQ(t_url2->short_name(), modern_default.short_name);
- EXPECT_EQ(t_url2->keyword(), modern_default.keyword());
- EXPECT_EQ(t_url2->url(), modern_default.url());
+ DefaultSearchManager manager(test_util()->profile()->GetPrefs(),
+ DefaultSearchManager::ObserverCallback());
+ TemplateURLData* modern_default = manager.GetDefaultSearchEngine(NULL);
+ ASSERT_TRUE(modern_default);
+ EXPECT_EQ(t_url2->short_name(), modern_default->short_name);
+ EXPECT_EQ(t_url2->keyword(), modern_default->keyword());
+ EXPECT_EQ(t_url2->url(), modern_default->url());
}
TEST_F(DefaultSearchPrefMigrationTest,
@@ -124,9 +127,10 @@ TEST_F(DefaultSearchPrefMigrationTest,
test_util()->profile()->GetPrefs());
// Test that the legacy value is not migrated, as it is not user-selected.
- TemplateURLData modern_default;
- ASSERT_FALSE(DefaultSearchManager(test_util()->profile()->GetPrefs())
- .GetDefaultSearchEngine(&modern_default));
+ ASSERT_EQ(DefaultSearchManager::FROM_FALLBACK,
+ DefaultSearchManager(test_util()->profile()->GetPrefs(),
+ DefaultSearchManager::ObserverCallback())
+ .GetDefaultSearchEngineSource());
}
TEST_F(DefaultSearchPrefMigrationTest, ManagedValueIsNotMigrated) {
@@ -164,8 +168,13 @@ TEST_F(DefaultSearchPrefMigrationTest, ManagedValueIsNotMigrated) {
ConfigureDefaultSearchPrefMigrationToDictionaryValue(
test_util()->profile()->GetPrefs());
+ // TODO(caitkp/erikwright): Look into loading policy values in tests. In
+ // practice, the DefaultSearchEngineSource() would be FROM_POLICY in this
+ // case, but since we are not loading the policy here, it will be
+ // FROM_FALLBACK instead.
// Test that the policy-defined value is not migrated.
- TemplateURLData modern_default;
- ASSERT_FALSE(DefaultSearchManager(test_util()->profile()->GetPrefs())
- .GetDefaultSearchEngine(&modern_default));
+ ASSERT_EQ(DefaultSearchManager::FROM_FALLBACK,
+ DefaultSearchManager(test_util()->profile()->GetPrefs(),
+ DefaultSearchManager::ObserverCallback())
+ .GetDefaultSearchEngineSource());
}
diff --git a/chrome/browser/search_engines/template_url_service.cc b/chrome/browser/search_engines/template_url_service.cc
index 817756c..10d5e95 100644
--- a/chrome/browser/search_engines/template_url_service.cc
+++ b/chrome/browser/search_engines/template_url_service.cc
@@ -290,7 +290,9 @@ TemplateURLService::TemplateURLService(Profile* profile)
processing_syncer_changes_(false),
pending_synced_default_search_(false),
dsp_change_origin_(DSP_CHANGE_OTHER),
- default_search_manager_(new DefaultSearchManager(GetPrefs())) {
+ default_search_manager_(
+ new DefaultSearchManager(GetPrefs(),
+ DefaultSearchManager::ObserverCallback())) {
DCHECK(profile_);
Init(NULL, 0);
}