| Index: LayoutTests/http/tests/serviceworker/fetch-access-control.html
|
| diff --git a/LayoutTests/http/tests/serviceworker/fetch-access-control.html b/LayoutTests/http/tests/serviceworker/fetch-access-control.html
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..93598de2bc81ce8b41072d1195918d8b2ce1f9ca
|
| --- /dev/null
|
| +++ b/LayoutTests/http/tests/serviceworker/fetch-access-control.html
|
| @@ -0,0 +1,275 @@
|
| +<!DOCTYPE html>
|
| +<title>Service Worker: fetch()</title>
|
| +<script src="../resources/testharness.js"></script>
|
| +<script src="../resources/testharnessreport.js"></script>
|
| +<script src="resources/test-helpers.js"></script>
|
| +<script>
|
| +var test = async_test('Verify access control of fetch() in a Service Worker');
|
| +test.step(function() {
|
| + window.addEventListener('message', onMessage, false);
|
| + var scope = 'resources/fetch-access-control-iframe.html';
|
| + service_worker_unregister_and_register(
|
| + test, 'resources/fetch-access-control-worker.js', scope).then(test.step_func(onRegister));
|
| +
|
| +
|
| + var kBaseUrl = 'http://127.0.0.1:8000/serviceworker/resources/fetch-access-control.php?';
|
| + var kCorsBaseUrl = 'http://localhost:8000/serviceworker/resources/fetch-access-control.php?';
|
| + var kIframeUrl = 'http://127.0.0.1:8000/serviceworker/resources/fetch-access-control-iframe.html';
|
| +
|
| + var shouldBeResolved = function (url, data) {
|
| + assert_true(data.event != 'rejected' && data.event != 'error', url + ' should be resolved');
|
| + };
|
| + var shouldBeRejected = function (url, data) {
|
| + assert_true(data.event != 'resolved' && data.event != 'error', url + ' should be rejected');
|
| + };
|
| + var shouldThrowError = function (url, data) {
|
| + assert_true(data.event != 'rejected' && data.event != 'resolved', url + ' should throw error');
|
| + };
|
| + var shouldHaveHeader = function (url, name, value, data) {
|
| + if (data.event != 'report') {
|
| + return;
|
| + }
|
| + assert_equals(data.headers[name], value,
|
| + 'the request header to ' + url + ' should have ' + name + '/' + value);
|
| + };
|
| + var shouldNotHaveHeader = function (url, name, data) {
|
| + if (data.event != 'report') {
|
| + return;
|
| + }
|
| + assert_equals(data.headers[name], undefined,
|
| + 'the request header to ' + url + ' should not have ' + name);
|
| + };
|
| + var methodCheck = function (url, method, data) {
|
| + if (data.event != 'report') {
|
| + return;
|
| + }
|
| + assert_equals(data.method, method, 'Method must match');
|
| + };
|
| + var headerCheck = function (url, hasContentLength, hasXServiceWorkerServerHeader, data) {
|
| + if (data.event != 'resolved') {
|
| + return;
|
| + }
|
| + var hasCL = false;
|
| + var hasXSWSH = false;
|
| + for (var i = 0; i < data.headers.length; ++i) {
|
| + if (data.headers[i][0] == 'content-length') {
|
| + hasCL = true;
|
| + } else if (data.headers[i][0] == 'x-serviceworker-serverheader') {
|
| + hasXSWSH = true;
|
| + }
|
| + }
|
| + assert_equals(hasCL, hasContentLength, 'hasContentLength must match');
|
| + assert_equals(hasXSWSH, hasXServiceWorkerServerHeader, 'hasContentLength must match');
|
| + };
|
| + var testTargets = [];
|
| + [kBaseUrl, kCorsBaseUrl].forEach(function(baseUrl) {
|
| + ['same-origin', 'no-cors', 'cors'].forEach(function(mode) {
|
| + var headersTestList = ['', '{}', 'HEADER_WITHOUT_ACA'];
|
| + var ACAOriginTestList = [''];
|
| + if (mode == 'cors') {
|
| + headersTestList.push('HEADER_WITH_ACA');
|
| + ACAOriginTestList.push('*');
|
| + ACAOriginTestList.push('http://127.0.0.1:8000');
|
| + ACAOriginTestList.push('http://127.0.0.1:8000,http://www.example.com');
|
| + ACAOriginTestList.push('http://localhost:8000');
|
| + }
|
| + ['GET', 'POST', 'PUT', 'XXX'].forEach(function(method) {
|
| + headersTestList.forEach(function(headers) {
|
| + ACAOriginTestList.forEach(function(ACAOrigin) {
|
| + var ACAMethodsTestList = [''];
|
| + if (mode == 'cors' && headers == '{}' && ACAOrigin == '*') {
|
| + ACAMethodsTestList.push('*');
|
| + ACAMethodsTestList.push('XXX');
|
| + ACAMethodsTestList.push('PUT');
|
| + ACAMethodsTestList.push('PUT, XXX');
|
| + }
|
| + ACAMethodsTestList.forEach(function(ACAMethods) {
|
| + var ACEHeadersList = [''];
|
| + if (mode == 'cors' && headers == '{}' && ACAOrigin == '*') {
|
| + ACEHeadersList.push('X-ServiceWorker-ServerHeader');
|
| + ACEHeadersList.push('Content-Length, X-ServiceWorker-ServerHeader');
|
| + }
|
| + ACEHeadersList.forEach(function(ACEHeaders){
|
| + var url = baseUrl +
|
| + 'mode=' + mode +
|
| + '&method=' + method;
|
| + if (headers == '{}') {
|
| + url += '&headers=' + headers;
|
| + } else if (headers == 'HEADER_WITHOUT_ACA') {
|
| + url += '&headers={\"X-ServiceWorker-Test\":\ \"test\"}';
|
| + } else if (headers == 'HEADER_WITH_ACA') {
|
| + url += '&headers={\"X-ServiceWorker-Test\":\ \"test\"}';
|
| + url += '&ACAHeaders=x-serviceworker-test';
|
| + }
|
| + if (ACAOrigin) {
|
| + url += '&ACAOrigin=' + ACAOrigin;
|
| + }
|
| + if (ACAMethods) {
|
| + url += '&ACAMethods=' + ACAMethods;
|
| + }
|
| + if (ACEHeaders) {
|
| + url += '&ACEHeaders=' + ACEHeaders;
|
| + }
|
| + var checkFunctions = [];
|
| + var error = false;
|
| + if (method != 'GET' && method != 'POST') {
|
| + if (mode == 'no-cors') {
|
| + error = true;
|
| + }
|
| + }
|
| + var resolve = true;
|
| + if (!error) {
|
| + if (baseUrl == kCorsBaseUrl) {
|
| + if (mode == 'same-origin') {
|
| + resolve = false;
|
| + } else if (mode == 'cors') {
|
| + if (headers == '{}' || headers == 'HEADER_WITH_ACA') {
|
| + if (ACAOrigin == '' ||
|
| + ACAOrigin == 'http://localhost:8000' ||
|
| + ACAOrigin == 'http://127.0.0.1:8000,http://www.example.com') {
|
| + resolve = false;
|
| + }
|
| + } else {
|
| + resolve = false;
|
| + }
|
| + if (method != 'GET' && method != 'POST') {
|
| + if (ACAMethods.indexOf(method) == -1) {
|
| + resolve = false;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| + if (error) {
|
| + checkFunctions.push(shouldThrowError.bind(this, url));
|
| + } else if (resolve) {
|
| + checkFunctions.push(shouldBeResolved.bind(this, url));
|
| + } else {
|
| + checkFunctions.push(shouldBeRejected.bind(this, url));
|
| + }
|
| + var haveHeader = false;
|
| + if (resolve) {
|
| + if (headers == 'HEADER_WITHOUT_ACA' || headers == 'HEADER_WITH_ACA') {
|
| + if (mode == 'same-origin' || mode == 'cors') {
|
| + haveHeader = true;
|
| + }
|
| + }
|
| + }
|
| + if (haveHeader) {
|
| + checkFunctions.push(shouldHaveHeader.bind(
|
| + this, url, 'x-serviceworker-test', 'test'));
|
| + } else {
|
| + checkFunctions.push(shouldNotHaveHeader.bind(
|
| + this, url, 'x-serviceworker-test'));
|
| + }
|
| + if (resolve) {
|
| + var expectedMethod = method;
|
| + if (baseUrl == kBaseUrl) {
|
| + if (mode == 'no-cors' && method != 'POST') {
|
| + expectedMethod = 'GET';
|
| + }
|
| + } else {
|
| + if (mode == 'no-cors' && method != 'POST') {
|
| + expectedMethod = 'GET';
|
| + }
|
| + }
|
| + checkFunctions.push(methodCheck.bind(this, url, expectedMethod));
|
| + var hasContentLength = false;
|
| + var hasXServiceWorkerServerHeader = false;
|
| + if (baseUrl == kBaseUrl) {
|
| + if (mode == 'cors') {
|
| + if (ACEHeaders.indexOf('Content-Length') != -1) {
|
| + hasContentLength = true;
|
| + }
|
| + if (ACEHeaders.indexOf('X-ServiceWorker-ServerHeader') != -1) {
|
| + hasXServiceWorkerServerHeader = true;
|
| + }
|
| + } else {
|
| + hasContentLength = true;
|
| + hasXServiceWorkerServerHeader = true;
|
| + }
|
| + } else {
|
| + if (mode == 'cors') {
|
| + if (ACEHeaders.indexOf('Content-Length') != -1) {
|
| + hasContentLength = true;
|
| + }
|
| + if (ACEHeaders.indexOf('X-ServiceWorker-ServerHeader') != -1) {
|
| + hasXServiceWorkerServerHeader = true;
|
| + }
|
| + }
|
| + }
|
| + checkFunctions.push(headerCheck.bind(this, url, hasContentLength, hasXServiceWorkerServerHeader));
|
| + }
|
| + testTargets.push([url, checkFunctions]);
|
| + });
|
| + });
|
| + });
|
| + });
|
| + });
|
| + });
|
| + });
|
| +
|
| + function onRegister(worker) {
|
| + worker.addEventListener('statechange', test.step_func(onStateChange));
|
| + var messageChannel = new MessageChannel();
|
| + messageChannel.port1.onmessage = onWorkerMessage;
|
| + worker.postMessage({port: messageChannel.port2}, [messageChannel.port2]);
|
| + }
|
| +
|
| + function onWorkerMessage(e) {
|
| + var message = e.data;
|
| + testTargets[message.id][1].forEach(function(checkFunc){
|
| + checkFunc.call(this, message);
|
| + });
|
| + if (message.event == 'resolved') {
|
| + var hasContentLength = false;
|
| + var hasXServiceWorkerServerHeader = false;
|
| + for (var i = 0; i < message.headers.length; ++i) {
|
| + if (message.headers[i][0] == 'content-length') {
|
| + hasContentLength = true;
|
| + } else if (message.headers[i][0] == 'x-serviceworker-serverheader') {
|
| + hasXServiceWorkerServerHeader = true;
|
| + }
|
| + }
|
| + // console.log('resolved type:' + message.data.type +
|
| + // ' hasContentLength:' + hasContentLength +
|
| + // ' hasXServiceWorkerServerHeader:' + hasXServiceWorkerServerHeader);
|
| + } else if (message.event == 'rejected') {
|
| + // console.log('rejected');
|
| + } else if (message.event == 'error') {
|
| + // console.log('error');
|
| + }
|
| + }
|
| +
|
| + var jsonpResultCount = 0;
|
| + function onMessage(e) {
|
| + var message = e.data;
|
| + testTargets[message.id][1].forEach(function(checkFunc){
|
| + checkFunc.call(this, message);
|
| + });
|
| + ++jsonpResultCount;
|
| + // console.log(message.event + ' ' + message.method + ' ' + message.headers['x-serviceworker-test']);
|
| + if (jsonpResultCount == testTargets.length) {
|
| + service_worker_unregister_and_done(test, scope);
|
| + } else {
|
| + loadNext();
|
| + }
|
| + }
|
| + var frameWindow = {};
|
| + function loadNext() {
|
| + // console.log(testTargets[jsonpResultCount][0]);
|
| + frameWindow.postMessage(
|
| + {url: testTargets[jsonpResultCount][0] + '&id=' + jsonpResultCount},
|
| + kIframeUrl);
|
| + }
|
| + function onStateChange(event) {
|
| + if (event.target.state != 'active')
|
| + return;
|
| + with_iframe('resources/fetch-access-control-iframe.html')
|
| + .then(function(frame) {
|
| + frameWindow = frame.contentWindow;
|
| + loadNext();
|
| + });
|
| + }
|
| +});
|
| +</script>
|
|
|