summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/automation/automation_provider.cc4
-rw-r--r--chrome/browser/extensions/extension_preference_api.h2
-rw-r--r--chrome/browser/extensions/extension_proxy_api.cc6
-rw-r--r--chrome/browser/extensions/extension_proxy_api_constants.cc1
-rw-r--r--chrome/browser/extensions/extension_proxy_api_constants.h1
-rw-r--r--chrome/browser/extensions/extension_proxy_api_helpers.cc30
-rw-r--r--chrome/browser/extensions/extension_proxy_api_helpers.h4
-rw-r--r--chrome/browser/extensions/extension_proxy_api_helpers_unittest.cc26
-rw-r--r--chrome/browser/net/pref_proxy_config_service.cc3
-rw-r--r--chrome/browser/net/pref_proxy_config_service_unittest.cc4
-rw-r--r--chrome/browser/policy/configuration_policy_pref_store.cc2
-rw-r--r--chrome/browser/prefs/command_line_pref_store.cc2
-rw-r--r--chrome/browser/prefs/proxy_config_dictionary.cc31
-rw-r--r--chrome/browser/prefs/proxy_config_dictionary.h5
-rw-r--r--chrome/browser/prefs/proxy_config_dictionary_unittest.cc2
-rw-r--r--chrome/common/automation_constants.cc1
-rw-r--r--chrome/common/automation_constants.h1
-rw-r--r--chrome/common/extensions/api/extension_api.json3
-rw-r--r--chrome/common/extensions/docs/examples/extensions/proxy_configuration.zipbin144472 -> 107504 bytes
-rw-r--r--chrome/common/extensions/docs/examples/extensions/proxy_configuration/proxy_form_controller.js6
-rw-r--r--chrome/common/extensions/docs/experimental.proxy.html68
-rw-r--r--chrome/common/extensions/docs/samples.json2
-rw-r--r--chrome/test/data/extensions/api_test/proxy/pacdata/test.js3
-rw-r--r--net/base/net_error_list.h6
-rw-r--r--net/proxy/proxy_config.cc14
-rw-r--r--net/proxy/proxy_config.h16
-rw-r--r--net/proxy/proxy_service.cc45
-rw-r--r--net/proxy/proxy_service.h4
28 files changed, 241 insertions, 51 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc
index 5a86ca7..a5a6686 100644
--- a/chrome/browser/automation/automation_provider.cc
+++ b/chrome/browser/automation/automation_provider.cc
@@ -550,6 +550,10 @@ class SetProxyConfigTask : public Task {
if (dict.GetString(automation::kJSONProxyPacUrl, &pac_url)) {
pc->set_pac_url(GURL(pac_url));
}
+ bool pac_mandatory;
+ if (dict.GetBoolean(automation::kJSONProxyPacMandatory, &pac_mandatory)) {
+ pc->set_pac_mandatory(pac_mandatory);
+ }
std::string proxy_bypass_list;
if (dict.GetString(automation::kJSONProxyBypassList, &proxy_bypass_list)) {
pc->proxy_rules().bypass_rules.ParseFromString(proxy_bypass_list);
diff --git a/chrome/browser/extensions/extension_preference_api.h b/chrome/browser/extensions/extension_preference_api.h
index 31c4452..19325d5 100644
--- a/chrome/browser/extensions/extension_preference_api.h
+++ b/chrome/browser/extensions/extension_preference_api.h
@@ -50,6 +50,8 @@ class PrefTransformerInterface {
// Returns the pref store representation in case of success or sets
// |error| and returns NULL otherwise.
// 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;
diff --git a/chrome/browser/extensions/extension_proxy_api.cc b/chrome/browser/extensions/extension_proxy_api.cc
index ccf62bd..ad9aae9 100644
--- a/chrome/browser/extensions/extension_proxy_api.cc
+++ b/chrome/browser/extensions/extension_proxy_api.cc
@@ -73,11 +73,14 @@ Value* ProxyPrefTransformer::ExtensionToBrowserPref(const Value* extension_pref,
// If a values has been passed to set but could not be parsed, we bail
// out and return NULL.
ProxyPrefs::ProxyMode mode_enum;
+ bool pac_mandatory;
std::string pac_url;
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) ||
!helpers::GetProxyRulesStringFromExtensionPref(
@@ -87,7 +90,8 @@ Value* ProxyPrefTransformer::ExtensionToBrowserPref(const Value* extension_pref,
}
return helpers::CreateProxyConfigDict(
- mode_enum, pac_url, pac_data, proxy_rules_string, bypass_list, error);
+ mode_enum, pac_mandatory, pac_url, pac_data, proxy_rules_string,
+ bypass_list, error);
}
Value* ProxyPrefTransformer::BrowserToExtensionPref(const Value* browser_pref) {
diff --git a/chrome/browser/extensions/extension_proxy_api_constants.cc b/chrome/browser/extensions/extension_proxy_api_constants.cc
index f7f52bb..9078265 100644
--- a/chrome/browser/extensions/extension_proxy_api_constants.cc
+++ b/chrome/browser/extensions/extension_proxy_api_constants.cc
@@ -12,6 +12,7 @@ namespace extension_proxy_api_constants {
const char kProxyConfigMode[] = "mode";
const char kProxyConfigPacScript[] = "pacScript";
+const char kProxyConfigPacScriptMandatory[] = "mandatory";
const char kProxyConfigPacScriptUrl[] = "url";
const char kProxyConfigPacScriptData[] = "data";
const char kProxyConfigRules[] = "rules";
diff --git a/chrome/browser/extensions/extension_proxy_api_constants.h b/chrome/browser/extensions/extension_proxy_api_constants.h
index 13fbe67..1b8a99d 100644
--- a/chrome/browser/extensions/extension_proxy_api_constants.h
+++ b/chrome/browser/extensions/extension_proxy_api_constants.h
@@ -13,6 +13,7 @@ namespace extension_proxy_api_constants {
// String literals in dictionaries used to communicate with extension.
extern const char kProxyConfigMode[];
extern const char kProxyConfigPacScript[];
+extern const char kProxyConfigPacScriptMandatory[];
extern const char kProxyConfigPacScriptUrl[];
extern const char kProxyConfigPacScriptData[];
extern const char kProxyConfigRules[];
diff --git a/chrome/browser/extensions/extension_proxy_api_helpers.cc b/chrome/browser/extensions/extension_proxy_api_helpers.cc
index 6429843..8c258b0 100644
--- a/chrome/browser/extensions/extension_proxy_api_helpers.cc
+++ b/chrome/browser/extensions/extension_proxy_api_helpers.cc
@@ -72,6 +72,25 @@ bool GetProxyModeFromExtensionPref(const DictionaryValue* proxy_config,
return true;
}
+bool GetPacMandatoryFromExtensionPref(const DictionaryValue* proxy_config,
+ bool* out,
+ std::string* error){
+ DictionaryValue* pac_dict = NULL;
+ proxy_config->GetDictionary(keys::kProxyConfigPacScript, &pac_dict);
+ if (!pac_dict)
+ return true;
+
+ bool mandatory_pac = false;
+ if (pac_dict->HasKey(keys::kProxyConfigPacScriptMandatory) &&
+ !pac_dict->GetBoolean(keys::kProxyConfigPacScriptMandatory,
+ &mandatory_pac)) {
+ LOG(ERROR) << "'pacScript.mandatory' could not be parsed.";
+ return false;
+ }
+ *out = mandatory_pac;
+ return true;
+}
+
bool GetPacUrlFromExtensionPref(const DictionaryValue* proxy_config,
std::string* out,
std::string* error) {
@@ -272,6 +291,7 @@ bool GetBypassListFromExtensionPref(const DictionaryValue* proxy_config,
}
DictionaryValue* CreateProxyConfigDict(ProxyPrefs::ProxyMode mode_enum,
+ bool pac_mandatory,
const std::string& pac_url,
const std::string& pac_data,
const std::string& proxy_rules_string,
@@ -299,7 +319,8 @@ DictionaryValue* CreateProxyConfigDict(ProxyPrefs::ProxyMode mode_enum,
"either a 'url' field or a 'data' field.";
return NULL;
}
- result_proxy_config = ProxyConfigDictionary::CreatePacScript(url);
+ result_proxy_config =
+ ProxyConfigDictionary::CreatePacScript(url, pac_mandatory);
break;
}
case ProxyPrefs::MODE_FIXED_SERVERS: {
@@ -419,6 +440,11 @@ DictionaryValue* CreatePacScriptDict(
LOG(ERROR) << "Invalid proxy configuration. Missing PAC URL.";
return NULL;
}
+ bool pac_mandatory = false;
+ if (!proxy_config.GetPacMandatory(&pac_mandatory)) {
+ LOG(ERROR) << "Invalid proxy configuration. Missing PAC mandatory field.";
+ return NULL;
+ }
if (pac_url.find("data") == 0) {
std::string pac_data;
@@ -430,6 +456,8 @@ DictionaryValue* CreatePacScriptDict(
} else {
pac_script_dict->SetString(keys::kProxyConfigPacScriptUrl, pac_url);
}
+ pac_script_dict->SetBoolean(keys::kProxyConfigPacScriptMandatory,
+ pac_mandatory);
return pac_script_dict.release();
}
diff --git a/chrome/browser/extensions/extension_proxy_api_helpers.h b/chrome/browser/extensions/extension_proxy_api_helpers.h
index d1d6782..11eb6b9 100644
--- a/chrome/browser/extensions/extension_proxy_api_helpers.h
+++ b/chrome/browser/extensions/extension_proxy_api_helpers.h
@@ -46,6 +46,9 @@ bool CreatePACScriptFromDataURL(
bool GetProxyModeFromExtensionPref(const DictionaryValue* proxy_config,
ProxyPrefs::ProxyMode* out,
std::string* error);
+bool GetPacMandatoryFromExtensionPref(const DictionaryValue* proxy_config,
+ bool* out,
+ std::string* error);
bool GetPacUrlFromExtensionPref(const DictionaryValue* proxy_config,
std::string* out,
std::string* error);
@@ -63,6 +66,7 @@ bool GetBypassListFromExtensionPref(const DictionaryValue* proxy_config,
// API) from the given parameters. Ownership is passed to the caller.
// Depending on the value of |mode_enum|, several of the strings may be empty.
DictionaryValue* CreateProxyConfigDict(ProxyPrefs::ProxyMode mode_enum,
+ bool pac_mandatory,
const std::string& pac_url,
const std::string& pac_data,
const std::string& proxy_rules_string,
diff --git a/chrome/browser/extensions/extension_proxy_api_helpers_unittest.cc b/chrome/browser/extensions/extension_proxy_api_helpers_unittest.cc
index ef1fe16..2f73547 100644
--- a/chrome/browser/extensions/extension_proxy_api_helpers_unittest.cc
+++ b/chrome/browser/extensions/extension_proxy_api_helpers_unittest.cc
@@ -189,40 +189,42 @@ TEST(ExtensionProxyApiHelpers, CreateProxyConfigDict) {
std::string error;
scoped_ptr<DictionaryValue> exp_direct(ProxyConfigDictionary::CreateDirect());
scoped_ptr<DictionaryValue> out_direct(
- CreateProxyConfigDict(ProxyPrefs::MODE_DIRECT, "", "", "", "", &error));
+ CreateProxyConfigDict(ProxyPrefs::MODE_DIRECT, false, "", "", "", "",
+ &error));
EXPECT_TRUE(Value::Equals(exp_direct.get(), out_direct.get()));
scoped_ptr<DictionaryValue> exp_auto(
ProxyConfigDictionary::CreateAutoDetect());
scoped_ptr<DictionaryValue> out_auto(
- CreateProxyConfigDict(ProxyPrefs::MODE_AUTO_DETECT, "", "", "", "",
+ CreateProxyConfigDict(ProxyPrefs::MODE_AUTO_DETECT, false, "", "", "", "",
&error));
EXPECT_TRUE(Value::Equals(exp_auto.get(), out_auto.get()));
scoped_ptr<DictionaryValue> exp_pac_url(
- ProxyConfigDictionary::CreatePacScript(kSamplePacScriptUrl));
+ ProxyConfigDictionary::CreatePacScript(kSamplePacScriptUrl, false));
scoped_ptr<DictionaryValue> out_pac_url(
- CreateProxyConfigDict(ProxyPrefs::MODE_PAC_SCRIPT, kSamplePacScriptUrl,
- "", "", "", &error));
+ CreateProxyConfigDict(ProxyPrefs::MODE_PAC_SCRIPT, false,
+ kSamplePacScriptUrl, "", "", "", &error));
EXPECT_TRUE(Value::Equals(exp_pac_url.get(), out_pac_url.get()));
scoped_ptr<DictionaryValue> exp_pac_data(
- ProxyConfigDictionary::CreatePacScript(kSamplePacScriptAsDataUrl));
+ ProxyConfigDictionary::CreatePacScript(kSamplePacScriptAsDataUrl, false));
scoped_ptr<DictionaryValue> out_pac_data(
- CreateProxyConfigDict(ProxyPrefs::MODE_PAC_SCRIPT, "",
+ CreateProxyConfigDict(ProxyPrefs::MODE_PAC_SCRIPT, false, "",
kSamplePacScript, "", "", &error));
EXPECT_TRUE(Value::Equals(exp_pac_data.get(), out_pac_data.get()));
scoped_ptr<DictionaryValue> exp_fixed(
ProxyConfigDictionary::CreateFixedServers("foo:80", "localhost"));
scoped_ptr<DictionaryValue> out_fixed(
- CreateProxyConfigDict(ProxyPrefs::MODE_FIXED_SERVERS, "", "",
+ CreateProxyConfigDict(ProxyPrefs::MODE_FIXED_SERVERS, false, "", "",
"foo:80", "localhost", &error));
EXPECT_TRUE(Value::Equals(exp_fixed.get(), out_fixed.get()));
scoped_ptr<DictionaryValue> exp_system(ProxyConfigDictionary::CreateSystem());
scoped_ptr<DictionaryValue> out_system(
- CreateProxyConfigDict(ProxyPrefs::MODE_SYSTEM, "", "", "", "", &error));
+ CreateProxyConfigDict(ProxyPrefs::MODE_SYSTEM, false, "", "", "", "",
+ &error));
EXPECT_TRUE(Value::Equals(exp_system.get(), out_system.get()));
// Neither of them should have set an error.
@@ -291,13 +293,14 @@ TEST(ExtensionProxyApiHelpers, CreateProxyRulesDict) {
// Test if a PAC script URL is specified.
TEST(ExtensionProxyApiHelpers, CreatePacScriptDictWithUrl) {
scoped_ptr<DictionaryValue> browser_pref(
- ProxyConfigDictionary::CreatePacScript(kSamplePacScriptUrl));
+ ProxyConfigDictionary::CreatePacScript(kSamplePacScriptUrl, false));
ProxyConfigDictionary config(browser_pref.get());
scoped_ptr<DictionaryValue> extension_pref(CreatePacScriptDict(config));
ASSERT_TRUE(extension_pref.get());
scoped_ptr<DictionaryValue> expected(new DictionaryValue);
expected->SetString(keys::kProxyConfigPacScriptUrl, kSamplePacScriptUrl);
+ expected->SetBoolean(keys::kProxyConfigPacScriptMandatory, false);
EXPECT_TRUE(Value::Equals(expected.get(), extension_pref.get()));
}
@@ -305,13 +308,14 @@ TEST(ExtensionProxyApiHelpers, CreatePacScriptDictWithUrl) {
// Test if a PAC script is encoded in a data URL.
TEST(ExtensionProxyApiHelpers, CreatePacScriptDictWidthData) {
scoped_ptr<DictionaryValue> browser_pref(
- ProxyConfigDictionary::CreatePacScript(kSamplePacScriptAsDataUrl));
+ ProxyConfigDictionary::CreatePacScript(kSamplePacScriptAsDataUrl, false));
ProxyConfigDictionary config(browser_pref.get());
scoped_ptr<DictionaryValue> extension_pref(CreatePacScriptDict(config));
ASSERT_TRUE(extension_pref.get());
scoped_ptr<DictionaryValue> expected(new DictionaryValue);
expected->SetString(keys::kProxyConfigPacScriptData, kSamplePacScript);
+ expected->SetBoolean(keys::kProxyConfigPacScriptMandatory, false);
EXPECT_TRUE(Value::Equals(expected.get(), extension_pref.get()));
}
diff --git a/chrome/browser/net/pref_proxy_config_service.cc b/chrome/browser/net/pref_proxy_config_service.cc
index 7862be9..f867923 100644
--- a/chrome/browser/net/pref_proxy_config_service.cc
+++ b/chrome/browser/net/pref_proxy_config_service.cc
@@ -137,6 +137,9 @@ bool PrefProxyConfigTracker::PrefConfigToNetConfig(
return true;
}
config->set_pac_url(proxy_pac_url);
+ bool pac_mandatory = false;
+ proxy_dict.GetPacMandatory(&pac_mandatory);
+ config->set_pac_mandatory(pac_mandatory);
return true;
}
case ProxyPrefs::MODE_FIXED_SERVERS: {
diff --git a/chrome/browser/net/pref_proxy_config_service_unittest.cc b/chrome/browser/net/pref_proxy_config_service_unittest.cc
index 19bb53b..6d959a3 100644
--- a/chrome/browser/net/pref_proxy_config_service_unittest.cc
+++ b/chrome/browser/net/pref_proxy_config_service_unittest.cc
@@ -177,7 +177,7 @@ TEST_F(PrefProxyConfigServiceTest, Observers) {
CONFIG_VALID)).Times(1);
pref_service_->SetManagedPref(
prefs::kProxy,
- ProxyConfigDictionary::CreatePacScript(kFixedPacUrl));
+ ProxyConfigDictionary::CreatePacScript(kFixedPacUrl, false));
loop_.RunAllPending();
Mock::VerifyAndClearExpectations(&observer);
@@ -242,7 +242,7 @@ TEST_F(PrefProxyConfigServiceTest, Fallback) {
CONFIG_VALID)).Times(1);
pref_service_->SetManagedPref(
prefs::kProxy,
- ProxyConfigDictionary::CreatePacScript(kFixedPacUrl));
+ ProxyConfigDictionary::CreatePacScript(kFixedPacUrl, false));
loop_.RunAllPending();
Mock::VerifyAndClearExpectations(&observer);
EXPECT_EQ(CONFIG_VALID,
diff --git a/chrome/browser/policy/configuration_policy_pref_store.cc b/chrome/browser/policy/configuration_policy_pref_store.cc
index e24cbfd..b5ab3d0 100644
--- a/chrome/browser/policy/configuration_policy_pref_store.cc
+++ b/chrome/browser/policy/configuration_policy_pref_store.cc
@@ -692,7 +692,7 @@ void ConfigurationPolicyPrefKeeper::ApplyProxySettings() {
std::string pac_url;
proxy_policies_[kPolicyProxyPacUrl]->GetAsString(&pac_url);
prefs_.SetValue(prefs::kProxy,
- ProxyConfigDictionary::CreatePacScript(pac_url));
+ ProxyConfigDictionary::CreatePacScript(pac_url, false));
break;
}
case ProxyPrefs::MODE_FIXED_SERVERS: {
diff --git a/chrome/browser/prefs/command_line_pref_store.cc b/chrome/browser/prefs/command_line_pref_store.cc
index a992ced..03b6ef6 100644
--- a/chrome/browser/prefs/command_line_pref_store.cc
+++ b/chrome/browser/prefs/command_line_pref_store.cc
@@ -86,7 +86,7 @@ void CommandLinePrefStore::ApplyProxyMode() {
std::string pac_script_url =
command_line_->GetSwitchValueASCII(switches::kProxyPacUrl);
SetValue(prefs::kProxy,
- ProxyConfigDictionary::CreatePacScript(pac_script_url));
+ ProxyConfigDictionary::CreatePacScript(pac_script_url, false));
} else if (command_line_->HasSwitch(switches::kProxyAutoDetect)) {
SetValue(prefs::kProxy,
ProxyConfigDictionary::CreateAutoDetect());
diff --git a/chrome/browser/prefs/proxy_config_dictionary.cc b/chrome/browser/prefs/proxy_config_dictionary.cc
index 0c063cd..a99fa7c 100644
--- a/chrome/browser/prefs/proxy_config_dictionary.cc
+++ b/chrome/browser/prefs/proxy_config_dictionary.cc
@@ -19,6 +19,10 @@ const char kProxyMode[] = "mode";
const char kProxyServer[] = "server";
// URL to the proxy .pac file.
const char kProxyPacUrl[] = "pac_url";
+// Optional boolean flag indicating whether a valid PAC script is mandatory.
+// If true, network traffic does not fall back to direct connections in case the
+// PAC script is not available.
+const char kProxyPacMandatory[] = "pac_mandatory";
// String containing proxy bypass rules. For a specification of the
// expected syntax see net::ProxyBypassRules::ParseFromString().
const char kProxyBypassList[] = "bypass_list";
@@ -41,6 +45,14 @@ bool ProxyConfigDictionary::GetPacUrl(std::string* out) const {
return dict_->GetString(kProxyPacUrl, out);
}
+bool ProxyConfigDictionary::GetPacMandatory(bool* out) const {
+ if (!dict_->HasKey(kProxyPacMandatory)) {
+ *out = false;
+ return true;
+ }
+ return dict_->GetBoolean(kProxyPacMandatory, out);
+}
+
bool ProxyConfigDictionary::GetProxyServer(std::string* out) const {
return dict_->GetString(kProxyServer, out);
}
@@ -55,18 +67,20 @@ bool ProxyConfigDictionary::HasBypassList() const {
// static
DictionaryValue* ProxyConfigDictionary::CreateDirect() {
- return CreateDictionary(ProxyPrefs::MODE_DIRECT, "", "", "");
+ return CreateDictionary(ProxyPrefs::MODE_DIRECT, "", false, "", "");
}
// static
DictionaryValue* ProxyConfigDictionary::CreateAutoDetect() {
- return CreateDictionary(ProxyPrefs::MODE_AUTO_DETECT, "", "", "");
+ return CreateDictionary(ProxyPrefs::MODE_AUTO_DETECT, "", false, "", "");
}
// static
DictionaryValue* ProxyConfigDictionary::CreatePacScript(
- const std::string& pac_url) {
- return CreateDictionary(ProxyPrefs::MODE_PAC_SCRIPT, pac_url, "", "");
+ const std::string& pac_url,
+ bool pac_mandatory) {
+ return CreateDictionary(ProxyPrefs::MODE_PAC_SCRIPT,
+ pac_url, pac_mandatory, "", "");
}
// static
@@ -75,7 +89,7 @@ DictionaryValue* ProxyConfigDictionary::CreateFixedServers(
const std::string& bypass_list) {
if (!proxy_server.empty()) {
return CreateDictionary(
- ProxyPrefs::MODE_FIXED_SERVERS, "", proxy_server, bypass_list);
+ ProxyPrefs::MODE_FIXED_SERVERS, "", false, proxy_server, bypass_list);
} else {
return CreateDirect();
}
@@ -83,19 +97,22 @@ DictionaryValue* ProxyConfigDictionary::CreateFixedServers(
// static
DictionaryValue* ProxyConfigDictionary::CreateSystem() {
- return CreateDictionary(ProxyPrefs::MODE_SYSTEM, "", "", "");
+ return CreateDictionary(ProxyPrefs::MODE_SYSTEM, "", false, "", "");
}
// static
DictionaryValue* ProxyConfigDictionary::CreateDictionary(
ProxyPrefs::ProxyMode mode,
const std::string& pac_url,
+ bool pac_mandatory,
const std::string& proxy_server,
const std::string& bypass_list) {
DictionaryValue* dict = new DictionaryValue();
dict->SetString(kProxyMode, ProxyModeToString(mode));
- if (!pac_url.empty())
+ if (!pac_url.empty()) {
dict->SetString(kProxyPacUrl, pac_url);
+ dict->SetBoolean(kProxyPacMandatory, pac_mandatory);
+ }
if (!proxy_server.empty())
dict->SetString(kProxyServer, proxy_server);
if (!bypass_list.empty())
diff --git a/chrome/browser/prefs/proxy_config_dictionary.h b/chrome/browser/prefs/proxy_config_dictionary.h
index c05f182..3eeac12 100644
--- a/chrome/browser/prefs/proxy_config_dictionary.h
+++ b/chrome/browser/prefs/proxy_config_dictionary.h
@@ -31,13 +31,15 @@ class ProxyConfigDictionary {
bool GetMode(ProxyPrefs::ProxyMode* out) const;
bool GetPacUrl(std::string* out) const;
+ bool GetPacMandatory(bool* out) const;
bool GetProxyServer(std::string* out) const;
bool GetBypassList(std::string* out) const;
bool HasBypassList() const;
static DictionaryValue* CreateDirect();
static DictionaryValue* CreateAutoDetect();
- static DictionaryValue* CreatePacScript(const std::string& pac_url);
+ static DictionaryValue* CreatePacScript(const std::string& pac_url,
+ bool pac_mandatory);
static DictionaryValue* CreateFixedServers(
const std::string& proxy_server,
const std::string& bypass_list);
@@ -45,6 +47,7 @@ class ProxyConfigDictionary {
private:
static DictionaryValue* CreateDictionary(ProxyPrefs::ProxyMode mode,
const std::string& pac_url,
+ bool pac_mandatory,
const std::string& proxy_server,
const std::string& bypass_list);
diff --git a/chrome/browser/prefs/proxy_config_dictionary_unittest.cc b/chrome/browser/prefs/proxy_config_dictionary_unittest.cc
index 5575b66..8301266 100644
--- a/chrome/browser/prefs/proxy_config_dictionary_unittest.cc
+++ b/chrome/browser/prefs/proxy_config_dictionary_unittest.cc
@@ -43,7 +43,7 @@ TEST(ProxyConfigDictionaryTest, CreateAutoDetect) {
TEST(ProxyConfigDictionaryTest, CreatePacScript) {
scoped_ptr<DictionaryValue> dict_value(
- ProxyConfigDictionary::CreatePacScript("pac"));
+ ProxyConfigDictionary::CreatePacScript("pac", false));
ProxyConfigDictionary dict(dict_value.get());
ProxyConfigHolder h;
diff --git a/chrome/common/automation_constants.cc b/chrome/common/automation_constants.cc
index 1956ab5..f380088 100644
--- a/chrome/common/automation_constants.cc
+++ b/chrome/common/automation_constants.cc
@@ -11,6 +11,7 @@ namespace automation {
const char kJSONProxyAutoconfig[] = "proxy.autoconfig";
const char kJSONProxyNoProxy[] = "proxy.no_proxy";
const char kJSONProxyPacUrl[] = "proxy.pac_url";
+const char kJSONProxyPacMandatory[] = "proxy.pac_mandatory";
const char kJSONProxyBypassList[] = "proxy.bypass_list";
const char kJSONProxyServer[] = "proxy.server";
diff --git a/chrome/common/automation_constants.h b/chrome/common/automation_constants.h
index ed7f2d2..e1f1d63 100644
--- a/chrome/common/automation_constants.h
+++ b/chrome/common/automation_constants.h
@@ -14,6 +14,7 @@ namespace automation {
extern const char kJSONProxyAutoconfig[];
extern const char kJSONProxyNoProxy[];
extern const char kJSONProxyPacUrl[];
+extern const char kJSONProxyPacMandatory[];
extern const char kJSONProxyBypassList[];
extern const char kJSONProxyServer[];
diff --git a/chrome/common/extensions/api/extension_api.json b/chrome/common/extensions/api/extension_api.json
index 989d82d..8993dcc 100644
--- a/chrome/common/extensions/api/extension_api.json
+++ b/chrome/common/extensions/api/extension_api.json
@@ -4000,7 +4000,8 @@
"description": "An object holding proxy auto-config information. Exactly one of the fields should be non-empty.",
"properties": {
"url": {"type": "string", "optional": true, "description": "URL of the PAC file to be used."},
- "data": {"type": "string", "optional": true, "description": "A PAC script."}
+ "data": {"type": "string", "optional": true, "description": "A PAC script."},
+ "mandatory": {"type": "boolean", "optional": true, "description": "If true, an invalid PAC script will prevent the network stack from falling back to direct connections. Defaults to false."}
}
},
{
diff --git a/chrome/common/extensions/docs/examples/extensions/proxy_configuration.zip b/chrome/common/extensions/docs/examples/extensions/proxy_configuration.zip
index 5b7cb0a..fa7b74b 100644
--- a/chrome/common/extensions/docs/examples/extensions/proxy_configuration.zip
+++ b/chrome/common/extensions/docs/examples/extensions/proxy_configuration.zip
Binary files differ
diff --git a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/proxy_form_controller.js b/chrome/common/extensions/docs/examples/extensions/proxy_configuration/proxy_form_controller.js
index 6b4fc09..796d7b0 100644
--- a/chrome/common/extensions/docs/examples/extensions/proxy_configuration/proxy_form_controller.js
+++ b/chrome/common/extensions/docs/examples/extensions/proxy_configuration/proxy_form_controller.js
@@ -590,9 +590,11 @@ ProxyFormController.prototype = {
var pacScriptURL = this.pacURL;
var pacManual = this.manualPac;
if (pacScriptURL)
- return {mode: 'pac_script', pacScript: {url: pacScriptURL}};
+ return {mode: 'pac_script',
+ pacScript: {url: pacScriptURL, mandatory: true}};
else if (pacManual)
- return {mode: 'pac_script', pacScript: {data: pacManual}};
+ return {mode: 'pac_script',
+ pacScript: {data: pacManual, mandatory: true}};
else
return {mode: 'auto_detect'};
case ProxyFormController.ProxyTypes.FIXED:
diff --git a/chrome/common/extensions/docs/experimental.proxy.html b/chrome/common/extensions/docs/experimental.proxy.html
index 44cd5fe..4010576 100644
--- a/chrome/common/extensions/docs/experimental.proxy.html
+++ b/chrome/common/extensions/docs/experimental.proxy.html
@@ -2042,6 +2042,74 @@ element.
</dd>
</div>
+ </div><div>
+ <div>
+ <dt>
+ <var>mandatory</var>
+ <em>
+
+ <!-- TYPE -->
+ <div style="display:inline">
+ (
+ <span class="optional">optional</span>
+ <span class="enum" style="display: none; ">enumerated</span>
+ <span id="typeTemplate">
+ <span style="display: none; ">
+ <a> Type</a>
+ </span>
+ <span>
+ <span style="display: none; ">
+ array of <span><span></span></span>
+ </span>
+ <span>boolean</span>
+ <span style="display: none; "></span>
+ </span>
+ </span>
+ )
+ </div>
+
+ </em>
+ </dt>
+ <dd class="todo" style="display: none; ">
+ Undocumented.
+ </dd>
+ <dd>If true, an invalid PAC script will prevent the network stack from falling back to direct connections. Defaults to false.</dd>
+ <dd style="display: none; ">
+ This parameter was added in version
+ <b><span></span></b>.
+ You must omit this parameter in earlier versions,
+ and you may omit it in any version. If you require this
+ parameter, the manifest key
+ <a href="manifest.html#minimum_chrome_version">minimum_chrome_version</a>
+ can ensure that your extension won't be run in an earlier browser version.
+ </dd>
+
+ <!-- OBJECT PROPERTIES -->
+ <dd style="display: none; ">
+ <dl>
+ <div>
+ <div>
+ </div>
+ </div>
+ </dl>
+ </dd>
+
+ <!-- OBJECT METHODS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- OBJECT EVENT FIELDS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ <!-- FUNCTION PARAMETERS -->
+ <dd style="display: none; ">
+ <div></div>
+ </dd>
+
+ </div>
</div>
</dl>
</dd>
diff --git a/chrome/common/extensions/docs/samples.json b/chrome/common/extensions/docs/samples.json
index 56efe9a..66b4bba 100644
--- a/chrome/common/extensions/docs/samples.json
+++ b/chrome/common/extensions/docs/samples.json
@@ -1530,7 +1530,7 @@
"test\/proxy_form_controller_test.js",
"test\/unittest.css"
],
- "source_hash": "8f6768d78649cc4e69e595e7e43b3f06431c84e0",
+ "source_hash": "7b3ff4599334eaa9f50aa70940bb5dead970665f",
"zip_path": "examples\/extensions\/proxy_configuration.zip"
},
{
diff --git a/chrome/test/data/extensions/api_test/proxy/pacdata/test.js b/chrome/test/data/extensions/api_test/proxy/pacdata/test.js
index e5cb541..deec64d 100644
--- a/chrome/test/data/extensions/api_test/proxy/pacdata/test.js
+++ b/chrome/test/data/extensions/api_test/proxy/pacdata/test.js
@@ -18,7 +18,8 @@ chrome.test.runTests([
" if (host == 'foobar.com')\n" +
" return 'PROXY blackhole:80';\n" +
" return 'DIRECT';\n" +
- "}"
+ "}",
+ mandatory: false
};
var config = {
mode: "pac_script",
diff --git a/net/base/net_error_list.h b/net/base/net_error_list.h
index 1147267..9979394 100644
--- a/net/base/net_error_list.h
+++ b/net/base/net_error_list.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -180,7 +180,9 @@ NET_ERROR(SSL_WEAK_SERVER_EPHEMERAL_DH_KEY, -129)
// of an HTTP proxy.
NET_ERROR(PROXY_CONNECTION_FAILED, -130)
-// Free: 131
+// A mandatory proxy configuration could not be used. Currently this means
+// that a mandatory PAC script could not be fetched, parsed or executed.
+NET_ERROR(MANDATORY_PROXY_CONFIGURATION_FAILED, -131)
// We detected an ESET product intercepting our HTTPS connections. Since these
// products are False Start intolerant, we return this error so that we can
diff --git a/net/proxy/proxy_config.cc b/net/proxy/proxy_config.cc
index 70e6549..42589a9 100644
--- a/net/proxy/proxy_config.cc
+++ b/net/proxy/proxy_config.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -158,12 +158,14 @@ ProxyServer* ProxyConfig::ProxyRules::MapUrlSchemeToProxyNoFallback(
return NULL; // No mapping for this scheme.
}
-ProxyConfig::ProxyConfig() : auto_detect_(false), id_(INVALID_ID) {
+ProxyConfig::ProxyConfig()
+ : auto_detect_(false), pac_mandatory_(false), id_(INVALID_ID) {
}
ProxyConfig::ProxyConfig(const ProxyConfig& config)
: auto_detect_(config.auto_detect_),
pac_url_(config.pac_url_),
+ pac_mandatory_(config.pac_mandatory_),
proxy_rules_(config.proxy_rules_),
id_(config.id_) {
}
@@ -174,6 +176,7 @@ ProxyConfig::~ProxyConfig() {
ProxyConfig& ProxyConfig::operator=(const ProxyConfig& config) {
auto_detect_ = config.auto_detect_;
pac_url_ = config.pac_url_;
+ pac_mandatory_ = config.pac_mandatory_;
proxy_rules_ = config.proxy_rules_;
id_ = config.id_;
return *this;
@@ -184,6 +187,7 @@ bool ProxyConfig::Equals(const ProxyConfig& other) const {
// have the same settings.
return auto_detect_ == other.auto_detect_ &&
pac_url_ == other.pac_url_ &&
+ pac_mandatory_ == other.pac_mandatory_ &&
proxy_rules_.Equals(other.proxy_rules());
}
@@ -202,8 +206,11 @@ Value* ProxyConfig::ToValue() const {
// Output the automatic settings.
if (auto_detect_)
dict->SetBoolean("auto_detect", auto_detect_);
- if (has_pac_url())
+ if (has_pac_url()) {
dict->SetString("pac_url", pac_url_.possibly_invalid_spec());
+ if (pac_mandatory_)
+ dict->SetBoolean("pac_mandatory", pac_mandatory_);
+ }
// Output the manual settings.
if (proxy_rules_.type != ProxyRules::TYPE_NO_RULES) {
@@ -246,4 +253,3 @@ Value* ProxyConfig::ToValue() const {
}
} // namespace net
-
diff --git a/net/proxy/proxy_config.h b/net/proxy/proxy_config.h
index 9012a31..dc0fd71 100644
--- a/net/proxy/proxy_config.h
+++ b/net/proxy/proxy_config.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -148,6 +148,14 @@ class ProxyConfig {
return pac_url_;
}
+ void set_pac_mandatory(bool enable_pac_mandatory) {
+ pac_mandatory_ = enable_pac_mandatory;
+ }
+
+ bool pac_mandatory() const {
+ return pac_mandatory_;
+ }
+
bool has_pac_url() const {
return pac_url_.is_valid();
}
@@ -175,6 +183,8 @@ class ProxyConfig {
static ProxyConfig CreateFromCustomPacURL(const GURL& pac_url) {
ProxyConfig config;
config.set_pac_url(pac_url);
+ // By default fall back to direct connection in case PAC script fails.
+ config.set_pac_mandatory(false);
return config;
}
@@ -185,6 +195,10 @@ class ProxyConfig {
// If non-empty, indicates the URL of the proxy auto-config file to use.
GURL pac_url_;
+ // If true, blocks all traffic in case fetching the pac script from |pac_url_|
+ // fails. Only valid if |pac_url_| is non-empty.
+ bool pac_mandatory_;
+
// Manual proxy settings.
ProxyRules proxy_rules_;
diff --git a/net/proxy/proxy_service.cc b/net/proxy/proxy_service.cc
index 75411c3..15ad381 100644
--- a/net/proxy/proxy_service.cc
+++ b/net/proxy/proxy_service.cc
@@ -562,6 +562,11 @@ int ProxyService::TryToCompleteSynchronously(const GURL& url,
DCHECK_NE(config_.id(), ProxyConfig::INVALID_ID);
+ // If it was impossible to fetch or parse the PAC script, we cannot complete
+ // the request here and bail out.
+ if (permanent_error_ != OK)
+ return permanent_error_;
+
if (config_.HasAutomaticSettings())
return ERR_IO_PENDING; // Must submit the request to the proxy resolver.
@@ -652,11 +657,20 @@ void ProxyService::OnInitProxyResolverComplete(int result) {
init_proxy_resolver_.reset();
if (result != OK) {
- VLOG(1) << "Failed configuring with PAC script, falling-back to manual "
- "proxy servers.";
- config_ = fetched_config_;
- config_.ClearAutomaticSettings();
+ if (fetched_config_.pac_mandatory()) {
+ VLOG(1) << "Failed configuring with mandatory PAC script, blocking all "
+ "traffic.";
+ config_ = fetched_config_;
+ result = ERR_MANDATORY_PROXY_CONFIGURATION_FAILED;
+ } else {
+ VLOG(1) << "Failed configuring with PAC script, falling-back to manual "
+ "proxy servers.";
+ config_ = fetched_config_;
+ config_.ClearAutomaticSettings();
+ result = OK;
+ }
}
+ permanent_error_ = result;
config_.set_id(fetched_config_.id());
@@ -733,15 +747,19 @@ int ProxyService::DidFinishResolvingProxy(ProxyInfo* result,
make_scoped_refptr(new NetLogIntegerParameter(
"net_error", result_code)));
- // Fall-back to direct when the proxy resolver fails. This corresponds
- // with a javascript runtime error in the PAC script.
- //
- // This implicit fall-back to direct matches Firefox 3.5 and
- // Internet Explorer 8. For more information, see:
- //
- // http://www.chromium.org/developers/design-documents/proxy-settings-fallback
- result->UseDirect();
- result_code = OK;
+ if (!config_.pac_mandatory()) {
+ // Fall-back to direct when the proxy resolver fails. This corresponds
+ // with a javascript runtime error in the PAC script.
+ //
+ // This implicit fall-back to direct matches Firefox 3.5 and
+ // Internet Explorer 8. For more information, see:
+ //
+ // http://www.chromium.org/developers/design-documents/proxy-settings-fallback
+ result->UseDirect();
+ result_code = OK;
+ } else {
+ result_code = ERR_MANDATORY_PROXY_CONFIGURATION_FAILED;
+ }
}
net_log.EndEvent(NetLog::TYPE_PROXY_SERVICE, NULL);
@@ -766,6 +784,7 @@ ProxyService::State ProxyService::ResetProxyConfig(bool reset_fetched_config) {
DCHECK(CalledOnValidThread());
State previous_state = current_state_;
+ permanent_error_ = OK;
proxy_retry_info_.clear();
init_proxy_resolver_.reset();
SuspendAllPendingRequests();
diff --git a/net/proxy/proxy_service.h b/net/proxy/proxy_service.h
index 4838954..f7856e5 100644
--- a/net/proxy/proxy_service.h
+++ b/net/proxy/proxy_service.h
@@ -330,6 +330,10 @@ class ProxyService : public NetworkChangeNotifier::IPAddressObserver,
State current_state_;
+ // Either OK or an ERR_* value indicating that a permanent error (e.g.
+ // failed to fetch the PAC script) prevents proxy resolution.
+ int permanent_error_;
+
// This is the log where any events generated by |init_proxy_resolver_| are
// sent to.
NetLog* net_log_;