diff options
author | battre@chromium.org <battre@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-03 16:58:04 +0000 |
---|---|---|
committer | battre@chromium.org <battre@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-05-03 16:58:04 +0000 |
commit | ca943e7182d3e4bc7ae2e8c1c80df5310fbdab38 (patch) | |
tree | ae89245b223e5d4920c113993ca186f8365f0495 /chrome/browser | |
parent | d6c19b2bc1f0e3b90c55d46ca0646cb24b245e14 (diff) | |
download | chromium_src-ca943e7182d3e4bc7ae2e8c1c80df5310fbdab38.zip chromium_src-ca943e7182d3e4bc7ae2e8c1c80df5310fbdab38.tar.gz chromium_src-ca943e7182d3e4bc7ae2e8c1c80df5310fbdab38.tar.bz2 |
Improve error handling in proxy settings api
Introduce a bad_message parameter in order to simulate EXTENSION_FUNCTION_VALIDATE. This allows the Proxy Settings API to terminate extensions that circumvent the input parameter validation performed by the generic extension api.
BUG=none
TEST=none
Review URL: http://codereview.chromium.org/6902039
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@83901 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
7 files changed, 112 insertions, 47 deletions
diff --git a/chrome/browser/extensions/extension_preference_api.cc b/chrome/browser/extensions/extension_preference_api.cc index 08ca7f1..48b40e6 100644 --- a/chrome/browser/extensions/extension_preference_api.cc +++ b/chrome/browser/extensions/extension_preference_api.cc @@ -72,7 +72,8 @@ class IdentityPrefTransformer : public PrefTransformerInterface { virtual ~IdentityPrefTransformer() { } virtual Value* ExtensionToBrowserPref(const Value* extension_pref, - std::string* error) { + std::string* error, + bool* bad_message) { return extension_pref->DeepCopy(); } @@ -370,9 +371,12 @@ bool SetPreferenceFunction::RunImpl() { PrefTransformerInterface* transformer = PrefMapping::GetInstance()->FindTransformerForBrowserPref(browser_pref); std::string error; - Value* browserPrefValue = transformer->ExtensionToBrowserPref(value, &error); + bool bad_message = false; + Value* browserPrefValue = + transformer->ExtensionToBrowserPref(value, &error, &bad_message); if (!browserPrefValue) { error_ = error; + bad_message_ = bad_message; return false; } prefs->SetExtensionControlledPref(extension_id(), diff --git a/chrome/browser/extensions/extension_preference_api.h b/chrome/browser/extensions/extension_preference_api.h index 19325d5..2ff2c1b 100644 --- a/chrome/browser/extensions/extension_preference_api.h +++ b/chrome/browser/extensions/extension_preference_api.h @@ -48,12 +48,12 @@ class PrefTransformerInterface { // Converts the representation of a preference as seen by the extension // into a representation that is used in the pref stores of the browser. // Returns the pref store representation in case of success or sets - // |error| and returns NULL otherwise. + // |error| and returns NULL otherwise. |bad_message| is passed to simulate + // the behavior of EXTENSION_FUNCTION_VALIDATE. It is never NULL. // The ownership of the returned value is passed to the caller. - // TODO(battre): add bool* bad_message to allow terminating the entire - // extension in order to simulate the behavior of EXTENSION_FUNCTION_VALIDATE. virtual Value* ExtensionToBrowserPref(const Value* extension_pref, - std::string* error) = 0; + std::string* error, + bool* bad_message) = 0; // Converts the representation of the preference as stored in the browser // into a representation that is used by the extension. diff --git a/chrome/browser/extensions/extension_proxy_api.cc b/chrome/browser/extensions/extension_proxy_api.cc index ad9aae9..5b562b5 100644 --- a/chrome/browser/extensions/extension_proxy_api.cc +++ b/chrome/browser/extensions/extension_proxy_api.cc @@ -59,7 +59,8 @@ ProxyPrefTransformer::~ProxyPrefTransformer() { } Value* ProxyPrefTransformer::ExtensionToBrowserPref(const Value* extension_pref, - std::string* error) { + std::string* error, + bool* bad_message) { // When ExtensionToBrowserPref is called, the format of |extension_pref| // has been verified already by the extension API to match the schema // defined in chrome/common/extensions/api/extension_api.json. @@ -78,14 +79,18 @@ Value* ProxyPrefTransformer::ExtensionToBrowserPref(const Value* extension_pref, std::string pac_data; std::string proxy_rules_string; std::string bypass_list; - if (!helpers::GetProxyModeFromExtensionPref(config, &mode_enum, error) || - !helpers::GetPacMandatoryFromExtensionPref(config, &pac_mandatory, - error) || - !helpers::GetPacUrlFromExtensionPref(config, &pac_url, error) || - !helpers::GetPacDataFromExtensionPref(config, &pac_data, error) || + if (!helpers::GetProxyModeFromExtensionPref( + config, &mode_enum, error, bad_message) || + !helpers::GetPacMandatoryFromExtensionPref( + config, &pac_mandatory, error, bad_message) || + !helpers::GetPacUrlFromExtensionPref( + config, &pac_url, error, bad_message) || + !helpers::GetPacDataFromExtensionPref( + config, &pac_data, error, bad_message) || !helpers::GetProxyRulesStringFromExtensionPref( - config, &proxy_rules_string, error) || - !helpers::GetBypassListFromExtensionPref(config, &bypass_list, error)) { + config, &proxy_rules_string, error, bad_message) || + !helpers::GetBypassListFromExtensionPref( + config, &bypass_list, error, bad_message)) { return NULL; } diff --git a/chrome/browser/extensions/extension_proxy_api.h b/chrome/browser/extensions/extension_proxy_api.h index 5fb1c8d..e30235d 100644 --- a/chrome/browser/extensions/extension_proxy_api.h +++ b/chrome/browser/extensions/extension_proxy_api.h @@ -28,7 +28,8 @@ class ProxyPrefTransformer : public PrefTransformerInterface { // Implementation of PrefTransformerInterface. virtual Value* ExtensionToBrowserPref(const Value* extension_pref, - std::string* error) OVERRIDE; + std::string* error, + bool* bad_message) OVERRIDE; virtual Value* BrowserToExtensionPref(const Value* browser_pref) OVERRIDE; private: diff --git a/chrome/browser/extensions/extension_proxy_api_helpers.cc b/chrome/browser/extensions/extension_proxy_api_helpers.cc index 8c258b0..6a9e14b 100644 --- a/chrome/browser/extensions/extension_proxy_api_helpers.cc +++ b/chrome/browser/extensions/extension_proxy_api_helpers.cc @@ -59,7 +59,8 @@ bool CreatePACScriptFromDataURL( bool GetProxyModeFromExtensionPref(const DictionaryValue* proxy_config, ProxyPrefs::ProxyMode* out, - std::string* error) { + std::string* error, + bool* bad_message) { std::string proxy_mode; // We can safely assume that this is ASCII due to the allowed enumeration @@ -67,6 +68,7 @@ bool GetProxyModeFromExtensionPref(const DictionaryValue* proxy_config, proxy_config->GetStringASCII(keys::kProxyConfigMode, &proxy_mode); if (!ProxyPrefs::StringToProxyMode(proxy_mode, out)) { LOG(ERROR) << "Invalid mode for proxy settings: " << proxy_mode; + *bad_message = true; return false; } return true; @@ -74,7 +76,8 @@ bool GetProxyModeFromExtensionPref(const DictionaryValue* proxy_config, bool GetPacMandatoryFromExtensionPref(const DictionaryValue* proxy_config, bool* out, - std::string* error){ + std::string* error, + bool* bad_message){ DictionaryValue* pac_dict = NULL; proxy_config->GetDictionary(keys::kProxyConfigPacScript, &pac_dict); if (!pac_dict) @@ -85,6 +88,7 @@ bool GetPacMandatoryFromExtensionPref(const DictionaryValue* proxy_config, !pac_dict->GetBoolean(keys::kProxyConfigPacScriptMandatory, &mandatory_pac)) { LOG(ERROR) << "'pacScript.mandatory' could not be parsed."; + *bad_message = true; return false; } *out = mandatory_pac; @@ -93,7 +97,8 @@ bool GetPacMandatoryFromExtensionPref(const DictionaryValue* proxy_config, bool GetPacUrlFromExtensionPref(const DictionaryValue* proxy_config, std::string* out, - std::string* error) { + std::string* error, + bool* bad_message) { DictionaryValue* pac_dict = NULL; proxy_config->GetDictionary(keys::kProxyConfigPacScript, &pac_dict); if (!pac_dict) @@ -104,6 +109,7 @@ bool GetPacUrlFromExtensionPref(const DictionaryValue* proxy_config, if (pac_dict->HasKey(keys::kProxyConfigPacScriptUrl) && !pac_dict->GetString(keys::kProxyConfigPacScriptUrl, &pac_url16)) { LOG(ERROR) << "'pacScript.url' could not be parsed."; + *bad_message = true; return false; } if (!IsStringASCII(pac_url16)) { @@ -117,7 +123,8 @@ bool GetPacUrlFromExtensionPref(const DictionaryValue* proxy_config, bool GetPacDataFromExtensionPref(const DictionaryValue* proxy_config, std::string* out, - std::string* error) { + std::string* error, + bool* bad_message) { DictionaryValue* pac_dict = NULL; proxy_config->GetDictionary(keys::kProxyConfigPacScript, &pac_dict); if (!pac_dict) @@ -127,6 +134,7 @@ bool GetPacDataFromExtensionPref(const DictionaryValue* proxy_config, if (pac_dict->HasKey(keys::kProxyConfigPacScriptData) && !pac_dict->GetString(keys::kProxyConfigPacScriptData, &pac_data16)) { LOG(ERROR) << "'pacScript.data' could not be parsed."; + *bad_message = true; return false; } if (!IsStringASCII(pac_data16)) { @@ -141,7 +149,8 @@ bool GetPacDataFromExtensionPref(const DictionaryValue* proxy_config, bool GetProxyServer(const DictionaryValue* proxy_server, net::ProxyServer::Scheme default_scheme, net::ProxyServer* out, - std::string* error) { + std::string* error, + bool* bad_message) { std::string scheme_string; // optional. // We can safely assume that this is ASCII due to the allowed enumeration @@ -157,6 +166,7 @@ bool GetProxyServer(const DictionaryValue* proxy_server, string16 host16; if (!proxy_server->GetString(keys::kProxyConfigRuleHost, &host16)) { LOG(ERROR) << "Could not parse a 'rules.*.host' entry."; + *bad_message = true; return false; } if (!IsStringASCII(host16)) { @@ -179,7 +189,8 @@ bool GetProxyServer(const DictionaryValue* proxy_server, bool GetProxyRulesStringFromExtensionPref(const DictionaryValue* proxy_config, std::string* out, - std::string* error) { + std::string* error, + bool* bad_message) { DictionaryValue* proxy_rules = NULL; proxy_config->GetDictionary(keys::kProxyConfigRules, &proxy_rules); if (!proxy_rules) @@ -201,7 +212,7 @@ bool GetProxyRulesStringFromExtensionPref(const DictionaryValue* proxy_config, if (has_proxy[i]) { net::ProxyServer::Scheme default_scheme = net::ProxyServer::SCHEME_HTTP; if (!GetProxyServer(proxy_dict, default_scheme, - &proxy_server[i], error)) { + &proxy_server[i], error, bad_message)) { // Don't set |error| here, as GetProxyServer takes care of that. return false; } @@ -246,7 +257,8 @@ bool GetProxyRulesStringFromExtensionPref(const DictionaryValue* proxy_config, bool JoinUrlList(ListValue* list, const std::string& joiner, std::string* out, - std::string* error) { + std::string* error, + bool* bad_message) { std::string result; for (size_t i = 0; i < list->GetSize(); ++i) { if (!result.empty()) @@ -256,6 +268,7 @@ bool JoinUrlList(ListValue* list, string16 entry; if (!list->GetString(i, &entry)) { LOG(ERROR) << "'rules.bypassList' could not be parsed."; + *bad_message = true; return false; } if (!IsStringASCII(entry)) { @@ -271,7 +284,8 @@ bool JoinUrlList(ListValue* list, bool GetBypassListFromExtensionPref(const DictionaryValue* proxy_config, std::string *out, - std::string* error) { + std::string* error, + bool* bad_message) { DictionaryValue* proxy_rules = NULL; proxy_config->GetDictionary(keys::kProxyConfigRules, &proxy_rules); if (!proxy_rules) @@ -283,11 +297,12 @@ bool GetBypassListFromExtensionPref(const DictionaryValue* proxy_config, } ListValue* bypass_list = NULL; if (!proxy_rules->GetList(keys::kProxyConfigBypassList, &bypass_list)) { - LOG(ERROR) << "'rules.bypassList' not be parsed."; + LOG(ERROR) << "'rules.bypassList' could not be parsed."; + *bad_message = true; return false; } - return JoinUrlList(bypass_list, ",", out, error); + return JoinUrlList(bypass_list, ",", out, error, bad_message); } DictionaryValue* CreateProxyConfigDict(ProxyPrefs::ProxyMode mode_enum, diff --git a/chrome/browser/extensions/extension_proxy_api_helpers.h b/chrome/browser/extensions/extension_proxy_api_helpers.h index 11eb6b9..1907a3d 100644 --- a/chrome/browser/extensions/extension_proxy_api_helpers.h +++ b/chrome/browser/extensions/extension_proxy_api_helpers.h @@ -43,24 +43,33 @@ bool CreatePACScriptFromDataURL( // and return true. // - If there are entries that could not be parsed, the functions set |error| // and return false. +// +// The parameter |bad_message| is passed to simulate the behavior of +// EXTENSION_FUNCTION_VALIDATE. It is never NULL. bool GetProxyModeFromExtensionPref(const DictionaryValue* proxy_config, ProxyPrefs::ProxyMode* out, - std::string* error); + std::string* error, + bool* bad_message); bool GetPacMandatoryFromExtensionPref(const DictionaryValue* proxy_config, bool* out, - std::string* error); + std::string* error, + bool* bad_message); bool GetPacUrlFromExtensionPref(const DictionaryValue* proxy_config, std::string* out, - std::string* error); + std::string* error, + bool* bad_message); bool GetPacDataFromExtensionPref(const DictionaryValue* proxy_config, std::string* out, - std::string* error); + std::string* error, + bool* bad_message); bool GetProxyRulesStringFromExtensionPref(const DictionaryValue* proxy_config, std::string* out, - std::string* error); + std::string* error, + bool* bad_message); bool GetBypassListFromExtensionPref(const DictionaryValue* proxy_config, std::string* out, - std::string* error); + std::string* error, + bool* bad_message); // Creates and returns a ProxyConfig dictionary (as defined in the extension // API) from the given parameters. Ownership is passed to the caller. @@ -81,14 +90,16 @@ DictionaryValue* CreateProxyConfigDict(ProxyPrefs::ProxyMode mode_enum, bool GetProxyServer(const DictionaryValue* proxy_server, net::ProxyServer::Scheme default_scheme, net::ProxyServer* out, - std::string* error); + std::string* error, + bool* bad_message); // Joins a list of URLs (stored as StringValues) in |list| with |joiner| // to |out|. Returns true if successful and sets |error| otherwise. bool JoinUrlList(ListValue* list, const std::string& joiner, std::string* out, - std::string* error); + std::string* error, + bool* bad_message); // Helper functions for browser->extension pref transformation: diff --git a/chrome/browser/extensions/extension_proxy_api_helpers_unittest.cc b/chrome/browser/extensions/extension_proxy_api_helpers_unittest.cc index 2f73547..dbbcf5a 100644 --- a/chrome/browser/extensions/extension_proxy_api_helpers_unittest.cc +++ b/chrome/browser/extensions/extension_proxy_api_helpers_unittest.cc @@ -63,18 +63,23 @@ TEST(ExtensionProxyApiHelpers, GetProxyModeFromExtensionPref) { DictionaryValue proxy_config; ProxyPrefs::ProxyMode mode; std::string error; + bool bad_message = false; // Test positive case. proxy_config.SetString( keys::kProxyConfigMode, ProxyPrefs::ProxyModeToString(ProxyPrefs::MODE_DIRECT)); - ASSERT_TRUE(GetProxyModeFromExtensionPref(&proxy_config, &mode, &error)); + ASSERT_TRUE(GetProxyModeFromExtensionPref(&proxy_config, &mode, &error, + &bad_message)); EXPECT_EQ(ProxyPrefs::MODE_DIRECT, mode); EXPECT_EQ(std::string(), error); + EXPECT_FALSE(bad_message); // Test negative case. proxy_config.SetString(keys::kProxyConfigMode, "foobar"); - EXPECT_FALSE(GetProxyModeFromExtensionPref(&proxy_config, &mode, &error)); + EXPECT_FALSE(GetProxyModeFromExtensionPref(&proxy_config, &mode, &error, + &bad_message)); + EXPECT_TRUE(bad_message); // Do not test |error|, as an invalid enumeration value is considered an // internal error. It should be filtered by the extensions API. @@ -83,6 +88,7 @@ TEST(ExtensionProxyApiHelpers, GetProxyModeFromExtensionPref) { TEST(ExtensionProxyApiHelpers, GetPacUrlFromExtensionPref) { std::string out; std::string error; + bool bad_message = false; DictionaryValue proxy_config; proxy_config.SetString( @@ -91,23 +97,28 @@ TEST(ExtensionProxyApiHelpers, GetPacUrlFromExtensionPref) { // Currently we are still missing a PAC script entry. // This is silently ignored. - ASSERT_TRUE(GetPacUrlFromExtensionPref(&proxy_config, &out, &error)); + ASSERT_TRUE(GetPacUrlFromExtensionPref(&proxy_config, &out, &error, + &bad_message)); EXPECT_EQ(std::string(), out); EXPECT_EQ(std::string(), error); + EXPECT_FALSE(bad_message); // Set up a pac script. DictionaryValue* pacScriptDict = new DictionaryValue; pacScriptDict->SetString(keys::kProxyConfigPacScriptUrl, kSamplePacScriptUrl); proxy_config.Set(keys::kProxyConfigPacScript, pacScriptDict); - ASSERT_TRUE(GetPacUrlFromExtensionPref(&proxy_config, &out, &error)); + ASSERT_TRUE(GetPacUrlFromExtensionPref(&proxy_config, &out, &error, + &bad_message)); EXPECT_EQ(kSamplePacScriptUrl, out); EXPECT_EQ(std::string(), error); + EXPECT_FALSE(bad_message); } TEST(ExtensionProxyApiHelpers, GetPacDataFromExtensionPref) { std::string out; std::string error; + bool bad_message = false; DictionaryValue proxy_config; proxy_config.SetString( @@ -115,23 +126,28 @@ TEST(ExtensionProxyApiHelpers, GetPacDataFromExtensionPref) { ProxyPrefs::ProxyModeToString(ProxyPrefs::MODE_PAC_SCRIPT)); // Currently we are still missing a PAC data entry. This is silently ignored. - ASSERT_TRUE(GetPacDataFromExtensionPref(&proxy_config, &out, &error)); + ASSERT_TRUE(GetPacDataFromExtensionPref(&proxy_config, &out, &error, + &bad_message)); EXPECT_EQ(std::string(), out); EXPECT_EQ(std::string(), error); + EXPECT_FALSE(bad_message); // Set up a PAC script. DictionaryValue* pacScriptDict = new DictionaryValue; pacScriptDict->SetString(keys::kProxyConfigPacScriptData, kSamplePacScript); proxy_config.Set(keys::kProxyConfigPacScript, pacScriptDict); - ASSERT_TRUE(GetPacDataFromExtensionPref(&proxy_config, &out, &error)); + ASSERT_TRUE(GetPacDataFromExtensionPref(&proxy_config, &out, &error, + &bad_message)); EXPECT_EQ(kSamplePacScript, out); EXPECT_EQ(std::string(), error); + EXPECT_FALSE(bad_message); } TEST(ExtensionProxyApiHelpers, GetProxyRulesStringFromExtensionPref) { std::string out; std::string error; + bool bad_message = false; DictionaryValue proxy_config; proxy_config.SetString( @@ -141,7 +157,8 @@ TEST(ExtensionProxyApiHelpers, GetProxyRulesStringFromExtensionPref) { // Currently we are still missing a proxy config entry. // This is silently ignored. ASSERT_TRUE( - GetProxyRulesStringFromExtensionPref(&proxy_config, &out, &error)); + GetProxyRulesStringFromExtensionPref(&proxy_config, &out, &error, + &bad_message)); EXPECT_EQ(std::string(), out); EXPECT_EQ(std::string(), error); @@ -151,14 +168,17 @@ TEST(ExtensionProxyApiHelpers, GetProxyRulesStringFromExtensionPref) { proxy_config.Set(keys::kProxyConfigRules, proxy_rules); ASSERT_TRUE( - GetProxyRulesStringFromExtensionPref(&proxy_config, &out, &error)); + GetProxyRulesStringFromExtensionPref(&proxy_config, &out, &error, + &bad_message)); EXPECT_EQ("http=proxy1:80;https=proxy2:80", out); EXPECT_EQ(std::string(), error); + EXPECT_FALSE(bad_message); } TEST(ExtensionProxyApiHelpers, GetBypassListFromExtensionPref) { std::string out; std::string error; + bool bad_message = false; DictionaryValue proxy_config; proxy_config.SetString( @@ -168,9 +188,11 @@ TEST(ExtensionProxyApiHelpers, GetBypassListFromExtensionPref) { // Currently we are still missing a proxy config entry. // This is silently ignored. ASSERT_TRUE( - GetBypassListFromExtensionPref(&proxy_config, &out, &error)); + GetBypassListFromExtensionPref(&proxy_config, &out, &error, + &bad_message)); EXPECT_EQ(std::string(), out); EXPECT_EQ(std::string(), error); + EXPECT_FALSE(bad_message); ListValue* bypass_list = new ListValue; bypass_list->Append(Value::CreateStringValue("host1")); @@ -180,9 +202,11 @@ TEST(ExtensionProxyApiHelpers, GetBypassListFromExtensionPref) { proxy_config.Set(keys::kProxyConfigRules, proxy_rules); ASSERT_TRUE( - GetBypassListFromExtensionPref(&proxy_config, &out, &error)); + GetBypassListFromExtensionPref(&proxy_config, &out, &error, + &bad_message)); EXPECT_EQ("host1,host2", out); EXPECT_EQ(std::string(), error); + EXPECT_FALSE(bad_message); } TEST(ExtensionProxyApiHelpers, CreateProxyConfigDict) { @@ -235,24 +259,28 @@ TEST(ExtensionProxyApiHelpers, GetProxyServer) { DictionaryValue proxy_server_dict; net::ProxyServer created; std::string error; + bool bad_message = false; // Test simplest case, no schema nor port specified --> defaults are used. proxy_server_dict.SetString(keys::kProxyConfigRuleHost, "proxy_server"); ASSERT_TRUE( GetProxyServer(&proxy_server_dict, net::ProxyServer::SCHEME_HTTP, - &created, &error)); + &created, &error, &bad_message)); EXPECT_EQ("PROXY proxy_server:80", created.ToPacString()); + EXPECT_FALSE(bad_message); // Test complete case. proxy_server_dict.SetString(keys::kProxyConfigRuleScheme, "socks4"); proxy_server_dict.SetInteger(keys::kProxyConfigRulePort, 1234); ASSERT_TRUE( GetProxyServer(&proxy_server_dict, net::ProxyServer::SCHEME_HTTP, - &created, &error)); + &created, &error, &bad_message)); EXPECT_EQ("SOCKS proxy_server:1234", created.ToPacString()); + EXPECT_FALSE(bad_message); } TEST(ExtensionProxyApiHelpers, JoinUrlList) { + bool bad_message = false; ListValue list; list.Append(Value::CreateStringValue("s1")); list.Append(Value::CreateStringValue("s2")); @@ -260,8 +288,9 @@ TEST(ExtensionProxyApiHelpers, JoinUrlList) { std::string out; std::string error; - ASSERT_TRUE(JoinUrlList(&list, ";", &out, &error)); + ASSERT_TRUE(JoinUrlList(&list, ";", &out, &error, &bad_message)); EXPECT_EQ("s1;s2;s3", out); + EXPECT_FALSE(bad_message); } // This tests CreateProxyServerDict as well. |