| OLD | NEW |
| 1 // Adapter for testharness.js-style tests with Service Workers | 1 // Adapter for testharness.js-style tests with Service Workers |
| 2 | 2 |
| 3 function service_worker_unregister_and_register(test, url, scope) { | 3 function service_worker_unregister_and_register(test, url, scope) { |
| 4 if (!scope || scope.length == 0) | 4 if (!scope || scope.length == 0) |
| 5 return Promise.reject(new Error('tests must define a scope')); | 5 return Promise.reject(new Error('tests must define a scope')); |
| 6 | 6 |
| 7 var options = { scope: scope }; | 7 var options = { scope: scope }; |
| 8 return service_worker_unregister(test, scope) | 8 return service_worker_unregister(test, scope) |
| 9 .then(function() { | 9 .then(function() { |
| 10 return navigator.serviceWorker.register(url, options); | 10 return navigator.serviceWorker.register(url, options); |
| 11 }) | 11 }) |
| 12 .catch(unreached_rejection(test, | 12 .catch(unreached_rejection(test, |
| 13 'unregister and register should not fail')); | 13 'unregister and register should not fail')); |
| 14 } | 14 } |
| 15 | 15 |
| 16 function service_worker_unregister(test, documentUrl) { | 16 function service_worker_unregister(test, documentUrl) { |
| 17 return navigator.serviceWorker.getRegistration(documentUrl) | 17 return navigator.serviceWorker.getRegistration(documentUrl) |
| 18 .then(function(registration) { | 18 .then(function(registration) { |
| 19 if (registration) | 19 if (registration) |
| 20 return registration.unregister(); | 20 return registration.unregister(); |
| 21 }) | 21 }) |
| 22 .catch(unreached_rejection(test, 'unregister should not fail')); | 22 .catch(unreached_rejection(test, 'unregister should not fail')); |
| 23 } | 23 } |
| 24 | 24 |
| 25 function service_worker_unregister_and_done(test, scope) { | 25 function service_worker_unregister_and_done(test, scope) { |
| 26 return service_worker_unregister(test, scope) | 26 return service_worker_unregister(test, scope) |
| 27 .then(test.done.bind(test)); | 27 .then(test.done.bind(test)); |
| 28 } | 28 } |
| 29 | 29 |
| 30 // Rejection-specific helper that provides more details | 30 // Rejection-specific helper that provides more details |
| 31 function unreached_rejection(test, prefix) { | 31 function unreached_rejection(test, prefix) { |
| 32 return test.step_func(function(error) { | 32 return test.step_func(function(error) { |
| 33 var reason = error.message || error.name || error; | 33 var reason = error.message || error.name || error; |
| 34 var error_prefix = prefix || 'unexpected rejection'; | 34 var error_prefix = prefix || 'unexpected rejection'; |
| 35 assert_unreached(error_prefix + ': ' + reason); | 35 assert_unreached(error_prefix + ': ' + reason); |
| 36 }); | 36 }); |
| 37 } | 37 } |
| 38 | 38 |
| 39 // FIXME: Clean up the iframe when the test completes. | 39 // FIXME: Clean up the iframe when the test completes. |
| 40 function with_iframe(url, f) { | 40 function with_iframe(url, f) { |
| 41 return new Promise(function(resolve, reject) { | 41 return new Promise(function(resolve, reject) { |
| 42 var frame = document.createElement('iframe'); | 42 var frame = document.createElement('iframe'); |
| 43 frame.src = url; | 43 frame.src = url; |
| 44 frame.onload = function() { | 44 frame.onload = function() { |
| 45 if (f) { | 45 if (f) { |
| 46 f(frame); | 46 f(frame); |
| 47 } | 47 } |
| 48 resolve(frame); | 48 resolve(frame); |
| 49 }; | 49 }; |
| 50 document.body.appendChild(frame); | 50 document.body.appendChild(frame); |
| 51 }); | 51 }); |
| 52 } | 52 } |
| 53 | 53 |
| 54 function unload_iframe(iframe) { | 54 function unload_iframe(iframe) { |
| 55 var saw_unload = new Promise(function(resolve) { | 55 var saw_unload = new Promise(function(resolve) { |
| 56 iframe.contentWindow.addEventListener('unload', function() { | 56 iframe.contentWindow.addEventListener('unload', function() { |
| 57 resolve(); | 57 resolve(); |
| 58 }); | 58 }); |
| 59 }); | 59 }); |
| 60 iframe.src = ''; | 60 iframe.src = ''; |
| 61 iframe.remove(); | 61 iframe.remove(); |
| 62 return saw_unload; | 62 return saw_unload; |
| 63 } | 63 } |
| 64 | 64 |
| 65 function normalizeURL(url) { | 65 function normalizeURL(url) { |
| 66 return new URL(url, document.location).toString().replace(/#.*$/, ''); | 66 return new URL(url, document.location).toString().replace(/#.*$/, ''); |
| 67 } | 67 } |
| 68 | 68 |
| 69 function get_newest_worker(registration) { | 69 function get_newest_worker(registration) { |
| 70 if (!registration) { | 70 if (!registration) { |
| 71 return Promise.reject(new Error( | 71 return Promise.reject(new Error( |
| 72 'get_newest_worker must be passed a ServiceWorkerRegistration')); | 72 'get_newest_worker must be passed a ServiceWorkerRegistration')); |
| 73 } | 73 } |
| 74 if (registration.installing) | 74 if (registration.installing) |
| 75 return Promise.resolve(registration.installing); | 75 return Promise.resolve(registration.installing); |
| 76 if (registration.waiting) | 76 if (registration.waiting) |
| 77 return Promise.resolve(registration.waiting); | 77 return Promise.resolve(registration.waiting); |
| 78 if (registration.active) | 78 if (registration.active) |
| 79 return Promise.resolve(registration.active); | 79 return Promise.resolve(registration.active); |
| 80 return Promise.reject(new Error( | 80 return Promise.reject(new Error( |
| 81 'registration must have at least one version')); | 81 'registration must have at least one version')); |
| 82 } | 82 } |
| 83 | 83 |
| 84 function wait_for_update(test, registration) { | 84 function wait_for_update(test, registration) { |
| 85 if (!registration || registration.unregister == undefined) { | 85 if (!registration || registration.unregister == undefined) { |
| 86 return Promise.reject(new Error( | 86 return Promise.reject(new Error( |
| 87 'wait_for_update must be passed a ServiceWorkerRegistration')); | 87 'wait_for_update must be passed a ServiceWorkerRegistration')); |
| 88 } | 88 } |
| 89 | 89 |
| 90 return new Promise(test.step_func(function(resolve) { | 90 return new Promise(test.step_func(function(resolve) { |
| 91 registration.addEventListener('updatefound', test.step_func(function() { | 91 registration.addEventListener('updatefound', test.step_func(function() { |
| 92 resolve(registration.installing); | 92 resolve(registration.installing); |
| 93 })); | 93 })); |
| 94 })); | 94 })); |
| 95 } | 95 } |
| 96 | 96 |
| 97 function wait_for_state(test, worker, state) { | 97 function wait_for_state(test, worker, state) { |
| 98 if (!worker || worker.state == undefined) { | 98 if (!worker || worker.state == undefined) { |
| 99 return Promise.reject(new Error( | 99 return Promise.reject(new Error( |
| 100 'wait_for_state must be passed a ServiceWorker')); | 100 'wait_for_state must be passed a ServiceWorker')); |
| 101 } | 101 } |
| 102 if (worker.state === state) | 102 if (worker.state === state) |
| 103 return Promise.resolve(state); | 103 return Promise.resolve(state); |
| 104 | 104 |
| 105 if (state === 'installing') { | 105 if (state === 'installing') { |
| 106 switch (worker.state) { | 106 switch (worker.state) { |
| 107 case 'installed': | 107 case 'installed': |
| 108 case 'activating': | 108 case 'activating': |
| 109 case 'activated': | 109 case 'activated': |
| 110 case 'redundant': | 110 case 'redundant': |
| 111 return Promise.reject(new Error( | 111 return Promise.reject(new Error( |
| 112 'worker is ' + worker.state + ' but waiting for ' + state)); | 112 'worker is ' + worker.state + ' but waiting for ' + state)); |
| 113 } | 113 } |
| 114 } | 114 } |
| 115 | 115 |
| 116 if (state === 'installed') { | 116 if (state === 'installed') { |
| 117 switch (worker.state) { | 117 switch (worker.state) { |
| 118 case 'activating': | 118 case 'activating': |
| 119 case 'activated': | 119 case 'activated': |
| 120 case 'redundant': | 120 case 'redundant': |
| 121 return Promise.reject(new Error( | 121 return Promise.reject(new Error( |
| 122 'worker is ' + worker.state + ' but waiting for ' + state)); | 122 'worker is ' + worker.state + ' but waiting for ' + state)); |
| 123 } | 123 } |
| 124 } | 124 } |
| 125 | 125 |
| 126 if (state === 'activating') { | 126 if (state === 'activating') { |
| 127 switch (worker.state) { | 127 switch (worker.state) { |
| 128 case 'activated': | 128 case 'activated': |
| 129 case 'redundant': | 129 case 'redundant': |
| 130 return Promise.reject(new Error( | 130 return Promise.reject(new Error( |
| 131 'worker is ' + worker.state + ' but waiting for ' + state)); | 131 'worker is ' + worker.state + ' but waiting for ' + state)); |
| 132 } | 132 } |
| 133 } | 133 } |
| 134 | 134 |
| 135 if (state === 'activated') { | 135 if (state === 'activated') { |
| 136 switch (worker.state) { | 136 switch (worker.state) { |
| 137 case 'redundant': | 137 case 'redundant': |
| 138 return Promise.reject(new Error( | 138 return Promise.reject(new Error( |
| 139 'worker is ' + worker.state + ' but waiting for ' + state)); | 139 'worker is ' + worker.state + ' but waiting for ' + state)); |
| 140 } | 140 } |
| 141 } | 141 } |
| 142 | 142 |
| 143 return new Promise(test.step_func(function(resolve) { | 143 return new Promise(test.step_func(function(resolve) { |
| 144 worker.addEventListener('statechange', test.step_func(function() { | 144 worker.addEventListener('statechange', test.step_func(function() { |
| 145 if (worker.state === state) | 145 if (worker.state === state) |
| 146 resolve(state); | 146 resolve(state); |
| 147 })); | 147 })); |
| 148 })); | 148 })); |
| 149 } | 149 } |
| 150 | 150 |
| 151 function wait_for_activated(test, registration) { | 151 function wait_for_activated(test, registration) { |
| 152 var expected_state = 'activated'; | 152 var expected_state = 'activated'; |
| 153 if (registration.active) | 153 if (registration.active) |
| 154 return wait_for_state(test, registration.active, expected_state); | 154 return wait_for_state(test, registration.active, expected_state); |
| 155 if (registration.waiting) | 155 if (registration.waiting) |
| 156 return wait_for_state(test, registration.waiting, expected_state); | 156 return wait_for_state(test, registration.waiting, expected_state); |
| 157 if (registration.installing) | 157 if (registration.installing) |
| 158 return wait_for_state(test, registration.installing, expected_state); | 158 return wait_for_state(test, registration.installing, expected_state); |
| 159 return Promise.reject( | 159 return Promise.reject( |
| 160 new Error('registration must have at least one version')); | 160 new Error('registration must have at least one version')); |
| 161 } | 161 } |
| 162 | 162 |
| 163 (function() { | 163 (function() { |
| 164 function fetch_tests_from_worker(worker) { | 164 function fetch_tests_from_worker(worker) { |
| 165 return new Promise(function(resolve, reject) { | 165 return new Promise(function(resolve, reject) { |
| 166 var messageChannel = new MessageChannel(); | 166 var messageChannel = new MessageChannel(); |
| 167 messageChannel.port1.addEventListener('message', function(message) { | 167 messageChannel.port1.addEventListener('message', function(message) { |
| 168 if (message.data.type == 'complete') { | 168 if (message.data.type == 'complete') { |
| 169 synthesize_tests(message.data.tests, message.data.status); | 169 synthesize_tests(message.data.tests, message.data.status); |
| 170 resolve(); | 170 resolve(); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 212 .then(function(worker) { return fetch_tests_from_worker(worker); }) | 212 .then(function(worker) { return fetch_tests_from_worker(worker); }) |
| 213 .then(function() { return registration.unregister(); }) | 213 .then(function() { return registration.unregister(); }) |
| 214 .then(function() { test.done(); }) | 214 .then(function() { test.done(); }) |
| 215 .catch(test.step_func(function(e) { throw e; })); | 215 .catch(test.step_func(function(e) { throw e; })); |
| 216 }; | 216 }; |
| 217 | 217 |
| 218 self.service_worker_test = service_worker_test; | 218 self.service_worker_test = service_worker_test; |
| 219 })(); | 219 })(); |
| 220 | 220 |
| 221 function get_host_info() { | 221 function get_host_info() { |
| 222 var ORIGINAL_HOST = '127.0.0.1'; | 222 var ORIGINAL_HOST = '127.0.0.1'; |
| 223 var REMOTE_HOST = 'localhost'; | 223 var REMOTE_HOST = 'localhost'; |
| 224 var UNAUTHENTICATED_HOST = 'example.test'; | 224 var UNAUTHENTICATED_HOST = 'example.test'; |
| 225 var HTTP_PORT = 8000; | 225 var HTTP_PORT = 8000; |
| 226 var HTTPS_PORT = 8443; | 226 var HTTPS_PORT = 8443; |
| 227 try { | 227 try { |
| 228 // In W3C test, we can get the hostname and port number in config.json | 228 // In W3C test, we can get the hostname and port number in config.json |
| 229 // using wptserve's built-in pipe. | 229 // using wptserve's built-in pipe. |
| 230 // http://wptserve.readthedocs.org/en/latest/pipes.html#built-in-pipes | 230 // http://wptserve.readthedocs.org/en/latest/pipes.html#built-in-pipes |
| 231 HTTP_PORT = eval('{{ports[http][0]}}'); | 231 HTTP_PORT = eval('{{ports[http][0]}}'); |
| 232 HTTPS_PORT = eval('{{ports[https][0]}}'); | 232 HTTPS_PORT = eval('{{ports[https][0]}}'); |
| 233 ORIGINAL_HOST = eval('\'{{host}}\''); | 233 ORIGINAL_HOST = eval('\'{{host}}\''); |
| 234 REMOTE_HOST = 'www1.' + ORIGINAL_HOST; | 234 REMOTE_HOST = 'www1.' + ORIGINAL_HOST; |
| 235 } catch(e) { | 235 } catch (e) { |
| 236 } | 236 } |
| 237 return { | 237 return { |
| 238 HTTP_ORIGIN: 'http://' + ORIGINAL_HOST + ':' + HTTP_PORT, | 238 HTTP_ORIGIN: 'http://' + ORIGINAL_HOST + ':' + HTTP_PORT, |
| 239 HTTPS_ORIGIN: 'https://' + ORIGINAL_HOST + ':' + HTTPS_PORT, | 239 HTTPS_ORIGIN: 'https://' + ORIGINAL_HOST + ':' + HTTPS_PORT, |
| 240 HTTP_REMOTE_ORIGIN: 'http://' + REMOTE_HOST + ':' + HTTP_PORT, | 240 HTTP_REMOTE_ORIGIN: 'http://' + REMOTE_HOST + ':' + HTTP_PORT, |
| 241 HTTPS_REMOTE_ORIGIN: 'https://' + REMOTE_HOST + ':' + HTTPS_PORT, | 241 HTTPS_REMOTE_ORIGIN: 'https://' + REMOTE_HOST + ':' + HTTPS_PORT, |
| 242 UNAUTHENTICATED_ORIGIN: 'http://' + UNAUTHENTICATED_HOST + ':' + HTTP_PO
RT | 242 UNAUTHENTICATED_ORIGIN: 'http://' + UNAUTHENTICATED_HOST + ':' + HTTP_PORT |
| 243 }; | 243 }; |
| 244 } | 244 } |
| 245 | 245 |
| 246 function base_path() { | 246 function base_path() { |
| 247 return location.pathname.replace(/\/[^\/]*$/, '/'); | 247 return location.pathname.replace(/\/[^\/]*$/, '/'); |
| 248 } | 248 } |
| 249 | 249 |
| 250 function test_login(test, origin, username, password) { | 250 function test_login(test, origin, username, password) { |
| 251 return new Promise(function(resolve, reject) { | 251 return new Promise(function(resolve, reject) { |
| 252 with_iframe( | 252 with_iframe( |
| 253 origin + base_path() + | 253 origin + base_path() + |
| 254 'resources/fetch-access-control-login.html') | 254 'resources/fetch-access-control-login.html') |
| 255 .then(test.step_func(function(frame) { | 255 .then(test.step_func(function(frame) { |
| 256 var channel = new MessageChannel(); | 256 var channel = new MessageChannel(); |
| 257 channel.port1.onmessage = test.step_func(function() { | 257 channel.port1.onmessage = test.step_func(function() { |
| 258 unload_iframe(frame).catch(function() {}); | 258 unload_iframe(frame).catch(function() {}); |
| 259 resolve(); | 259 resolve(); |
| 260 }); | 260 }); |
| 261 frame.contentWindow.postMessage( | 261 frame.contentWindow.postMessage( |
| 262 {username: username, password: password}, | 262 {username: username, password: password}, |
| 263 [channel.port2], origin); | 263 [channel.port2], origin); |
| 264 })); | 264 })); |
| 265 }); | 265 }); |
| 266 } | 266 } |
| OLD | NEW |