Introduces a search term extraction mechanism working for arbitrary search providers.
Repalces the omnibox content with the actual search term when searching on the user's default search engine.
Meant to be used with instant extended.
Note: Will only convert URLs that have the espv=1 query parameter.
BUG=139176, 135106
Review URL: https://chromiumcodereview.appspot.com/10908226
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@160884 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/app/policy/policy_templates.json b/chrome/app/policy/policy_templates.json
index 9924524a..3d6d223 100644
--- a/chrome/app/policy/policy_templates.json
+++ b/chrome/app/policy/policy_templates.json
@@ -112,7 +112,7 @@
# persistent IDs for all fields (but not for groups!) are needed. These are
# specified by the 'id' keys of each policy. NEVER CHANGE EXISTING IDs,
# because doing so would break the deployed wire format!
-# For your editing convenience: highest ID currently used: 161
+# For your editing convenience: highest ID currently used: 162
#
# Placeholders:
# The following placeholder strings are automatically substituted:
@@ -1569,6 +1569,24 @@
This policy is only respected if the 'DefaultSearchProviderEnabled' policy is enabled.''',
},
+ {
+ 'name': 'DefaultSearchProviderAlternateURLs',
+ 'type': 'list',
+ 'schema': {
+ 'type': 'array',
+ 'items': { 'type': 'string' },
+ },
+ 'supported_on': ['chrome.*:24-', 'chrome_os:0.24-'],
+ 'features': {'dynamic_refresh': True},
+ 'example_value': ['http://search.my.company/suggest#q={searchTerms}', 'http://search.my.company/suggest/search#q={searchTerms}'],
+ 'id': 162,
+ 'caption': '''List of alternate URLs for the default search provider.''',
+ 'desc': '''Specifies a list of alternate URLs that can be used to extract search terms from the search engine. The URLs should contain the string <ph name="SEARCH_TERM_MARKER">'{searchTerms}'</ph>, which will be used to extract the search terms.
+
+ This policy is optional. If not set, no alternate urls will be used to extract search terms.
+
+ This policy is only respected if the 'DefaultSearchProviderEnabled' policy is enabled.''',
+ },
],
},
{
diff --git a/chrome/browser/google/google_util.cc b/chrome/browser/google/google_util.cc
index 013437ec..0d47f56 100644
--- a/chrome/browser/google/google_util.cc
+++ b/chrome/browser/google/google_util.cc
@@ -19,8 +19,6 @@
#include "chrome/common/net/url_util.h"
#include "chrome/installer/util/google_update_settings.h"
#include "googleurl/src/gurl.h"
-#include "googleurl/src/url_parse.h"
-#include "net/base/escape.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#if defined(OS_MACOSX)
@@ -57,30 +55,6 @@
bool gUseMockLinkDoctorBaseURLForTesting = false;
-// Finds the first key-value pair where the key matches |query_key|. Returns
-// true if a match is found and sets |search_terms| to the value.
-bool ExtractSearchTermsFromComponent(const std::string& url,
- url_parse::Component* component,
- string16* search_terms) {
- const std::string query_key = "q";
- url_parse::Component key, value;
-
- while (url_parse::ExtractQueryKeyValue(url.c_str(), component,
- &key, &value)) {
- if (url.compare(key.begin, key.len, query_key) != 0)
- continue;
- std::string value_str = url.substr(value.begin, value.len);
- *search_terms = net::UnescapeAndDecodeUTF8URLComponent(
- value_str,
- net::UnescapeRule::SPACES |
- net::UnescapeRule::URL_SPECIAL_CHARS |
- net::UnescapeRule::REPLACE_PLUS_WITH_SPACE,
- NULL);
- return true;
- }
- return false;
-}
-
} // anonymous namespace
namespace google_util {
@@ -179,25 +153,6 @@
#endif
-string16 GetSearchTermsFromGoogleSearchURL(const std::string& url) {
- if (!IsInstantExtendedAPIGoogleSearchUrl(url))
- return string16();
-
- url_parse::Parsed parsed_url;
- url_parse::ParseStandardURL(url.c_str(), url.length(), &parsed_url);
-
- string16 search_terms;
- // The search terms can be in either the query or ref component - for
- // instance, in a regular Google search they'll be in the query but in a
- // Google Instant search they can be in both. The ref is the correct one to
- // return in this case, so test the ref component first.
- if (ExtractSearchTermsFromComponent(url, &parsed_url.ref, &search_terms) ||
- ExtractSearchTermsFromComponent(url, &parsed_url.query, &search_terms)) {
- return search_terms;
- }
- return string16();
-}
-
bool IsGoogleDomainUrl(const std::string& url,
SubdomainPermission subdomain_permission,
PortPermission port_permission) {
diff --git a/chrome/browser/google/google_util.h b/chrome/browser/google/google_util.h
index f35ea009..b398bfa 100644
--- a/chrome/browser/google/google_util.h
+++ b/chrome/browser/google/google_util.h
@@ -10,7 +10,6 @@
#include <string>
#include "base/basictypes.h"
-#include "base/string16.h"
class GURL;
class Profile;
@@ -45,9 +44,6 @@
// install. Returns false if the information is not available.
bool GetReactivationBrand(std::string* brand);
-// Returns in the search terms used to create the Google search URL |url|.
-string16 GetSearchTermsFromGoogleSearchURL(const std::string& url);
-
// WARNING: The following IsGoogleXXX() functions use heuristics to rule out
// "obviously false" answers. They do NOT guarantee that the string in question
// is actually on a Google-owned domain, just that it looks plausible. If you
diff --git a/chrome/browser/google/google_util_unittest.cc b/chrome/browser/google/google_util_unittest.cc
index 174b91cd..fa3db0a 100644
--- a/chrome/browser/google/google_util_unittest.cc
+++ b/chrome/browser/google/google_util_unittest.cc
@@ -376,53 +376,3 @@
google_util::DISALLOW_SUBDOMAIN,
google_util::DISALLOW_NON_STANDARD_PORTS));
}
-
-TEST(GoogleUtilTest, SearchTerms) {
- // Simple searches.
- EXPECT_EQ(string16(), google_util::GetSearchTermsFromGoogleSearchURL(
- "http://google.com/search?q=tractor+supply"));
- EXPECT_EQ(ASCIIToUTF16("tractor supply"),
- google_util::GetSearchTermsFromGoogleSearchURL(
- "http://google.com/search?q=tractor+supply&espv=1"));
- // espv=1 only applies in query.
- EXPECT_EQ(string16(), google_util::GetSearchTermsFromGoogleSearchURL(
- "http://google.com/search?q=potato#espv=1"));
-
- // Instant searches.
- EXPECT_EQ(string16(), google_util::GetSearchTermsFromGoogleSearchURL(
- "http://google.com/webhp#q=tractor+supply"));
- EXPECT_EQ(ASCIIToUTF16("tractor supply"),
- google_util::GetSearchTermsFromGoogleSearchURL(
- "http://google.com/webhp?espv=1#q=tractor+supply"));
- // espv=1 only applies in query.
- EXPECT_EQ(string16(), google_util::GetSearchTermsFromGoogleSearchURL(
- "http://google.com/webhp?#espv=1&q=potato"));
-
- // Both query and ref components have a search term.
- EXPECT_EQ(ASCIIToUTF16("tractor supply"),
- google_util::GetSearchTermsFromGoogleSearchURL(
- "http://google.com/webhp?q=potato&espv=1#q=tractor+supply"));
-
- // Blank queries.
- EXPECT_EQ(string16(), google_util::GetSearchTermsFromGoogleSearchURL(
- "http://google.com/search?q=&q=potato&espv=1"));
- EXPECT_EQ(string16(), google_util::GetSearchTermsFromGoogleSearchURL(
- "http://google.com/webhp?espv=1#q=&q=tractor+supply"));
-
- // Multiple non-empty queries.
- EXPECT_EQ(ASCIIToUTF16("tractor supply"),
- google_util::GetSearchTermsFromGoogleSearchURL(
- "http://google.com/search?q=tractor+supply&q=potato&espv=1"));
- EXPECT_EQ(ASCIIToUTF16("tractor supply"),
- google_util::GetSearchTermsFromGoogleSearchURL(
- "http://google.com/webhp?espv=1#q=tractor+supply&q=potato"));
-
- // Blank terms in ref override non-blank terms in query.
- EXPECT_EQ(string16(), google_util::GetSearchTermsFromGoogleSearchURL(
- "http://google.com/search?q=potato&espv=1#q="));
-
- // Blank terms in query do not override non-blank terms in ref.
- EXPECT_EQ(ASCIIToUTF16("tractor supply"),
- google_util::GetSearchTermsFromGoogleSearchURL(
- "http://google.com/search?q=&espv=1#q=tractor+supply"));
-}
diff --git a/chrome/browser/policy/configuration_policy_handler.cc b/chrome/browser/policy/configuration_policy_handler.cc
index cf8dfd3..709e2e0 100644
--- a/chrome/browser/policy/configuration_policy_handler.cc
+++ b/chrome/browser/policy/configuration_policy_handler.cc
@@ -89,6 +89,9 @@
{ key::kDefaultSearchProviderEncodings,
prefs::kDefaultSearchProviderEncodings,
Value::TYPE_LIST },
+ { key::kDefaultSearchProviderAlternateURLs,
+ prefs::kDefaultSearchProviderAlternateURLs,
+ Value::TYPE_LIST },
};
// List of entries determining which proxy policies can be specified, depending
@@ -651,6 +654,8 @@
prefs->SetString(prefs::kDefaultSearchProviderEncodings, std::string());
prefs->SetString(prefs::kDefaultSearchProviderKeyword, std::string());
prefs->SetString(prefs::kDefaultSearchProviderInstantURL, std::string());
+ prefs->SetValue(prefs::kDefaultSearchProviderAlternateURLs,
+ new ListValue());
} else {
// The search URL is required. The other entries are optional. Just make
// sure that they are all specified via policy, so that the regular prefs
@@ -667,6 +672,7 @@
EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderEncodings);
EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderKeyword);
EnsureStringPrefExists(prefs, prefs::kDefaultSearchProviderInstantURL);
+ EnsureListPrefExists(prefs, prefs::kDefaultSearchProviderAlternateURLs);
// For the name and keyword, default to the host if not specified. If
// there is no host (file: URLs? Not sure), use "_" to guarantee that the
@@ -753,6 +759,15 @@
prefs->SetString(path, value);
}
+void DefaultSearchPolicyHandler::EnsureListPrefExists(
+ PrefValueMap* prefs,
+ const std::string& path) {
+ base::Value* value;
+ base::ListValue* list_value;
+ if (!prefs->GetValue(path, &value) || !value->GetAsList(&list_value))
+ prefs->SetValue(path, new ListValue());
+}
+
// ProxyPolicyHandler implementation -------------------------------------------
diff --git a/chrome/browser/policy/configuration_policy_handler.h b/chrome/browser/policy/configuration_policy_handler.h
index 0403808..b292cb3 100644
--- a/chrome/browser/policy/configuration_policy_handler.h
+++ b/chrome/browser/policy/configuration_policy_handler.h
@@ -285,10 +285,14 @@
const Value** url_value,
std::string* url_string);
- // Make sure that the |path| if present in |prefs_|. If not, set it to
+ // Make sure that the |path| is present in |prefs_|. If not, set it to
// a blank string.
void EnsureStringPrefExists(PrefValueMap* prefs, const std::string& path);
+ // Make sure that the |path| is present in |prefs_| and is a ListValue. If
+ // not, set it to an empty list.
+ void EnsureListPrefExists(PrefValueMap* prefs, const std::string& path);
+
// The ConfigurationPolicyHandler handlers for each default search policy.
std::vector<ConfigurationPolicyHandler*> handlers_;
diff --git a/chrome/browser/policy/configuration_policy_pref_store_unittest.cc b/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
index 62c983d..4044950 100644
--- a/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
+++ b/chrome/browser/policy/configuration_policy_pref_store_unittest.cc
@@ -556,23 +556,78 @@
}
class ConfigurationPolicyPrefStoreDefaultSearchTest
- : public ConfigurationPolicyPrefStoreTest {};
+ : public ConfigurationPolicyPrefStoreTest {
+ public:
+ ConfigurationPolicyPrefStoreDefaultSearchTest() {
+ default_alternate_urls_.AppendString(
+ "http://www.google.com/#q={searchTerms}");
+ default_alternate_urls_.AppendString(
+ "http://www.google.com/search#q={searchTerms}");
+ }
+
+ protected:
+ static const char* const kSearchURL;
+ static const char* const kSuggestURL;
+ static const char* const kIconURL;
+ static const char* const kName;
+ static const char* const kKeyword;
+
+ // Build a default search policy by setting search-related keys in |policy| to
+ // reasonable values. You can update any of the keys after calling this
+ // method.
+ void BuildDefaultSearchPolicy(PolicyMap* policy);
+
+ base::ListValue default_alternate_urls_;
+};
+
+const char* const ConfigurationPolicyPrefStoreDefaultSearchTest::kSearchURL =
+ "http://test.com/search?t={searchTerms}";
+const char* const ConfigurationPolicyPrefStoreDefaultSearchTest::kSuggestURL =
+ "http://test.com/sugg?={searchTerms}";
+const char* const ConfigurationPolicyPrefStoreDefaultSearchTest::kIconURL =
+ "http://test.com/icon.jpg";
+const char* const ConfigurationPolicyPrefStoreDefaultSearchTest::kName =
+ "MyName";
+const char* const ConfigurationPolicyPrefStoreDefaultSearchTest::kKeyword =
+ "MyKeyword";
+
+void ConfigurationPolicyPrefStoreDefaultSearchTest::
+ BuildDefaultSearchPolicy(PolicyMap* policy) {
+ base::ListValue* encodings = new base::ListValue();
+ encodings->AppendString("UTF-16");
+ encodings->AppendString("UTF-8");
+ policy->Set(key::kDefaultSearchProviderEnabled, POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER, base::Value::CreateBooleanValue(true));
+ policy->Set(key::kDefaultSearchProviderSearchURL, POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER, base::Value::CreateStringValue(kSearchURL));
+ policy->Set(key::kDefaultSearchProviderName, POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER, base::Value::CreateStringValue(kName));
+ policy->Set(key::kDefaultSearchProviderKeyword, POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER, base::Value::CreateStringValue(kKeyword));
+ policy->Set(key::kDefaultSearchProviderSuggestURL, POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER, base::Value::CreateStringValue(kSuggestURL));
+ policy->Set(key::kDefaultSearchProviderIconURL, POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER, base::Value::CreateStringValue(kIconURL));
+ policy->Set(key::kDefaultSearchProviderEncodings, POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER, encodings);
+ policy->Set(key::kDefaultSearchProviderAlternateURLs, POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER, default_alternate_urls_.DeepCopy());
+}
// Checks that if the policy for default search is valid, i.e. there's a
// search URL, that all the elements have been given proper defaults.
TEST_F(ConfigurationPolicyPrefStoreDefaultSearchTest, MinimallyDefined) {
PolicyMap policy;
- const char* const search_url = "http://test.com/search?t={searchTerms}";
policy.Set(key::kDefaultSearchProviderEnabled, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER, base::Value::CreateBooleanValue(true));
policy.Set(key::kDefaultSearchProviderSearchURL, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, base::Value::CreateStringValue(search_url));
+ POLICY_SCOPE_USER, base::Value::CreateStringValue(kSearchURL));
provider_.UpdateChromePolicy(policy);
const base::Value* value = NULL;
EXPECT_EQ(PrefStore::READ_OK,
store_->GetValue(prefs::kDefaultSearchProviderSearchURL, &value));
- EXPECT_TRUE(base::StringValue(search_url).Equals(value));
+ EXPECT_TRUE(base::StringValue(kSearchURL).Equals(value));
EXPECT_EQ(PrefStore::READ_OK,
store_->GetValue(prefs::kDefaultSearchProviderName, &value));
@@ -597,85 +652,56 @@
EXPECT_EQ(PrefStore::READ_OK,
store_->GetValue(prefs::kDefaultSearchProviderInstantURL, &value));
EXPECT_TRUE(base::StringValue(std::string()).Equals(value));
+
+ EXPECT_EQ(PrefStore::READ_OK,
+ store_->GetValue(prefs::kDefaultSearchProviderAlternateURLs,
+ &value));
+ EXPECT_TRUE(base::ListValue().Equals(value));
}
// Checks that for a fully defined search policy, all elements have been
// read properly.
TEST_F(ConfigurationPolicyPrefStoreDefaultSearchTest, FullyDefined) {
PolicyMap policy;
- const char* const search_url = "http://test.com/search?t={searchTerms}";
- const char* const suggest_url = "http://test.com/sugg?={searchTerms}";
- const char* const icon_url = "http://test.com/icon.jpg";
- const char* const name = "MyName";
- const char* const keyword = "MyKeyword";
- base::ListValue* encodings = new base::ListValue();
- encodings->Append(base::Value::CreateStringValue("UTF-16"));
- encodings->Append(base::Value::CreateStringValue("UTF-8"));
- policy.Set(key::kDefaultSearchProviderEnabled, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, base::Value::CreateBooleanValue(true));
- policy.Set(key::kDefaultSearchProviderSearchURL, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, base::Value::CreateStringValue(search_url));
- policy.Set(key::kDefaultSearchProviderName, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, base::Value::CreateStringValue(name));
- policy.Set(key::kDefaultSearchProviderKeyword, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, base::Value::CreateStringValue(keyword));
- policy.Set(key::kDefaultSearchProviderSuggestURL, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, base::Value::CreateStringValue(suggest_url));
- policy.Set(key::kDefaultSearchProviderIconURL, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, base::Value::CreateStringValue(icon_url));
- policy.Set(key::kDefaultSearchProviderEncodings, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, encodings);
+ BuildDefaultSearchPolicy(&policy);
provider_.UpdateChromePolicy(policy);
const base::Value* value = NULL;
EXPECT_EQ(PrefStore::READ_OK,
store_->GetValue(prefs::kDefaultSearchProviderSearchURL, &value));
- EXPECT_TRUE(base::StringValue(search_url).Equals(value));
+ EXPECT_TRUE(base::StringValue(kSearchURL).Equals(value));
EXPECT_EQ(PrefStore::READ_OK,
store_->GetValue(prefs::kDefaultSearchProviderName, &value));
- EXPECT_TRUE(base::StringValue(name).Equals(value));
+ EXPECT_TRUE(base::StringValue(kName).Equals(value));
EXPECT_EQ(PrefStore::READ_OK,
store_->GetValue(prefs::kDefaultSearchProviderKeyword, &value));
- EXPECT_TRUE(base::StringValue(keyword).Equals(value));
+ EXPECT_TRUE(base::StringValue(kKeyword).Equals(value));
EXPECT_EQ(PrefStore::READ_OK,
store_->GetValue(prefs::kDefaultSearchProviderSuggestURL, &value));
- EXPECT_TRUE(base::StringValue(suggest_url).Equals(value));
+ EXPECT_TRUE(base::StringValue(kSuggestURL).Equals(value));
EXPECT_EQ(PrefStore::READ_OK,
store_->GetValue(prefs::kDefaultSearchProviderIconURL, &value));
- EXPECT_TRUE(base::StringValue(icon_url).Equals(value));
+ EXPECT_TRUE(base::StringValue(kIconURL).Equals(value));
EXPECT_EQ(PrefStore::READ_OK,
store_->GetValue(prefs::kDefaultSearchProviderEncodings, &value));
EXPECT_TRUE(base::StringValue("UTF-16;UTF-8").Equals(value));
+
+ EXPECT_EQ(PrefStore::READ_OK, store_->GetValue(
+ prefs::kDefaultSearchProviderAlternateURLs, &value));
+ EXPECT_TRUE(default_alternate_urls_.Equals(value));
}
// Checks that if the default search policy is missing, that no elements of the
// default search policy will be present.
TEST_F(ConfigurationPolicyPrefStoreDefaultSearchTest, MissingUrl) {
PolicyMap policy;
- const char* const suggest_url = "http://test.com/sugg?t={searchTerms}";
- const char* const icon_url = "http://test.com/icon.jpg";
- const char* const name = "MyName";
- const char* const keyword = "MyKeyword";
- base::ListValue* encodings = new base::ListValue();
- encodings->Append(base::Value::CreateStringValue("UTF-16"));
- encodings->Append(base::Value::CreateStringValue("UTF-8"));
- policy.Set(key::kDefaultSearchProviderEnabled, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, base::Value::CreateBooleanValue(true));
- policy.Set(key::kDefaultSearchProviderName, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, base::Value::CreateStringValue(name));
- policy.Set(key::kDefaultSearchProviderKeyword, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, base::Value::CreateStringValue(keyword));
- policy.Set(key::kDefaultSearchProviderSuggestURL, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, base::Value::CreateStringValue(suggest_url));
- policy.Set(key::kDefaultSearchProviderIconURL, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, base::Value::CreateStringValue(icon_url));
- policy.Set(key::kDefaultSearchProviderEncodings, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, encodings);
+ BuildDefaultSearchPolicy(&policy);
+ policy.Erase(key::kDefaultSearchProviderSearchURL);
provider_.UpdateChromePolicy(policy);
EXPECT_EQ(PrefStore::READ_NO_VALUE,
@@ -690,35 +716,19 @@
store_->GetValue(prefs::kDefaultSearchProviderIconURL, NULL));
EXPECT_EQ(PrefStore::READ_NO_VALUE,
store_->GetValue(prefs::kDefaultSearchProviderEncodings, NULL));
+ EXPECT_EQ(PrefStore::READ_NO_VALUE,
+ store_->GetValue(prefs::kDefaultSearchProviderAlternateURLs, NULL));
}
// Checks that if the default search policy is invalid, that no elements of the
// default search policy will be present.
TEST_F(ConfigurationPolicyPrefStoreDefaultSearchTest, Invalid) {
PolicyMap policy;
+ BuildDefaultSearchPolicy(&policy);
const char* const bad_search_url = "http://test.com/noSearchTerms";
- const char* const suggest_url = "http://test.com/sugg?t={searchTerms}";
- const char* const icon_url = "http://test.com/icon.jpg";
- const char* const name = "MyName";
- const char* const keyword = "MyKeyword";
- base::ListValue* encodings = new base::ListValue();
- encodings->Append(base::Value::CreateStringValue("UTF-16"));
- encodings->Append(base::Value::CreateStringValue("UTF-8"));
- policy.Set(key::kDefaultSearchProviderEnabled, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, base::Value::CreateBooleanValue(true));
policy.Set(key::kDefaultSearchProviderSearchURL, POLICY_LEVEL_MANDATORY,
POLICY_SCOPE_USER,
base::Value::CreateStringValue(bad_search_url));
- policy.Set(key::kDefaultSearchProviderName, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, base::Value::CreateStringValue(name));
- policy.Set(key::kDefaultSearchProviderKeyword, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, base::Value::CreateStringValue(keyword));
- policy.Set(key::kDefaultSearchProviderSuggestURL, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, base::Value::CreateStringValue(suggest_url));
- policy.Set(key::kDefaultSearchProviderIconURL, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, base::Value::CreateStringValue(icon_url));
- policy.Set(key::kDefaultSearchProviderEncodings, POLICY_LEVEL_MANDATORY,
- POLICY_SCOPE_USER, encodings);
provider_.UpdateChromePolicy(policy);
EXPECT_EQ(PrefStore::READ_NO_VALUE,
@@ -733,6 +743,8 @@
store_->GetValue(prefs::kDefaultSearchProviderIconURL, NULL));
EXPECT_EQ(PrefStore::READ_NO_VALUE,
store_->GetValue(prefs::kDefaultSearchProviderEncodings, NULL));
+ EXPECT_EQ(PrefStore::READ_NO_VALUE,
+ store_->GetValue(prefs::kDefaultSearchProviderAlternateURLs, NULL));
}
// Checks that if the default search policy is invalid, that no elements of the
diff --git a/chrome/browser/policy/policy_browsertest.cc b/chrome/browser/policy/policy_browsertest.cc
index 898cee0b..426c42c 100644
--- a/chrome/browser/policy/policy_browsertest.cc
+++ b/chrome/browser/policy/policy_browsertest.cc
@@ -633,6 +633,86 @@
EXPECT_EQ(GURL(chrome::kAboutBlankURL), web_contents->GetURL());
}
+IN_PROC_BROWSER_TEST_F(PolicyTest, ReplaceSearchTerms) {
+ CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableInstantExtendedAPI);
+
+ // Verifies that a default search is made using the provider configured via
+ // policy. Also checks that default search can be completely disabled.
+ const string16 kKeyword(ASCIIToUTF16("testsearch"));
+ const std::string kSearchURL("http://search.example/search?q={searchTerms}");
+ const std::string kAlternateURL0(
+ "http://search.example/search#q={searchTerms}");
+ const std::string kAlternateURL1("http://search.example/#q={searchTerms}");
+
+ TemplateURLService* service = TemplateURLServiceFactory::GetForProfile(
+ browser()->profile());
+ ui_test_utils::WaitForTemplateURLServiceToLoad(service);
+ TemplateURL* default_search = service->GetDefaultSearchProvider();
+ ASSERT_TRUE(default_search);
+ EXPECT_NE(kKeyword, default_search->keyword());
+ EXPECT_NE(kSearchURL, default_search->url());
+ EXPECT_NE(kAlternateURL0, default_search->alternate_urls()[0]);
+ EXPECT_NE(kAlternateURL1, default_search->alternate_urls()[1]);
+
+ // Override the default search provider using policies.
+ PolicyMap policies;
+ policies.Set(key::kDefaultSearchProviderEnabled, POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER, base::Value::CreateBooleanValue(true));
+ policies.Set(key::kDefaultSearchProviderKeyword, POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER, base::Value::CreateStringValue(kKeyword));
+ policies.Set(key::kDefaultSearchProviderSearchURL, POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER, base::Value::CreateStringValue(kSearchURL));
+ base::ListValue* alternate_urls = new base::ListValue();
+ alternate_urls->AppendString(kAlternateURL0);
+ alternate_urls->AppendString(kAlternateURL1);
+ policies.Set(key::kDefaultSearchProviderAlternateURLs, POLICY_LEVEL_MANDATORY,
+ POLICY_SCOPE_USER, alternate_urls);
+ provider_.UpdateChromePolicy(policies);
+ default_search = service->GetDefaultSearchProvider();
+ ASSERT_TRUE(default_search);
+ EXPECT_EQ(kKeyword, default_search->keyword());
+ EXPECT_EQ(kSearchURL, default_search->url());
+ EXPECT_EQ(kAlternateURL0, default_search->alternate_urls()[0]);
+ EXPECT_EQ(kAlternateURL1, default_search->alternate_urls()[1]);
+
+ // Verify that searching from the omnibox does search term replacement with
+ // first URL pattern.
+ chrome::FocusLocationBar(browser());
+ LocationBar* location_bar = browser()->window()->GetLocationBar();
+ ui_test_utils::SendToOmniboxAndSubmit(location_bar,
+ "http://search.example/#q=foobar");
+ OmniboxEditModel* model = location_bar->GetLocationEntry()->model();
+ EXPECT_TRUE(model->CurrentMatch().destination_url.is_valid());
+ EXPECT_EQ(ASCIIToUTF16("foobar"), model->CurrentMatch().contents);
+
+ // Verify that searching from the omnibox does search term replacement with
+ // second URL pattern.
+ chrome::FocusLocationBar(browser());
+ ui_test_utils::SendToOmniboxAndSubmit(location_bar,
+ "http://search.example/search#q=banana");
+ model = location_bar->GetLocationEntry()->model();
+ EXPECT_TRUE(model->CurrentMatch().destination_url.is_valid());
+ EXPECT_EQ(ASCIIToUTF16("banana"), model->CurrentMatch().contents);
+
+ // Verify that searching from the omnibox does search term replacement with
+ // standard search URL pattern.
+ chrome::FocusLocationBar(browser());
+ ui_test_utils::SendToOmniboxAndSubmit(location_bar,
+ "http://search.example/search?q=tractor+parts");
+ model = location_bar->GetLocationEntry()->model();
+ EXPECT_TRUE(model->CurrentMatch().destination_url.is_valid());
+ EXPECT_EQ(ASCIIToUTF16("tractor parts"), model->CurrentMatch().contents);
+
+ // Verify that searching from the omnibox prioritizes hash over query.
+ chrome::FocusLocationBar(browser());
+ ui_test_utils::SendToOmniboxAndSubmit(location_bar,
+ "http://search.example/search?q=tractor+parts#q=foobar");
+ model = location_bar->GetLocationEntry()->model();
+ EXPECT_TRUE(model->CurrentMatch().destination_url.is_valid());
+ EXPECT_EQ(ASCIIToUTF16("foobar"), model->CurrentMatch().contents);
+}
+
// The linux and win bots can't create a GL context. http://crbug.com/103379
#if defined(OS_MACOSX)
IN_PROC_BROWSER_TEST_F(PolicyTest, Disable3DAPIs) {
diff --git a/chrome/browser/search_engines/template_url.cc b/chrome/browser/search_engines/template_url.cc
index 1612f5a..7e617e43 100644
--- a/chrome/browser/search_engines/template_url.cc
+++ b/chrome/browser/search_engines/template_url.cc
@@ -107,6 +107,28 @@
return true;
}
+// Extract query key and host given a list of parameters coming from the URL
+// query or ref.
+std::string FindSearchTermsKey(const std::string& params) {
+ if (params.empty())
+ return std::string();
+ url_parse::Component query, key, value;
+ query.len = static_cast<int>(params.size());
+ while (url_parse::ExtractQueryKeyValue(params.c_str(), &query, &key,
+ &value)) {
+ if (key.is_nonempty() && value.is_nonempty()) {
+ std::string value_string = params.substr(value.begin, value.len);
+ if (value_string.find(kSearchTermsParameterFull, 0) !=
+ std::string::npos ||
+ value_string.find(kGoogleUnescapedSearchTermsParameterFull, 0) !=
+ std::string::npos) {
+ return params.substr(key.begin, key.len);
+ }
+ }
+ }
+ return std::string();
+}
+
} // namespace
@@ -123,11 +145,27 @@
TemplateURLRef::TemplateURLRef(TemplateURL* owner, Type type)
: owner_(owner),
type_(type),
+ index_in_owner_(-1),
parsed_(false),
valid_(false),
supports_replacements_(false),
+ search_term_key_location_(url_parse::Parsed::QUERY),
prepopulated_(false) {
DCHECK(owner_);
+ DCHECK_NE(INDEXED, type_);
+}
+
+TemplateURLRef::TemplateURLRef(TemplateURL* owner, size_t index_in_owner)
+ : owner_(owner),
+ type_(INDEXED),
+ index_in_owner_(index_in_owner),
+ parsed_(false),
+ valid_(false),
+ supports_replacements_(false),
+ search_term_key_location_(url_parse::Parsed::QUERY),
+ prepopulated_(false) {
+ DCHECK(owner_);
+ DCHECK_LT(index_in_owner_, owner_->URLCount());
}
TemplateURLRef::~TemplateURLRef() {
@@ -138,6 +176,7 @@
case SEARCH: return owner_->url();
case SUGGEST: return owner_->suggestions_url();
case INSTANT: return owner_->instant_url();
+ case INDEXED: return owner_->GetURL(index_in_owner_);
default: NOTREACHED(); return std::string(); // NOLINT
}
}
@@ -404,6 +443,56 @@
return false;
}
+bool TemplateURLRef::ExtractSearchTermsFromURL(const GURL& url,
+ string16* search_terms) const {
+ DCHECK(search_terms);
+ search_terms->clear();
+
+ ParseIfNecessary();
+
+ // We need a search term in the template URL to extract something.
+ if (search_term_key_.empty())
+ return false;
+
+ // TODO(beaudoin): Support patterns of the form http://foo/{searchTerms}/
+ // See crbug.com/153798
+
+ // Fill-in the replacements. We don't care about search terms in the pattern,
+ // so we use the empty string.
+ GURL pattern(ReplaceSearchTerms(SearchTermsArgs(string16())));
+ // Scheme, host, path and port must match.
+ if (!url.SchemeIs(pattern.scheme().c_str()) ||
+ url.port() != pattern.port() ||
+ url.host() != host_ ||
+ url.path() != path_) {
+ return false;
+ }
+
+ // Parameter must be present either in the query or the ref.
+ const std::string& params(
+ (search_term_key_location_ == url_parse::Parsed::QUERY) ?
+ url.query() : url.ref());
+
+ url_parse::Component query, key, value;
+ query.len = static_cast<int>(params.size());
+ while (url_parse::ExtractQueryKeyValue(params.c_str(), &query, &key,
+ &value)) {
+ if (key.is_nonempty()) {
+ if (params.substr(key.begin, key.len) == search_term_key_) {
+ // Extract the search term.
+ *search_terms = net::UnescapeAndDecodeUTF8URLComponent(
+ params.substr(value.begin, value.len),
+ net::UnescapeRule::SPACES |
+ net::UnescapeRule::URL_SPECIAL_CHARS |
+ net::UnescapeRule::REPLACE_PLUS_WITH_SPACE,
+ NULL);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
void TemplateURLRef::InvalidateCachedValues() const {
supports_replacements_ = valid_ = parsed_ = false;
host_.clear();
@@ -556,31 +645,24 @@
kGoogleBaseSuggestURLParameterFull,
search_terms_data.GoogleBaseSuggestURLValue());
+ search_term_key_.clear();
+ host_.clear();
+ path_.clear();
+ search_term_key_location_ = url_parse::Parsed::REF;
+
GURL url(url_string);
if (!url.is_valid())
return;
- std::string query_string = url.query();
- if (query_string.empty())
- return;
-
- url_parse::Component query, key, value;
- query.len = static_cast<int>(query_string.size());
- while (url_parse::ExtractQueryKeyValue(query_string.c_str(), &query, &key,
- &value)) {
- if (key.is_nonempty() && value.is_nonempty()) {
- std::string value_string = query_string.substr(value.begin, value.len);
- if (value_string.find(kSearchTermsParameterFull, 0) !=
- std::string::npos ||
- value_string.find(kGoogleUnescapedSearchTermsParameterFull, 0) !=
- std::string::npos) {
- search_term_key_ = query_string.substr(key.begin, key.len);
- host_ = url.host();
- path_ = url.path();
- break;
- }
- }
- }
+ std::string query_key = FindSearchTermsKey(url.query());
+ std::string ref_key = FindSearchTermsKey(url.ref());
+ if (query_key.empty() == ref_key.empty())
+ return; // No key or multiple keys found. We only handle having one key.
+ search_term_key_ = query_key.empty() ? ref_key : query_key;
+ search_term_key_location_ = query_key.empty() ?
+ url_parse::Parsed::REF : url_parse::Parsed::QUERY;
+ host_ = url.host();
+ path_ = url.path();
}
@@ -690,6 +772,41 @@
return GURL(data_.url()).SchemeIs(chrome::kExtensionScheme);
}
+size_t TemplateURL::URLCount() const {
+ // Add 1 for the regular search URL.
+ return data_.alternate_urls.size() + 1;
+}
+
+const std::string& TemplateURL::GetURL(size_t index) const {
+ DCHECK_LT(index, URLCount());
+
+ return (index < data_.alternate_urls.size()) ?
+ data_.alternate_urls[index] : url();
+}
+
+bool TemplateURL::ExtractSearchTermsFromURL(
+ const GURL& url, string16* search_terms) {
+ DCHECK(search_terms);
+ search_terms->clear();
+
+ // Then try to match with every pattern.
+ for (size_t i = 0; i < URLCount(); ++i) {
+ TemplateURLRef ref(this, i);
+ if (ref.ExtractSearchTermsFromURL(url, search_terms)) {
+ // If ExtractSearchTermsFromURL() returns true and |search_terms| is empty
+ // it means the pattern matched but no search terms were present. In this
+ // case we fail immediately without looking for matches in subsequent
+ // patterns. This means that given patterns
+ // [ "http://foo/#q={searchTerms}", "http://foo/?q={searchTerms}" ],
+ // calling ExtractSearchTermsFromURL() on "http://foo/?q=bar#q=' would
+ // return false. This is important for at least Google, where such URLs
+ // are invalid.
+ return !search_terms->empty();
+ }
+ }
+ return false;
+}
+
void TemplateURL::CopyFrom(const TemplateURL& other) {
if (this == &other)
return;
diff --git a/chrome/browser/search_engines/template_url.h b/chrome/browser/search_engines/template_url.h
index 4241f52..af104407 100644
--- a/chrome/browser/search_engines/template_url.h
+++ b/chrome/browser/search_engines/template_url.h
@@ -12,6 +12,7 @@
#include "base/time.h"
#include "chrome/browser/search_engines/template_url_id.h"
#include "googleurl/src/gurl.h"
+#include "googleurl/src/url_parse.h"
class Profile;
class SearchTermsData;
@@ -40,11 +41,13 @@
};
// Which kind of URL within our owner we are. This allows us to get at the
- // correct string field.
+ // correct string field. Use |INDEXED| to indicate that the numerical
+ // |index_in_owner_| should be used instead.
enum Type {
SEARCH,
SUGGEST,
INSTANT,
+ INDEXED
};
// This struct encapsulates arguments passed to
@@ -70,6 +73,7 @@
};
TemplateURLRef(TemplateURL* owner, Type type);
+ TemplateURLRef(TemplateURL* owner, size_t index_in_owner);
~TemplateURLRef();
// Returns the raw URL. None of the parameters will have been replaced.
@@ -128,6 +132,13 @@
// {google:baseURL} or {google:baseSuggestURL}.
bool HasGoogleBaseURLs() const;
+ // Use the pattern referred to by this TemplateURLRef to match the provided
+ // |url| and extract |search_terms| from it. Returns true if the pattern
+ // matches, even if |search_terms| is empty. Returns false and an empty
+ // |search_terms| if the pattern does not match.
+ bool ExtractSearchTermsFromURL(const GURL& url,
+ string16* search_terms) const;
+
private:
friend class TemplateURL;
FRIEND_TEST_ALL_PREFIXES(TemplateURLTest, SetPrepopulatedAndParse);
@@ -212,6 +223,10 @@
// What kind of URL we are.
const Type type_;
+ // If |type_| is |INDEXED|, this |index_in_owner_| is used instead to refer to
+ // a url within our owner.
+ const size_t index_in_owner_;
+
// Whether the URL has been parsed.
mutable bool parsed_;
@@ -229,11 +244,12 @@
// into the string, and may be empty.
mutable Replacements replacements_;
- // Host, path and key of the search term. These are only set if the url
- // contains one search term.
+ // Host, path, key and location of the search term. These are only set if the
+ // url contains one search term.
mutable std::string host_;
mutable std::string path_;
mutable std::string search_term_key_;
+ mutable url_parse::Parsed::ComponentType search_term_key_location_;
// Whether the contained URL is a pre-populated URL.
bool prepopulated_;
@@ -325,6 +341,10 @@
// regardless of whether they have been associated with Sync.
std::string sync_guid;
+ // A list of URL patterns that can be used, in addition to |url_|, to extract
+ // search terms from a URL.
+ std::vector<std::string> alternate_urls;
+
private:
// Private so we can enforce using the setters and thus enforce that these
// fields are never empty.
@@ -369,6 +389,9 @@
const std::string& url() const { return data_.url(); }
const std::string& suggestions_url() const { return data_.suggestions_url; }
const std::string& instant_url() const { return data_.instant_url; }
+ const std::vector<std::string>& alternate_urls() const {
+ return data_.alternate_urls;
+ }
const GURL& favicon_url() const { return data_.favicon_url; }
const GURL& originating_url() const { return data_.originating_url; }
@@ -422,6 +445,28 @@
std::string GetExtensionId() const;
bool IsExtensionKeyword() const;
+ // Returns the total number of URLs comprised in this template, including
+ // search and alternate URLs.
+ size_t URLCount() const;
+
+ // Gets the search URL at the given index. The alternate URLs, if any, are
+ // numbered starting at 0, and the primary search URL follows. This is used
+ // to decode the search term given a search URL (see
+ // ExtractSearchTermsFromURL()).
+ const std::string& GetURL(size_t index) const;
+
+ // Use the alternate URLs and the search URL to match the provided |url|
+ // and extract |search_terms| from it. Returns false and an empty
+ // |search_terms| if no search terms can be matched. The order in which the
+ // alternate URLs are listed dictates their priority, the URL at index 0
+ // is treated as the highest priority and the primary search URL is treated
+ // as the lowest priority (see GetURL()). For example, if a TemplateURL has
+ // alternate URL "http://foo/#q={searchTerms}" and search URL
+ // "http://foo/?q={searchTerms}", and the URL to be decoded is
+ // "http://foo/?q=a#q=b", the alternate URL will match first and the decoded
+ // search term will be "b".
+ bool ExtractSearchTermsFromURL(const GURL& url, string16* search_terms);
+
private:
friend class TemplateURLService;
diff --git a/chrome/browser/search_engines/template_url_prepopulate_data.cc b/chrome/browser/search_engines/template_url_prepopulate_data.cc
index c89a3f0..eaf98255 100644
--- a/chrome/browser/search_engines/template_url_prepopulate_data.cc
+++ b/chrome/browser/search_engines/template_url_prepopulate_data.cc
@@ -9,6 +9,7 @@
#endif
#include "base/command_line.h"
+#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/memory/scoped_vector.h"
#include "base/string16.h"
@@ -54,6 +55,9 @@
// suggestions.
const char* const instant_url; // If NULL, this engine does not support
// instant.
+ // A JSON array containing a list of URL patterns that can be used, in
+ // addition to |search_url|, to extract search terms from a URL. Can be NULL.
+ const char* const alternate_urls;
// SEARCH_ENGINE_OTHER if there is no matching type.
const SearchEngineType type;
// Unique id for this prepopulate engine (corresponds to
@@ -97,6 +101,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_ABCSOK,
72,
};
@@ -109,6 +114,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_ALTAVISTA,
89,
};
@@ -121,6 +127,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_ALTAVISTA,
89,
};
@@ -133,6 +140,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_ALTAVISTA,
89,
};
@@ -145,6 +153,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
35,
};
@@ -157,6 +166,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
12,
};
@@ -169,6 +179,7 @@
"UTF-8",
"http://ss.ask.com/query?q={searchTerms}&li=ff",
NULL,
+ NULL,
SEARCH_ENGINE_ASK,
4,
};
@@ -181,6 +192,7 @@
"UTF-8",
"http://ss.de.ask.com/query?q={searchTerms}&li=ff",
NULL,
+ NULL,
SEARCH_ENGINE_ASK,
4,
};
@@ -193,6 +205,7 @@
"UTF-8",
"http://ss.es.ask.com/query?q={searchTerms}&li=ff",
NULL,
+ NULL,
SEARCH_ENGINE_ASK,
4,
};
@@ -205,6 +218,7 @@
"UTF-8",
"http://ss.it.ask.com/query?q={searchTerms}&li=ff",
NULL,
+ NULL,
SEARCH_ENGINE_ASK,
4,
};
@@ -217,6 +231,7 @@
"UTF-8",
"http://ss.nl.ask.com/query?q={searchTerms}&li=ff",
NULL,
+ NULL,
SEARCH_ENGINE_ASK,
4,
};
@@ -229,6 +244,7 @@
"UTF-8",
"http://ss.uk.ask.com/query?q={searchTerms}&li=ff",
NULL,
+ NULL,
SEARCH_ENGINE_ASK,
4,
};
@@ -241,6 +257,7 @@
"windows-1250",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
27,
};
@@ -253,6 +270,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
27,
};
@@ -265,6 +283,7 @@
"GB2312",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_BAIDU,
21,
};
@@ -277,6 +296,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -289,6 +309,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
7, // Can't be 3 as this has to appear in the Arabian countries' lists
// alongside bing_en_XA.
@@ -302,6 +323,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -314,6 +336,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -326,6 +349,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -338,6 +362,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -350,6 +375,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -362,6 +388,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -374,6 +401,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -386,6 +414,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -398,6 +427,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -410,6 +440,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -422,6 +453,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -434,6 +466,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -446,6 +479,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -458,6 +492,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -470,6 +505,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -482,6 +518,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -494,6 +531,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -506,6 +544,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -518,6 +557,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -530,6 +570,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -542,6 +583,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -554,6 +596,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -566,6 +609,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -578,6 +622,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -590,6 +635,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -602,6 +648,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -614,6 +661,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -626,6 +674,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
7,
};
@@ -638,6 +687,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
7,
};
@@ -650,6 +700,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
7,
};
@@ -662,6 +713,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -674,6 +726,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -686,6 +739,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -698,6 +752,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -710,6 +765,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -722,6 +778,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -734,6 +791,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -746,6 +804,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -758,6 +817,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -770,6 +830,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -782,6 +843,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -794,6 +856,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -806,6 +869,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -818,6 +882,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -830,6 +895,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -842,6 +908,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -854,6 +921,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -866,6 +934,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -878,6 +947,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -890,6 +960,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -902,6 +973,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -914,6 +986,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -926,6 +999,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -938,6 +1012,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -950,6 +1025,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -962,6 +1038,7 @@
"UTF-8",
"http://api.bing.com/osjson.aspx?query={searchTerms}&language={language}",
NULL,
+ NULL,
SEARCH_ENGINE_BING,
3,
};
@@ -974,6 +1051,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_CENTRUM,
26,
};
@@ -986,6 +1064,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_CENTRUM,
26,
};
@@ -999,6 +1078,7 @@
"http://sug.search.daum.net/search_nsuggest?mod=fxjson&code=utf_in_out&"
"q={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_DAUM,
68,
};
@@ -1011,6 +1091,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_DELFI,
45,
};
@@ -1023,6 +1104,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_DELFI,
45,
};
@@ -1035,6 +1117,7 @@
"windows-1251",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_DIRI,
32,
};
@@ -1047,6 +1130,7 @@
"ISO-8859-1",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
29,
};
@@ -1059,6 +1143,7 @@
"ISO-8859-1",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
29,
};
@@ -1071,6 +1156,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
46,
};
@@ -1083,6 +1169,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_GOO,
23,
};
@@ -1101,6 +1188,8 @@
"sugkey={google:suggestAPIKeyParameter}",
"{google:baseURL}webhp?sourceid=chrome-instant&{google:RLZ}"
"{google:instantEnabledParameter}ie={inputEncoding}",
+ "[\"{google:baseURL}#q={searchTerms}\", "
+ "\"{google:baseURL}search#q={searchTerms}\"]",
SEARCH_ENGINE_GOOGLE,
1,
};
@@ -1113,6 +1202,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
38,
};
@@ -1125,6 +1215,7 @@
"iso-8859-1",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
18,
};
@@ -1137,6 +1228,7 @@
"ISO-8859-7",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_IN,
54,
};
@@ -1149,6 +1241,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
19,
};
@@ -1161,6 +1254,7 @@
"ISO-8859-1",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
28,
};
@@ -1173,6 +1267,7 @@
"ISO-8859-1",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
73,
};
@@ -1185,6 +1280,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
71,
};
@@ -1197,6 +1293,7 @@
"ISO-8859-1",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
59,
};
@@ -1209,6 +1306,7 @@
"ISO-8859-1",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
63,
};
@@ -1221,6 +1319,7 @@
"windows-1251",
"http://suggests.go.mail.ru/chrome?q={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_MAILRU,
83,
};
@@ -1233,6 +1332,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
13,
};
@@ -1245,6 +1345,7 @@
"windows-1256",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
14,
};
@@ -1257,6 +1358,7 @@
"windows-1254",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
101,
};
@@ -1269,6 +1371,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_NAJDI,
87,
};
@@ -1281,6 +1384,7 @@
"EUC-KR",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
69,
};
@@ -1294,6 +1398,7 @@
"http://ac.search.naver.com/autocompl?m=s&ie={inputEncoding}&oe=utf-8&"
"q={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_NAVER,
67,
};
@@ -1306,6 +1411,7 @@
"ISO-8859-1",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_NETI,
44,
};
@@ -1318,6 +1424,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_NETSPRINT,
30,
};
@@ -1330,6 +1437,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
20,
};
@@ -1342,6 +1450,7 @@
"ISO-8859-2",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OK,
6,
};
@@ -1354,6 +1463,7 @@
"ISO-8859-2",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
75,
};
@@ -1366,6 +1476,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_POGODAK,
24,
};
@@ -1378,6 +1489,7 @@
"windows-1251",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_RAMBLER,
16,
};
@@ -1390,6 +1502,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
37,
};
@@ -1402,6 +1515,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
41,
};
@@ -1414,6 +1528,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_SANOOK,
100,
};
@@ -1426,6 +1541,7 @@
"UTF-8",
"http://pesquisa.sapo.pt/livesapo?q={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_SAPO,
77,
};
@@ -1438,6 +1554,7 @@
"ISO-8859-1",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
51,
};
@@ -1450,6 +1567,7 @@
"ISO-8859-1",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
22,
};
@@ -1463,6 +1581,7 @@
"http:///suggest.fulltext.seznam.cz/?dict=fulltext_ff&phrase={searchTerms}&"
"encoding={inputEncoding}&response_encoding=utf-8",
NULL,
+ NULL,
SEARCH_ENGINE_SEZNAM,
25,
};
@@ -1475,6 +1594,7 @@
"ISO-8859-1",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
90,
};
@@ -1487,6 +1607,7 @@
"ISO-8859-1",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
90,
};
@@ -1499,6 +1620,7 @@
"windows-1251",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_TUT,
17,
};
@@ -1511,6 +1633,7 @@
"ISO-8859-1",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
82,
};
@@ -1523,6 +1646,7 @@
"ISO-8859-1",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_VIRGILIO,
62,
};
@@ -1535,6 +1659,7 @@
"windows-1255",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_WALLA,
55,
};
@@ -1547,6 +1672,7 @@
"ISO-8859-2",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
76,
};
@@ -1559,6 +1685,7 @@
"UTF-8",
"http://ff.search.yahoo.com/gossip?output=fxjson&command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1576,6 +1703,7 @@
"http://ar-sayt.ff.search.yahoo.com/gossip-ar-sayt?output=fxjson&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1589,6 +1717,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1603,6 +1732,7 @@
"http://aue-sayt.ff.search.yahoo.com/gossip-au-sayt?output=fxjson&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1617,6 +1747,7 @@
"http://br-sayt.ff.search.yahoo.com/gossip-br-sayt?output=fxjson&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1631,6 +1762,7 @@
"http://gossip.ca.yahoo.com/gossip-ca-sayt?output=fxjsonp&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1644,6 +1776,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1658,6 +1791,7 @@
"http://gossip.telemundo.yahoo.com/gossip-e1-sayt?output=fxjson&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1671,6 +1805,7 @@
"GB2312",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1685,6 +1820,7 @@
"http://gossip.telemundo.yahoo.com/gossip-e1-sayt?output=fxjson&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1699,6 +1835,7 @@
"http://de-sayt.ff.search.yahoo.com/gossip-de-sayt?output=fxjson&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1712,6 +1849,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1726,6 +1864,7 @@
"http://es-sayt.ff.search.yahoo.com/gossip-es-sayt?output=fxjson&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1739,6 +1878,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1753,6 +1893,7 @@
"http://fr-sayt.ff.search.yahoo.com/gossip-fr-sayt?output=fxjson&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1766,6 +1907,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1780,6 +1922,7 @@
"http://id-sayt.ff.search.yahoo.com/gossip-id-sayt?output=fxjson&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1794,6 +1937,7 @@
"http://in-sayt.ff.search.yahoo.com/gossip-in-sayt?output=fxjson&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1808,6 +1952,7 @@
"http://it-sayt.ff.search.yahoo.com/gossip-it-sayt?output=fxjson&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1821,6 +1966,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_YAHOOJP,
2,
};
@@ -1835,6 +1981,7 @@
"http://kr.atc.search.yahoo.com/atcx.php?property=main&ot=fxjson&"
"ei=utf8&eo=utf8&command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1849,6 +1996,7 @@
"http://my-sayt.ff.search.yahoo.com/gossip-my-sayt?output=fxjson&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1863,6 +2011,7 @@
"http://gossip.mx.yahoo.com/gossip-mx-sayt?output=fxjsonp&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1876,6 +2025,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1889,6 +2039,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1903,6 +2054,7 @@
"http://aue-sayt.ff.search.yahoo.com/gossip-nz-sayt?output=fxjson&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1917,6 +2069,7 @@
"http://gossip.telemundo.yahoo.com/gossip-e1-sayt?output=fxjson&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1931,6 +2084,7 @@
"http://ph-sayt.ff.search.yahoo.com/gossip-ph-sayt?output=fxjson&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1944,6 +2098,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_YAHOOQC,
5, // Can't be 2 as this has to appear in the Canada list alongside yahoo_ca.
};
@@ -1957,6 +2112,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1970,6 +2126,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1984,6 +2141,7 @@
"http://sg-sayt.ff.search.yahoo.com/gossip-sg-sayt?output=fxjson&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -1998,6 +2156,7 @@
"http://th-sayt.ff.search.yahoo.com/gossip-th-sayt?output=fxjson&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -2011,6 +2170,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -2025,6 +2185,7 @@
"http://uk-sayt.ff.search.yahoo.com/gossip-uk-sayt?output=fxjson&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -2039,6 +2200,7 @@
"http://gossip.telemundo.yahoo.com/gossip-e1-sayt?output=fxjson&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -2053,6 +2215,7 @@
"http://vn-sayt.ff.search.yahoo.com/gossip-vn-sayt?output=fxjson&"
"command={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YAHOO,
2,
};
@@ -2065,6 +2228,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_OTHER,
11,
};
@@ -2077,6 +2241,7 @@
"UTF-8",
"http://suggest.yandex.net/suggest-ff.cgi?part={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YANDEX,
15,
};
@@ -2089,6 +2254,7 @@
"UTF-8",
"http://suggest.yandex.net/suggest-ff.cgi?part={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YANDEX,
15,
};
@@ -2101,6 +2267,7 @@
"windows-1250",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_ZOZNAM,
85,
};
@@ -2119,6 +2286,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_ALL_BY,
33,
};
@@ -2131,6 +2299,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_APORT,
34,
};
@@ -2143,6 +2312,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_AVG,
50,
};
@@ -2155,6 +2325,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_AVG,
52,
};
@@ -2167,6 +2338,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_CONDUIT,
36,
};
@@ -2179,6 +2351,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_ICQ,
39,
};
@@ -2191,6 +2364,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_META_UA,
40,
};
@@ -2203,6 +2377,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_METABOT_RU,
42,
};
@@ -2215,6 +2390,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_NIGMA,
43,
};
@@ -2227,6 +2403,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_QIP,
47,
};
@@ -2239,6 +2416,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_UKR_NET,
48,
};
@@ -2251,6 +2429,7 @@
"UTF-8",
NULL,
NULL,
+ NULL,
SEARCH_ENGINE_WEBALTA,
49,
};
@@ -2263,6 +2442,7 @@
"UTF-8",
"http://suggest.yandex.net/suggest-ff.cgi?part={searchTerms}",
NULL,
+ NULL,
SEARCH_ENGINE_YANDEX,
15,
};
@@ -3329,7 +3509,7 @@
int GetDataVersion(PrefService* prefs) {
// Increment this if you change the above data in ways that mean users with
// existing data should get a new version.
- const int kCurrentDataVersion = 43;
+ const int kCurrentDataVersion = 44;
// Allow tests to override the local version.
return (prefs && prefs->HasPrefPath(prefs::kSearchProviderOverridesVersion)) ?
prefs->GetInteger(prefs::kSearchProviderOverridesVersion) :
@@ -3342,15 +3522,24 @@
const base::StringPiece& search_url,
const base::StringPiece& suggest_url,
const base::StringPiece& instant_url,
+ const ListValue& alternate_urls,
const base::StringPiece& favicon_url,
const base::StringPiece& encoding,
int id) {
+
TemplateURLData data;
+
data.short_name = name;
data.SetKeyword(keyword);
data.SetURL(search_url.as_string());
data.suggestions_url = suggest_url.as_string();
data.instant_url = instant_url.as_string();
+ for (size_t i = 0; i < alternate_urls.GetSize(); ++i) {
+ std::string alternate_url;
+ alternate_urls.GetString(i, &alternate_url);
+ DCHECK(!alternate_url.empty());
+ data.alternate_urls.push_back(alternate_url);
+ }
data.favicon_url = GURL(favicon_url.as_string());
data.show_in_default_list = true;
data.safe_for_autoreplace = true;
@@ -3376,6 +3565,7 @@
std::string search_url;
std::string suggest_url;
std::string instant_url;
+ const ListValue* alternate_urls;
std::string favicon_url;
std::string encoding;
int id;
@@ -3389,6 +3579,7 @@
engine->GetString("search_url", &search_url) &&
engine->GetString("suggest_url", &suggest_url) &&
engine->GetString("instant_url", &instant_url) &&
+ engine->GetList("alternate_urls", &alternate_urls) &&
engine->GetString("favicon_url", &favicon_url) &&
engine->GetString("encoding", &encoding) &&
engine->GetInteger("id", &id)) {
@@ -3401,7 +3592,8 @@
continue;
}
t_urls->push_back(MakePrepopulatedTemplateURL(profile, name, keyword,
- search_url, suggest_url, instant_url, favicon_url, encoding, id));
+ search_url, suggest_url, instant_url, *alternate_urls, favicon_url,
+ encoding, id));
}
}
@@ -3409,9 +3601,23 @@
TemplateURL* MakePrepopulatedTemplateURLFromPrepopulateEngine(
Profile* profile,
const PrepopulatedEngine& engine) {
+
+ // Use an empty list if there are no alternate_urls.
+ ListValue empty_list;
+ ListValue* alternate_urls = &empty_list;
+ // Will hold the result of |ReadToValue|, which we own.
+ scoped_ptr<Value> value;
+ if (engine.alternate_urls) {
+ base::JSONReader json_reader;
+ value.reset(json_reader.ReadToValue(std::string(engine.alternate_urls)));
+ DCHECK(value.get());
+ value->GetAsList(&alternate_urls);
+ }
+
return MakePrepopulatedTemplateURL(profile, WideToUTF16(engine.name),
WideToUTF16(engine.keyword), engine.search_url, engine.suggest_url,
- engine.instant_url, engine.favicon_url, engine.encoding, engine.id);
+ engine.instant_url, *alternate_urls,
+ engine.favicon_url, engine.encoding, engine.id);
}
void GetPrepopulatedEngines(Profile* profile,
diff --git a/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc b/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc
index 70898d6..542e9d1 100644
--- a/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc
+++ b/chrome/browser/search_engines/template_url_prepopulate_data_unittest.cc
@@ -104,6 +104,7 @@
entry->SetString("favicon_url", "http://foi.com/favicon.ico");
entry->SetString("suggest_url", "");
entry->SetString("instant_url", "");
+ entry->Set("alternate_urls", new ListValue());
entry->SetString("encoding", "UTF-8");
entry->SetInteger("id", 1001);
overrides->Append(entry);
diff --git a/chrome/browser/search_engines/template_url_service.cc b/chrome/browser/search_engines/template_url_service.cc
index 0d46d5e..a7d943f 100644
--- a/chrome/browser/search_engines/template_url_service.cc
+++ b/chrome/browser/search_engines/template_url_service.cc
@@ -85,7 +85,8 @@
(url1->favicon_url() == url2->favicon_url()) &&
(url1->safe_for_autoreplace() == url2->safe_for_autoreplace()) &&
(url1->show_in_default_list() == url2->show_in_default_list()) &&
- (url1->input_encodings() == url2->input_encodings());
+ (url1->input_encodings() == url2->input_encodings()) &&
+ (url1->alternate_urls() == url2->alternate_urls());
}
const char kFirstPotentialEngineHistogramName[] =
@@ -1301,6 +1302,9 @@
se_specifics->set_instant_url(turl.instant_url());
se_specifics->set_last_modified(turl.last_modified().ToInternalValue());
se_specifics->set_sync_guid(turl.sync_guid());
+ for (size_t i = 0; i < turl.alternate_urls().size(); ++i)
+ se_specifics->add_alternate_urls(turl.alternate_urls()[i]);
+
return syncer::SyncData::CreateLocalData(se_specifics->sync_guid(),
se_specifics->keyword(),
specifics);
@@ -1360,6 +1364,9 @@
data.last_modified = base::Time::FromInternalValue(specifics.last_modified());
data.prepopulate_id = specifics.prepopulate_id();
data.sync_guid = specifics.sync_guid();
+ data.alternate_urls.clear();
+ for (int i = 0; i < specifics.alternate_urls_size(); ++i)
+ data.alternate_urls.push_back(specifics.alternate_urls(i));
TemplateURL* turl = new TemplateURL(profile, data);
DCHECK(!turl->IsExtensionKeyword());
@@ -1627,6 +1634,7 @@
std::string keyword;
std::string id_string;
std::string prepopulate_id;
+ ListValue alternate_urls;
if (t_url) {
DCHECK(!t_url->IsExtensionKeyword());
enabled = true;
@@ -1641,6 +1649,8 @@
keyword = UTF16ToUTF8(t_url->keyword());
id_string = base::Int64ToString(t_url->id());
prepopulate_id = base::Int64ToString(t_url->prepopulate_id());
+ for (size_t i = 0; i < t_url->alternate_urls().size(); ++i)
+ alternate_urls.AppendString(t_url->alternate_urls()[i]);
}
prefs->SetBoolean(prefs::kDefaultSearchProviderEnabled, enabled);
prefs->SetString(prefs::kDefaultSearchProviderSearchURL, search_url);
@@ -1652,6 +1662,7 @@
prefs->SetString(prefs::kDefaultSearchProviderKeyword, keyword);
prefs->SetString(prefs::kDefaultSearchProviderID, id_string);
prefs->SetString(prefs::kDefaultSearchProviderPrepopulateID, prepopulate_id);
+ prefs->Set(prefs::kDefaultSearchProviderAlternateURLs, alternate_urls);
}
bool TemplateURLService::LoadDefaultSearchProviderFromPrefs(
@@ -1700,6 +1711,8 @@
std::string id_string = prefs->GetString(prefs::kDefaultSearchProviderID);
std::string prepopulate_id =
prefs->GetString(prefs::kDefaultSearchProviderPrepopulateID);
+ const ListValue* alternate_urls =
+ prefs->GetList(prefs::kDefaultSearchProviderAlternateURLs);
TemplateURLData data;
data.short_name = name;
@@ -1709,6 +1722,12 @@
data.instant_url = instant_url;
data.favicon_url = GURL(icon_url);
data.show_in_default_list = true;
+ data.alternate_urls.clear();
+ for (size_t i = 0; i < alternate_urls->GetSize(); ++i) {
+ std::string alternate_url;
+ if (alternate_urls->GetString(i, &alternate_url))
+ data.alternate_urls.push_back(alternate_url);
+ }
base::SplitString(encodings, ';', &data.input_encodings);
if (!id_string.empty() && !*is_managed) {
int64 value;
diff --git a/chrome/browser/search_engines/template_url_service_factory.cc b/chrome/browser/search_engines/template_url_service_factory.cc
index 6d8b0cb..198fdae 100644
--- a/chrome/browser/search_engines/template_url_service_factory.cc
+++ b/chrome/browser/search_engines/template_url_service_factory.cc
@@ -78,6 +78,8 @@
prefs->RegisterStringPref(prefs::kDefaultSearchProviderEncodings,
std::string(),
PrefService::UNSYNCABLE_PREF);
+ prefs->RegisterListPref(prefs::kDefaultSearchProviderAlternateURLs,
+ PrefService::UNSYNCABLE_PREF);
}
bool TemplateURLServiceFactory::ServiceRedirectedInIncognito() const {
diff --git a/chrome/browser/search_engines/template_url_unittest.cc b/chrome/browser/search_engines/template_url_unittest.cc
index 089c1a1..f621e19 100644
--- a/chrome/browser/search_engines/template_url_unittest.cc
+++ b/chrome/browser/search_engines/template_url_unittest.cc
@@ -641,3 +641,104 @@
EXPECT_EQ(TemplateURLRef::SEARCH_TERMS, replacements[0].type);
EXPECT_TRUE(valid);
}
+
+TEST_F(TemplateURLTest, GetURLNoInstantURL) {
+ TemplateURLData data;
+ data.SetURL("http://google.com/?q={searchTerms}");
+ data.suggestions_url = "http://google.com/suggest?q={searchTerms}";
+ data.alternate_urls.push_back("http://google.com/alt?q={searchTerms}");
+ data.alternate_urls.push_back("{google:baseURL}/alt/#q={searchTerms}");
+ TemplateURL url(NULL, data);
+ ASSERT_EQ(3U, url.URLCount());
+ EXPECT_EQ("http://google.com/alt?q={searchTerms}", url.GetURL(0));
+ EXPECT_EQ("{google:baseURL}/alt/#q={searchTerms}", url.GetURL(1));
+ EXPECT_EQ("http://google.com/?q={searchTerms}", url.GetURL(2));
+}
+
+TEST_F(TemplateURLTest, GetURLNoSuggestionsURL) {
+ TemplateURLData data;
+ data.SetURL("http://google.com/?q={searchTerms}");
+ data.instant_url = "http://google.com/instant#q={searchTerms}";
+ data.alternate_urls.push_back("http://google.com/alt?q={searchTerms}");
+ data.alternate_urls.push_back("{google:baseURL}/alt/#q={searchTerms}");
+ TemplateURL url(NULL, data);
+ ASSERT_EQ(3U, url.URLCount());
+ EXPECT_EQ("http://google.com/alt?q={searchTerms}", url.GetURL(0));
+ EXPECT_EQ("{google:baseURL}/alt/#q={searchTerms}", url.GetURL(1));
+ EXPECT_EQ("http://google.com/?q={searchTerms}", url.GetURL(2));
+}
+
+TEST_F(TemplateURLTest, GetURLOnlyOneURL) {
+ TemplateURLData data;
+ data.SetURL("http://www.google.co.uk/");
+ TemplateURL url(NULL, data);
+ ASSERT_EQ(1U, url.URLCount());
+ EXPECT_EQ("http://www.google.co.uk/", url.GetURL(0));
+}
+
+TEST_F(TemplateURLTest, ExtractSearchTermsFromURL) {
+ TemplateURLData data;
+ data.SetURL("http://google.com/?q={searchTerms}");
+ data.instant_url = "http://google.com/instant#q={searchTerms}";
+ data.alternate_urls.push_back("http://google.com/alt/#q={searchTerms}");
+ data.alternate_urls.push_back(
+ "http://google.com/alt/?ext=foo&q={searchTerms}#ref=bar");
+ TemplateURL url(NULL, data);
+ string16 result;
+
+ EXPECT_TRUE(url.ExtractSearchTermsFromURL(
+ GURL("http://google.com/?q=something"), &result));
+ EXPECT_EQ(ASCIIToUTF16("something"), result);
+
+ EXPECT_FALSE(url.ExtractSearchTermsFromURL(
+ GURL("http://google.ca/?q=something"), &result));
+ EXPECT_EQ(string16(), result);
+
+ EXPECT_FALSE(url.ExtractSearchTermsFromURL(
+ GURL("http://google.com/foo/?q=foo"), &result));
+ EXPECT_EQ(string16(), result);
+
+ EXPECT_FALSE(url.ExtractSearchTermsFromURL(
+ GURL("https://google.com/?q=foo"), &result));
+ EXPECT_EQ(string16(), result);
+
+ EXPECT_FALSE(url.ExtractSearchTermsFromURL(
+ GURL("http://google.com:8080/?q=foo"), &result));
+ EXPECT_EQ(string16(), result);
+
+ EXPECT_TRUE(url.ExtractSearchTermsFromURL(
+ GURL("http://google.com/?q=1+2+3&b=456"), &result));
+ EXPECT_EQ(ASCIIToUTF16("1 2 3"), result);
+
+ EXPECT_TRUE(url.ExtractSearchTermsFromURL(
+ GURL("http://google.com/alt/?q=123#q=456"), &result));
+ EXPECT_EQ(ASCIIToUTF16("456"), result);
+
+ EXPECT_TRUE(url.ExtractSearchTermsFromURL(
+ GURL("http://google.com/alt/?a=012&q=123&b=456#f=789"), &result));
+ EXPECT_EQ(ASCIIToUTF16("123"), result);
+
+ EXPECT_TRUE(url.ExtractSearchTermsFromURL(GURL(
+ "http://google.com/alt/?a=012&q=123&b=456#j=abc&q=789&h=def9"), &result));
+ EXPECT_EQ(ASCIIToUTF16("789"), result);
+
+ EXPECT_FALSE(url.ExtractSearchTermsFromURL(
+ GURL("http://google.com/alt/?q="), &result));
+ EXPECT_EQ(string16(), result);
+
+ EXPECT_FALSE(url.ExtractSearchTermsFromURL(
+ GURL("http://google.com/alt/?#q="), &result));
+ EXPECT_EQ(string16(), result);
+
+ EXPECT_FALSE(url.ExtractSearchTermsFromURL(
+ GURL("http://google.com/alt/?q=#q="), &result));
+ EXPECT_EQ(string16(), result);
+
+ EXPECT_FALSE(url.ExtractSearchTermsFromURL(
+ GURL("http://google.com/alt/?q=123#q="), &result));
+ EXPECT_EQ(string16(), result);
+
+ EXPECT_TRUE(url.ExtractSearchTermsFromURL(
+ GURL("http://google.com/alt/?q=#q=123"), &result));
+ EXPECT_EQ(ASCIIToUTF16("123"), result);
+}
diff --git a/chrome/browser/ui/toolbar/toolbar_model.cc b/chrome/browser/ui/toolbar/toolbar_model.cc
index c37d461..46efad6c 100644
--- a/chrome/browser/ui/toolbar/toolbar_model.cc
+++ b/chrome/browser/ui/toolbar/toolbar_model.cc
@@ -6,9 +6,11 @@
#include "base/utf_string_conversions.h"
#include "chrome/browser/autocomplete/autocomplete_input.h"
-#include "chrome/browser/google/google_util.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/search_engines/template_url.h"
+#include "chrome/browser/search_engines/template_url_service.h"
+#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/ssl/ssl_error_info.h"
#include "chrome/browser/ui/search/search.h"
#include "chrome/browser/ui/toolbar/toolbar_model_delegate.h"
@@ -198,14 +200,21 @@
string16 ToolbarModel::TryToExtractSearchTermsFromURL(const GURL& url) const {
Profile* profile = GetProfile();
- if (profile &&
- chrome::search::IsInstantExtendedAPIEnabled(profile) &&
- google_util::IsInstantExtendedAPIGoogleSearchUrl(url.spec())) {
- // TODO(dominich): http://crbug.com/135106 - Replace this with whatever the
- // final solution is as per http://crbug.com/139176.
- return google_util::GetSearchTermsFromGoogleSearchURL(url.spec());
- }
- return string16();
+
+ // Ensure instant extended API is enabled.
+ if (!profile || !chrome::search::IsInstantExtendedAPIEnabled(profile))
+ return string16();
+
+ TemplateURLService* template_url_service =
+ TemplateURLServiceFactory::GetForProfile(profile);
+
+ TemplateURL *template_url = template_url_service->GetDefaultSearchProvider();
+ if (!template_url)
+ return string16();
+
+ string16 result;
+ template_url->ExtractSearchTermsFromURL(url, &result);
+ return result;
}
Profile* ToolbarModel::GetProfile() const {
diff --git a/chrome/browser/ui/toolbar/toolbar_model_unittest.cc b/chrome/browser/ui/toolbar/toolbar_model_unittest.cc
index 4dfd7c0d..efbf593 100644
--- a/chrome/browser/ui/toolbar/toolbar_model_unittest.cc
+++ b/chrome/browser/ui/toolbar/toolbar_model_unittest.cc
@@ -83,17 +83,17 @@
true
},
{
- GURL("http://google.com/search?q=tractor+supply"),
- ASCIIToUTF16("google.com/search?q=tractor+supply"),
- ASCIIToUTF16("google.com/search?q=tractor+supply"),
- ASCIIToUTF16("google.com/search?q=tractor+supply"),
+ GURL("http://google.ca/search?q=tractor+supply"),
+ ASCIIToUTF16("google.ca/search?q=tractor+supply"),
+ ASCIIToUTF16("google.ca/search?q=tractor+supply"),
+ ASCIIToUTF16("google.ca/search?q=tractor+supply"),
false,
true
},
{
- GURL("http://google.com/search?q=tractor+supply&espv=1"),
- ASCIIToUTF16("google.com/search?q=tractor+supply&espv=1"),
- ASCIIToUTF16("google.com/search?q=tractor+supply&espv=1"),
+ GURL("http://google.com/search?q=tractor+supply"),
+ ASCIIToUTF16("google.com/search?q=tractor+supply"),
+ ASCIIToUTF16("google.com/search?q=tractor+supply"),
ASCIIToUTF16("tractor supply"),
true,
true
@@ -184,7 +184,7 @@
}
}
-// Test that we don't replace any URLs when the InstantExtended API is enabled.
+// Test that we replace URLs when the InstantExtended API is enabled.
TEST_F(ToolbarModelTest, ShouldDisplayURLInstantExtendedAPIEnabled) {
CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableInstantExtendedAPI);
diff --git a/chrome/browser/webdata/keyword_table.cc b/chrome/browser/webdata/keyword_table.cc
index fd0cb02..6d3a0645 100644
--- a/chrome/browser/webdata/keyword_table.cc
+++ b/chrome/browser/webdata/keyword_table.cc
@@ -6,6 +6,8 @@
#include <set>
+#include "base/json/json_reader.h"
+#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram.h"
@@ -15,6 +17,7 @@
#include "base/string_util.h"
#include "base/stringprintf.h"
#include "base/utf_string_conversions.h"
+#include "base/values.h"
#include "chrome/browser/history/history_database.h"
#include "chrome/browser/protector/histograms.h"
#include "chrome/browser/protector/protector_utils.h"
@@ -35,40 +38,45 @@
"Default Search Provider ID Backup";
const char KeywordTable::kBackupSignatureKey[] =
"Default Search Provider ID Backup Signature";
-const char KeywordTable::kKeywordColumns[] = "id, short_name, keyword, "
- "favicon_url, url, safe_for_autoreplace, originating_url, date_created, "
- "usage_count, input_encodings, show_in_default_list, suggest_url, "
- "prepopulate_id, created_by_policy, instant_url, last_modified, sync_guid";
namespace {
// Keys used in the meta table.
const char kBuiltinKeywordVersion[] = "Builtin Keyword Version";
-// The set of columns up through version 44. (There were different columns
-// below version 29 but none of the code below needs to worry about that case.)
-const char kKeywordColumnsVersion44Concatenated[] = "id || short_name || "
- "keyword || favicon_url || url || safe_for_autoreplace || "
- "originating_url || date_created || usage_count || input_encodings || "
- "show_in_default_list || suggest_url || prepopulate_id || "
- "autogenerate_keyword || logo_id || created_by_policy || instant_url || "
- "last_modified || sync_guid";
-const char kKeywordColumnsVersion44[] = "id, short_name, keyword, favicon_url, "
- "url, safe_for_autoreplace, originating_url, date_created, usage_count, "
- "input_encodings, show_in_default_list, suggest_url, prepopulate_id, "
- "autogenerate_keyword, logo_id, created_by_policy, instant_url, "
- "last_modified, sync_guid";
-// NOTE: Remember to change what |kKeywordColumnsVersion45| says if the column
-// set in |kKeywordColumns| changes, and update any code that needs to switch
-// column sets based on a version number!
-const char* const kKeywordColumnsVersion45 = KeywordTable::kKeywordColumns;
+const std::string ColumnsForVersion(int version, bool concatenated) {
+ std::vector<std::string> columns;
-// The current columns.
-const char kKeywordColumnsConcatenated[] = "id || short_name || keyword || "
- "favicon_url || url || safe_for_autoreplace || originating_url || "
- "date_created || usage_count || input_encodings || show_in_default_list || "
- "suggest_url || prepopulate_id || created_by_policy || instant_url || "
- "last_modified || sync_guid";
+ columns.push_back("id");
+ columns.push_back("short_name");
+ columns.push_back("keyword");
+ columns.push_back("favicon_url");
+ columns.push_back("url");
+ columns.push_back("safe_for_autoreplace");
+ columns.push_back("originating_url");
+ columns.push_back("date_created");
+ columns.push_back("usage_count");
+ columns.push_back("input_encodings");
+ columns.push_back("show_in_default_list");
+ columns.push_back("suggest_url");
+ columns.push_back("prepopulate_id");
+ if (version <= 44) {
+ // Columns removed after version 44.
+ columns.push_back("autogenerate_keyword");
+ columns.push_back("logo_id");
+ }
+ columns.push_back("created_by_policy");
+ columns.push_back("instant_url");
+ columns.push_back("last_modified");
+ columns.push_back("sync_guid");
+ if (version >= 47) {
+ // Column added in version 47.
+ columns.push_back("alternate_urls");
+ }
+
+ return JoinString(columns, std::string(concatenated ? " || " : ", "));
+}
+
// Inserts the data from |data| into |s|. |s| is assumed to have slots for all
// the columns in the keyword table. |id_column| is the slot number to bind
@@ -78,6 +86,16 @@
sql::Statement* s,
int id_column,
int starting_column) {
+ // Serialize |alternate_urls| to JSON.
+ // TODO(beaudoin): Check what it would take to use a new table to store
+ // alternate_urls while keeping backups and table signature in a good state.
+ // See: crbug.com/153520
+ ListValue alternate_urls_value;
+ for (size_t i = 0; i < data.alternate_urls.size(); ++i)
+ alternate_urls_value.AppendString(data.alternate_urls[i]);
+ std::string alternate_urls;
+ base::JSONWriter::Write(&alternate_urls_value, &alternate_urls);
+
s->BindInt64(id_column, data.id);
s->BindString16(starting_column, data.short_name);
s->BindString16(starting_column + 1, data.keyword());
@@ -99,6 +117,7 @@
s->BindString(starting_column + 13, data.instant_url);
s->BindInt64(starting_column + 14, data.last_modified.ToTimeT());
s->BindString(starting_column + 15, data.sync_guid);
+ s->BindString(starting_column + 16, alternate_urls);
}
} // anonymous namespace
@@ -129,7 +148,8 @@
"created_by_policy INTEGER DEFAULT 0,"
"instant_url VARCHAR,"
"last_modified INTEGER DEFAULT 0,"
- "sync_guid VARCHAR)") &&
+ "sync_guid VARCHAR,"
+ "alternate_urls VARCHAR)") &&
UpdateBackupSignature(WebDatabase::kCurrentVersionNumber));
}
@@ -139,8 +159,8 @@
bool KeywordTable::AddKeyword(const TemplateURLData& data) {
DCHECK(data.id);
- std::string query("INSERT INTO keywords (" + std::string(kKeywordColumns) +
- ") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
+ std::string query("INSERT INTO keywords (" + GetKeywordColumns() +
+ ") VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)");
sql::Statement s(db_->GetUniqueStatement(query.c_str()));
BindURLToStatement(data, &s, 0, 1);
@@ -157,7 +177,7 @@
}
bool KeywordTable::GetKeywords(Keywords* keywords) {
- std::string query("SELECT " + std::string(kKeywordColumns) +
+ std::string query("SELECT " + GetKeywordColumns() +
" FROM keywords ORDER BY id ASC");
sql::Statement s(db_->GetUniqueStatement(query.c_str()));
@@ -182,9 +202,9 @@
"keyword=?, favicon_url=?, url=?, safe_for_autoreplace=?, "
"originating_url=?, date_created=?, usage_count=?, input_encodings=?, "
"show_in_default_list=?, suggest_url=?, prepopulate_id=?, "
- "created_by_policy=?, instant_url=?, last_modified=?, sync_guid=? WHERE "
- "id=?"));
- BindURLToStatement(data, &s, 16, 0); // "16" binds id() as the last item.
+ "created_by_policy=?, instant_url=?, last_modified=?, sync_guid=?, "
+ "alternate_urls=? WHERE id=?"));
+ BindURLToStatement(data, &s, 17, 0); // "17" binds id() as the last item.
return s.Run() && UpdateBackupSignature(WebDatabase::kCurrentVersionNumber);
}
@@ -212,7 +232,7 @@
LOG(ERROR) << "No default search id backup found.";
return false;
}
- std::string query("SELECT " + std::string(kKeywordColumns) +
+ std::string query("SELECT " + GetKeywordColumns() +
" FROM keywords_backup WHERE id=?");
sql::Statement s(db_->GetUniqueStatement(query.c_str()));
s.BindInt64(0, backup_id);
@@ -289,6 +309,11 @@
return meta_table_->GetValue(kBuiltinKeywordVersion, &version) ? version : 0;
}
+// static
+std::string KeywordTable::GetKeywordColumns() {
+ return ColumnsForVersion(WebDatabase::kCurrentVersionNumber, false);
+}
+
bool KeywordTable::MigrateToVersion21AutoGenerateKeywordColumn() {
return db_->Execute("ALTER TABLE keywords ADD COLUMN autogenerate_keyword "
"INTEGER DEFAULT 0");
@@ -309,7 +334,7 @@
"INTEGER DEFAULT 0");
}
-bool KeywordTable::MigrateToVersion29InstantUrlToSupportsInstant() {
+bool KeywordTable::MigrateToVersion29InstantURLToSupportsInstant() {
sql::Transaction transaction(db_);
return transaction.Begin() &&
db_->Execute("ALTER TABLE keywords ADD COLUMN instant_url VARCHAR") &&
@@ -386,10 +411,39 @@
return transaction.Commit();
}
+bool KeywordTable::MigrateToVersion47AddAlternateURLsColumn() {
+ sql::Transaction transaction(db_);
+
+ // Fill the |alternate_urls| column with empty strings, otherwise it breaks
+ // code relying on GetTableContents that concatenates the strings from all
+ // the columns.
+ if (!transaction.Begin() ||
+ !db_->Execute("ALTER TABLE keywords ADD COLUMN "
+ "alternate_urls VARCHAR DEFAULT ''"))
+ return false;
+
+ if (IsBackupSignatureValid(46)) {
+ // Migrate the keywords backup table as well.
+ if (!db_->Execute("ALTER TABLE keywords_backup ADD COLUMN "
+ "alternate_urls VARCHAR DEFAULT ''") ||
+ !SignBackup(47))
+ return false;
+ } else {
+ // Old backup was invalid; drop the table entirely, which will trigger the
+ // protector code to prompt the user and recreate the table.
+ if (db_->DoesTableExist("keywords_backup") &&
+ !db_->Execute("DROP TABLE keywords_backup"))
+ return false;
+ }
+
+ return transaction.Commit();
+}
+
// static
bool KeywordTable::GetKeywordDataFromStatement(const sql::Statement& s,
TemplateURLData* data) {
DCHECK(data);
+
data->short_name = s.ColumnString16(1);
data->SetKeyword(s.ColumnString16(2));
// Due to past bugs, we might have persisted entries with empty URLs. Avoid
@@ -413,6 +467,19 @@
data->usage_count = s.ColumnInt(8);
data->prepopulate_id = s.ColumnInt(12);
data->sync_guid = s.ColumnString(16);
+
+ data->alternate_urls.clear();
+ base::JSONReader json_reader;
+ scoped_ptr<Value> value(json_reader.ReadToValue(s.ColumnString(17)));
+ ListValue* alternate_urls_value;
+ if (value.get() && value->GetAsList(&alternate_urls_value)) {
+ std::string alternate_url;
+ for (size_t i = 0; i < alternate_urls_value->GetSize(); ++i) {
+ if (alternate_urls_value->GetString(i, &alternate_url))
+ data->alternate_urls.push_back(alternate_url);
+ }
+ }
+
return true;
}
@@ -444,9 +511,7 @@
return false;
contents->clear();
- std::string query("SELECT " +
- std::string((table_version <= 44) ?
- kKeywordColumnsVersion44Concatenated : kKeywordColumnsConcatenated) +
+ std::string query("SELECT " + ColumnsForVersion(table_version, true) +
" FROM " + std::string(table_name) + " ORDER BY id ASC");
sql::Statement s((table_version == WebDatabase::kCurrentVersionNumber) ?
db_->GetCachedStatement(sql::StatementID(table_name), query.c_str()) :
@@ -473,8 +538,7 @@
return false;
std::string query("CREATE TABLE keywords_backup AS SELECT " +
- std::string((table_version <= 44) ?
- kKeywordColumnsVersion44 : kKeywordColumns) +
+ ColumnsForVersion(table_version, false) +
" FROM keywords ORDER BY id ASC");
if (!db_->Execute(query.c_str())) {
LOG(ERROR) << "Failed to create keywords_backup table.";
@@ -511,7 +575,8 @@
bool KeywordTable::GetKeywordAsString(TemplateURLID id,
const std::string& table_name,
std::string* result) {
- std::string query("SELECT " + std::string(kKeywordColumnsConcatenated) +
+ std::string query("SELECT " +
+ ColumnsForVersion(WebDatabase::kCurrentVersionNumber, true) +
" FROM " + table_name + " WHERE id=?");
sql::Statement s(db_->GetUniqueStatement(query.c_str()));
s.BindInt64(0, id);
@@ -564,7 +629,7 @@
"sync_guid VARCHAR)"))
return false;
std::string sql("INSERT INTO keywords_temp SELECT " +
- std::string(kKeywordColumnsVersion45) + " FROM " + name);
+ ColumnsForVersion(46, false) + " FROM " + name);
if (!db_->Execute(sql.c_str()))
return false;
diff --git a/chrome/browser/webdata/keyword_table.h b/chrome/browser/webdata/keyword_table.h
index 1293a4b..ff1385a 100644
--- a/chrome/browser/webdata/keyword_table.h
+++ b/chrome/browser/webdata/keyword_table.h
@@ -51,6 +51,8 @@
// in version 38.
// sync_guid See TemplateURLData::sync_guid. This was added in
// version 39.
+// alternate_urls See TemplateURLData::alternate_urls. This was added
+// in version 47.
//
// keywords_backup The full copy of the |keywords| table. Added in
// version 43. Must be in sync with |keywords|
@@ -89,8 +91,6 @@
// provider. The default search provider ID and the |keywords_backup| table
// are signed.
static const char kBackupSignatureKey[];
- // Comma-separated list of keyword table column names, in order.
- static const char kKeywordColumns[];
KeywordTable(sql::Connection* db, sql::MetaTable* meta_table);
virtual ~KeywordTable();
@@ -131,16 +131,21 @@
bool SetBuiltinKeywordVersion(int version);
int GetBuiltinKeywordVersion();
+ // Returns a comma-separated list of the keyword columns for the current
+ // version of the table.
+ static std::string GetKeywordColumns();
+
// Table migration functions.
bool MigrateToVersion21AutoGenerateKeywordColumn();
bool MigrateToVersion25AddLogoIDColumn();
bool MigrateToVersion26AddCreatedByPolicyColumn();
bool MigrateToVersion28SupportsInstantColumn();
- bool MigrateToVersion29InstantUrlToSupportsInstant();
+ bool MigrateToVersion29InstantURLToSupportsInstant();
bool MigrateToVersion38AddLastModifiedColumn();
bool MigrateToVersion39AddSyncGUIDColumn();
bool MigrateToVersion44AddDefaultSearchProviderBackup();
bool MigrateToVersion45RemoveLogoIDAndAutogenerateColumns();
+ bool MigrateToVersion47AddAlternateURLsColumn();
private:
FRIEND_TEST_ALL_PREFIXES(KeywordTableTest, DefaultSearchProviderBackup);
@@ -194,7 +199,7 @@
bool UpdateDefaultSearchProviderIDBackup(TemplateURLID* id);
// Migrates table |name| (which should be either "keywords" or
- // "keywords_backup" from version 44 to version 45.
+ // "keywords_backup") from version 44 to version 45.
bool MigrateKeywordsTableForVersion45(const std::string& name);
// Whether the backup was overwritten during migration.
diff --git a/chrome/browser/webdata/keyword_table_unittest.cc b/chrome/browser/webdata/keyword_table_unittest.cc
index 416ce1ab..1583ed5 100644
--- a/chrome/browser/webdata/keyword_table_unittest.cc
+++ b/chrome/browser/webdata/keyword_table_unittest.cc
@@ -259,6 +259,8 @@
keyword.date_created = base::Time::UnixEpoch();
keyword.last_modified = base::Time::UnixEpoch();
keyword.sync_guid = "1234-5678-90AB-CDEF";
+ keyword.alternate_urls.push_back("a_url1");
+ keyword.alternate_urls.push_back("a_url2");
EXPECT_TRUE(keyword_table->AddKeyword(keyword));
keyword.SetKeyword(ASCIIToUTF16("url"));
@@ -268,12 +270,13 @@
keyword.id = 2;
keyword.prepopulate_id = 5;
keyword.sync_guid = "FEDC-BA09-8765-4321";
+ keyword.alternate_urls.clear();
EXPECT_TRUE(keyword_table->AddKeyword(keyword));
const char kTestContents[] = "1short_namekeywordhttp://favicon.url/"
- "http://url/1001url20001234-5678-90AB-CDEF2short_nameurl"
- "http://favicon.url/http://url/1http://originating.url/00Shift_JIS1url250"
- "http://instant2/0FEDC-BA09-8765-4321";
+ "http://url/1001url20001234-5678-90AB-CDEF[\"a_url1\",\"a_url2\"]"
+ "2short_nameurlhttp://favicon.url/http://url/1http://originating.url/00"
+ "Shift_JIS1url250http://instant2/0FEDC-BA09-8765-4321[]";
std::string contents;
EXPECT_TRUE(keyword_table->GetTableContents("keywords",
@@ -302,6 +305,8 @@
keyword.date_created = base::Time::UnixEpoch();
keyword.last_modified = base::Time::UnixEpoch();
keyword.sync_guid = "1234-5678-90AB-CDEF";
+ keyword.alternate_urls.push_back("a_url1");
+ keyword.alternate_urls.push_back("a_url2");
EXPECT_TRUE(keyword_table->AddKeyword(keyword));
keyword.SetKeyword(ASCIIToUTF16("url"));
@@ -311,12 +316,14 @@
keyword.id = 1;
keyword.prepopulate_id = 5;
keyword.sync_guid = "FEDC-BA09-8765-4321";
+ keyword.alternate_urls.clear();
EXPECT_TRUE(keyword_table->AddKeyword(keyword));
const char kTestContents[] = "1short_nameurlhttp://favicon.url/http://url/1"
"http://originating.url/00Shift_JIS1url250http://instant2/0"
- "FEDC-BA09-8765-43212short_namekeywordhttp://favicon.url/http://url/1001"
- "url20001234-5678-90AB-CDEF";
+ "FEDC-BA09-8765-4321[]"
+ "2short_namekeywordhttp://favicon.url/http://url/1001"
+ "url20001234-5678-90AB-CDEF[\"a_url1\",\"a_url2\"]";
std::string contents;
EXPECT_TRUE(keyword_table->GetTableContents("keywords",
diff --git a/chrome/browser/webdata/web_database.cc b/chrome/browser/webdata/web_database.cc
index 5e6601e2..cdf9d58 100644
--- a/chrome/browser/webdata/web_database.cc
+++ b/chrome/browser/webdata/web_database.cc
@@ -21,11 +21,11 @@
// corresponding changes must happen in the unit tests, and new migration test
// added. See |WebDatabaseMigrationTest::kCurrentTestedVersionNumber|.
// static
-const int WebDatabase::kCurrentVersionNumber = 46;
+const int WebDatabase::kCurrentVersionNumber = 47;
namespace {
-const int kCompatibleVersionNumber = 46;
+const int kCompatibleVersionNumber = 47;
// Change the version number and possibly the compatibility version of
// |meta_table_|.
@@ -239,7 +239,7 @@
// FALL THROUGH
case 28:
- if (!keyword_table_->MigrateToVersion29InstantUrlToSupportsInstant())
+ if (!keyword_table_->MigrateToVersion29InstantURLToSupportsInstant())
return FailedMigrationTo(29);
ChangeVersion(&meta_table_, 29, true);
@@ -343,6 +343,13 @@
ChangeVersion(&meta_table_, 46, true);
// FALL THROUGH
+ case 46:
+ if (!keyword_table_->MigrateToVersion47AddAlternateURLsColumn())
+ return FailedMigrationTo(47);
+
+ ChangeVersion(&meta_table_, 47, true);
+ // FALL THROUGH
+
// Add successive versions here. Each should set the version number and
// compatible version number as appropriate, then fall through to the next
// case.
diff --git a/chrome/browser/webdata/web_database_migration_unittest.cc b/chrome/browser/webdata/web_database_migration_unittest.cc
index 513cfa73..90bdebe 100644
--- a/chrome/browser/webdata/web_database_migration_unittest.cc
+++ b/chrome/browser/webdata/web_database_migration_unittest.cc
@@ -195,7 +195,7 @@
DISALLOW_COPY_AND_ASSIGN(WebDatabaseMigrationTest);
};
-const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 46;
+const int WebDatabaseMigrationTest::kCurrentTestedVersionNumber = 47;
void WebDatabaseMigrationTest::LoadDatabase(const FilePath::StringType& file) {
std::string contents;
@@ -558,8 +558,7 @@
EXPECT_EQ(std::string(), s.ColumnString(0));
// Verify the data made it over.
- stmt = "SELECT " + std::string(KeywordTable::kKeywordColumns) +
- " FROM keywords";
+ stmt = "SELECT " + KeywordTable::GetKeywordColumns() + " FROM keywords";
sql::Statement s2(connection.GetUniqueStatement(stmt.c_str()));
ASSERT_TRUE(s2.Step());
EXPECT_EQ(2, s2.ColumnInt(0));
@@ -1783,7 +1782,7 @@
EXPECT_FALSE(default_search_provider_id_backup_signature.empty());
EXPECT_TRUE(connection.DoesTableExist("keywords_backup"));
- std::string query("SELECT " + std::string(KeywordTable::kKeywordColumns) +
+ std::string query("SELECT " + KeywordTable::GetKeywordColumns() +
" FROM keywords_backup");
sql::Statement s(connection.GetUniqueStatement(query.c_str()));
ASSERT_TRUE(s.Step());
@@ -2209,3 +2208,49 @@
EXPECT_LE(45, VersionFromConnection(&connection));
}
}
+
+// Tests that the |alternate_urls| column is added to the keyword table schema
+// for a version 45 database.
+TEST_F(WebDatabaseMigrationTest, MigrateVersion46ToCurrent) {
+ ASSERT_NO_FATAL_FAILURE(
+ LoadDatabase(FILE_PATH_LITERAL("version_46.sql")));
+
+ // Verify pre-conditions. These are expectations for version 46 of the
+ // database.
+ {
+ sql::Connection connection;
+ ASSERT_TRUE(connection.Open(GetDatabasePath()));
+ ASSERT_TRUE(sql::MetaTable::DoesTableExist(&connection));
+
+ sql::MetaTable meta_table;
+ ASSERT_TRUE(meta_table.Init(&connection, 46, 46));
+
+ ASSERT_FALSE(connection.DoesColumnExist("keywords", "alternate_urls"));
+ ASSERT_FALSE(connection.DoesColumnExist("keywords_backup",
+ "alternate_urls"));
+ }
+
+ // Load the database via the WebDatabase class and migrate the database to
+ // the current version.
+ {
+ WebDatabase db;
+ ASSERT_EQ(sql::INIT_OK, db.Init(GetDatabasePath()));
+ ASSERT_FALSE(db.GetKeywordTable()->DidDefaultSearchProviderChange());
+ }
+
+ // Verify post-conditions. These are expectations for current version of the
+ // database.
+ {
+ sql::Connection connection;
+ ASSERT_TRUE(connection.Open(GetDatabasePath()));
+ ASSERT_TRUE(sql::MetaTable::DoesTableExist(&connection));
+
+ // Check version.
+ EXPECT_EQ(kCurrentTestedVersionNumber, VersionFromConnection(&connection));
+
+ // A new column should have been created.
+ EXPECT_TRUE(connection.DoesColumnExist("keywords", "alternate_urls"));
+ ASSERT_TRUE(connection.DoesColumnExist("keywords_backup",
+ "alternate_urls"));
+ }
+}
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
index e335e1a..ce4cdd2 100644
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -419,6 +419,10 @@
const char kDefaultSearchProviderPrepopulateID[] =
"default_search_provider.prepopulate_id";
+// The alternate urls of the default search provider.
+const char kDefaultSearchProviderAlternateURLs[] =
+ "default_search_provider.alternate_urls";
+
// The dictionary key used when the default search providers are given
// in the preferences file. Normally they are copied from the master
// preferences file.
diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h
index aab4d19..33863e7 100644
--- a/chrome/common/pref_names.h
+++ b/chrome/common/pref_names.h
@@ -165,6 +165,7 @@
extern const char kDefaultSearchProviderKeyword[];
extern const char kDefaultSearchProviderID[];
extern const char kDefaultSearchProviderPrepopulateID[];
+extern const char kDefaultSearchProviderAlternateURLs[];
extern const char kSearchProviderOverrides[];
extern const char kSearchProviderOverridesVersion[];
extern const char kPromptForDownload[];
diff --git a/chrome/test/data/policy/policy_test_cases.json b/chrome/test/data/policy/policy_test_cases.json
index 994b65d..db9030f 100644
--- a/chrome/test/data/policy/policy_test_cases.json
+++ b/chrome/test/data/policy/policy_test_cases.json
@@ -564,6 +564,13 @@
"os": ["win", "linux", "mac", "chromeos"]
},
+ "DefaultSearchProviderAlternateURLs": {
+ "pref": "default_search_provider.alternate_urls",
+ "test_policy": { "DefaultSearchProviderSearchURL": "http://www.google.com/?q={searchTerms}", "DefaultSearchProviderAlternateURLs": ["http://www.google.com/#q={searchTerms}", "http://www.google.com/search#q={searchTerms}"] },
+ "settings_pages": [],
+ "os": ["win", "linux", "mac", "chromeos"]
+ },
+
"DefaultCookiesSetting": {
"pref": "profile.managed_default_content_settings.cookies",
"test_policy": { "DefaultCookiesSetting": 2 },