Bug 417075 - Update postMessage and MessageEvent to reflect domain/uri being replaced by origin, optional origin argument. r+sr=sicking, a=beltzner

This commit is contained in:
jwalden@mit.edu 2008-02-26 19:48:54 -08:00
parent 28ea51311b
commit ca08279648
35 changed files with 858 additions and 216 deletions

View File

@ -216,7 +216,7 @@ user_pref("capability.principal.codebase.p%(i)d.subjectName", "");
function FindProxyForURL(url, host)
{
var servers = [%(quotedServers)s];
var regex = new RegExp('http://(.*?(:\\\\\\\\d+)?)/');
var regex = new RegExp('http://(?:[^/@]*@)?(.*?(:\\\\\\\\d+)?)/');
var matches = regex.exec(url);
if (!matches)
return 'DIRECT';
@ -272,4 +272,4 @@ def runApp(testURL, env, app, profileDir):
if status != 0:
print "FAIL Exited with code " + str(status) + " during test run"
return start
return start

View File

@ -65,16 +65,9 @@ nsDOMMessageEvent::GetData(nsAString& aData)
}
NS_IMETHODIMP
nsDOMMessageEvent::GetDomain(nsAString& aDomain)
nsDOMMessageEvent::GetOrigin(nsAString& aOrigin)
{
aDomain = mDomain;
return NS_OK;
}
NS_IMETHODIMP
nsDOMMessageEvent::GetUri(nsAString& aURI)
{
aURI = mURI;
aOrigin = mOrigin;
return NS_OK;
}
@ -90,16 +83,14 @@ nsDOMMessageEvent::InitMessageEvent(const nsAString& aType,
PRBool aCanBubble,
PRBool aCancelable,
const nsAString& aData,
const nsAString& aDomain,
const nsAString& aURI,
const nsAString& aOrigin,
nsIDOMWindow* aSource)
{
nsresult rv = nsDOMEvent::InitEvent(aType, aCanBubble, aCancelable);
NS_ENSURE_SUCCESS(rv, rv);
mData = aData;
mDomain = aDomain;
mURI = aURI;
mOrigin = aOrigin;
mSource = aSource;
return NS_OK;
@ -111,8 +102,7 @@ nsDOMMessageEvent::InitMessageEventNS(const nsAString& aNamespaceURI,
PRBool aCanBubble,
PRBool aCancelable,
const nsAString& aData,
const nsAString& aDomain,
const nsAString& aURI,
const nsAString& aOrigin,
nsIDOMWindow* aSource)
{
return NS_ERROR_NOT_IMPLEMENTED;

View File

@ -68,8 +68,7 @@ public:
private:
nsString mData;
nsString mDomain;
nsString mURI;
nsString mOrigin;
nsCOMPtr<nsIDOMWindow> mSource;
};

View File

@ -214,5 +214,6 @@ interface nsIDOMWindowInternal : nsIDOMWindow2
*
* See the WHATWG HTML5 specification, section 6.4, for more details.
*/
[binaryname(PostMessageMoz)] void postMessage(in DOMString message);
[binaryname(PostMessageMoz)] void postMessage(in DOMString message,
[optional] in DOMString origin);
};

View File

@ -45,7 +45,7 @@
* For more information on this interface, please see
* http://www.whatwg.org/specs/web-apps/current-work/multipage/section-event0.html#event0
*/
[scriptable, uuid(3CF6163E-0227-49D9-B52B-F061828FB9B8)]
[scriptable, uuid(ca081997-91f9-40c1-890c-3edf39b6c571)]
interface nsIDOMMessageEvent : nsIDOMEvent
{
/**
@ -54,14 +54,12 @@ interface nsIDOMMessageEvent : nsIDOMEvent
readonly attribute DOMString data;
/**
* The domain of the site from which this event originated.
* The origin of the site from which this event originated, which is the
* scheme, ":", and if the URI has a host, "//" followed by the
* host, and if the port is not the default for the given scheme,
* ":" followed by that port. This value does not have a trailing slash.
*/
readonly attribute DOMString domain;
/**
* The URI of the site from which this event was created.
*/
readonly attribute DOMString uri;
readonly attribute DOMString origin;
/**
* The window which originated this event.
@ -71,27 +69,25 @@ interface nsIDOMMessageEvent : nsIDOMEvent
/**
* Initializes this event with the given data, in a manner analogous to
* the similarly-named method on the nsIDOMEvent interface, also setting the
* data, domain, uri, and source attributes of this appropriately.
* data, origin, and source attributes of this appropriately.
*/
void initMessageEvent(in DOMString aType,
in boolean aCanBubble,
in boolean aCancelable,
in DOMString aData,
in DOMString aDomain,
in DOMString aURI,
in DOMString aOrigin,
in nsIDOMWindow aSource);
/**
* Initializes this event with the given data, in a manner analogous to
* the similarly-named method on the Event interface, also setting the data,
* domain, uri, and source attributes of this appropriately.
* origin, and source attributes of this appropriately.
*/
void initMessageEventNS(in DOMString aNamespaceURI,
in DOMString aType,
in boolean aCanBubble,
in boolean aCancelable,
in DOMString aData,
in DOMString aDomain,
in DOMString aURI,
in DOMString aOrigin,
in nsIDOMWindow aSource);
};

View File

