Bug 1433723 - URL in workers should use a proxy if the protocol is not http nor https, r=valentin

This commit is contained in:
Andrea Marchesini 2018-01-29 20:51:32 +01:00
parent f73158969a
commit 6ab3b67d62
5 changed files with 119 additions and 19 deletions

View File

@ -708,6 +708,13 @@ URLWorker::GetHref(nsAString& aHref, ErrorResult& aRv) const
void
URLWorker::SetHref(const nsAString& aHref, ErrorResult& aRv)
{
SetHrefInternal(aHref, eUseProxyIfNeeded, aRv);
}
void
URLWorker::SetHrefInternal(const nsAString& aHref, Strategy aStrategy,
ErrorResult& aRv)
{
nsAutoCString scheme;
nsresult rv = net_ExtractURLScheme(NS_ConvertUTF16toUTF8(aHref), scheme);
@ -716,7 +723,8 @@ URLWorker::SetHref(const nsAString& aHref, ErrorResult& aRv)
return;
}
if (scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https")) {
if (aStrategy == eUseProxyIfNeeded &&
(scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https"))) {
nsCOMPtr<nsIURI> uri;
aRv = NS_MutateURI(new nsStandardURL::Mutator())
.SetSpec(NS_ConvertUTF16toUTF8(aHref))
@ -807,29 +815,43 @@ URLWorker::GetProtocol(nsAString& aProtocol, ErrorResult& aRv) const
void
URLWorker::SetProtocol(const nsAString& aProtocol, ErrorResult& aRv)
{
if (mStdURL) {
nsAString::const_iterator start, end;
aProtocol.BeginReading(start);
aProtocol.EndReading(end);
nsAString::const_iterator iter(start);
nsAString::const_iterator start, end;
aProtocol.BeginReading(start);
aProtocol.EndReading(end);
nsAString::const_iterator iter(start);
FindCharInReadable(':', iter, end);
FindCharInReadable(':', iter, end);
NS_ConvertUTF16toUTF8 scheme(Substring(start, iter));
nsresult rv = mStdURL->SetScheme(NS_ConvertUTF16toUTF8(Substring(start, iter)));
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
nsAutoCString href;
rv = mStdURL->GetSpec(href);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
SetHref(NS_ConvertUTF8toUTF16(href), aRv);
// If we are using nsStandardURL on the owning thread, we can continue only if
// the scheme is http or https.
if (mStdURL &&
(scheme.EqualsLiteral("http") || scheme.EqualsLiteral("https"))) {
mStdURL->SetScheme(scheme);
return;
}
// If we are using mStandardURL but the new scheme is not http nor https, we
// have to migrate to the URL proxy.
if (mStdURL) {
nsAutoCString href;
nsresult rv = mStdURL->GetSpec(href);
if (NS_WARN_IF(NS_FAILED(rv))) {
return;
}
SetHrefInternal(NS_ConvertUTF8toUTF16(href), eAlwaysUseProxy, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
// We want a proxy here.
MOZ_ASSERT(!mStdURL);
MOZ_ASSERT(mURLProxy);
// Now we can restart setting the protocol.
}
MOZ_ASSERT(mURLProxy);
RefPtr<SetterRunnable> runnable =
new SetterRunnable(mWorkerPrivate, SetterRunnable::SetterProtocol,

View File

@ -122,6 +122,16 @@ public:
private:
~URLWorker();
enum Strategy {
eAlwaysUseProxy,
eUseProxyIfNeeded,
};
void
SetHrefInternal(const nsAString& aHref,
Strategy aStrategy,
ErrorResult& aRv);
workers::WorkerPrivate* mWorkerPrivate;
RefPtr<URLProxy> mURLProxy;
RefPtr<net::nsStandardURL> mStdURL;

View File

@ -21,3 +21,5 @@ support-files =
[test_worker_urlSearchParams.html]
[test_unknown_url_origin.html]
[test_bloburl_location.html]
[test_worker_protocol.html]
support-files = protocol_worker.js

View File

@ -0,0 +1,25 @@
function ok(a, msg) {
postMessage({ type: "status", status: !!a, msg });
}
function is(a, b, msg) {
ok(a === b, msg);
}
function finish() {
postMessage({ type: "finish" });
}
let url = new URL("http://example.com");
is(url.protocol, "http:", "http: expected");
url.protocol = "https:";
is(url.protocol, "https:", "http: -> https:");
url.protocol = "ftp:";
is(url.protocol, "ftp:", "https: -> ftp:");
url.protocol = "https:";
is(url.protocol, "https:", "ftp: -> https:");
finish();

View File

@ -0,0 +1,41 @@
<!--
Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/
-->
<!DOCTYPE HTML>
<html>
<head>
<title>Test for URL protocol setter in workers</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p id="display"></p>
<div id="content" style="display: none"></div>
<pre id="test"></pre>
<script class="testbody" type="text/javascript">
let worker = new Worker("protocol_worker.js");
worker.onmessage = function(event) {
is(event.target, worker, "Correct worker");
if (event.data.type == "finish") {
SimpleTest.finish();
return;
}
if (event.data.type == "status") {
ok(event.data.status, event.data.msg);
return;
}
ok(false, "Invalid message.");
};
SimpleTest.waitForExplicitFinish();
</script>
</pre>
</body>
</html>