feat: Added support for all proxy modes (#24937)
* feat: Added support for all proxy modes This commit extended setProxy to support all proxy modes including direct, auto_detect, pac_script, fixed_servers and system. * feat: New api for reload proxy configurations
This commit is contained in:
parent
33ac7dbd48
commit
201fc11b4b
4 changed files with 155 additions and 18 deletions
|
@ -283,6 +283,27 @@ Writes any unwritten DOMStorage data to disk.
|
|||
#### `ses.setProxy(config)`
|
||||
|
||||
* `config` Object
|
||||
* `mode` String (optional) - The proxy mode. Should be one of `direct`,
|
||||
`auto_detect`, `pac_script`, `fixed_servers` or `system`. If it's
|
||||
unspecified, it will be automatically determined based on other specified
|
||||
options.
|
||||
* `direct`
|
||||
In direct mode all connections are created directly, without any proxy involved.
|
||||
* `auto_detect`
|
||||
In auto_detect mode the proxy configuration is determined by a PAC script that can
|
||||
be downloaded at http://wpad/wpad.dat.
|
||||
* `pac_script`
|
||||
In pac_script mode the proxy configuration is determined by a PAC script that is
|
||||
retrieved from the URL specified in the `pacScript`. This is the default mode
|
||||
if `pacScript` is specified.
|
||||
* `fixed_servers`
|
||||
In fixed_servers mode the proxy configuration is specified in `proxyRules`.
|
||||
This is the default mode if `proxyRules` is specified.
|
||||
* `system`
|
||||
In system mode the proxy configuration is taken from the operating system.
|
||||
Note that the system mode is different from setting no proxy configuration.
|
||||
In the latter case, Electron falls back to the system settings
|
||||
only if no command-line options influence the proxy configuration.
|
||||
* `pacScript` String (optional) - The URL associated with the PAC file.
|
||||
* `proxyRules` String (optional) - Rules indicating which proxies to use.
|
||||
* `proxyBypassRules` String (optional) - Rules indicating which URLs should
|
||||
|
@ -292,7 +313,7 @@ Returns `Promise<void>` - Resolves when the proxy setting process is complete.
|
|||
|
||||
Sets the proxy settings.
|
||||
|
||||
When `pacScript` and `proxyRules` are provided together, the `proxyRules`
|
||||
When `mode` is unspecified, `pacScript` and `proxyRules` are provided together, the `proxyRules`
|
||||
option is ignored and `pacScript` configuration is applied.
|
||||
|
||||
You may need `ses.closeAllConnections` to close currently in flight connections to prevent
|
||||
|
@ -366,6 +387,10 @@ The `proxyBypassRules` is a comma separated list of rules described below:
|
|||
|
||||
Returns `Promise<String>` - Resolves with the proxy information for `url`.
|
||||
|
||||
#### `ses.forceReloadProxyConfig()`
|
||||
|
||||
Returns `Promise<void>` - Resolves when the all internal states of proxy service is reset and the latest proxy configuration is reapplied if it's already available. The pac script will be fetched from `pacScript` again if the proxy mode is `pac_script`.
|
||||
|
||||
#### `ses.setDownloadPath(path)`
|
||||
|
||||
* `path` String - The download location.
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "components/prefs/value_map_pref_store.h"
|
||||
#include "components/proxy_config/proxy_config_dictionary.h"
|
||||
#include "components/proxy_config/proxy_config_pref_names.h"
|
||||
#include "components/proxy_config/proxy_prefs.h"
|
||||
#include "content/public/browser/browser_task_traits.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/download_item_utils.h"
|
||||
|
@ -504,26 +505,50 @@ v8::Local<v8::Promise> Session::SetProxy(gin::Arguments* args) {
|
|||
return handle;
|
||||
}
|
||||
|
||||
std::string proxy_rules, bypass_list, pac_url;
|
||||
std::string mode, proxy_rules, bypass_list, pac_url;
|
||||
|
||||
options.Get("pacScript", &pac_url);
|
||||
options.Get("proxyRules", &proxy_rules);
|
||||
options.Get("proxyBypassRules", &bypass_list);
|
||||
|
||||
ProxyPrefs::ProxyMode proxy_mode = ProxyPrefs::MODE_FIXED_SERVERS;
|
||||
if (!options.Get("mode", &mode)) {
|
||||
// pacScript takes precedence over proxyRules.
|
||||
if (!pac_url.empty()) {
|
||||
browser_context_->in_memory_pref_store()->SetValue(
|
||||
proxy_config::prefs::kProxy,
|
||||
std::make_unique<base::Value>(ProxyConfigDictionary::CreatePacScript(
|
||||
pac_url, true /* pac_mandatory */)),
|
||||
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
|
||||
proxy_mode = ProxyPrefs::MODE_PAC_SCRIPT;
|
||||
} else {
|
||||
browser_context_->in_memory_pref_store()->SetValue(
|
||||
proxy_config::prefs::kProxy,
|
||||
std::make_unique<base::Value>(ProxyConfigDictionary::CreateFixedServers(
|
||||
proxy_rules, bypass_list)),
|
||||
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
|
||||
proxy_mode = ProxyPrefs::MODE_FIXED_SERVERS;
|
||||
}
|
||||
} else {
|
||||
if (!ProxyPrefs::StringToProxyMode(mode, &proxy_mode)) {
|
||||
promise.RejectWithErrorMessage(
|
||||
"Invalid mode, must be one of direct, auto_detect, pac_script, "
|
||||
"fixed_servers or system");
|
||||
return handle;
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<base::Value> proxy_config;
|
||||
if (proxy_mode == ProxyPrefs::MODE_DIRECT) {
|
||||
proxy_config =
|
||||
std::make_unique<base::Value>(ProxyConfigDictionary::CreateDirect());
|
||||
} else if (proxy_mode == ProxyPrefs::MODE_SYSTEM) {
|
||||
proxy_config =
|
||||
std::make_unique<base::Value>(ProxyConfigDictionary::CreateSystem());
|
||||
} else if (proxy_mode == ProxyPrefs::MODE_AUTO_DETECT) {
|
||||
proxy_config = std::make_unique<base::Value>(
|
||||
ProxyConfigDictionary::CreateAutoDetect());
|
||||
} else if (proxy_mode == ProxyPrefs::MODE_PAC_SCRIPT) {
|
||||
proxy_config =
|
||||
std::make_unique<base::Value>(ProxyConfigDictionary::CreatePacScript(
|
||||
pac_url, true /* pac_mandatory */));
|
||||
} else {
|
||||
proxy_config = std::make_unique<base::Value>(
|
||||
ProxyConfigDictionary::CreateFixedServers(proxy_rules, bypass_list));
|
||||
}
|
||||
browser_context_->in_memory_pref_store()->SetValue(
|
||||
proxy_config::prefs::kProxy, std::move(proxy_config),
|
||||
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
|
||||
|
||||
base::ThreadTaskRunnerHandle::Get()->PostTask(
|
||||
FROM_HERE, base::BindOnce(gin_helper::Promise<void>::ResolvePromise,
|
||||
|
@ -532,6 +557,19 @@ v8::Local<v8::Promise> Session::SetProxy(gin::Arguments* args) {
|
|||
return handle;
|
||||
}
|
||||
|
||||
v8::Local<v8::Promise> Session::ForceReloadProxyConfig() {
|
||||
v8::Isolate* isolate = JavascriptEnvironment::GetIsolate();
|
||||
gin_helper::Promise<void> promise(isolate);
|
||||
auto handle = promise.GetHandle();
|
||||
|
||||
content::BrowserContext::GetDefaultStoragePartition(browser_context_)
|
||||
->GetNetworkContext()
|
||||
->ForceReloadProxyConfig(base::BindOnce(
|
||||
gin_helper::Promise<void>::ResolvePromise, std::move(promise)));
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
void Session::SetDownloadPath(const base::FilePath& path) {
|
||||
browser_context_->prefs()->SetFilePath(prefs::kDownloadDefaultDirectory,
|
||||
path);
|
||||
|
@ -1100,6 +1138,7 @@ gin::ObjectTemplateBuilder Session::GetObjectTemplateBuilder(
|
|||
.SetMethod("clearStorageData", &Session::ClearStorageData)
|
||||
.SetMethod("flushStorageData", &Session::FlushStorageData)
|
||||
.SetMethod("setProxy", &Session::SetProxy)
|
||||
.SetMethod("forceReloadProxyConfig", &Session::ForceReloadProxyConfig)
|
||||
.SetMethod("setDownloadPath", &Session::SetDownloadPath)
|
||||
.SetMethod("enableNetworkEmulation", &Session::EnableNetworkEmulation)
|
||||
.SetMethod("disableNetworkEmulation", &Session::DisableNetworkEmulation)
|
||||
|
|
|
@ -95,6 +95,7 @@ class Session : public gin::Wrappable<Session>,
|
|||
v8::Local<v8::Promise> ClearStorageData(gin::Arguments* args);
|
||||
void FlushStorageData();
|
||||
v8::Local<v8::Promise> SetProxy(gin::Arguments* args);
|
||||
v8::Local<v8::Promise> ForceReloadProxyConfig();
|
||||
void SetDownloadPath(const base::FilePath& path);
|
||||
void EnableNetworkEmulation(const gin_helper::Dictionary& options);
|
||||
void DisableNetworkEmulation();
|
||||
|
|
|
@ -384,10 +384,18 @@ describe('session module', () => {
|
|||
res.end(pac);
|
||||
});
|
||||
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
|
||||
{
|
||||
const config = { pacScript: `http://127.0.0.1:${(server.address() as AddressInfo).port}` };
|
||||
await customSession.setProxy(config);
|
||||
const proxy = await customSession.resolveProxy('https://google.com');
|
||||
expect(proxy).to.equal('PROXY myproxy:8132');
|
||||
}
|
||||
{
|
||||
const config = { mode: 'pac_script' as any, pacScript: `http://127.0.0.1:${(server.address() as AddressInfo).port}` };
|
||||
await customSession.setProxy(config);
|
||||
const proxy = await customSession.resolveProxy('https://google.com');
|
||||
expect(proxy).to.equal('PROXY myproxy:8132');
|
||||
}
|
||||
});
|
||||
|
||||
it('allows bypassing proxy settings', async () => {
|
||||
|
@ -399,6 +407,70 @@ describe('session module', () => {
|
|||
const proxy = await customSession.resolveProxy('http://example/');
|
||||
expect(proxy).to.equal('DIRECT');
|
||||
});
|
||||
|
||||
it('allows configuring proxy settings with mode `direct`', async () => {
|
||||
const config = { mode: 'direct' as any, proxyRules: 'http=myproxy:80' };
|
||||
await customSession.setProxy(config);
|
||||
const proxy = await customSession.resolveProxy('http://example.com/');
|
||||
expect(proxy).to.equal('DIRECT');
|
||||
});
|
||||
|
||||
it('allows configuring proxy settings with mode `auto_detect`', async () => {
|
||||
const config = { mode: 'auto_detect' as any };
|
||||
await customSession.setProxy(config);
|
||||
});
|
||||
|
||||
it('allows configuring proxy settings with mode `pac_script`', async () => {
|
||||
const config = { mode: 'pac_script' as any };
|
||||
await customSession.setProxy(config);
|
||||
const proxy = await customSession.resolveProxy('http://example.com/');
|
||||
expect(proxy).to.equal('DIRECT');
|
||||
});
|
||||
|
||||
it('allows configuring proxy settings with mode `fixed_servers`', async () => {
|
||||
const config = { mode: 'fixed_servers' as any, proxyRules: 'http=myproxy:80' };
|
||||
await customSession.setProxy(config);
|
||||
const proxy = await customSession.resolveProxy('http://example.com/');
|
||||
expect(proxy).to.equal('PROXY myproxy:80');
|
||||
});
|
||||
|
||||
it('allows configuring proxy settings with mode `system`', async () => {
|
||||
const config = { mode: 'system' as any };
|
||||
await customSession.setProxy(config);
|
||||
});
|
||||
|
||||
it('disallows configuring proxy settings with mode `invalid`', async () => {
|
||||
const config = { mode: 'invalid' as any };
|
||||
await expect(customSession.setProxy(config)).to.eventually.be.rejectedWith(/Invalid mode/);
|
||||
});
|
||||
|
||||
it('reload proxy configuration', async () => {
|
||||
let proxyPort = 8132;
|
||||
server = http.createServer((req, res) => {
|
||||
const pac = `
|
||||
function FindProxyForURL(url, host) {
|
||||
return "PROXY myproxy:${proxyPort}";
|
||||
}
|
||||
`;
|
||||
res.writeHead(200, {
|
||||
'Content-Type': 'application/x-ns-proxy-autoconfig'
|
||||
});
|
||||
res.end(pac);
|
||||
});
|
||||
await new Promise(resolve => server.listen(0, '127.0.0.1', resolve));
|
||||
const config = { mode: 'pac_script' as any, pacScript: `http://127.0.0.1:${(server.address() as AddressInfo).port}` };
|
||||
await customSession.setProxy(config);
|
||||
{
|
||||
const proxy = await customSession.resolveProxy('https://google.com');
|
||||
expect(proxy).to.equal(`PROXY myproxy:${proxyPort}`);
|
||||
}
|
||||
{
|
||||
proxyPort = 8133;
|
||||
await customSession.forceReloadProxyConfig();
|
||||
const proxy = await customSession.resolveProxy('https://google.com');
|
||||
expect(proxy).to.equal(`PROXY myproxy:${proxyPort}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('ses.getBlobData()', () => {
|
||||
|
|
Loading…
Reference in a new issue