Skip to content

Commit

Permalink
feat: promisify session proxy methods
Browse files Browse the repository at this point in the history
  • Loading branch information
codebytere committed Mar 8, 2019
1 parent 17dab8f commit 48ecf61
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 25 deletions.
39 changes: 30 additions & 9 deletions atom/browser/api/atom_api_session.cc
Expand Up @@ -214,6 +214,7 @@ std::map<uint32_t, v8::Global<v8::Object>> g_sessions;
void RunCallbackInUI(const base::Callback<void()>& callback) {
base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI}, callback);
}

template <typename... T>
void RunCallbackInUI(const base::Callback<void(T...)>& callback, T... result) {
base::PostTaskWithTraits(FROM_HERE, {BrowserThread::UI},
Expand Down Expand Up @@ -414,10 +415,20 @@ void Session::OnDownloadCreated(content::DownloadManager* manager,
}
}

void Session::ResolveProxy(
const GURL& url,
const ResolveProxyHelper::ResolveProxyCallback& callback) {
browser_context_->GetResolveProxyHelper()->ResolveProxy(url, callback);
v8::Local<v8::Promise> Session::ResolveProxy(mate::Arguments* args) {
v8::Isolate* isolate = args->isolate();
util::Promise promise(isolate);
v8::Local<v8::Promise> handle = promise.GetHandle();

GURL url;
args->GetNext(&url);

browser_context_->GetResolveProxyHelper()->ResolveProxy(
url,
base::Bind(util::CopyablePromise::ResolveCopyablePromise<std::string>,
atom::util::CopyablePromise(promise)));

return handle;
}

template <Session::CacheAction action>
Expand Down Expand Up @@ -454,11 +465,17 @@ void Session::FlushStorageData() {
storage_partition->Flush();
}

void Session::SetProxy(const mate::Dictionary& options,
const base::Closure& callback) {
v8::Local<v8::Promise> Session::SetProxy(mate::Arguments* args) {
v8::Isolate* isolate = args->isolate();
util::Promise promise(isolate);
v8::Local<v8::Promise> handle = promise.GetHandle();

mate::Dictionary options;
args->GetNext(&options);

if (!browser_context_->in_memory_pref_store()) {
callback.Run();
return;
promise.Resolve();
return handle;
}

std::string proxy_rules, bypass_list, pac_url;
Expand All @@ -482,7 +499,11 @@ void Session::SetProxy(const mate::Dictionary& options,
WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS);
}

base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback);
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(util::Promise::ResolveEmptyPromise, std::move(promise)));

return handle;
}

void Session::SetDownloadPath(const base::FilePath& path) {
Expand Down
5 changes: 2 additions & 3 deletions atom/browser/api/atom_api_session.h
Expand Up @@ -62,13 +62,12 @@ class Session : public mate::TrackableObject<Session>,
v8::Local<v8::FunctionTemplate> prototype);