@ -5106,9 +5106,9 @@ nsGlobalWindow::CallerInnerWindow()
}
NS_IMETHODIMP
nsGlobalWindow::PostMessageMoz(const nsAString& aMessage)
nsGlobalWindow::PostMessageMoz(const nsAString& aMessage, const nsAString& aOrigin)
{
FORWARD_TO_INNER_CREATE(PostMessageMoz, (aMessage));
FORWARD_TO_INNER_CREATE(PostMessageMoz, (aMessage, aOrigin));
//
// Window.postMessage is an intentional subversion of the same-origin policy.
@ -5125,69 +5125,104 @@ nsGlobalWindow::PostMessageMoz(const nsAString& aMessage)
return NS_OK;
NS_ASSERTION(callerInnerWin->IsInnerWindow(), "should have gotten an inner window here");
// Obtain the caller's principal, from which we can usually extract a URI
// and domain for the event.
// Compute the caller's origin either from its principal or, in the case the
// principal doesn't carry a URI (e.g. the system principal), the caller's
// document.
nsIPrincipal* callerPrin = callerInnerWin->GetPrincipal();
if (!callerPrin)
return NS_OK;
nsCOMPtr<nsIURI> docURI;
if (NS_FAILED(callerPrin->GetURI(getter_AddRefs(docURI))))
nsCOMPtr<nsIURI> callerURI;
if (NS_FAILED(callerPrin->GetURI(getter_AddRefs(callerURI))))
return NS_OK;
// If we hit this, we're probably in chrome context and have the URI-less
// system principal, so get the URI off the caller's document.
if (!docURI) {
if (!callerURI) {
nsCOMPtr<nsIDocument> doc = do_QueryInterface(callerInnerWin->mDocument);
if (!doc)
return NS_OK;
callerURI = doc->GetDocumentURI();
if (!callerURI)
return NS_OK;
}
const nsCString& empty = EmptyCString();
nsCOMPtr<nsIURI> callerOrigin;
if (NS_FAILED(callerURI->Clone(getter_AddRefs(callerOrigin))) ||
NS_FAILED(callerOrigin->SetUserPass(empty)))
return NS_OK;
docURI = doc->GetDocumentURI();
if (!docURI)
// Calling postMessage on a closed window does nothing.
if (!mDocument)
return NS_OK;
nsCOMPtr<nsIDOMEventTarget> targetDoc = do_QueryInterface(mDocument);
nsCOMPtr<nsIDOMDocumentEvent> docEvent = do_QueryInterface(mDocument);
// Ensure that any origin which might have been provided is the origin of this
// window's document.
if (!aOrigin.IsVoid()) {
nsCOMPtr<nsIURI> providedOrigin;
if (NS_FAILED(NS_NewURI(getter_AddRefs(providedOrigin), aOrigin)))
return NS_ERROR_DOM_SYNTAX_ERR;
if (NS_FAILED(providedOrigin->SetUserPass(empty)) ||
NS_FAILED(providedOrigin->SetPath(empty)))
return NS_OK;
// Get the target's origin either from its principal or, in the case the
// principal doesn't carry a URI (e.g. the system principal), the target's
// document.
nsIPrincipal* targetPrin = GetPrincipal();
if (!targetPrin)
return NS_OK;
nsCOMPtr<nsIURI> targetURI;
if (NS_FAILED(targetPrin->GetURI(getter_AddRefs(targetURI))))
return NS_OK;
if (!targetURI) {
nsCOMPtr<nsIDocument> targetDoc = do_QueryInterface(mDocument);
if (!targetDoc)
return NS_OK;
targetURI = targetDoc->GetDocumentURI();
if (!targetURI)
return NS_OK;
}
nsCOMPtr<nsIURI> targetOrigin;
if (NS_FAILED(targetURI->Clone(getter_AddRefs(targetOrigin))) ||
NS_FAILED(targetOrigin->SetUserPass(empty)) ||
NS_FAILED(targetOrigin->SetPath(empty)))
return NS_OK;
PRBool equal = PR_FALSE;
if (NS_FAILED(targetOrigin->Equals(providedOrigin, &equal)) || !equal)
return NS_OK;
}
nsCAutoString domain, uri;
nsresult rv = docURI->GetSpec(uri);
if (NS_FAILED(rv))
return NS_OK;
// This really shouldn't be necessary -- URLs which don't have a host should
// return the empty string -- but nsSimpleURI just errors instead of
// truncating domain. We could just ignore the returned error, but in the
// interests of playing it safe in a sensitive API, we check and truncate if
// GetHost fails. Empty hosts are valid for some URI schemes, and any code
// which expects a non-empty host should ignore the message we'll dispatch.
if (NS_FAILED(docURI->GetHost(domain)))
domain.Truncate();
// Create the event
nsCOMPtr<nsIDOMDocumentEvent> docEvent = do_QueryInterface(mDocument);
if (!docEvent)
return NS_OK;
nsCOMPtr<nsIDOMEvent> event;
docEvent->CreateEvent(NS_LITERAL_STRING("MessageEvent"),
getter_AddRefs(event));
if (!event)
return NS_ERROR_FAILURE;
return NS_OK;
nsCAutoString origin;
if (NS_FAILED(callerOrigin->GetPrePath(origin)))
return NS_OK;
nsCOMPtr<nsIDOMMessageEvent> message = do_QueryInterface(event);
rv = message->InitMessageEvent(NS_LITERAL_STRING("message"),
PR_TRUE /* bubbling */,
PR_TRUE /* cancelable */,
aMessage,
NS_ConvertUTF8toUTF16(domain),
NS_ConvertUTF8toUTF16(uri),
nsContentUtils::IsCallerChrome()
? nsnull
: callerInnerWin->GetOuterWindowInternal());
nsresult rv = message->InitMessageEvent(NS_LITERAL_STRING("message"),
PR_TRUE /* bubbling */,
PR_TRUE /* cancelable */,
aMessage,
NS_ConvertUTF8toUTF16(origin),
nsContentUtils::IsCallerChrome()
? nsnull
: callerInnerWin->GetOuterWindowInternal());
if (NS_FAILED(rv))
return rv;
return NS_OK;
// Finally, dispatch the event, ignoring the result to prevent an exception
// from revealing anything about the document for this window.
PRBool dummy;
nsCOMPtr<nsIDOMEventTarget> targetDoc = do_QueryInterface(mDocument);
targetDoc->DispatchEvent(message, &dummy);
// Cancel exceptions that might somehow be pending. XPConnect swallows these

View File

@ -21,7 +21,7 @@ SimpleTest.waitForExplicitFinish();
function receiveMessage(evt)
{
is(evt.domain, "127.0.0.1", "wrong sender");
is(evt.origin, "http://127.0.0.1:8888", "wrong sender");
ok(evt.source === window.frames.child, "wrong sender");
is(evt.data, "child-response", "got wrong response");

View File

@ -12,7 +12,7 @@ function run()
function receiveMessage(evt)
{
if (evt.domain !== "localhost")
if (evt.origin !== "http://localhost:8888")
return;
var message = evt.data + "-response";

View File

@ -27,7 +27,7 @@ function runTest() {
catch (e) {
otherDomainVar = -1;
}
ok(otherDomainVar == -1, "access other domain inner window variable");
is(otherDomainVar, -1, "access other domain inner window variable");
SimpleTest.finish();
}

View File

@ -71,11 +71,22 @@ var noWhitelistRegex =
new RegExp("^http://sub1\\.exämple\\.test/tests/dom/tests/" +
"mochitest/dom-level0/idn_child\\.html\\?(.+)$");
var state = 0;
var messages =
[
"idn-whitelist",
"punycode-whitelist",
"idn-nowhitelist",
"punycode-nowhitelist",
];
function receiveMessage(evt)
{
var domain = evt.domain;
var origin = evt.origin;
var match;
if (/test$/.test(domain))
if (/test$/.test(origin))
{
// XXX bug 414090
// The value of MessageEvent.domain with postMessage *should* always be IDN;
@ -87,28 +98,20 @@ function receiveMessage(evt)
//
// These two tests should illustrate what currently happens and what should
// happen once bug 414090 is fixed.
todo_is(evt.domain, "sub1.exämple.test", "wrong sender");
todo_isnot(evt.domain, "sub1.xn--exmple-cua.test", "wrong sender");
match = noWhitelistRegex.exec(evt.uri);
todo(match, "unexpected sender");
if (!match)
match = [, evt.uri.substring(evt.uri.indexOf("?") + 1)];
todo_is(evt.origin, "http://sub1.exämple.test", "wrong sender");
todo_isnot(evt.origin, "http://sub1.xn--exmple-cua.test", "wrong sender");
}
else
{
// We're receiving data from the Greek IDN name; since that TLD is
// whitelisted for now, the domain we get isn't going to be punycoded.
is(evt.domain, "sub1.παράδειγμα.δοκιμή", "wrong sender");
match = whitelistRegex.exec(evt.uri);
ok(match, "should have matched, unexpected sender");
is(evt.origin, "http://sub1.παράδειγμα.δοκιμή", "wrong sender");
}
is(match[1] + "-response", evt.data.split(" ")[0],
is(messages[state] + "-response", evt.data.split(" ")[0],
"unexpected data: " + evt.data);
switch (match[1])
switch (messages[state])
{
case "idn-whitelist":
gotIDNWhitelist = true;
@ -138,6 +141,8 @@ function receiveMessage(evt)
ok(false, "unreached");
break;
}
state++;
}
function run()

View File

@ -21,7 +21,7 @@ SimpleTest.waitForExplicitFinish();
function receiveMessage(evt)
{
is(evt.domain, "127.0.0.1", "wrong sender");
is(evt.origin, "http://127.0.0.1:8888", "wrong sender");
ok(evt.source === window.frames.child, "wrong sender");
is(evt.data, "child-response", "got wrong response");

View File

@ -67,6 +67,12 @@ _TEST_FILES = \
test_postMessage_basehref.html \
test_postMessage_hash.html \
postMessage_hash.html \
test_postMessage_userpass.html \
postMessage_userpass_helper.html \
test_postMessage_origin.xhtml \
postMessage_origin_helper.xhtml \
test_postMessage_closed.html \
postMessage_closed_helper.html \
$(NULL)
_CHROME_FILES = \

View File

@ -3,9 +3,6 @@
<head>
<title>postMessage chrome message receiver</title>
<script type="application/javascript">
var sourcePath = "chrome://mochikit/content/chrome/" +
"dom/tests/mochitest/whatwg/test_postMessage_chrome.html";
function receiveMessage(evt)
{
// Content cannot post to chrome without privileges
@ -19,10 +16,8 @@
msg += " unexpected-untrusted-event";
if (evt.type !== "message")
msg += " wrong-type(" + evt.type + ")";
if (evt.uri !== sourcePath)
msg += " wrong-uri(" + evt.uri + ")";
if (evt.domain !== "mochikit")
msg += " wrong-domain(" + evt.domain + ")";
if (evt.origin !== "chrome://mochikit")
msg += " wrong-origin(" + evt.origin + ")";
if (evt.data !== "post-to-content")
msg += " wrong-message(" + evt.data + ")";

View File

@ -0,0 +1,26 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>postMessage closed page</title>
<script type="application/javascript">
function receiveMessage(evt)
{
evt.source.postMessage("FAIL");
}
document.addEventListener("message", receiveMessage, false);
function setup()
{
var query = location.search.substring(1);
if (query == "opener")
window.opener.postMessage("message");
}
window.addEventListener("load", setup, false);
</script>
</head>
<body>
</body>
</html>

View File

@ -10,10 +10,8 @@ function receiveMessage(evt)
if (window.location.href !== "http://localhost:8888/tests/dom/tests/mochitest/whatwg/postMessage_hash.html#hash")
response += " kid-at-wrong-uri(" + window.location.href + ")";
if (evt.domain !== "localhost")
response += " wrong-domain(" + evt.domain + ")";
if (evt.uri !== "http://localhost:8888/tests/dom/tests/mochitest/whatwg/test_postMessage_hash.html")
response += " wrong-uri(" + evt.uri + ")";
if (evt.origin !== "http://localhost:8888")
response += " wrong-origin(" + evt.origin + ")";
if (evt.source !== window.parent)
response += " wrong-source";
if (evt.data !== "from-parent")

View File

@ -11,8 +11,6 @@
$("domain").textContent = location.hostname + ":" + (location.port || 80);
}
var otherPath = "/tests/dom/tests/mochitest/whatwg/test_postMessage.html";
function receiveMessage(evt)
{
var response = evt.data + "-response";
@ -52,10 +50,8 @@
var source = evt.source;
try
{
if (evt.domain != "localhost")
response += " unexpected-domain(" + evt.domain + ")";
if (evt.uri != "http://localhost:8888" + otherPath)
response += " unexpected-uri(" + evt.uri + ")";
if (evt.origin != "http://localhost:8888")
response += " unexpected-origin(" + evt.origin + ")";
try
{
@ -79,10 +75,8 @@
function receiveCross(evt, response)
{
var source = evt.source;
if (evt.domain != "localhost")
response += " unexpected-domain(" + evt.domain + ")";
if (evt.uri != "http://localhost:8888" + otherPath)
response += " unexpected-uri(" + evt.uri + ")";
if (evt.origin != "http://localhost:8888")
response += " unexpected-origin(" + evt.origin + ")";
try
{

View File

@ -9,10 +9,8 @@
if (!(evt instanceof MessageEvent))
response += " not-a-MessageEvent";
if (evt.uri !== "http://localhost:8888/tests/dom/tests/mochitest/whatwg/test_postMessage_idn.xhtml")
response += " wrong-sender-uri(" + evt.uri + ")";
if (evt.domain !== "localhost")
response += " wrong-sender-domain(" + evt.domain + ")";
if (evt.origin !== "http://localhost:8888")
response += " wrong-sender-origin(" + evt.origin + ")";
if (evt.data !== "idn-message")
response += " wrong-data(" + evt.data + ")";
if (evt.source !== window.parent)

View File

@ -41,32 +41,17 @@ http://sub1.test1.example.org/tests/dom/tests/mochitest/whatwg/postMessage_joine
response += " unexpected-trusted-event";
}
var uri, domain;
var origin;
if (data == "subframe-test-finished")
{
uri = "http://example.org/tests/dom/tests/mochitest/whatwg/postMessage_joined_helper2.html";
domain = "example.org";
}
origin = "http://example.org";
else if (data === "start-test")
{
uri = "http://localhost:8888/tests/dom/tests/mochitest/whatwg/test_postMessage_joined.html";
domain = "localhost";
}
origin = "http://localhost:8888";
else
{
uri = "unreached";
domain = "unreached";
}
origin = "unreached";
if (evt.uri !== uri)
if (evt.origin !== origin)
{
response += " wrong-uri(" + evt.uri + ")";
response += " location(" + window.location.href + ")";
}
if (evt.domain !== domain)
{
response += " wrong-domain(" + evt.domain + ")";
response += " wrong-origin(" + evt.origin + ")";
response += " location(" + window.location.href + ")";
}

View File

@ -45,15 +45,9 @@ http://example.org/tests/dom/tests/mochitest/whatwg/postMessage_joined_helper2.h
if (!passed)
response += " expected-joined-domains";
if (evt.uri !== "http://sub1.test1.example.org/tests/dom/tests/mochitest/whatwg/postMessage_joined_helper.html")
if (evt.origin !== "http://sub1.test1.example.org")
{
response += " wrong-uri(" + evt.uri + ")";
response += " location(" + window.location.href + ")";
}
if (evt.domain !== "sub1.test1.example.org")
{
response += " wrong-domain(" + evt.domain + ")";
response += " wrong-origin(" + evt.origin + ")";
response += " location(" + window.location.href + ")";
}

View File

@ -23,10 +23,8 @@
if (evt.data !== "message-from-sibling")
response += " wrong-data(" + evt.data + ")";
if (evt.uri !== "http://localhost:8888/tests/dom/tests/mochitest/whatwg/postMessage_onOther.html")
response += " failed-wrong-uri(" + evt.uri + ")";
if (evt.domain !== "localhost")
response += " failed-wrong-domain(" + evt.domain + ")";
if (evt.origin !== "http://localhost:8888")
response += " failed-wrong-origin(" + evt.origin + ")";
if (evt.source !== window.parent.firstFrame)
response += " failed-wrong-source";

View File

@ -0,0 +1,37 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>postMessage throwing page</title>
<script type="application/javascript"><![CDATA[
function receiveMessage(evt)
{
var response = "PASS";
if (evt.origin !== "http://localhost:8888")
response += " wrong-origin(" + evt.origin + ")";
if (evt.source !== window.parent)
response += " wrong-source";
if (evt.data !== "PASS")
response += " wrong-data(" + evt.data + ")";
window.parent.postMessage(response);
}
document.addEventListener("message", receiveMessage, false);
// Aids for identifying origins
function setup()
{
var target = document.getElementById("location");
target.textContent = document.domain + ":" + (location.port || 80);
}
window.addEventListener("load", setup, false);
]]></script>
</head>
<body>
<h1 id="location">No location!</h1>
</body>
</html>

View File

@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<title>Username/password page for postMessage tests</title>
<script type="application/javascript">
function sendMessage(evt)
{
var msg = "child-message";
if (evt.origin !== "http://localhost:8888")
msg += " wrong-origin(" + evt.origin + ")";
if (evt.data !== "parent-message")
msg += " wrong-data(" + evt.data + ")";
if (evt.source !== window.parent)
msg += " wrong-source";
// It would be good to guarantee that we've been opened with a userinfo of
// "bobhope:password", but Gecko elides that from the content-visible URL,
// and I can't find another way to actually detect this programmatically.
window.parent.postMessage(msg);
}
document.addEventListener("message", sendMessage, false);
</script>
</head>
<body>
<p>Kid iframe</p>
</body>
</html>

View File

@ -26,8 +26,7 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=postMessage
SimpleTest.waitForExplicitFinish();
var data = "foobar";
var domain = "cool.example.com";
var uri = "http://cool.example.com/bar";
var origin = "http://cool.example.com";
var bubbles = true, cancelable = true;
var target;
@ -47,14 +46,13 @@ function sendMsg()
"not initialized yet, so null in our implementation");
}
evt.initMessageEvent("message", bubbles, cancelable, data, domain, uri, null);
evt.initMessageEvent("message", bubbles, cancelable, data, origin, null);
ok(evt.source === null, "null source is fine for a MessageEvent");
evt.initMessageEvent("message", bubbles, cancelable, data, domain, uri, window);
evt.initMessageEvent("message", bubbles, cancelable, data, origin, window);
is(evt.data, data, "unexpected data");
is(evt.domain, domain, "unexpected domain");
is(evt.uri, uri, "unexpected uri");
is(evt.origin, origin, "unexpected origin");
is(evt.cancelable, cancelable, "wrong cancelable property");
is(evt.bubbles, bubbles, "wrong bubbling property");
@ -72,8 +70,7 @@ function sendMsg()
function recvMsg(evt)
{
is(evt.data, data, "unexpected data");
is(evt.domain, domain, "unexpected domain");
is(evt.uri, uri, "unexpected uri");
is(evt.origin, origin, "unexpected origin");
is(evt.cancelable, cancelable, "wrong cancelable property");
is(evt.bubbles, bubbles, "wrong bubbling property");

View File

@ -28,7 +28,7 @@ function run()
{
var msg = document.createEvent("MessageEvent");
msg.initMessageEvent("message", true, true,
"foo", "evil.com", "http://evil.com/", window);
"foo", "http://evil.com", window);
try
{

View File

@ -27,9 +27,6 @@ https://bugzilla.mozilla.org/show_bug.cgi?id=postMessage
SimpleTest.waitForExplicitFinish();
var otherPath = "/tests/dom/tests/mochitest/whatwg/postMessage_helper.html";
var path = "/tests/dom/tests/mochitest/whatwg/test_postMessage.html";
var testsCompletedCount = 0;
/** Variable for receivers to attempt to get. */
@ -103,8 +100,7 @@ function messageReceiver(evt)
function respondToSelf(evt)
{
is(evt.domain, "localhost", "what domain are we on again?");
is(evt.uri, "http://localhost:8888" + path, "event has wrong URI");
is(evt.origin, "http://localhost:8888", "event has wrong origin");
is(evt.source, window, "we posted this message!");
evt.source.postMessage("post-to-self-response");
@ -117,25 +113,22 @@ function respondToSelf(evt)
function receiveSelf(evt)
{
is(evt.domain, "localhost", "what domain are we on again?");
is(evt.uri, "http://localhost:8888" + path, "event has wrong URI");
is(evt.origin, "http://localhost:8888", "event has wrong origin");
is(evt.source, window, "we posted this message!");
}
function receiveOtherSameDomain(evt)
{
is(evt.domain, "localhost", "we should be same domain");
is(evt.uri, "http://localhost:8888" + otherPath,
"same-domain response event has wrong URI");
is(evt.origin, "http://localhost:8888",
"same-domain response event has wrong origin");
is(evt.source, window.frames.otherSameDomain,
"wrong source for same-domain message!");
}
function receiveOtherCrossDomain(evt)
{
is(evt.domain, "example.org", "we should be same domain");
is(evt.uri, "http://example.org:8000" + otherPath,
"same-domain response event has wrong URI");
is(evt.origin, "http://example.org:8000",
"same-domain response event has wrong origin");
// can't use |is| here, because ok tries to get properties on its arguments
// for creating a formatted logging message

View File

@ -24,9 +24,7 @@ SimpleTest.waitForExplicitFinish();
function receiveMessage(evt)
{
is(evt.domain, "localhost", "wrong sender");
is(evt.uri, "http://localhost:8888/tests/dom/tests/mochitest/whatwg/test_postMessage_basehref.html",
"wrong sender");
is(evt.origin, "http://localhost:8888", "wrong sender");
ok(evt.source === window, "wrong source");
is(evt.data, "generate-event", "wrong data");

View File

@ -29,10 +29,6 @@ chrome://mochikit/content/chrome/dom/tests/mochitest/whatwg/test_postMessage_chr
SimpleTest.waitForExplicitFinish();
var pathHead = "chrome://mochikit/content/chrome";
var path = "/dom/tests/mochitest/whatwg/test_postMessage_chrome.html";
var otherPath = "/tests/dom/tests/mochitest/whatwg/postMessage_chrome_helper.html";
var testsCompletedCount = 0;
/** Receives MessageEvents to this window. */
@ -69,8 +65,7 @@ function messageReceiver(evt)
function checkSelf(evt)
{
is(evt.isTrusted, true, "should have sent a trusted event");
is(evt.domain, "mochikit", "chrome: protocol's domain is the package");
is(evt.uri, pathHead + path, "event has wrong URI");
is(evt.origin, "chrome://mochikit", "wrong origin for chrome: URL");
is(evt.source, null, "chrome posters get a null source, for security");
}
@ -82,9 +77,7 @@ function checkSelf(evt)
function receiveContent(evt)
{
is(evt.isTrusted, true, "should have sent a trusted event");
is(evt.domain, "example.org", "wrong domain for content page");
is(evt.uri, "http://example.org" + otherPath,
"content response event has wrong URI");
is(evt.origin, "http://example.org", "content response event has wrong URI");
is(evt.source, window.frames.contentDomain,
"wrong source for same-domain message!");
}

View File

@ -0,0 +1,73 @@
<!DOCTYPE html>
<html>
<head>
<title>postMessage's interaction with closed windows</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="browserFu.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<p><a href="https://bugzilla.mozilla.org/show_bug.cgi?id=417075">Bug 417075</a></p>
<p id="display"></p>
<div id="content" style="display: none"></div>
<div id="holder"></div>
<pre id="test">
<script class="testbody" type="application/javascript">
SimpleTest.waitForExplicitFinish();
function receiveMessage(evt)
{
is(evt.origin, "http://localhost:8888", "wrong origin");
ok(evt.source === openedWindow, "wrong source");
is(evt.data, "message", "wrong data");
if (evt.data !== "message")
return; // prevent recursion if bugs
evt.source.close();
function afterClose()
{
document.removeEventListener("message", receiveMessage, false);
evt.source.postMessage("NOT-RECEIVED");
var iframe = document.createElement("iframe");
iframe.id = "insertedIframe";
$("holder").appendChild(iframe);
iframe.addEventListener("load", iframeLoaded, false);
iframe.src = "postMessage_closed_helper.html?parent";
}
setTimeout(afterClose, 0);
}
document.addEventListener("message", receiveMessage, false);
function iframeLoaded(evt)
{
var iframe = $("insertedIframe");
iframe.removeEventListener("load", iframeLoaded, false);
var iframeWindow = iframe.contentWindow;
$("holder").removeChild($("insertedIframe"));
iframeWindow.postMessage("NOT-RECEIVED");
SimpleTest.finish();
}
var openedWindow;
function run()
{
openedWindow = window.open("postMessage_closed_helper.html?opener", "foobar");
}
window.addEventListener("load", run, false);
</script>
</pre>
</body>
</html>

View File

@ -23,9 +23,7 @@ SimpleTest.waitForExplicitFinish();
function receiveMessage(evt)
{
is(evt.domain, "localhost", "wrong sender");
is(evt.uri, "http://localhost:8888/tests/dom/tests/mochitest/whatwg/postMessage_hash.html#hash",
"wrong sender");
is(evt.origin, "http://localhost:8888", "wrong origin");
ok(evt.source === window.frames.kid, "wrong source");
is(evt.data, "response-message", "wrong data");

View File

@ -37,10 +37,8 @@ function receiveMessage(evt)
ok(evt.isTrusted === false, "shouldn't have been a trusted event");
}
is(evt.uri, "http://sub1.ält.example.org:8000/tests/dom/tests/mochitest/whatwg/postMessage_idn_helper.html",
"wrong URI -- IDN issue, perhaps?");
is(evt.domain, "sub1.ält.example.org",
"wrong domain -- IDN issue, perhaps?");
is(evt.origin, "http://sub1.ält.example.org:8000",
"wrong origin -- IDN issue, perhaps?");
is(evt.data, "idn-response", "unexpected test result");
ok(evt.source === idnWindow, "wrong source");

View File

@ -31,10 +31,8 @@ var finished = false;
/** Receives MessageEvents to this window. */
function messageReceiver(evt)
{
var fromURI = "http://example.org:8000/tests/dom/tests/mochitest/whatwg/postMessage_onOther.html";
ok(evt instanceof MessageEvent, "wrong event type");
is(evt.uri, fromURI, "unexpected URI");
is(evt.domain, "example.org", "unexpected domain");
is(evt.origin, "http://example.org:8000", "unexpected origin");
is(evt.data, "response-to-sibling-sent-message",
"unexpected data in message");

View File

@ -0,0 +1,470 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=417075
-->
<head>
<title>postMessage from about:blank, data URLs</title>
<script type="text/javascript" src="/MochiKit/packed.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="browserFu.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=417075">Mozilla Bug 417075</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<iframe src="http://localhost:8888/tests/dom/tests/mochitest/whatwg/postMessage_origin_helper.xhtml"
id="sameDomain"></iframe>
<iframe src="http://example.com/tests/dom/tests/mochitest/whatwg/postMessage_origin_helper.xhtml"
id="otherDomain"></iframe>
<iframe src="http://example.org:8000/tests/dom/tests/mochitest/whatwg/postMessage_origin_helper.xhtml"
id="otherDomainPort"></iframe>
<iframe src="ftp://localhost:27534/tests/dom/tests/mochitest/whatwg/postMessage_origin_helper.xhtml"
id="localNoExist"></iframe>
<iframe src="http://sub1.παράδειγμα.δοκιμή/tests/dom/tests/mochitest/whatwg/postMessage_origin_helper.xhtml"
id="idnKidWhitelist"></iframe>
<iframe src="http://sub1.exämple.test/tests/dom/tests/mochitest/whatwg/postMessage_origin_helper.xhtml"
id="idnKidNoWhitelist"></iframe>
<pre id="test">
<script class="testbody" type="application/javascript"><![CDATA[
/** Test for Bug 417075 **/
SimpleTest.waitForExplicitFinish();
function errorCheck(i, called, errorCode, actualCode)
{
ok(!called, "receiver should not have been called for test #" + i);
is(actualCode, errorCode, "wrong error thrown in test #" + i);
}
function errorCheckTodo(i, called, errorCode, actualCode)
{
todo(!called, "receiver should not have been called for test #" + i);
todo_is(actualCode, errorCode, "wrong error thrown in test #" + i);
}
var ONE_PASS = ["PASS"];
var tests =
[
// 0
{
args: ["NOT-RECEIVED", ""],
source: "sameDomain",
code: DOMException.SYNTAX_ERR
},
{
args: ["NOT-RECEIVED", "null"],
source: "sameDomain",
code: DOMException.SYNTAX_ERR
},
{
args: ["NOT-RECEIVED", "a"],
source: "sameDomain",
code: DOMException.SYNTAX_ERR
},
{
args: ["NOT-RECEIVED", "http :"],
source: "sameDomain",
code: DOMException.SYNTAX_ERR
},
{
args: ["NOT-RECEIVED", "http: //"],
source: "sameDomain",
code: DOMException.SYNTAX_ERR,
throwsNoException: true
},
// 5
{
args: ["NOT-RECEIVED", "http ://"],
source: "sameDomain",
code: DOMException.SYNTAX_ERR
},
{
args: ["TODO", " http://localhost:8888"],
source: "sameDomain",
code: DOMException.SYNTAX_ERR,
returnOrigin: "http://localhost:8888",
throwsNoException: true
},
{
args: ["NOT-RECEIVED", "hä"],
source: "sameDomain",
code: DOMException.SYNTAX_ERR
},
{
args: ["NOT-RECEIVED", "http://lo\0k.com"],
source: "sameDomain",
code: DOMException.SYNTAX_ERR
},
{
args: ["NOT-RECEIVED", "http: //localhost:8888"],
source: "sameDomain",
code: DOMException.SYNTAX_ERR,
throwsNoException: true
},
// 10
{
args: ["NOT-RECEIVED", "http://localhost :8888"],
source: "sameDomain",
code: DOMException.SYNTAX_ERR
},
{
args: ["NOT-RECEIVED", "http:// localhost:8888"],
source: "sameDomain",
code: DOMException.SYNTAX_ERR,
throwsNoException: true
},
{
args: ["TODO", "http://\nlocalhost:8888"],
source: "sameDomain",
code: DOMException.SYNTAX_ERR,
returnOrigin: "http://localhost:8888",
throwsNoException: true
},
{
args: ["TODO", "http://localhost:8888\0"],
source: "sameDomain",
code: DOMException.SYNTAX_ERR,
returnOrigin: "http://localhost:8888",
throwsNoException: true
},
{
args: ["TODO", "http://localhost:8888\n"],
source: "sameDomain",
code: DOMException.SYNTAX_ERR,
returnOrigin: "http://localhost:8888",
throwsNoException: true
},
// 15
{
args: ONE_PASS,
source: "sameDomain",
returnOrigin: "http://localhost:8888"
},
{
args: ["PASS", null],
source: "sameDomain",
returnOrigin: "http://localhost:8888"
},
{
args: ["PASS", "http://example.com"],
source: "otherDomain",
returnOrigin: "http://example.com"
},
{
args: ["PASS", "http://example.com/"],
source: "otherDomain",
returnOrigin: "http://example.com"
},
{
args: ["PASS", "http://example.com:80"],
source: "otherDomain",
returnOrigin: "http://example.com"
},
// 20
{
args: ["PASS", "http://example.com:80/"],
source: "otherDomain",
returnOrigin: "http://example.com"
},
{
args: ["PASS", "http://example.com:80/foobar"],
source: "otherDomain",
returnOrigin: "http://example.com"
},
{
args: ["PASS", "http://example.com/foobar"],
source: "otherDomain",
returnOrigin: "http://example.com"
},
{
args: ["PASS", "http://example.com:8000"],
source: "otherDomain",
expectNoCallback: true
},
{
args: ["PASS", "http://example.com:8000/"],
source: "otherDomain",
expectNoCallback: true
},
// 25
{
args: ["PASS", "http://example.org:8000"],
source: "otherDomainPort",
returnOrigin: "http://example.org:8000"
},
{
args: ["PASS", "http://example.org:8000/"],
source: "otherDomainPort",
returnOrigin: "http://example.org:8000"
},
{
args: ["PASS", "http://example.org:8000/tests/dom/test/mochitest/whatwg/postMessage_origin_helper.xhtml"],
source: "otherDomainPort",
returnOrigin: "http://example.org:8000"
},
{
args: ["PASS", "http://example.org:8000/tests/dom/test/mochitest/whatwg/this_file_does_not_exist.xhtml"],
source: "otherDomainPort",
returnOrigin: "http://example.org:8000"
},
{
args: ["PASS", "http://example.org"],
source: "otherDomainPort",
expectNoCallback: true
},
// 30
{
args: ["PASS", "http://example.org:80"],
source: "otherDomainPort",
expectNoCallback: true
},
{
args: ["PASS", "http://example.org/"],
source: "otherDomainPort",
expectNoCallback: true
},
{
args: ["PASS", "http://example.org"],
source: "otherDomain",
expectNoCallback: true
},
{
args: ["PASS", "ftp://localhost:8888"],
source: "sameDomain",
expectNoCallback: true
},
{
args: ["PASS", "http://localhost:8888"],
source: "sameDomain",
returnOrigin: "http://localhost:8888"
},
// 35
{
args: ["PASS", "http://localhost:27534"],
source: "sameDomain",
expectNoCallback: true
},
{
args: ["PASS", "http://sub1.παράδειγμα.δοκιμή"],
source: "idnKidWhitelist",
returnOrigin: "http://sub1.παράδειγμα.δοκιμή"
},
{
args: ["PASS", "http://sub1.παράδειγμα.δοκιμή:80"],
source: "idnKidWhitelist",
returnOrigin: "http://sub1.παράδειγμα.δοκιμή"
},
{
args: ["PASS", "http://sub1.παράδειγμα.δοκιμή:80/"],
source: "idnKidWhitelist",
returnOrigin: "http://sub1.παράδειγμα.δοκιμή"
},
{
args: ["PASS", "http://sub1.παράδειγμα.δοκιμή:80/foobar"],
source: "idnKidWhitelist",
returnOrigin: "http://sub1.παράδειγμα.δοκιμή"
},
// 40
{
args: ["PASS", "http://sub1.παράδειγμα.δοκιμή/foobar"],
source: "idnKidWhitelist",
returnOrigin: "http://sub1.παράδειγμα.δοκιμή"
},
{
args: ["PASS", "http://sub1.xn--hxajbheg2az3al.xn--jxalpdlp"],
source: "idnKidWhitelist",
returnOrigin: "http://sub1.παράδειγμα.δοκιμή"
},
{
args: ["PASS", "http://sub1.xn--hxajbheg2az3al.xn--jxalpdlp:80"],
source: "idnKidWhitelist",
returnOrigin: "http://sub1.παράδειγμα.δοκιμή"
},
{
args: ["PASS", "http://sub1.xn--hxajbheg2az3al.xn--jxalpdlp:80/"],
source: "idnKidWhitelist",
returnOrigin: "http://sub1.παράδειγμα.δοκιμή"
},
{
args: ["PASS", "http://sub1.xn--hxajbheg2az3al.xn--jxalpdlp:80/foo"],
source: "idnKidWhitelist",
returnOrigin: "http://sub1.παράδειγμα.δοκιμή"
},
// 45
{
args: ["PASS", "http://sub1.exämple.test"],
source: "idnKidNoWhitelist",
returnOrigin: "http://sub1.exämple.test",
wrongReturnOrigin: true
},
{
args: ["PASS", "http://sub1.exämple.test:80"],
source: "idnKidNoWhitelist",
returnOrigin: "http://sub1.exämple.test",
wrongReturnOrigin: true
},
{
args: ["PASS", "http://sub1.exämple.test:80/"],
source: "idnKidNoWhitelist",
returnOrigin: "http://sub1.exämple.test",
wrongReturnOrigin: true
},
{
args: ["PASS", "http://sub1.exämple.test/"],
source: "idnKidNoWhitelist",
returnOrigin: "http://sub1.exämple.test",
wrongReturnOrigin: true
},
{
args: ["PASS", "http://sub1.exämple.test/foobar"],
source: "idnKidNoWhitelist",
returnOrigin: "http://sub1.exämple.test",
wrongReturnOrigin: true
},
// 50
{
args: ["PASS", "http://sub1.xn--exmple-cua.test"],
source: "idnKidNoWhitelist",
returnOrigin: "http://sub1.exämple.test",
wrongReturnOrigin: true
},
{
args: ["PASS", "http://sub1.xn--exmple-cua.test:80"],
source: "idnKidNoWhitelist",
returnOrigin: "http://sub1.exämple.test",
wrongReturnOrigin: true
},
{
args: ["PASS", "http://sub1.xn--exmple-cua.test:80/"],
source: "idnKidNoWhitelist",
returnOrigin: "http://sub1.exämple.test",
wrongReturnOrigin: true
},
{
args: ["PASS", "http://sub1.xn--exmple-cua.test/"],
source: "idnKidNoWhitelist",
returnOrigin: "http://sub1.exämple.test",
wrongReturnOrigin: true
},
{
args: ["PASS", "http://sub1.xn--exmple-cua.test/foobar"],
source: "idnKidNoWhitelist",
returnOrigin: "http://sub1.exämple.test",
wrongReturnOrigin: true
},
];
function allTests()
{
var test, target, called;
function receive(evt)
{
var originCheck = test.wrongReturnOrigin ? todo_is : is;
originCheck(evt.origin, test.returnOrigin, "wrong origin for #" + i);
if (test.args[0] == "TODO")
todo_is(evt.data, "PASS", "wrong data");
else
is(evt.data, "PASS", "wrong data");
ok(evt.source === target, "wrong source");
called = true;
}
function post(win, args, err)
{
called = false;
win.postMessage.apply(win, args);
}
document.addEventListener("message", receive, false);
for (var i = 0, sz = tests.length; i < sz; i++)
{
test = tests[i];
target = $(test.source).contentWindow;
try
{
called = false;
target.postMessage.apply(target, test.args);
if (test.throwsNoException)
todo(false, "should throw on test #" + i);
else if (test.expectNoCallback)
(test.checkCallback || ok)(!called, "shouldn't have been called #" + i);
else
(test.checkCallback || ok)(called, "should have been called #" + i);
}
catch (e)
{
(test.errorCheck || errorCheck)(i, called, e.code, test.code);
}
}
document.removeEventListener("message", receive, false);
}
function oddballTests()
{
var called;
function receive(evt)
{
is(evt.origin, "http://localhost:8888", "wrong sender");
is(evt.data, "PASS", "wrong data");
ok(evt.source === window, "wrong source");
called = true;
}
document.addEventListener("message", receive, false);
try
{
called = false;
window.postMessage("PASS");
is(called, true, "should have been called");
called = false;
window.postMessage("PASS", null);
is(called, true, "should have been called");
}
finally
{
document.removeEventListener("message", receive, false);
}
}
function run()
{
oddballTests();
allTests();
SimpleTest.finish();
}
window.addEventListener("load", run, false);
]]></script>
</pre>
</body>
</html>

View File

@ -129,22 +129,15 @@ function messageReceiver(evt)
// not codified yet which of these two causes the identifier tokens on
// the event generated by the new window to be those of this window, but
// in either case this is what they should be.
is(evt.uri, "http://localhost:8888/tests/dom/tests/mochitest/whatwg/test_postMessage_special.xhtml",
"wrong uri for event from about:blank");
ok(evt.domain === "localhost",
"wrong domain for event from about:blank; " +
"got " + sourceify(evt.domain) + ", " +
"expected 'localhost'");
is(evt.origin, "http://localhost:8888",
"wrong origin for event from about:blank");
is(evt.source, aboutBlankWindow, "wrong source");
aboutBlankResponseReceived = true;
}
else if (evt.data === "about:blank2-response")
{
is(evt.uri, "http://localhost:8888/tests/dom/tests/mochitest/whatwg/test_postMessage_special.xhtml",
"wrong uri for event from about:blank #2");
ok(evt.domain === "localhost",
"wrong domain for event from about:blank; " +
"got " + sourceify(evt.domain) + ", expected 'localhost'");
is(evt.origin, "http://localhost:8888",
"wrong origin for event from about:blank #2");
is(evt.source, aboutBlank2Window, "wrong source");
aboutBlank2ResponseReceived = true;
}
@ -162,14 +155,11 @@ function messageReceiver(evt)
// then.
if (isMozilla)
{
is(evt.uri, "http://localhost:8888/tests/dom/tests/mochitest/whatwg/test_postMessage_special.xhtml",
"wrong uri for event from data URL (but note that this URI is " +
is(evt.origin, "http://localhost:8888",
"wrong origin for event from data URL (but note that this URI is " +
"the result of Mozilla's current policy that data: URLs inherit " +
"the principal of their opener/parent, a policy not currently " +
"specified by any standards)");
ok(evt.domain === "localhost",
"wrong domain for event from data URL; " +
"got " + sourceify(evt.domain) + ", expected ''");
}
is(evt.source, dataWindow, "wrong source");
@ -200,10 +190,8 @@ function getContents(description, responseText)
"\n" +
" if (evt.source !== window.parent)\n" +
" response += ' wrong-source';\n" +
" if (evt.uri !== 'http://localhost:8888/tests/dom/tests/mochitest/whatwg/test_postMessage_special.xhtml')\n" +
" response += ' wrong-uri(' + evt.uri + ')';\n" +
" if (evt.domain !== 'localhost')\n" +
" response += ' wrong-domain(' + evt.domain + ')';\n" +
" if (evt.origin !== 'http://localhost:8888')\n" +
" response += ' wrong-origin(' + evt.origin + ')';\n" +
" if (evt.data !== 'from-opener')\n" +
" response += ' wrong-data(' + evt.data + ')';\n" +
"\n" +

View File

@ -0,0 +1,46 @@
<!DOCTYPE html>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=417075
-->
<head>
<title>postMessage from a page with username/password in its URI</title>
<script type="text/javascript" src="/MochiKit/MochiKit.js"></script>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=417075">Mozilla Bug 417075</a>
<p id="display"></p>
<div id="content" style="display: none"></div>
<iframe src="http://bobhope:password@example.org/tests/dom/tests/mochitest/whatwg/postMessage_userpass_helper.html"
name="userPassKid"></iframe>
<pre id="test">
<script class="testbody" type="application/javascript">
/** Test for Bug 417075 **/
SimpleTest.waitForExplicitFinish();
function receiveMessage(evt)
{
is(evt.origin, "http://example.org", "wrong origin");
is(evt.data, "child-message", "wrong data");
ok(evt.source === window.frames.userPassKid, "wrong source");
SimpleTest.finish();
}
document.addEventListener("message", receiveMessage, false);
function sendMessage(evt)
{
window.frames.userPassKid.postMessage("parent-message");
}
window.addEventListener("load", sendMessage, false);
</script>
</pre>
</body>
</html>

View File

@ -460,8 +460,10 @@ SERVERPREFEND
$pacURL .= "{ ";
$pacURL .= " var servers = [$quotedServers]; ";
$pacURL .= " var regex = ";
$pacURL .= " new RegExp('http://(.*?(:\\\\\\\\d+)?)/'); ";
$pacURL .= " new RegExp('http://(?:[^/@]*@)?(.*?(:\\\\\\\\d+)?)/'); ";
$pacURL .= " var matches = regex.exec(url); ";
$pacURL .= " if (!matches) ";
$pacURL .= " return 'DIRECT'; ";
$pacURL .= " var hostport = matches[1], port = matches[2]; ";
$pacURL .= " if (!port) ";
$pacURL .= " hostport += ':80'; ";