"use strict" ;
// utility functions for worker/window communication
function isInWorker() {
try {
return !(self
instanceof Window);
}
catch (e) {
return true ;
}
}
function message(aData) {
if (isInWorker()) {
self.postMessage(aData);
}
else {
self.postMessage(aData,
"*" );
}
}
message.ping = 0;
message.pong = 0;
function is(aActual, aExpected, aMessage) {
var obj = {
type:
"is" ,
actual: aActual,
expected: aExpected,
message: aMessage,
};
++message.ping;
message(obj);
}
function ok(aBool, aMessage) {
var obj = {
type:
"ok" ,
bool: aBool,
message: aMessage,
};
++message.ping;
message(obj);
}
function info(aMessage) {
var obj = {
type:
"info" ,
message: aMessage,
};
++message.ping;
message(obj);
}
function request(aURL) {
return new Promise(
function (aResolve) {
var xhr =
new XMLHttpRequest();
xhr.open(
"GET" , aURL);
xhr.addEventListener(
"load" ,
function () {
xhr.succeeded =
true ;
aResolve(xhr);
});
xhr.addEventListener(
"error" ,
function () {
xhr.succeeded =
false ;
aResolve(xhr);
});
xhr.send();
});
}
function createSequentialRequest(aParameters, aTest) {
var sequence = aParameters.reduce(
function (aPromise, aParam) {
return aPromise
.then(
function () {
return request(aParam.requestURL);
})
.then(
function (aXHR) {
return aTest(aXHR, aParam);
});
}, Promise.resolve());
return sequence;
}
function testSuccessResponse() {
var blob =
new Blob([
"data" ], { type:
"text/plain" });
var blobURL = URL.createObjectURL(blob);
var parameters = [
// tests that start with same-origin request
{
message:
"request to same-origin without redirect" ,
requestURL:
"http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text ",
responseURL:
"http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text ",
},
{
message:
"request to same-origin redirect to same-origin URL" ,
requestURL:
"http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text ",
responseURL:
"http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text ",
},
{
message:
"request to same-origin redirects several times and finally go to same-origin URL" ,
requestURL:
"http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url= " +
encodeURIComponent(
"http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text "
),
responseURL:
"http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text ",
},
{
message:
"request to same-origin redirect to cross-origin URL" ,
requestURL:
"http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text ",
responseURL:
"http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text ",
},
{
message:
"request to same-origin redirects several times and finally go to cross-origin URL" ,
requestURL:
"http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url= " +
encodeURIComponent(
"http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text "
),
responseURL:
"http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text ",
},
// tests that start with cross-origin request
{
message:
"request to cross-origin without redirect" ,
requestURL:
"http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text ",
responseURL:
"http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text ",
},
{
message:
"request to cross-origin redirect back to same-origin URL" ,
requestURL:
"http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text ",
responseURL:
"http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text ",
},
{
message:
"request to cross-origin redirect to the same cross-origin URL" ,
requestURL:
"http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text ",
responseURL:
"http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text ",
},
{
message:
"request to cross-origin redirect to another cross-origin URL" ,
requestURL:
"http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://example.org/tests/dom/xhr/tests/file_XHRResponseURL.text ",
responseURL:
"http://example.org/tests/dom/xhr/tests/file_XHRResponseURL.text ",
},
{
message:
"request to cross-origin redirects several times and finally go to same-origin URL" ,
requestURL:
"http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url= " +
encodeURIComponent(
"http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text "
),
responseURL:
"http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text ",
},
{
message:
"request to cross-origin redirects several times and finally go to the same cross-origin URL" ,
requestURL:
"http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url= " +
encodeURIComponent(
"http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text "
),
responseURL:
"http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.text ",
},
{
message:
"request to cross-origin redirects several times and finally go to another cross-origin URL" ,
requestURL:
"http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url= " +
encodeURIComponent(
"http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://example.org/tests/dom/xhr/tests/file_XHRResponseURL.text "
),
responseURL:
"http://example.org/tests/dom/xhr/tests/file_XHRResponseURL.text ",
},
{
message:
"request to cross-origin redirects to another cross-origin and finally go to the other cross-origin URL" ,
requestURL:
"http://example.com/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url= " +
encodeURIComponent(
"http://example.org/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://test1.example.com/tests/dom/xhr/tests/file_XHRResponseURL.text "
),
responseURL:
"http://test1.example.com/tests/dom/xhr/tests/file_XHRResponseURL.text ",
},
{
message:
"request URL has fragment" ,
requestURL:
"http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text#fragment ",
responseURL:
"http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text ",
},
// tests for non-http(s) URL
{
message:
"request to data: URL" ,
requestURL:
"data:text/plain,data" ,
responseURL:
"data:text/plain,data" ,
},
{
message:
"request to blob: URL" ,
requestURL: blobURL,
responseURL: blobURL,
},
];
var sequence = createSequentialRequest(parameters,
function (aXHR, aParam) {
ok(aXHR.succeeded,
"assert request succeeded" );
is(aXHR.responseURL, aParam.responseURL, aParam.message);
});
sequence.then(
function () {
URL.revokeObjectURL(blobURL);
});
return sequence;
}
function testFailedResponse() {
info(
"test not to leak responseURL for denied cross-origin request" );
var parameters = [
{
message:
"should be empty for denied cross-origin request without redirect" ,
requestURL:
"http://example.com/tests/dom/xhr/tests/file_XHRResponseURL_nocors.text ",
},
{
message:
"should be empty for denied cross-origin request with redirect" ,
requestURL:
"http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://example.com/tests/dom/xhr/tests/file_XHRResponseURL_nocors.text ",
},
];
var sequence = createSequentialRequest(parameters,
function (aXHR, aParam) {
ok(!aXHR.succeeded,
"assert request failed" );
is(aXHR.responseURL,
"" , aParam.message);
});
return sequence;
}
function testNotToLeakResponseURLWhileDoingRedirects() {
info(
"test not to leak responeseURL while doing redirects" );
if (isInWorker()) {
return testNotToLeakResponseURLWhileDoingRedirectsInWorker();
}
return testNotToLeakResponseURLWhileDoingRedirectsInWindow();
}
function testNotToLeakResponseURLWhileDoingRedirectsInWindow() {
var xhr =
new XMLHttpRequest();
var requestObserver = {
observe() {
is(xhr.readyState, XMLHttpRequest.OPENED,
"assert for XHR state" );
is(
xhr.responseURL,
"" ,
"responseURL should return empty string before HEADERS_RECEIVED"
);
},
};
SpecialPowers.addObserver(
requestObserver,
"specialpowers-http-notify-request"
);
return new Promise(
function (aResolve) {
xhr.open(
"GET" ,
"http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text "
);
xhr.addEventListener(
"load" ,
function () {
SpecialPowers.removeObserver(
requestObserver,
"specialpowers-http-notify-request"
);
aResolve();
});
xhr.addEventListener(
"error" ,
function () {
ok(
false ,
"unexpected request falilure" );
SpecialPowers.removeObserver(
requestObserver,
"specialpowers-http-notify-request"
);
aResolve();
});
xhr.send();
});
}
function testNotToLeakResponseURLWhileDoingRedirectsInWorker() {
var xhr =
new XMLHttpRequest();
var testRedirect =
function (e) {
if (e.data ===
"request" && xhr.readyState === XMLHttpRequest.OPENED) {
is(
xhr.responseURL,
"" ,
"responseURL should return empty string before HEADERS_RECEIVED"
);
}
};
return new Promise(
function (aResolve) {
self.addEventListener(
"message" , testRedirect);
message({ type:
"redirect_test" , status:
"start" });
xhr.open(
"GET" ,
"http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.sjs?url=http://mochi.test:8888/tests/dom/xhr/tests/file_XHRResponseURL.text "
);
xhr.addEventListener(
"load" ,
function () {
self.removeEventListener(
"message" , testRedirect);
message({ type:
"redirect_test" , status:
"end" });
aResolve();
});
xhr.addEventListener(
"error" ,
function () {
ok(
false ,
"unexpected request falilure" );
self.removeEventListener(
"message" , testRedirect);
message({ type:
"redirect_test" , status:
"end" });
aResolve();
});
xhr.send();
});
}
function waitForAllMessagesProcessed() {
return new Promise(
function (aResolve) {
var id = setInterval(
function () {
if (message.ping === message.pong) {
clearInterval(id);
aResolve();
}
}, 100);
});
}
self.addEventListener(
"message" ,
function (aEvent) {
if (aEvent.data ===
"start" ) {
ok(
"responseURL" in
new XMLHttpRequest(),
"XMLHttpRequest should have responseURL attribute"
);
is(
new XMLHttpRequest().responseURL,
"" ,
"responseURL should be empty string if response's url is null"
);
var promise = testSuccessResponse();
promise
.then(
function () {
return testFailedResponse();
})
.then(
function () {
return testNotToLeakResponseURLWhileDoingRedirects();
})
.then(
function () {
return waitForAllMessagesProcessed();
})
.then(
function () {
message(
"done" );
});
}
if (aEvent.data ===
"pong" ) {
++message.pong;
}
});
Messung V0.5 C=90 H=100 G=95
¤ Dauer der Verarbeitung: 0.0 Sekunden
(vorverarbeitet)
¤
*© Formatika GbR, Deutschland