// Methods.
void ResolveProxy(const GURL& url,
const ResolveProxyHelper::ResolveProxyCallback& callback);
v8::Local<v8::Promise> ResolveProxy(mate::Arguments* args);
template <CacheAction action>
void DoCacheAction(const net::CompletionCallback& callback);
void ClearStorageData(mate::Arguments* args);
void FlushStorageData();
void SetProxy(const mate::Dictionary& options, const base::Closure& callback);
v8::Local<v8::Promise> SetProxy(mate::Arguments* args);
void SetDownloadPath(const base::FilePath& path);
void EnableNetworkEmulation(const mate::Dictionary& options);
void DisableNetworkEmulation();
Expand Down
2 changes: 1 addition & 1 deletion atom/common/promise_util.h
Expand Up @@ -172,7 +172,7 @@ class CopyablePromise {
if (!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)) {
base::PostTaskWithTraits(
FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(Promise::ResolvePromise, promise.GetPromise(),
base::BindOnce(Promise::ResolvePromise<T>, promise.GetPromise(),
std::move(result)));
} else {
promise.GetPromise().Resolve(result);
Expand Down
4 changes: 2 additions & 2 deletions docs/api/promisification.md
Expand Up @@ -16,8 +16,6 @@ When a majority of affected functions are migrated, this flag will be enabled by
- [ses.getCacheSize(callback)](https://github.com/electron/electron/blob/master/docs/api/session.md#getCacheSize)
- [ses.clearCache(callback)](https://github.com/electron/electron/blob/master/docs/api/session.md#clearCache)
- [ses.clearStorageData([options, callback])](https://github.com/electron/electron/blob/master/docs/api/session.md#clearStorageData)
- [ses.setProxy(config, callback)](https://github.com/electron/electron/blob/master/docs/api/session.md#setProxy)
- [ses.resolveProxy(url, callback)](https://github.com/electron/electron/blob/master/docs/api/session.md#resolveProxy)
- [ses.clearHostResolverCache([callback])](https://github.com/electron/electron/blob/master/docs/api/session.md#clearHostResolverCache)
- [ses.getBlobData(identifier, callback)](https://github.com/electron/electron/blob/master/docs/api/session.md#getBlobData)
- [ses.clearAuthCache(options[, callback])](https://github.com/electron/electron/blob/master/docs/api/session.md#clearAuthCache)
Expand Down Expand Up @@ -47,6 +45,8 @@ When a majority of affected functions are migrated, this flag will be enabled by
- [dialog.showSaveDialog([browserWindow, ]options[, callback])](https://github.com/electron/electron/blob/master/docs/api/dialog.md#showSaveDialog)
- [netLog.stopLogging([callback])](https://github.com/electron/electron/blob/master/docs/api/net-log.md#stopLogging)
- [protocol.isProtocolHandled(scheme, callback)](https://github.com/electron/electron/blob/master/docs/api/protocol.md#isProtocolHandled)
- [ses.setProxy(config, callback)](https://github.com/electron/electron/blob/master/docs/api/session.md#setProxy)
- [ses.resolveProxy(url, callback)](https://github.com/electron/electron/blob/master/docs/api/session.md#resolveProxy)
- [shell.openExternal(url[, options, callback])](https://github.com/electron/electron/blob/master/docs/api/shell.md#openExternal)
- [webviewTag.capturePage([rect, ]callback)](https://github.com/electron/electron/blob/master/docs/api/webview-tag.md#capturePage)
- [webviewTag.printToPDF(options, callback)](https://github.com/electron/electron/blob/master/docs/api/webview-tag.md#printToPDF)
Expand Down
87 changes: 87 additions & 0 deletions docs/api/session.md
Expand Up @@ -165,6 +165,85 @@ For example:

The `proxyBypassRules` is a comma separated list of rules described below:

* `[ URL_SCHEME "://" ] HOSTNAME_PATTERN [ ":" <port> ]`

Match all hostnames that match the pattern HOSTNAME_PATTERN.

Examples:
"foobar.com", "*foobar.com", "*.foobar.com", "*foobar.com:99",
"https://x.*.y.com:99"

* `"." HOSTNAME_SUFFIX_PATTERN [ ":" PORT ]`

Match a particular domain suffix.

Examples:
".google.com", ".com", "http://.google.com"

* `[ SCHEME "://" ] IP_LITERAL [ ":" PORT ]`

Match URLs which are IP address literals.

Examples:
"127.0.1", "[0:0::1]", "[::1]", "http://[::1]:99"

* `IP_LITERAL "/" PREFIX_LENGTH_IN_BITS`

Match any URL that is to an IP literal that falls between the
given range. IP range is specified using CIDR notation.

Examples:
"192.168.1.1/16", "fefe:13::abc/33".

* `<local>`

Match local addresses. The meaning of `<local>` is whether the
host matches one of: "127.0.0.1", "::1", "localhost".

**[Deprecated Soon](promisification.md)**

#### `ses.setProxy(config)`

* `config` Object
* `pacScript` String - The URL associated with the PAC file.
* `proxyRules` String - Rules indicating which proxies to use.
* `proxyBypassRules` String - Rules indicating which URLs should
bypass the proxy settings.

Returns `Promise<void>` - Resolves when the proxy setting process is complete.

Sets the proxy settings.

When `pacScript` and `proxyRules` are provided together, the `proxyRules`
option is ignored and `pacScript` configuration is applied.

The `proxyRules` has to follow the rules below:

```sh
proxyRules = schemeProxies[";"<schemeProxies>]
schemeProxies = [<urlScheme>"="]<proxyURIList>
urlScheme = "http" | "https" | "ftp" | "socks"
proxyURIList = <proxyURL>[","<proxyURIList>]
proxyURL = [<proxyScheme>"://"]<proxyHost>[":"<proxyPort>]
```

For example:

* `http=foopy:80;ftp=foopy2` - Use HTTP proxy `foopy:80` for `http://` URLs, and
HTTP proxy `foopy2:80` for `ftp://` URLs.
* `foopy:80` - Use HTTP proxy `foopy:80` for all URLs.
* `foopy:80,bar,direct://` - Use HTTP proxy `foopy:80` for all URLs, failing
over to `bar` if `foopy:80` is unavailable, and after that using no proxy.
* `socks4://foopy` - Use SOCKS v4 proxy `foopy:1080` for all URLs.
* `http=foopy,socks5://bar.com` - Use HTTP proxy `foopy` for http URLs, and fail
over to the SOCKS5 proxy `bar.com` if `foopy` is unavailable.
* `http=foopy,direct://` - Use HTTP proxy `foopy` for http URLs, and use no
proxy if `foopy` is unavailable.
* `http=foopy;socks=foopy2` - Use HTTP proxy `foopy` for http URLs, and use
`socks4://foopy2` for all other URLs.

The `proxyBypassRules` is a comma separated list of rules described below:

* `[ URL_SCHEME "://" ] HOSTNAME_PATTERN [ ":" <port> ]`

Match all hostnames that match the pattern HOSTNAME_PATTERN.
Expand Down Expand Up @@ -209,6 +288,14 @@ The `proxyBypassRules` is a comma separated list of rules described below:
Resolves the proxy information for `url`. The `callback` will be called with
`callback(proxy)` when the request is performed.

**[Deprecated Soon](promisification.md)**

#### `ses.resolveProxy(url)`

* `url` URL

Returns `Promise<string>` - Resolves with the proxy information for `url`.

#### `ses.setDownloadPath(path)`

* `path` String - The download location.
Expand Down
3 changes: 3 additions & 0 deletions lib/browser/api/session.js
Expand Up @@ -23,6 +23,9 @@ Session.prototype._init = function () {
app.emit('session-created', this)
}

Session.prototype.resolveProxy = deprecate.promisify(Session.prototype.resolveProxy)
Session.prototype.setProxy = deprecate.promisify(Session.prototype.setProxy)

Cookies.prototype.flushStore = deprecate.promisify(Cookies.prototype.flushStore)
Cookies.prototype.get = deprecate.promisify(Cookies.prototype.get)
Cookies.prototype.remove = deprecate.promisify(Cookies.prototype.remove)
Expand Down
52 changes: 42 additions & 10 deletions spec/api-session-spec.js
Expand Up @@ -613,7 +613,7 @@ describe('session module', () => {
})
})

describe('ses.setProxy(options, callback)', () => {
describe('ses.setProxy(options)', () => {
let server = null
let customSession = null

Expand All @@ -635,30 +635,51 @@ describe('session module', () => {
}
})

it('allows configuring proxy settings', (done) => {
it('allows configuring proxy settings', async () => {
const config = { proxyRules: 'http=myproxy:80' }
await customSession.setProxy(config)
const proxy = await customSession.resolveProxy('http://example.com/')
assert.strictEqual(proxy, 'PROXY myproxy:80')
})

// TODO(codebytere): remove when Promisification is complete
it('allows configuring proxy settings (callback)', (done) => {
const config = { proxyRules: 'http=myproxy:80' }
customSession.setProxy(config, () => {
customSession.resolveProxy('http://example.com/', (proxy) => {
customSession.resolveProxy('http://example.com/', proxy => {
assert.strictEqual(proxy, 'PROXY myproxy:80')
done()
})
})
})

it('allows removing the implicit bypass rules for localhost', (done) => {
it('allows removing the implicit bypass rules for localhost', async () => {
const config = {
proxyRules: 'http=myproxy:80',
proxyBypassRules: '<-loopback>'
}
customSession.setProxy(config, () => {
customSession.resolveProxy('http://localhost', (proxy) => {

await customSession.setProxy(config)
const proxy = await customSession.resolveProxy('http://localhost')
assert.strictEqual(proxy, 'PROXY myproxy:80')
})

// TODO(codebytere): remove when Promisification is complete
it('allows removing the implicit bypass rules for localhost (callback)', (done) => {
const config = {
proxyRules: 'http=myproxy:80',
proxyBypassRules: '<-loopback>'
}
customSession.setProxy(config).then(() => {
customSession.resolveProxy('http://localhost').then(proxy => {
assert.strictEqual(proxy, 'PROXY myproxy:80')
done()
})
})
})

it('allows configuring proxy settings with pacScript', (done) => {
// TODO(codebytere): reconfigure when Promisification is complete
it('allows configuring proxy settings with pacScript (callback)', (done) => {
server = http.createServer((req, res) => {
const pac = `
function FindProxyForURL(url, host) {
Expand All @@ -673,21 +694,32 @@ describe('session module', () => {
server.listen(0, '127.0.0.1', () => {
const config = { pacScript: `http://127.0.0.1:${server.address().port}` }
customSession.setProxy(config, () => {
customSession.resolveProxy('https://google.com', (proxy) => {
customSession.resolveProxy('https://google.com', proxy => {
assert.strictEqual(proxy, 'PROXY myproxy:8132')
done()
})
})
})
})

it('allows bypassing proxy settings', (done) => {
it('allows bypassing proxy settings', async () => {
const config = {
proxyRules: 'http=myproxy:80',
proxyBypassRules: '<local>'
}
await customSession.setProxy(config)
const proxy = await customSession.resolveProxy('http://example/')
assert.strictEqual(proxy, 'DIRECT')
})

// TODO(codebytere): remove when Promisification is complete
it('allows bypassing proxy settings (callback)', (done) => {
const config = {
proxyRules: 'http=myproxy:80',
proxyBypassRules: '<local>'
}
customSession.setProxy(config, () => {
customSession.resolveProxy('http://example/', (proxy) => {
customSession.resolveProxy('http://example/', proxy => {
assert.strictEqual(proxy, 'DIRECT')
done()
})
Expand Down

0 comments on commit 48ecf61

Please sign in to comment.