Skip to content

Commit

Permalink
Fix nwjs#916: support pac_url and auto proxy detection
Browse files Browse the repository at this point in the history
Add test cases for pac url.

(cherry picked from commit 206df0d)
  • Loading branch information
fujunwei committed Feb 21, 2017
1 parent bb46362 commit c28b852
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 26 deletions.
5 changes: 3 additions & 2 deletions docs/References/App.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,11 +62,12 @@ These 2 functions crashes the browser process and the renderer process respectiv

Query the proxy to be used for loading `url` in DOM. The return value is in the same format used in [PAC](http://en.wikipedia.org/wiki/Proxy_auto-config) (e.g. "DIRECT", "PROXY localhost:8080").

## App.setProxyConfig(config)
## App.setProxyConfig(config, pac_url)

* `config` `{String}` Proxy rules
* `pac_url` `{String}` PAC url

Set the proxy config which the web engine will be used to request network resources.
Set the proxy config which the web engine will be used to request network resources or PAC url to detect proxy automatically.

Rule (copied from [`net/proxy/proxy_config.h`](https://github.com/nwjs/chromium.src/blob/nw13/net/proxy/proxy_config.h))

Expand Down
2 changes: 1 addition & 1 deletion src/api/nw_app.idl
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ namespace nw.App {
static void closeAllWindows();
static void clearCache();
static void clearAppCache(DOMString manifest_url);
static void setProxyConfig(DOMString config);
static void setProxyConfig(DOMString config, optional DOMString pac_url);
[nocompile] static DOMString getProxyForURL(DOMString url);
[nocompile] static void addOriginAccessWhitelistEntry(DOMString sourceOrigin, DOMString destinationProtocol, DOMString destinationHost, boolean allowDestinationSubdomains);
[nocompile] static void removeOriginAccessWhitelistEntry(DOMString sourceOrigin, DOMString destinationProtocol, DOMString destinationHost, boolean allowDestinationSubdomains);
Expand Down
25 changes: 21 additions & 4 deletions src/api/nw_app_api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "chrome/browser/devtools/devtools_window.h"
#include "chrome/browser/extensions/devtools_util.h"
#include "chrome/browser/extensions/extension_service.h"
#include "content/nw/src/api/nw_app.h"
#include "content/nw/src/nw_base.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_view_host.h"
Expand All @@ -24,6 +25,8 @@
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"

using namespace extensions::nwapi::nw__app;

namespace {
void SetProxyConfigCallback(
base::WaitableEvent* done,
Expand Down Expand Up @@ -150,13 +153,27 @@ NwAppSetProxyConfigFunction::~NwAppSetProxyConfigFunction() {
}

bool NwAppSetProxyConfigFunction::RunNWSync(base::ListValue* response, std::string* error) {
std::string proxy_config;
EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &proxy_config));
net::ProxyConfig config;
std::unique_ptr<nwapi::nw__app::SetProxyConfig::Params> params(
nwapi::nw__app::SetProxyConfig::Params::Create(*args_));
EXTENSION_FUNCTION_VALIDATE(params.get());

std::string pac_url = params->pac_url.get() ? *params->pac_url : "";
if (!pac_url.empty()) {
if (pac_url == "<direct>")
config = net::ProxyConfig::CreateDirect();
else if (pac_url == "<auto>")
config = net::ProxyConfig::CreateAutoDetect();
else
config = net::ProxyConfig::CreateFromCustomPacURL(GURL(pac_url));
} else {
std::string proxy_config;
EXTENSION_FUNCTION_VALIDATE(args_->GetString(0, &proxy_config));
config.proxy_rules().ParseFromString(proxy_config);
}

base::ThreadRestrictions::ScopedAllowWait allow_wait;

net::ProxyConfig config;
config.proxy_rules().ParseFromString(proxy_config);
content::RenderProcessHost* render_process_host = GetSenderWebContents()->GetRenderProcessHost();
net::URLRequestContextGetter* context_getter =
render_process_host->GetStoragePartition()->GetURLRequestContext();
Expand Down
19 changes: 19 additions & 0 deletions test/sanity/app-getproxyforurl/bg.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
(function(){
const http = require('http');
let id = 1;

// Create an HTTP server
var srv = http.createServer( (req, res) => {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write('function FindProxyForURL(url, host) {\n');
res.write(' if (host == \'www.port3128.com\')\n');
res.write(' return \'PROXY localhost:3128\';\n');
res.write(' else if (host == \'www.port4040.com\')\n');
res.write(' return \'PROXY localhost:4040\';\n');
res.write(' return "DIRECT";\n');
res.write('}');
res.end();
});

srv.listen(nw.App.manifest.port, '127.0.0.1');
})()
62 changes: 48 additions & 14 deletions test/sanity/app-getproxyforurl/index.html
Original file line number Diff line number Diff line change
@@ -1,20 +1,54 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>App.getProxyForURL</title>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>App.getProxyForURL</title>
</head>
<body>
<script>
nw.App.setProxyConfig('dummy:8080');
var proxy = nw.App.getProxyForURL('http://www.example.com/');
var expect = 'PROXY dummy:8080';
if (proxy === expect) {
document.write('<h1 id="result">success</h1>');
} else {
document.write('<h1 id="result">failure: expect "' + expect + '" but get ' + proxy +'</h1>');
}
</script>
<button id="pac" onclick="requestPac()">Request pac</button>
<button id="open-devtools" onclick="openDevTools()">Open DevTools</button>
<script>
nw.App.setProxyConfig('dummy:8080');
var proxy = nw.App.getProxyForURL('http://www.example.com/');
var expect = 'PROXY dummy:8080';
if (proxy === expect) {
document.write('<h1 id="result">success</h1>');
} else {
document.write('<h1 id="result">failure: expect "' + expect + '" but get ' + proxy +'</h1>');
}

// Reset Proxy
nw.App.setProxyConfig("", "<direct>");

function requestPac() {
var xhr = new XMLHttpRequest();
xhr.open('GET', `http://localhost:${nw.App.manifest.port}/`, true);
xhr.send();
xhr.onload = ()=>{
var b = new Buffer(xhr.responseText);
var encodedUrl = "data:application/x-ns-proxy-autoconfig;base64," + b.toString('base64');
nw.App.setProxyConfig('dummy:8080', encodedUrl);
var proxy = nw.App.getProxyForURL('http://www.port3128.com/');
var expect = 'PROXY localhost:3128';
if (proxy === expect) {
document.write('<h1 id="result2">success</h1>');
} else {
document.write('<h1 id="result2">failure: expect "' + expect + '" but get ' + proxy +'</h1>');
}
var proxy = nw.App.getProxyForURL('http://www.port4040.com/');
var expect = 'PROXY localhost:4040';
if (proxy === expect) {
document.write('<h1 id="result3">success</h1>');
} else {
document.write('<h1 id="result3">failure: expect "' + expect + '" but get ' + proxy +'</h1>');
}
};
}

function openDevTools() {
chrome.developerPrivate.openDevTools({renderProcessId: -1, renderViewId: -1, extensionId: chrome.runtime.id});
}
</script>
</body>
</html>
</html>
4 changes: 0 additions & 4 deletions test/sanity/app-getproxyforurl/package.json

This file was deleted.

35 changes: 34 additions & 1 deletion test/sanity/app-getproxyforurl/test.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,50 @@
import time
import os
import sys
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from nw_util import *

from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common import utils

test_dir = os.path.dirname(os.path.abspath(__file__))
chrome_options = Options()
chrome_options.add_argument("nwapp=" + os.path.dirname(os.path.abspath(__file__)))
chrome_options.add_argument("nwapp=" + test_dir)

port = str(utils.free_port())

pkgjson = '''
{
"name": "app-getproxyforurl",
"main": "index.html",
"bg-script": "bg.js",
"port": "%s"
}
''' % port

with open(os.path.join(test_dir, 'package.json'), 'w') as bg:
bg.write(pkgjson)

driver = webdriver.Chrome(executable_path=os.environ['CHROMEDRIVER'], chrome_options=chrome_options)
driver.implicitly_wait(2)
time.sleep(1)
try:
print driver.current_url

time.sleep(1)
result = driver.find_element_by_id('result')
print result.get_attribute('innerHTML')
assert("success" in result.get_attribute('innerHTML'))

wait_window_handles(driver, 1)
switch_to_app(driver)
driver.find_element_by_id('pac').click()
wait_window_handles(driver, 1)
result2 = driver.find_element_by_id('result2')
assert("success" in result2.get_attribute('innerHTML'))
wait_window_handles(driver, 1)
result3 = driver.find_element_by_id('result3')
assert("success" in result3.get_attribute('innerHTML'))
finally:
driver.quit()

0 comments on commit c28b852

Please sign in to comment.