Update WPT service workers test up to 0df7c68
authoryouenn@apple.com <youenn@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 12 Jun 2019 17:47:27 +0000 (17:47 +0000)
committeryouenn@apple.com <youenn@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 12 Jun 2019 17:47:27 +0000 (17:47 +0000)
https://bugs.webkit.org/show_bug.cgi?id=198720

Reviewed by Eric Carlson.

LayoutTests/imported/w3c:

* web-platform-tests/service-workers: Resynced.

LayoutTests:

* TestExpectations:
* tests-options.json:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@246363 268f45cc-cd09-0410-ab3c-d52691b4dbfc

227 files changed:
LayoutTests/ChangeLog
LayoutTests/TestExpectations
LayoutTests/imported/w3c/ChangeLog
LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/script-tests/cache-match.js
LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/serviceworker/cache-match.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/window/cache-match.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/service-workers/cache-storage/worker/cache-match.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/Service-Worker-Allowed-header.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/Service-Worker-Allowed-header.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/postmessage.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/unregister.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/ServiceWorkerGlobalScope/update.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/about-blank-replacement.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/activate-event-after-install-state-change.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/appcache-ordering-main.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/claim-fetch-with-appcache.https-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/claim-fetch-with-appcache.https.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/claim-fetch.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/claim-not-using-registration.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/claim-shared-worker-fetch.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/claim-using-registration.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/clients-get-resultingClientId.https-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/clients-get-resultingClientId.https.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/clients-matchall-client-types.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/clients-matchall-order.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/controller-on-reload.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/data-transfer-files.https-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/data-transfer-files.https.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/extendable-event-async-waituntil.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/extendable-event-async-waituntil.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-canvas-tainting-video-cache.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-canvas-tainting-video.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-csp.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-event-after-navigation-within-page.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-event-async-respond-with.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-event-async-respond-with.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-event-network-error.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-event-referrer-policy.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-event-referrer-policy.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-event-respond-with-argument.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-event-respond-with-body-loaded-in-chunk.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-event-respond-with-stops-propagation.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-event-throws-after-respond-with.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-request-css-base-url.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-request-css-base-url.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/fetch-request-redirect.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/getregistration.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/getregistration.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/import-scripts-resource-map.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/import-scripts-resource-map.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/interfaces-window.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/multiple-update.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/navigation-redirect.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/performance-timeline.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/postmessage-to-client-message-queue.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/postmessage.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/postmessage.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/ready.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/ready.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/register-default-scope.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/register-wait-forever-in-install-worker.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/registration-end-to-end.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/registration-mime-types.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/registration-schedule-job.https-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/registration-schedule-job.https.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/registration-updateviacache.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/registration-updateviacache.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resource-timing.sub.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/appcache-ordering.manifest
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/claim-worker.js
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/extendable-event-async-waituntil.js
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/fetch-event-async-respond-with-worker.js
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/fetch-event-network-fallback-worker.js
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/fetch-request-css-base-url-iframe.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/fetch-request-css-base-url-worker.js
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/get-resultingClientId-worker.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/import-relative.xsl [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/import-scripts-diff-resource-map-worker.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/import-scripts-get.py [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/postmessage-echo-worker.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/service-worker-csp-worker.py
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/test-helpers.sub.js
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/test-request-headers-worker.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/test-request-headers-worker.py [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/update-during-installation-worker.js
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/update-during-installation-worker.py [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/w3c-import.log
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/worker-interception-iframe.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/worker-load-interceptor.js
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/xhr-iframe.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/xhr-response-url-worker.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/xsl-base-url-iframe.xml [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/xsl-base-url-worker.js [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/xslt-pass.xsl [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/service-worker-csp-connect.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/service-worker-csp-default.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/service-worker-csp-script.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/serviceworker-message-event-historical.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/shared-worker-controlled.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/skip-waiting-installed.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/skip-waiting-using-registration.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/skip-waiting-without-using-registration.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/skip-waiting.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/svg-target-reftest.https-expected.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/svg-target-reftest.https.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/unregister-then-register-new-script.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/unregister-then-register-new-script.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/unregister-then-register.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/unregister-then-register.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-after-navigation-redirect.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-after-oneday.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-bytecheck.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-no-cache-request-headers.https-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-no-cache-request-headers.https.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-not-allowed.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-registration-with-type.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-registration-with-type.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/w3c-import.log
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/websocket.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/windowclient-navigate.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/worker-interception.https-expected.txt
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/worker-interception.https.html
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/xhr-response-url.https-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/xhr-response-url.https.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/xsl-base-url.https-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/xsl-base-url.https.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.1-service-worker-obj-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.1-service-worker-obj.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.1.1-service-worker-scope-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.1.1-service-worker-scope.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.1.2-service-worker-url-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.1.2-service-worker-url.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.1.3-service-worker-state-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.1.3-service-worker-state.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.1.4-service-worker-on-state-change-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.1.4-service-worker-on-state-change.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2-navigator-service-worker-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2-navigator-service-worker.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.1-navigator-service-worker-installing-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.1-navigator-service-worker-installing.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.10-navigator-service-worker-oncontrollerchange-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.10-navigator-service-worker-oncontrollerchange.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.11-navigator-service-worker-onreloadpage-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.11-navigator-service-worker-onreloadpage.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.12-navigator-service-worker-onerror-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.12-navigator-service-worker-onerror.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.2-navigator-service-worker-waiting-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.2-navigator-service-worker-waiting.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.3-navigator-service-worker-active-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.3-navigator-service-worker-active.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.4-navigator-service-worker-controller-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.4-navigator-service-worker-controller.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.5-navigator-service-worker-ready-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.5-navigator-service-worker-ready.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.6-navigator-service-worker-getAll-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.6-navigator-service-worker-getAll.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.7-navigator-service-worker-register-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.7-navigator-service-worker-register.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.8-navigator-service-worker-unregister-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.8-navigator-service-worker-unregister.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.9-navigator-service-worker-onupdatefound-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-3.2.9-navigator-service-worker-onupdatefound.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.1-service-worker-global-scope-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.1-service-worker-global-scope.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.1.1-service-worker-global-scope-caches-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.1.1-service-worker-global-scope-caches.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.1.2-service-worker-global-scope-clients-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.1.2-service-worker-global-scope-clients.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.1.3-service-worker-global-scope-scope-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.1.3-service-worker-global-scope-scope.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.1.4-service-worker-global-scope-fetch-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.1.4-service-worker-global-scope-fetch.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.1.5-service-worker-global-scope-update-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.1.5-service-worker-global-scope-update.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.1.6-service-worker-global-scope-unregister-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.1.6-service-worker-global-scope-unregister.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.1.7-service-worker-global-scope-onmessage-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.1.7-service-worker-global-scope-onmessage.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.2-client-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.2-client.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.3-service-worker-clients-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.3-service-worker-clients.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.3.1-get-serviced-method-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.3.1-get-serviced-method.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.3.2-reloadall-method-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.3.2-reloadall-method.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.4-request-objects-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.4-request-objects.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.5-response-objects-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.5-response-objects.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.5.2-response-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.5.2-response.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.5.4-opaque-response-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.5.4-opaque-response.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.6-cache-objects-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.6-cache-objects.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.6.1-cache-lifetimes-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.6.1-cache-lifetimes.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.6.2-cache-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.6.2-cache.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.6.3-cache-storage-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.6.3-cache-storage.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.7.1-install-phase-event-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.7.1-install-phase-event.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.7.1.1-wait-until-method-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.7.1.1-wait-until-method.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.7.2-install-event-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.7.2-install-event.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.7.2.1-install-event-section-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.7.2.1-install-event-section.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.7.2.2-replace-method-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.7.2.2-replace-method.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.7.3-activate-event-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.7.3-activate-event.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.7.4.1-fetch-event-section-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.7.4.1-fetch-event-section.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.7.4.2-respond-with-method-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.7.4.2-respond-with-method.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.7.4.3-default-method-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.7.4.3-default-method.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.7.4.4-is-reload-attribute-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-4.7.4.4-is-reload-attribute.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-5.1-origin-relativity-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-5.1-origin-relativity.html [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-5.2-cross-origin-resources-expected.txt [new file with mode: 0644]
LayoutTests/imported/w3c/web-platform-tests/service-workers/stub-5.2-cross-origin-resources.html [new file with mode: 0644]
LayoutTests/tests-options.json

index 7d2522e..7c56f5c 100644 (file)
@@ -1,3 +1,13 @@
+2019-06-12  Youenn Fablet  <youenn@apple.com>
+
+        Update WPT service workers test up to 0df7c68
+        https://bugs.webkit.org/show_bug.cgi?id=198720
+
+        Reviewed by Eric Carlson.
+
+        * TestExpectations:
+        * tests-options.json:
+
 2019-06-12  Truitt Savell  <tsavell@apple.com>
 
         Unreviewed, rolling out r246350.
index 71b58f0..70c85b2 100644 (file)
@@ -2452,6 +2452,7 @@ webkit.org/b/179851 imported/w3c/web-platform-tests/html/browsers/offline/manife
 webkit.org/b/182177 imported/w3c/web-platform-tests/html/semantics/scripting-1/the-script-element/module/errorhandling.html [ Pass Failure ]
 
 webkit.org/b/182311 imported/w3c/web-platform-tests/service-workers/service-worker/navigation-redirect.https.html [ Skip ]
+imported/w3c/web-platform-tests/service-workers/service-worker/svg-target-reftest.https.html [ ImageOnlyFailure ]
 
 webkit.org/b/90980 fast/forms/textarea/textarea-state-restore.html [ Pass Timeout ]
 
index ddcfdb4..9534b3f 100644 (file)
@@ -1,3 +1,12 @@
+2019-06-12  Youenn Fablet  <youenn@apple.com>
+
+        Update WPT service workers test up to 0df7c68
+        https://bugs.webkit.org/show_bug.cgi?id=198720
+
+        Reviewed by Eric Carlson.
+
+        * web-platform-tests/service-workers: Resynced.
+
 2019-06-11  Devin Rousso  <drousso@apple.com>
 
         Sort the computed styles list
index ba359fe..8bf7fda 100644 (file)
@@ -144,6 +144,25 @@ cache_test(function(cache) {
         });
   }, 'Cache.match supports ignoreVary');
 
+cache_test(function(cache) {
+    let has_cache_name = false;
+    const opts = {
+      get cacheName() {
+        has_cache_name = true;
+        return undefined;
+      }
+    };
+    return self.caches.open('foo')
+      .then(function() {
+          return cache.match('bar', opts);
+        })
+      .then(function() {
+          assert_false(has_cache_name,
+                       'Cache.match does not support cacheName option ' +
+                       'which was removed in CacheQueryOptions.');
+        });
+  }, 'Cache.match does not support cacheName option');
+
 prepopulated_cache_test(simple_entries, function(cache, entries) {
     return cache.match(entries.cat.request.url + '#mouse')
       .then(function(result) {
@@ -337,4 +356,62 @@ cache_test(async (cache) => {
     assert_equals(headers.get('set-cookie'), null);
   }, 'cors-exposed header should be stored correctly.');
 
+cache_test(async (cache) => {
+    // A URL that should load a resource with a known mime type.
+    const url = '/service-workers/cache-storage/resources/blank.html';
+    const expected_mime_type = 'text/html';
+
+    // Verify we get the expected mime type from the network.  Note,
+    // we cannot use an exact match here since some browsers append
+    // character encoding information to the blob.type value.
+    const net_response = await fetch(url);
+    const net_mime_type = (await net_response.blob()).type;
+    assert_true(net_mime_type.includes(expected_mime_type),
+                'network response should include the expected mime type');
+
+    // Verify we get the exact same mime type when reading the same
+    // URL resource back out of the cache.
+    await cache.add(url);
+    const cache_response = await cache.match(url);
+    const cache_mime_type = (await cache_response.blob()).type;
+    assert_equals(cache_mime_type, net_mime_type,
+                  'network and cache response mime types should match');
+  }, 'MIME type should be set from content-header correctly.');
+
+cache_test(async (cache) => {
+    const url = '/dummy';
+    const original_type = 'text/html';
+    const init_with_headers = {
+      headers: {
+        'content-type': original_type
+      }
+    }
+
+    // Verify constructing a synthetic response with a content-type header
+    // gets the correct mime type.
+    const response = new Response('hello world', init_with_headers);
+    const original_response_type = (await response.blob()).type;
+    assert_true(original_response_type.includes(original_type),
+                'original response should include the expected mime type');
+
+    // Verify overwriting the content-type header does not change the mime
+    // type.  It should be fixed at Response construction time.
+    const overwritten_response = new Response('hello world', init_with_headers);
+    overwritten_response.headers.set('content-type', 'text/plain');
+    const overwritten_response_type = (await overwritten_response.blob()).type;
+    assert_equals(overwritten_response_type, original_response_type,
+                  'original and overwritten response mime types should match');
+
+    // Verify the Response read from Cache uses the original mime type
+    // computed when it was first constructed.
+    const tmp = new Response('hello world', init_with_headers);
+    tmp.headers.set('content-type', 'text/plain');
+    await cache.put(url, tmp);
+    const cache_response = await cache.match(url);
+    const cache_mime_type = (await cache_response.blob()).type;
+    assert_equals(cache_mime_type, original_response_type,
+                  'original and cached overwritten response mime types ' +
+                  'should match');
+  }, 'MIME type should be frozen at response construction.');
+
 done();
index 53a4a1e..76ba4e5 100644 (file)
@@ -10,6 +10,7 @@ PASS Cache.match with ignoreSearch option (request with no search parameters)
 PASS Cache.match with ignoreSearch option (request with search parameter) 
 PASS Cache.match supports ignoreMethod 
 PASS Cache.match supports ignoreVary 
+FAIL Cache.match does not support cacheName option assert_false: Cache.match does not support cacheName option which was removed in CacheQueryOptions. expected false got true
 PASS Cache.match with URL containing fragment 
 PASS Cache.match with string fragment "http" as query 
 PASS Cache.match with responses containing "Vary" header 
@@ -21,4 +22,6 @@ PASS Cache.match with a non-2xx Response
 PASS Cache.match with a network error Response 
 PASS Cache produces large Responses that can be cloned and read correctly. 
 FAIL cors-exposed header should be stored correctly. assert_equals: expected (string) "bar" but got (object) null
+FAIL MIME type should be set from content-header correctly. assert_equals: network and cache response mime types should match expected "text/html" but got ""
+FAIL MIME type should be frozen at response construction. assert_equals: original and cached overwritten response mime types should match expected "text/html" but got ""
 
index dff99fa..564096a 100644 (file)
@@ -9,6 +9,7 @@ PASS Cache.match with ignoreSearch option (request with no search parameters)
 PASS Cache.match with ignoreSearch option (request with search parameter) 
 PASS Cache.match supports ignoreMethod 
 PASS Cache.match supports ignoreVary 
+FAIL Cache.match does not support cacheName option assert_false: Cache.match does not support cacheName option which was removed in CacheQueryOptions. expected false got true
 PASS Cache.match with URL containing fragment 
 PASS Cache.match with string fragment "http" as query 
 PASS Cache.match with responses containing "Vary" header 
@@ -20,4 +21,6 @@ PASS Cache.match with a non-2xx Response
 PASS Cache.match with a network error Response 
 PASS Cache produces large Responses that can be cloned and read correctly. 
 FAIL cors-exposed header should be stored correctly. assert_equals: expected (string) "bar" but got (object) null
+FAIL MIME type should be set from content-header correctly. assert_equals: network and cache response mime types should match expected "text/html" but got ""
+FAIL MIME type should be frozen at response construction. assert_equals: original and cached overwritten response mime types should match expected "text/html" but got ""
 
index dff99fa..564096a 100644 (file)
@@ -9,6 +9,7 @@ PASS Cache.match with ignoreSearch option (request with no search parameters)
 PASS Cache.match with ignoreSearch option (request with search parameter) 
 PASS Cache.match supports ignoreMethod 
 PASS Cache.match supports ignoreVary 
+FAIL Cache.match does not support cacheName option assert_false: Cache.match does not support cacheName option which was removed in CacheQueryOptions. expected false got true
 PASS Cache.match with URL containing fragment 
 PASS Cache.match with string fragment "http" as query 
 PASS Cache.match with responses containing "Vary" header 
@@ -20,4 +21,6 @@ PASS Cache.match with a non-2xx Response
 PASS Cache.match with a network error Response 
 PASS Cache produces large Responses that can be cloned and read correctly. 
 FAIL cors-exposed header should be stored correctly. assert_equals: expected (string) "bar" but got (object) null
+FAIL MIME type should be set from content-header correctly. assert_equals: network and cache response mime types should match expected "text/html" but got ""
+FAIL MIME type should be frozen at response construction. assert_equals: original and cached overwritten response mime types should match expected "text/html" but got ""
 
index e1759e0..618b92d 100644 (file)
@@ -4,7 +4,7 @@ PASS Registering within Service-Worker-Allowed path (absolute URL)
 PASS Registering within Service-Worker-Allowed path with parent reference 
 PASS Registering outside Service-Worker-Allowed path 
 PASS Registering outside Service-Worker-Allowed path with parent reference 
-PASS Service-Worker-Allowed is cross-origin to script, registering on a normally allowed scope 
-PASS Service-Worker-Allowed is cross-origin to script, registering on a normally disallowed scope 
+FAIL Service-Worker-Allowed is cross-origin to script, registering on a normally allowed scope assert_unreached: Should have rejected: undefined Reached unreachable code
+FAIL Service-Worker-Allowed is cross-origin to script, registering on a normally disallowed scope assert_unreached: Should have rejected: undefined Reached unreachable code
 PASS Service-Worker-Allowed is cross-origin to page, same-origin to script 
 
index 316067c..9045c0f 100644 (file)
@@ -17,88 +17,72 @@ function build_script_url(allowed_path, origin) {
   return `${url}?pipe=header(Service-Worker-Allowed,${allowed_path})`;
 }
 
-promise_test(async t => {
-  const script = build_script_url('/allowed-path');
-  const scope = '/allowed-path';
-  const registration = await service_worker_unregister_and_register(
-      t, script, scope);
-  assert_true(registration instanceof ServiceWorkerRegistration, 'registered');
-  assert_equals(registration.scope, normalizeURL(scope));
-  return registration.unregister();
-}, 'Registering within Service-Worker-Allowed path');
+// register_test is a promise_test that registers a service worker.
+function register_test(script, scope, description) {
+  promise_test(async t => {
+    t.add_cleanup(() => {
+      return service_worker_unregister(t, scope);
+    });
 
-promise_test(async t => {
-  const script = build_script_url(new URL('/allowed-path', document.location));
-  const scope = '/allowed-path';
-  const registration = await service_worker_unregister_and_register(
-      t, script, scope);
-  assert_true(registration instanceof ServiceWorkerRegistration, 'registered');
-  assert_equals(registration.scope, normalizeURL(scope));
-  return registration.unregister();
-}, 'Registering within Service-Worker-Allowed path (absolute URL)');
+    const registration = await service_worker_unregister_and_register(
+        t, script, scope);
+    assert_true(registration instanceof ServiceWorkerRegistration, 'registered');
+    assert_equals(registration.scope, normalizeURL(scope));
+  }, description);
+}
+
+// register_fail_test is like register_test but expects a SecurityError.
+function register_fail_test(script, scope, description) {
+  promise_test(async t => {
+    t.add_cleanup(() => {
+      return service_worker_unregister(t, scope);
+    });
+
+    await service_worker_unregister(t, scope);
+    await promise_rejects(t,
+                          'SecurityError',
+                          navigator.serviceWorker.register(script, {scope}));
+  }, description);
+}
+
+register_test(
+    build_script_url('/allowed-path'),
+    '/allowed-path',
+    'Registering within Service-Worker-Allowed path');
 
-promise_test(async t => {
-  const script = build_script_url('../allowed-path-with-parent');
-  const scope = 'allowed-path-with-parent';
-  const registration = await service_worker_unregister_and_register(
-      t, script, scope);
-  assert_true(registration instanceof ServiceWorkerRegistration, 'registered');
-  assert_equals(registration.scope, normalizeURL(scope));
-  return registration.unregister();
-}, 'Registering within Service-Worker-Allowed path with parent reference');
+register_test(
+    build_script_url(new URL('/allowed-path', document.location)),
+    '/allowed-path',
+    'Registering within Service-Worker-Allowed path (absolute URL)');
 
-promise_test(async t => {
-  const script = build_script_url('../allowed-path');
-  const scope = '/disallowed-path';
-  await service_worker_unregister(t, scope);
-  return promise_rejects(t,
-      'SecurityError',
-      navigator.serviceWorker.register(script, {scope: scope}),
-      'register should fail');
-}, 'Registering outside Service-Worker-Allowed path');
+register_test(
+    build_script_url('../allowed-path-with-parent'),
+    'allowed-path-with-parent',
+    'Registering within Service-Worker-Allowed path with parent reference');
 
-promise_test(async t => {
-  const script = build_script_url('../allowed-path-with-parent');
-  const scope = '/allowed-path-with-parent';
-  await service_worker_unregister(t, scope);
-  return promise_rejects(t,
-      'SecurityError',
-      navigator.serviceWorker.register(script, {scope: scope}),
-      'register should fail');
-}, 'Registering outside Service-Worker-Allowed path with parent reference');
+register_fail_test(
+    build_script_url('../allowed-path'),
+    '/disallowed-path',
+    'Registering outside Service-Worker-Allowed path'),
 
-promise_test(async t => {
-  const script = build_script_url(
-      host_info.HTTPS_REMOTE_ORIGIN + '/');
-  const scope = 'resources/this-scope-is-normally-allowed'
-  const registration = await service_worker_unregister_and_register(
-      t, script, scope);
-  assert_true(registration instanceof ServiceWorkerRegistration, 'registered');
-  assert_equals(registration.scope, normalizeURL(scope));
-  return registration.unregister();
-}, 'Service-Worker-Allowed is cross-origin to script, registering on a normally allowed scope');
+register_fail_test(
+    build_script_url('../allowed-path-with-parent'),
+    '/allowed-path-with-parent',
+    'Registering outside Service-Worker-Allowed path with parent reference');
 
-promise_test(async t => {
-  const script = build_script_url(
-      host_info.HTTPS_REMOTE_ORIGIN + '/');
-  const scope = '/this-scope-is-normally-disallowed'
-  const registration = await service_worker_unregister_and_register(
-      t, script, scope);
-  assert_true(registration instanceof ServiceWorkerRegistration, 'registered');
-  assert_equals(registration.scope, normalizeURL(scope));
-  return registration.unregister();
-}, 'Service-Worker-Allowed is cross-origin to script, registering on a normally disallowed scope');
+register_fail_test(
+    build_script_url(host_info.HTTPS_REMOTE_ORIGIN + '/'),
+    'resources/this-scope-is-normally-allowed',
+    'Service-Worker-Allowed is cross-origin to script, registering on a normally allowed scope');
 
-promise_test(async t => {
-  const script = build_script_url(
-      host_info.HTTPS_REMOTE_ORIGIN + '/cross-origin/',
-      host_info.HTTPS_REMOTE_ORIGIN);
-  const scope = '/cross-origin/';
-  await service_worker_unregister(t, scope);
-  return promise_rejects(t,
-      'SecurityError',
-      navigator.serviceWorker.register(script, {scope: scope}),
-      'register should fail');
-}, 'Service-Worker-Allowed is cross-origin to page, same-origin to script');
+register_fail_test(
+    build_script_url(host_info.HTTPS_REMOTE_ORIGIN + '/'),
+    '/this-scope-is-normally-disallowed',
+    'Service-Worker-Allowed is cross-origin to script, registering on a normally disallowed scope');
 
+register_fail_test(
+    build_script_url(host_info.HTTPS_REMOTE_ORIGIN + '/cross-origin/',
+                     host_info.HTTPS_REMOTE_ORIGIN),
+    '/cross-origin/',
+    'Service-Worker-Allowed is cross-origin to page, same-origin to script');
 </script>
index 17046ee..99dedeb 100644 (file)
@@ -12,7 +12,12 @@ promise_test(function(t) {
 
     return service_worker_unregister_and_register(t, script, scope)
       .then(function(r) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           registration = r;
+
           return wait_for_state(t, registration.installing, 'activated');
         })
       .then(function() {
@@ -28,7 +33,6 @@ promise_test(function(t) {
         })
       .then(function(result) {
           assert_equals(result, 'OK');
-          return service_worker_unregister_and_done(t, scope);
         });
   }, 'Post loopback messages');
 
@@ -41,6 +45,10 @@ promise_test(function(t) {
 
     return service_worker_unregister_and_register(t, script1, scope)
       .then(function(r) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           registration = r;
           return wait_for_state(t, registration.installing, 'activated');
         })
@@ -69,7 +77,6 @@ promise_test(function(t) {
       .then(function(result) {
           assert_equals(result, 'OK');
           frame.remove();
-          return service_worker_unregister_and_done(t, scope);
         });
   }, 'Post messages among service workers');
 
index 3133091..1a124d7 100644 (file)
@@ -11,6 +11,10 @@ promise_test(function(t) {
 
     return service_worker_unregister_and_register(t, script, scope)
       .then(function(registration) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return wait_for_state(t, registration.installing, 'redundant');
         })
       .then(function() {
@@ -21,7 +25,6 @@ promise_test(function(t) {
             result,
             undefined,
             'After unregister(), the registration should not found');
-          return service_worker_unregister_and_done(t, scope);
         });
   }, 'Unregister on script evaluation');
 
@@ -31,6 +34,10 @@ promise_test(function(t) {
 
     return service_worker_unregister_and_register(t, script, scope)
       .then(function(registration) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return wait_for_state(t, registration.installing, 'redundant');
         })
       .then(function() {
@@ -41,7 +48,6 @@ promise_test(function(t) {
             result,
             undefined,
             'After unregister(), the registration should not found');
-          return service_worker_unregister_and_done(t, scope);
         });
   }, 'Unregister on installing event');
 
@@ -51,6 +57,10 @@ promise_test(function(t) {
 
     return service_worker_unregister_and_register(t, script, scope)
       .then(function(registration) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return wait_for_state(t, registration.installing, 'redundant');
         })
       .then(function() {
@@ -61,7 +71,6 @@ promise_test(function(t) {
             result,
             undefined,
             'After unregister(), the registration should not found');
-          return service_worker_unregister_and_done(t, scope);
         });
   }, 'Unregister on activate event');
 
@@ -74,6 +83,10 @@ promise_test(function(t) {
 
     return service_worker_unregister_and_register(t, script, scope)
       .then(function(registration) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return wait_for_state(t, registration.installing, 'activated');
         })
       .then(function() { return with_iframe(scope); })
@@ -120,7 +133,6 @@ promise_test(function(t) {
 
           frame.remove();
           new_frame.remove();
-          return service_worker_unregister_and_done(t, scope);
         })
   }, 'Unregister controlling service worker');
 
index a9285a1..a7dde22 100644 (file)
@@ -13,6 +13,10 @@ promise_test(function(t) {
 
     return service_worker_unregister_and_register(t, script, scope)
       .then(function(r) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           registration = r;
           return wait_for_state(t, registration.installing, 'activated');
         })
@@ -38,7 +42,6 @@ promise_test(function(t) {
               'events seen by the worker');
           frame1.remove();
           frame2.remove();
-          return service_worker_unregister_and_done(t, scope);
         });
   }, 'Update a registration on ServiceWorkerGlobalScope');
 
index e1fefaf..b6efe3e 100644 (file)
@@ -60,6 +60,9 @@ function getClientIdByURL(worker, url) {
 
 async function doAsyncTest(t, scope) {
   let reg = await service_worker_unregister_and_register(t, worker, scope);
+
+  t.add_cleanup(() => service_worker_unregister(t, scope));
+
   await wait_for_state(t, reg.installing, 'activated');
 
   // Load the scope as a frame.  We expect this in turn to have a nested
@@ -96,7 +99,6 @@ async function doAsyncTest(t, scope) {
   }
 
   frame.remove();
-  await service_worker_unregister_and_done(t, scope);
 }
 
 promise_test(async function(t) {
@@ -126,6 +128,9 @@ promise_test(async function(t) {
   const scope = 'resources/about-blank-replacement-uncontrolled-nested-frame.html';
 
   let reg = await service_worker_unregister_and_register(t, worker, scope);
+
+  t.add_cleanup(() => service_worker_unregister(t, scope));
+
   await wait_for_state(t, reg.installing, 'activated');
 
   // Load the scope as a frame.  We expect this in turn to have a nested
@@ -147,7 +152,6 @@ promise_test(async function(t) {
                 'nested frame should not be controlled');
 
   frame.remove();
-  await service_worker_unregister_and_done(t, scope);
 }, 'Initial about:blank is controlled, exposed to clients.matchAll(), and ' +
    'final Client is not controlled by a service worker.');
 
index 57fccf1..016a52c 100644 (file)
@@ -11,6 +11,10 @@ promise_test(function(t) {
 
   return service_worker_unregister_and_register(t, script, scope)
     .then(function(registration) {
+        t.add_cleanup(function() {
+            return service_worker_unregister(t, scope);
+          });
+
         var sw = registration.installing;
 
         return new Promise(t.step_func(function(resolve) {
@@ -23,9 +27,6 @@ promise_test(function(t) {
           });
         }));
       })
-    .then(function() {
-        return service_worker_unregister_and_done(t, scope);
-      })
     .catch(unreached_rejection(t));
   }, 'installed event should be fired before activating service worker');
 
index 921dae0..a86671c 100644 (file)
@@ -5,7 +5,6 @@
 <body>
 <script>
 
-var INSTALL_APPCACHE_URL = "resources/appcache-ordering.install.html";
 var IS_APPCACHED_URL = "resources/appcache-ordering.is-appcached.html";
 var SERVICE_WORKER_SCOPE = "resources/appcache-ordering";
 var SERVICE_WORKER_SCRIPT = "resources/empty-worker.js";
@@ -15,31 +14,6 @@ var reject_install_appcache = undefined;
 
 var frames = [];
 
-// Called by the INSTALL_APPCACHE_URL child frame.
-function notify_appcache_installed(success) {
-  if (success)
-    resolve_install_appcache();
-  else
-    reject_install_appcache();
-}
-
-function install_appcache() {
-  return new Promise(function(resolve, reject) {
-      var frame = document.createElement('iframe');
-      frames.push(frame);
-      frame.src = INSTALL_APPCACHE_URL;
-      document.body.appendChild(frame);
-      resolve_install_appcache = function() {
-          document.body.removeChild(frame);
-          resolve();
-        };
-      reject_install_appcache = function() {
-          document.body.removeChild(frame);
-          reject();
-        };
-  });
-}
-
 var resolve_is_appcached = undefined;
 
 // Called by the IS_APPCACHED_URL child frame.
@@ -63,7 +37,7 @@ function is_appcached() {
 promise_test(function(t) {
     return service_worker_unregister(t, SERVICE_WORKER_SCOPE)
       .then(function() {
-          return install_appcache();
+          return install_appcache_ordering_manifest();
         })
       .then(function() {
           return is_appcached();
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/claim-fetch-with-appcache.https-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/claim-fetch-with-appcache.https-expected.txt
new file mode 100644 (file)
index 0000000..8f2c39e
--- /dev/null
@@ -0,0 +1,4 @@
+CONSOLE MESSAGE: line 1: ApplicationCache is deprecated. Please use ServiceWorkers instead.
+
+PASS fetch() should be intercepted after the client is claimed. 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/claim-fetch-with-appcache.https.html b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/claim-fetch-with-appcache.https.html
new file mode 100644 (file)
index 0000000..4890a84
--- /dev/null
@@ -0,0 +1,81 @@
+<!doctype html>
+<meta charset=utf-8>
+<title></title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/test-helpers.sub.js"></script>
+<body>
+<script>
+
+// This test makes a frame controlled by AppCache, then registers a service
+// worker that calls claim() to control the frame. AppCache should be completely
+// bypassed once the service worker claims the frame.
+
+const fetch_text = async frame => {
+  const response = await
+    frame.contentWindow.fetch('appcache-ordering.is-appcached.js');
+  return await response.text();
+};
+
+const check_is_appcached = async frame => {
+  // This should FALLBACK to ordering.is_appcached.js as in the manifest
+  // if the appcache is effective.
+  const response = await
+    frame.contentWindow.fetch('appcache-ordering.is-appcached404.js');
+  return await response.ok;
+};
+
+promise_test(async t => {
+  const scope = 'resources/';
+  const script = 'resources/claim-worker.js';
+
+  await install_appcache_ordering_manifest();
+
+  // Create the test iframe.
+  const frame = await with_iframe('resources/blank.html');
+  t.add_cleanup(async () => {
+    if (frame) frame.remove();
+    return service_worker_unregister(t, scope);
+  });
+
+  // Check that the appcache controls the frame.
+  assert_equals(await check_is_appcached(frame), true,
+                'AppCache should be present');
+
+  // Check the controller and test with fetch.
+  assert_equals(frame.contentWindow.navigator.controller, undefined,
+                'Should have no controller.');
+  assert_equals(await fetch_text(frame), 'var is_appcached = true;\n',
+                'fetch() should not be intercepted.');
+
+  // Register a service worker.
+  let registration = await service_worker_unregister_and_register(t, script, scope);
+  const worker = registration.installing;
+  await wait_for_state(t, worker, 'activated');
+
+  // Let the service worker claim the iframe.
+  const channel = new MessageChannel();
+  const check_message = new Promise(resolve => {
+    channel.port1.onmessage = async e => {
+      assert_equals(e.data, 'PASS', 'Worker call to claim() should fulfill.');
+      resolve();
+    };
+  });
+  worker.postMessage({port: channel.port2}, [channel.port2]);
+  await check_message;
+
+  // Check that the appcache does NOT control the frame.
+  assert_equals(await check_is_appcached(frame), false,
+                'AppCache should not be present');
+
+  // Check the controller and test with fetch.
+  registration = await
+    frame.contentWindow.navigator.serviceWorker.getRegistration(scope);
+  assert_equals(frame.contentWindow.navigator.serviceWorker.controller,
+                registration.active, 'iframe should be claimed.');
+  assert_equals(await fetch_text(frame), 'Intercepted!',
+                'fetch() should be intercepted.');
+}, 'fetch() should be intercepted after the client is claimed.')
+
+</script>
+</body>
index 050c1ea..400b593 100644 (file)
@@ -7,63 +7,80 @@
 <body>
 <script>
 
-promise_test(function(t) {
-  var frame;
-  var resource = 'simple.txt';
+async function try_fetch(fetch_func, path) {
+  let response;
+  try {
+   response = await fetch_func(path);
+  } catch (err) {
+    throw (`fetch() threw: ${err}`);
+  }
 
-  var worker;
-  var scope = 'resources/';
-  var script = 'resources/claim-worker.js';
+  let response_text;
+  try {
+   response_text = await response.text();
+  } catch (err) {
+   throw (`text() threw: ${err}`);
+  }
 
-  return Promise.resolve()
-    // Create the test iframe.
-    .then(() => with_iframe('resources/blank.html'))
-    .then(f => frame = f)
+  return response_text;
+}
 
-    // Check the controller and test with fetch.
-    .then(() => assert_equals(frame.contentWindow.navigator.controller,
-                              undefined,
-                              'Should have no controller.'))
-    .then(() => frame.contentWindow.fetch(resource))
-    .then(response => response.text())
-    .then(response_text => assert_equals(response_text,
-                                         'a simple text file\n',
-                                         'fetch() should not be intercepted.'))
+promise_test(async function(t) {
+  let frame;
+  const scope = 'resources/';
+  const script = 'resources/claim-worker.js';
+  t.add_cleanup(async () => {
+    if (frame)
+      frame.remove();
+    return service_worker_unregister(t, scope);
+  });
 
-    // Register a service worker.
-    .then(() => service_worker_unregister_and_register(t, script, scope))
-    .then(r => worker = r.installing)
-    .then(() => wait_for_state(t, worker, 'activated'))
+  const resource = 'simple.txt';
 
-    // Let the service worker claim the iframe.
-    .then(() => {
-      var channel = new MessageChannel();
-      var saw_message = new Promise(function(resolve) {
-        channel.port1.onmessage = t.step_func(function(e) {
-          assert_equals(e.data, 'PASS',
-                        'Worker call to claim() should fulfill.');
-          resolve();
-        });
-      });
-      worker.postMessage({port: channel.port2}, [channel.port2]);
-      return saw_message;
-    })
+  // Create the test frame.
+  await service_worker_unregister(t, scope);
+  frame = await with_iframe('resources/blank.html');
 
-    // Check the controller and test with fetch.
-    .then(() => frame.contentWindow.navigator.serviceWorker.getRegistration(scope))
-    .then(r => assert_equals(frame.contentWindow.navigator.serviceWorker.controller,
-                             r.active,
-                             'Test iframe should be claimed.'))
-    .then(() => frame.contentWindow.fetch(resource))
-    .then(response => response.text())
-    .then(response_text => assert_equals(response_text,
-                                         'Intercepted!',
-                                         'fetch() should be intercepted.'))
+  // Check the controller and test with fetch.
+  assert_equals(frame.contentWindow.navigator.controller, undefined,
+                'Should have no controller.');
+  let response;
+  try {
+    response = await try_fetch(frame.contentWindow.fetch, resource);
+  } catch (err) {
+    assert_unreached(`uncontrolled fetch failed: ${err}`);
+  }
+  assert_equals(response, 'a simple text file\n',
+                'fetch() should not be intercepted.');
 
-    // Cleanup this testcase.
-    .then(() => frame.remove())
-    .then(() => service_worker_unregister_and_done(t, scope));
-}, 'fetch() should be intercepted after the client is claimed.')
+  // Register a service worker.
+  const registration = await navigator.serviceWorker.register(script, {scope});
+  const worker = registration.installing;
+  await wait_for_state(t, worker, 'activated');
+
+  // Tell the service worker to claim the iframe.
+  const saw_message = new Promise((resolve) => {
+    const channel = new MessageChannel();
+    channel.port1.onmessage = t.step_func((event) => {
+      resolve(event.data);
+    });
+    worker.postMessage({port: channel.port2}, [channel.port2]);
+  });
+  const data = await saw_message;
+  assert_equals(data, 'PASS', 'Worker call to claim() should fulfill.');
+
+  // Check the controller and test with fetch.
+  const controller = frame.contentWindow.navigator.serviceWorker.controller;
+  assert_true(controller instanceof frame.contentWindow.ServiceWorker,
+              'iframe should be controlled.');
+  try {
+    response = await try_fetch(frame.contentWindow.fetch, resource);
+  } catch (err) {
+    assert_unreached(`controlled fetch failed: ${err}`);
+  }
+  assert_equals(response, 'Intercepted!',
+                'fetch() should be intercepted.');
+}, 'fetch() should be intercepted after the client is claimed.');
 
 </script>
 </body>
index 1138b74..fd61d05 100644 (file)
@@ -15,6 +15,10 @@ promise_test(function(t) {
     return service_worker_unregister_and_register(
         t, init_worker_url, init_scope)
       .then(function(registration) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, init_scope);
+            });
+
           return wait_for_state(t, registration.installing, 'activated');
         })
       .then(function() {
@@ -35,6 +39,10 @@ promise_test(function(t) {
                                                   {scope: claim_scope});
         })
       .then(function(registration) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, claim_scope);
+            });
+
           claim_worker = registration.installing;
           claim_registration = registration;
           return wait_for_state(t, registration.installing, 'activated');
@@ -67,9 +75,6 @@ promise_test(function(t) {
           frame1.remove();
           frame2.remove();
           return claim_registration.unregister();
-        })
-      .then(function() {
-          return service_worker_unregister_and_done(t, init_scope);
         });
   }, 'Test claim client which is not using registration');
 
@@ -86,6 +91,10 @@ promise_test(function(t) {
               claim_worker_url, {scope: claim_scope});
         })
       .then(function(registration) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, claim_scope);
+            });
+
           claim_worker = registration.installing;
           return wait_for_state(t, registration.installing, 'activated');
         })
@@ -94,6 +103,10 @@ promise_test(function(t) {
               installing_worker_url, {scope: scope});
         })
       .then(function() {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           var channel = new MessageChannel();
           var saw_message = new Promise(function(resolve) {
               channel.port1.onmessage = t.step_func(function(e) {
@@ -111,10 +124,6 @@ promise_test(function(t) {
               'Frame should not be claimed when a longer-matched ' +
               'registration exists');
           frame.remove();
-          return service_worker_unregister(t, claim_scope);
-        })
-      .then(function() {
-          return service_worker_unregister_and_done(t, scope);
         });
   }, 'Test claim client when there\'s a longer-matched registration not ' +
      'already used by the page');
index a07db7b..f5f4488 100644 (file)
@@ -30,9 +30,13 @@ promise_test(function(t) {
                                          'fetch() should not be intercepted.'))
     // Register a service worker.
     .then(() => service_worker_unregister_and_register(t, script, scope))
-    .then(r => worker = r.installing)
-    .then(() => wait_for_state(t, worker, 'activated'))
+    .then(r => {
+        t.add_cleanup(() => service_worker_unregister(t, scope));
 
+        worker = r.installing;
+
+        return wait_for_state(t, worker, 'activated')
+      })
     // Let the service worker claim the iframe and the shared worker.
     .then(() => {
       var channel = new MessageChannel();
@@ -60,8 +64,7 @@ promise_test(function(t) {
                         'fetch() in the shared worker should be intercepted.'))
 
     // Cleanup this testcase.
-    .then(() => frame.remove())
-    .then(() => service_worker_unregister_and_done(t, scope));
+    .then(() => frame.remove());
 }, 'fetch() in SharedWorker should be intercepted after the client is claimed.')
 
 </script>
index 7d77d38..8a2a6ff 100644 (file)
@@ -13,6 +13,10 @@ promise_test(function(t) {
     var worker, sw_registration, frame;
     return service_worker_unregister_and_register(t, url1, scope)
       .then(function(registration) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return wait_for_state(t, registration.installing, 'activated');
         })
       .then(function() {
@@ -50,9 +54,6 @@ promise_test(function(t) {
               'Frame1 controller scriptURL should be changed to url2');
           frame.remove();
           return sw_registration.unregister();
-        })
-      .then(function() {
-          return service_worker_unregister_and_done(t, scope);
         });
   }, 'Test worker claims client which is using another registration');
 
@@ -63,6 +64,10 @@ promise_test(function(t) {
     var frame, worker;
     return service_worker_unregister_and_register(t, url1, scope)
       .then(function(registration) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return wait_for_state(t, registration.installing, 'activated');
         })
       .then(function() {
@@ -91,7 +96,6 @@ promise_test(function(t) {
         })
       .then(function() {
           frame.remove();
-          return service_worker_unregister_and_done(t, scope);
         });
   }, 'Test for the waiting worker claims a client which is using the the ' +
      'same registration');
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/clients-get-resultingClientId.https-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/clients-get-resultingClientId.https-expected.txt
new file mode 100644 (file)
index 0000000..8274586
--- /dev/null
@@ -0,0 +1,8 @@
+
+PASS global setup 
+FAIL get(resultingClientId) for same-origin document assert_equals: promiseValue expected "client" but got "undefinedValue"
+FAIL get(resultingClientId) on cross-origin redirect assert_equals: get(event.resultingClientId) in the fetch event should fulfill expected (string) "fulfilled" but got (undefined) undefined
+FAIL get(resultingClientId) for document sandboxed by CSP header assert_equals: get(event.resultingClientId) in the fetch event should fulfill expected (string) "fulfilled" but got (undefined) undefined
+FAIL get(resultingClientId) for document sandboxed by CSP header with allow-same-origin assert_equals: get(event.resultingClientId) in the fetch event should fulfill expected (string) "fulfilled" but got (undefined) undefined
+PASS global cleanup 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/clients-get-resultingClientId.https.html b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/clients-get-resultingClientId.https.html
new file mode 100644 (file)
index 0000000..3419cf1
--- /dev/null
@@ -0,0 +1,177 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Test clients.get(resultingClientId)</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="/common/get-host-info.sub.js"></script>
+<script src="resources/test-helpers.sub.js"></script>
+<script>
+const scope = "resources/";
+let worker;
+
+// Setup. Keep this as the first promise_test.
+promise_test(async (t) => {
+  const registration = await service_worker_unregister_and_register(
+      t, 'resources/get-resultingClientId-worker.js',
+      scope);
+  worker = registration.installing;
+  await wait_for_state(t, worker, 'activated');
+}, 'global setup');
+
+// Sends |command| to the worker and returns a promise that resolves to its
+// response. There should only be one inflight command at a time.
+async function sendCommand(command) {
+  const saw_message = new Promise((resolve) => {
+    navigator.serviceWorker.onmessage = (event) => {
+      resolve(event.data);
+    };
+  });
+  worker.postMessage(command);
+  return saw_message;
+}
+
+// Wrapper for 'startTest' command. Tells the worker a test is starting,
+// so it resets state and keeps itself alive until 'finishTest'.
+async function startTest(t) {
+  const result = await sendCommand({command: 'startTest'});
+  assert_equals(result, 'ok', 'startTest');
+
+  t.add_cleanup(async () => {
+    return finishTest();
+  });
+}
+
+// Wrapper for 'finishTest' command.
+async function finishTest() {
+  const result = await sendCommand({command: 'finishTest'});
+  assert_equals(result, 'ok', 'finishTest');
+}
+
+// Wrapper for 'getResultingClient' command. Tells the worker to return
+// clients.get(event.resultingClientId) for the navigation that occurs
+// during this test.
+//
+// The return value describes how clients.get() settled. It also includes
+// |queriedId| which is the id passed to clients.get() (the resultingClientId
+// in this case).
+//
+// Example value:
+// {
+//   queriedId: 'abc',
+//   promiseState: fulfilled,
+//   promiseValue: client,
+//   client: {
+//     id: 'abc',
+//     url: '//example.com/client'
+//   }
+// }
+async function getResultingClient() {
+  return sendCommand({command: 'getResultingClient'});
+}
+
+// Wrapper for 'getClient' command. Tells the worker to return
+// clients.get(|id|). The return value is as in the getResultingClient()
+// documentation.
+async function getClient(id) {
+  return sendCommand({command: 'getClient', id: id});
+}
+
+// Navigates to |url|. Returns the result of clients.get() on the
+// resultingClientId.
+async function navigateAndGetResultingClient(t, url) {
+  const resultPromise = getResultingClient();
+  const frame = await with_iframe(url);
+  t.add_cleanup(() => {
+    frame.remove();
+  });
+  const result = await resultPromise;
+  const resultingClientId = result.queriedId;
+
+  // First test clients.get(event.resultingClientId) inside the fetch event. The
+  // behavior of this is subtle due to the use of iframes and about:blank
+  // replacement. The spec probably requires that it resolve to the original
+  // about:blank client, and that later that client should be discarded after
+  // load if the load was to another origin. Implementations might differ. For
+  // now, this test just asserts that the promise resolves. See
+  // https://github.com/w3c/ServiceWorker/issues/1385.
+  assert_equals(result.promiseState, 'fulfilled',
+                'get(event.resultingClientId) in the fetch event should fulfill');
+
+  // Test clients.get() on the previous resultingClientId again. By this
+  // time the load finished, so it's more straightforward how this promise
+  // should settle. Return the result of this promise.
+  return await getClient(resultingClientId);
+}
+
+// Test get(resultingClientId) in the basic same-origin case.
+promise_test(async (t) => {
+  await startTest(t);
+
+  const url = new URL('resources/empty.html', window.location);
+  const result = await navigateAndGetResultingClient(t, url);
+  assert_equals(result.promiseState, 'fulfilled', 'promiseState');
+  assert_equals(result.promiseValue, 'client', 'promiseValue');
+  assert_equals(result.client.url, url.href, 'client.url',);
+  assert_equals(result.client.id, result.queriedId, 'client.id');
+}, 'get(resultingClientId) for same-origin document');
+
+// Test get(resultingClientId) when the response redirects to another origin.
+promise_test(async (t) => {
+  await startTest(t);
+
+  // Navigate to a URL that redirects to another origin.
+  const base_url = new URL('.', window.location);
+  const host_info = get_host_info();
+  const other_origin_url = new URL(base_url.pathname + 'resources/empty.html',
+                                   host_info['HTTPS_REMOTE_ORIGIN']);
+  const url = new URL('resources/empty.html', window.location);
+  const pipe = `status(302)|header(Location, ${other_origin_url})`;
+  url.searchParams.set('pipe', pipe);
+
+  // The original reserved client should have been discarded on cross-origin
+  // redirect.
+  const result = await navigateAndGetResultingClient(t, url);
+  assert_equals(result.promiseState, 'fulfilled', 'promiseState');
+  assert_equals(result.promiseValue, 'undefinedValue', 'promiseValue');
+}, 'get(resultingClientId) on cross-origin redirect');
+
+// Test get(resultingClientId) when the document is sandboxed to a unique
+// origin using a CSP HTTP response header.
+promise_test(async (t) => {
+  await startTest(t);
+
+  // Navigate to a URL that has CSP sandboxing set in the HTTP response header.
+  const url = new URL('resources/empty.html', window.location);
+  const pipe = 'header(Content-Security-Policy, sandbox)';
+  url.searchParams.set('pipe', pipe);
+
+  // The original reserved client should have been discarded upon loading
+  // the sandboxed document.
+  const result = await navigateAndGetResultingClient(t, url);
+  assert_equals(result.promiseState, 'fulfilled', 'promiseState');
+  assert_equals(result.promiseValue, 'undefinedValue', 'promiseValue');
+}, 'get(resultingClientId) for document sandboxed by CSP header');
+
+// Test get(resultingClientId) when the document is sandboxed with
+// allow-same-origin.
+promise_test(async (t) => {
+  await startTest(t);
+
+  // Navigate to a URL that has CSP sandboxing set in the HTTP response header.
+  const url = new URL('resources/empty.html', window.location);
+  const pipe = 'header(Content-Security-Policy, sandbox allow-same-origin)';
+  url.searchParams.set('pipe', pipe);
+
+  // The client should be the original reserved client, as it's same-origin.
+  const result = await navigateAndGetResultingClient(t, url);
+  assert_equals(result.promiseState, 'fulfilled', 'promiseState');
+  assert_equals(result.promiseValue, 'client', 'promiseValue');
+  assert_equals(result.client.url, url.href, 'client.url',);
+  assert_equals(result.client.id, result.queriedId, 'client.id');
+}, 'get(resultingClientId) for document sandboxed by CSP header with allow-same-origin');
+
+// Cleanup. Keep this as the last promise_test.
+promise_test(async (t) => {
+  return service_worker_unregister(t, scope);
+}, 'global cleanup');
+</script>
index 2496717..a2a5681 100644 (file)
@@ -54,6 +54,10 @@ promise_test(function(t) {
     return service_worker_unregister_and_register(
         t, 'resources/clients-matchall-worker.js', scope)
       .then(function(registration) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return wait_for_state(t, registration.installing, 'activated');
         })
       .then(function() { return with_iframe(iframe_url); })
@@ -66,9 +70,7 @@ promise_test(function(t) {
         })
       .then(function() {
           frame.remove();
-          return service_worker_unregister_and_done(t, scope);
-        })
-      .catch(unreached_rejection(t));
+        });
   }, 'Verify matchAll() with window client type');
 
 promise_test(function(t) {
@@ -76,6 +78,10 @@ promise_test(function(t) {
     return service_worker_unregister_and_register(
         t, 'resources/clients-matchall-worker.js', scope)
       .then(function(registration) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return wait_for_state(t, registration.installing, 'activated');
         })
       .then(function() { return with_iframe(iframe_url); })
@@ -112,7 +118,6 @@ promise_test(function(t) {
         })
       .then(function() {
           frame.remove();
-          return service_worker_unregister_and_done(t, scope);
         });
 }, 'Verify matchAll() with {window, sharedworker, worker} client types');
 
index 0596050..ec650f2 100644 (file)
@@ -123,6 +123,8 @@ function matchAllOrderTest(t, opts) {
   let frameResultList;
   let extraWindowResult;
   return service_worker_unregister_and_register(t, script, opts.scope).then(swr => {
+    t.add_cleanup(() => service_worker_unregister(t, opts.scope));
+
     worker = swr.installing;
     return wait_for_state(t, worker, 'activated');
   }).then(_ => {
@@ -143,8 +145,6 @@ function matchAllOrderTest(t, opts) {
   }).then(_ => {
     frameResultList.forEach(result => result.top.remove());
     extraWindowResult.top.remove();
-  }).then(_ => {
-    return service_worker_unregister_and_done(t, opts.scope);
   }).catch(e => {
     if (frameResultList) {
       frameResultList.forEach(result => result.top.remove());
index e0beb72..2e966d4 100644 (file)
@@ -13,6 +13,10 @@ promise_test(function(t) {
     var controller;
     return service_worker_unregister(t, scope)
       .then(function() {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return with_iframe(scope);
         })
       .then(function(f) {
@@ -48,7 +52,6 @@ promise_test(function(t) {
       .then(function(frameRegistration) {
           assert_equals(frameRegistration.active, controller);
           frame.remove();
-          service_worker_unregister_and_done(t, scope);
         });
   }, 'controller is set upon reload after registration');
 </script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/data-transfer-files.https-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/data-transfer-files.https-expected.txt
new file mode 100644 (file)
index 0000000..59340fc
--- /dev/null
@@ -0,0 +1,5 @@
+
+
+
+FAIL Posting a File in a navigation handled by a service worker promise_test: Unhandled rejection with value: object "TypeError: function is not a constructor (evaluating 'new DataTransfer()')"
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/data-transfer-files.https.html b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/data-transfer-files.https.html
new file mode 100644 (file)
index 0000000..cc8ab6e
--- /dev/null
@@ -0,0 +1,41 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Post a file in a navigation controlled by a service worker</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/test-helpers.sub.js"></script>
+<body>
+<iframe id=testframe name=testframe></iframe>
+<form id=testform method=post action="/html/semantics/forms/form-submission-0/resources/file-submission.py" target=testframe enctype="multipart/form-data">
+<input name=testinput id=testinput type=file>
+</form>
+<script>
+// Test that DataTransfer with a File entry works when posted to a
+// service worker that falls back to network. Regression test for
+// https://crbug.com/944145.
+promise_test(async (t) => {
+  const scope = '/html/semantics/forms/form-submission-0/resources/';
+  const header = `pipe=header(Service-Worker-Allowed,${scope})`;
+  const script = `resources/fetch-event-network-fallback-worker.js?${header}`;
+
+  const registration = await service_worker_unregister_and_register(
+      t, script, scope);
+  await wait_for_state(t, registration.installing, 'activated');
+
+  const dataTransfer = new DataTransfer();
+  dataTransfer.items.add(new File(['foobar'], 'name'));
+  assert_equals(1, dataTransfer.files.length);
+
+  testinput.files = dataTransfer.files;
+  testform.submit();
+
+  const data = await new Promise(resolve => {
+    onmessage = e => {
+      if (e.source !== testframe) return;
+      resolve(e.data);
+    };
+  });
+  assert_equals(data, "FieldStorage('testinput', 'name', 'foobar')");
+}, 'Posting a File in a navigation handled by a service worker');
+</script>
+</body>
index 3110d3e..f757055 100644 (file)
@@ -1,13 +1,17 @@
 
 
-PASS Test calling waitUntil in a different task without an existing extension throws 
-FAIL Test calling waitUntil in a different microtask without an existing extension throws assert_equals: expected "InvalidStateError" but got "OK"
-PASS Test calling waitUntil in a different task with an existing extension succeeds 
-PASS Test calling waitUntil with an existing extension promise handler succeeds 
-FAIL Test calling waitUntil at the end of the microtask turn throws assert_equals: expected "InvalidStateError" but got "OK"
+PASS Test calling waitUntil in a task at the end of the event handler without an existing extension throws 
+PASS Test calling waitUntil in a microtask at the end of the event handler without an existing extension suceeds 
+PASS Test calling waitUntil in a different task an existing extension succeeds 
+PASS Test calling waitUntil at the end of an existing extension promise handler succeeds (event is still being dispatched) 
+PASS Test calling waitUntil in a microtask at the end of an existing extension promise handler succeeds (event is still being dispatched) 
+PASS Test calling waitUntil in an existing extension promise handler succeeds (event is not being dispatched) 
+PASS Test calling waitUntil in a microtask at the end of an existing extension promise handler throws (event is not being dispatched) 
 PASS Test calling waitUntil after the current extension expired in a different task fails 
 PASS Test calling waitUntil on a script constructed ExtendableEvent throws exception 
 PASS Test calling waitUntil asynchronously with pending respondWith promise. 
-PASS Test calling waitUntil synchronously inside microtask of respondWith promise. 
-FAIL Test calling waitUntil asynchronously inside microtask of respondWith promise. assert_equals: expected "InvalidStateError" but got "OK"
+PASS Test calling waitUntil synchronously inside microtask of respondWith promise (event is being dispatched). 
+PASS Test calling waitUntil asynchronously inside microtask of respondWith promise (event is being dispatched). 
+PASS Test calling waitUntil synchronously inside microtask of respondWith promise (event is not being dispatched). 
+PASS Test calling waitUntil asynchronously inside microtask of respondWith promise (event is not being dispatched). 
 
index cb4ed30..04e9826 100644 (file)
@@ -1,4 +1,5 @@
 <!DOCTYPE html>
+<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="resources/testharness-helpers.js"></script>
 <script src="/resources/testharnessreport.js"></script>
@@ -56,21 +57,25 @@ function msg_event_test(scope, test) {
 }
 
 promise_test(msg_event_test.bind(this, 'no-current-extension-different-task'),
-  'Test calling waitUntil in a different task without an existing extension throws');
+  'Test calling waitUntil in a task at the end of the event handler without an existing extension throws');
 
 promise_test(msg_event_test.bind(this, 'no-current-extension-different-microtask'),
-  'Test calling waitUntil in a different microtask without an existing extension throws');
+  'Test calling waitUntil in a microtask at the end of the event handler without an existing extension suceeds');
 
 promise_test(msg_event_test.bind(this, 'current-extension-different-task'),
-  'Test calling waitUntil in a different task with an existing extension succeeds');
+  'Test calling waitUntil in a different task an existing extension succeeds');
 
-promise_test(msg_event_test.bind(this, 'current-extension-expired-same-microtask-turn'),
-  'Test calling waitUntil with an existing extension promise handler succeeds');
+promise_test(msg_event_test.bind(this, 'during-event-dispatch-current-extension-expired-same-microtask-turn'),
+  'Test calling waitUntil at the end of an existing extension promise handler succeeds (event is still being dispatched)');
 
-// The promise handler will queue a new microtask after the check for new
-// extensions was performed.
-promise_test(msg_event_test.bind(this, 'current-extension-expired-same-microtask-turn-extra'),
-  'Test calling waitUntil at the end of the microtask turn throws');
+promise_test(msg_event_test.bind(this, 'during-event-dispatch-current-extension-expired-same-microtask-turn-extra'),
+  'Test calling waitUntil in a microtask at the end of an existing extension promise handler succeeds (event is still being dispatched)');
+
+promise_test(msg_event_test.bind(this, 'after-event-dispatch-current-extension-expired-same-microtask-turn'),
+  'Test calling waitUntil in an existing extension promise handler succeeds (event is not being dispatched)');
+
+promise_test(msg_event_test.bind(this, 'after-event-dispatch-current-extension-expired-same-microtask-turn-extra'),
+  'Test calling waitUntil in a microtask at the end of an existing extension promise handler throws (event is not being dispatched)');
 
 promise_test(msg_event_test.bind(this, 'current-extension-expired-different-task'),
   'Test calling waitUntil after the current extension expired in a different task fails');
@@ -80,24 +85,36 @@ promise_test(msg_event_test.bind(this, 'script-extendable-event'),
 
 promise_test(function(t) {
     var testBody = function(worker) {
-      return with_iframe('./resources/pending-respondwith-async-waituntil/dummy.html');
+      return with_iframe('./resources/pending-respondwith-async-waituntil');
     }
     return runTest(t, 'pending-respondwith-async-waituntil', testBody);
   }, 'Test calling waitUntil asynchronously with pending respondWith promise.');
 
 promise_test(function(t) {
     var testBody = function(worker) {
-      return with_iframe('./resources/respondwith-microtask-sync-waituntil/dummy.html');
+      return with_iframe('./resources/during-event-dispatch-respondwith-microtask-sync-waituntil');
     }
-    return runTest(t, 'respondwith-microtask-sync-waituntil', testBody);
-  }, 'Test calling waitUntil synchronously inside microtask of respondWith promise.');
+    return runTest(t, 'during-event-dispatch-respondwith-microtask-sync-waituntil', testBody);
+  }, 'Test calling waitUntil synchronously inside microtask of respondWith promise (event is being dispatched).');
 
 promise_test(function(t) {
     var testBody = function(worker) {
-      return with_iframe('./resources/respondwith-microtask-async-waituntil/dummy.html');
+      return with_iframe('./resources/during-event-dispatch-respondwith-microtask-async-waituntil');
     }
-    return runTest(t, 'respondwith-microtask-async-waituntil', testBody);
-  }, 'Test calling waitUntil asynchronously inside microtask of respondWith promise.');
+    return runTest(t, 'during-event-dispatch-respondwith-microtask-async-waituntil', testBody);
+  }, 'Test calling waitUntil asynchronously inside microtask of respondWith promise (event is being dispatched).');
 
+promise_test(function(t) {
+    var testBody = function(worker) {
+      return with_iframe('./resources/after-event-dispatch-respondwith-microtask-sync-waituntil');
+    }
+    return runTest(t, 'after-event-dispatch-respondwith-microtask-sync-waituntil', testBody);
+  }, 'Test calling waitUntil synchronously inside microtask of respondWith promise (event is not being dispatched).');
 
+promise_test(function(t) {
+    var testBody = function(worker) {
+      return with_iframe('./resources/after-event-dispatch-respondwith-microtask-async-waituntil');
+    }
+    return runTest(t, 'after-event-dispatch-respondwith-microtask-async-waituntil', testBody);
+  }, 'Test calling waitUntil asynchronously inside microtask of respondWith promise (event is not being dispatched).');
 </script>
index ef3d12b..c37e8e5 100644 (file)
@@ -1,6 +1,7 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
 <title>Service Worker: canvas tainting of the fetched video using cache responses</title>
+<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/common/get-host-info.sub.js"></script>
index 5776508..e8c23a2 100644 (file)
@@ -1,6 +1,7 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
 <title>Service Worker: canvas tainting of the fetched video</title>
+<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/common/get-host-info.sub.js"></script>
index 91a774a..4f17622 100644 (file)
@@ -32,6 +32,10 @@ promise_test(function(t) {
 
     return service_worker_unregister_and_register(t, SCRIPT, SCOPE)
       .then(function(registration) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, SCOPE);
+            });
+
           return wait_for_state(t, registration.installing, 'activated');
         })
       .then(function() {
@@ -105,7 +109,6 @@ promise_test(function(t) {
         })
       .then(function() {
           frame.remove();
-          service_worker_unregister_and_done(t, SCOPE);
         });
   }, 'Verify CSP control of fetch() in a Service Worker');
 </script>
index dce1f79..4812d8a 100644 (file)
@@ -15,6 +15,10 @@ promise_test(function(t) {
 
     return service_worker_unregister_and_register(t, worker, scope)
       .then(function(reg) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return wait_for_state(t, reg.installing, 'activated');
         })
       .then(function() { return with_iframe(scope); })
@@ -30,7 +34,6 @@ promise_test(function(t) {
       .then(function(response) {
           assert_equals(response, 'intercepted by service worker');
           frame.remove();
-          return service_worker_unregister_and_done(t, scope);
         })
   }, 'Service Worker should respond to fetch event after the hash changes');
 
@@ -43,6 +46,10 @@ promise_test(function(t) {
 
     return service_worker_unregister_and_register(t, worker, scope)
       .then(function(reg) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return wait_for_state(t, reg.installing, 'activated');
         })
       .then(function() { return with_iframe(scope); })
@@ -58,7 +65,6 @@ promise_test(function(t) {
       .then(function(response) {
           assert_equals(response, 'intercepted by service worker');
           frame.remove();
-          return service_worker_unregister_and_done(t, scope);
         })
   }, 'Service Worker should respond to fetch event after the pushState');
 
index 7e11bce..e3da13c 100644 (file)
@@ -1,3 +1,9 @@
+CONSOLE MESSAGE: Unhandled Promise Rejection: TypeError: cancelled
 
-PASS Calling respondWith asynchronously throws an exception 
+Harness Error (FAIL), message = cancelled
+
+PASS global setup 
+PASS respondWith in a task throws InvalidStateError 
+PASS respondWith in a microtask does not throw 
+PASS global cleanup 
 
index a2b93ac..ae64fcb 100644 (file)
@@ -1,33 +1,71 @@
 <!DOCTYPE html>
+<html>
+<title>respondWith cannot be called asynchronously</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
 <script>
-promise_test(function(t) {
-    var script = 'resources/fetch-event-async-respond-with-worker.js';
-    var scope = 'resources/simple.html';
-
-    return service_worker_unregister_and_register(t, script, scope)
-      .then(function(registration) {
-          return wait_for_state(t, registration.installing, 'activated');
-        })
-      .then(function() {
-          return with_iframe(scope);
-        })
-      .then(function(frame) {
-          add_completion_callback(function() { frame.remove(); });
-          var channel = new MessageChannel();
-          var saw_message = new Promise(function(resolve) {
-              channel.port1.onmessage = function(e) { resolve(e.data); }
-            });
-          var worker = frame.contentWindow.navigator.serviceWorker.controller;
-
-          worker.postMessage({port: channel.port2}, [channel.port2]);
-          return saw_message;
-        })
-      .then(function(message) {
-          assert_equals(message, 'PASS');
-          return service_worker_unregister_and_done(t, scope);
-        })
-  }, 'Calling respondWith asynchronously throws an exception');
+// This file has tests that call respondWith() asynchronously.
+
+let frame;
+let worker;
+const script = 'resources/fetch-event-async-respond-with-worker.js';
+const scope = 'resources/simple.html';
+
+// Global setup: this must be the first promise_test.
+promise_test(async (t) => {
+  const registration =
+      await service_worker_unregister_and_register(t, script, scope);
+  worker = registration.installing;
+  await wait_for_state(t, worker, 'activated');
+  frame = await with_iframe(scope);
+}, 'global setup');
+
+// Waits for a single message from the service worker and then removes the
+// message handler. Not safe for concurrent use.
+function wait_for_message() {
+  return new Promise((resolve) => {
+    const handler = (event) => {
+      navigator.serviceWorker.removeEventListener('message', handler);
+      resolve(event.data);
+    };
+    navigator.serviceWorker.addEventListener('message', handler);
+  });
+}
+
+// Does one test case. It fetches |url|. The service worker gets a fetch event
+// for |url| and attempts to call respondWith() asynchronously. It reports back
+// to the test whether an exception was thrown.
+async function do_test(url) {
+  // Send a message to tell the worker a new test case is starting.
+  const message = wait_for_message();
+  worker.postMessage('initializeMessageHandler');
+  const response = await message;
+  assert_equals(response, 'messageHandlerInitialized');
+
+  // Start a fetch.
+  frame.contentWindow.fetch(url);
+
+  // Receive the test result from the service worker.
+  return wait_for_message();
+};
+
+promise_test(async (t) => {
+  const result = await do_test('respondWith-in-task');
+  assert_true(result.didThrow, 'should throw');
+  assert_equals(result.error, 'InvalidStateError');
+}, 'respondWith in a task throws InvalidStateError');
+
+promise_test(async (t) => {
+  const result = await do_test('respondWith-in-microtask');
+  assert_equals(result.didThrow, false, 'should not throw');
+}, 'respondWith in a microtask does not throw');
+
+// Global cleanup: the final promise_test.
+promise_test(async (t) => {
+  if (frame)
+    frame.remove();
+  await service_worker_unregister(t, scope);
+}, 'global cleanup');
 </script>
+</html>
index 254919e..fea2ad1 100644 (file)
@@ -22,6 +22,10 @@ promise_test(function(t) {
 
     return service_worker_unregister_and_register(t, script, scope)
       .then(function(registration) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return wait_for_state(t, registration.installing, 'activated');
         })
       .then(function() {
@@ -34,7 +38,6 @@ promise_test(function(t) {
       .then(function(result) {
           frame.remove();
           assert_equals(result, 'PASS');
-          return service_worker_unregister_and_done(t, scope);
         });
   }, 'Rejecting the fetch event or using preventDefault() causes a network ' +
      'error');
index c33b7d9..82aa5e0 100644 (file)
@@ -1,76 +1,10 @@
-CONSOLE MESSAGE: line 32: The page at https://localhost:9443/service-workers/service-worker/fetch-event-referrer-policy.https.html was allowed to display insecure content from http://localhost:8800/service-workers/service-worker//resources/simple.html?referrerFull.
+CONSOLE MESSAGE: line 29: [blocked] The page at https://localhost:9443/service-workers/service-worker/fetch-event-referrer-policy.https.html was not allowed to display insecure content from http://localhost:8800/service-workers/service-worker//resources/simple.html?referrerFull.
 
-CONSOLE MESSAGE: line 54: The page at https://localhost:9443/service-workers/service-worker/fetch-event-referrer-policy.https.html was allowed to display insecure content from http://localhost:8800/service-workers/service-worker//resources/simple.html?referrerFull.
+CONSOLE MESSAGE: line 29: Not allowed to request resource
+CONSOLE MESSAGE: line 29: Fetch API cannot load http://localhost:8800/service-workers/service-worker//resources/simple.html?referrerFull due to access control checks.
 
-CONSOLE MESSAGE: line 76: The page at https://localhost:9443/service-workers/service-worker/fetch-event-referrer-policy.https.html was allowed to display insecure content from http://localhost:8800/service-workers/service-worker//resources/simple.html?referrerFull.
 
-CONSOLE MESSAGE: line 98: The page at https://localhost:9443/service-workers/service-worker/fetch-event-referrer-policy.https.html was allowed to display insecure content from http://localhost:8800/service-workers/service-worker//resources/simple.html?referrerFull.
-
-CONSOLE MESSAGE: line 120: The page at https://localhost:9443/service-workers/service-worker/fetch-event-referrer-policy.https.html was allowed to display insecure content from http://localhost:8800/service-workers/service-worker//resources/simple.html?referrerFull.
-
-CONSOLE MESSAGE: line 132: The page at https://localhost:9443/service-workers/service-worker/fetch-event-referrer-policy.https.html was allowed to display insecure content from http://localhost:8800/service-workers/service-worker//resources/simple.html?referrerFull.
-
-CONSOLE MESSAGE: line 197: The page at https://localhost:9443/service-workers/service-worker/fetch-event-referrer-policy.https.html was allowed to display insecure content from http://localhost:8800/service-workers/service-worker//resources/simple.html?referrerFull.
-
-CONSOLE MESSAGE: line 231: The page at https://localhost:9443/service-workers/service-worker/fetch-event-referrer-policy.https.html was allowed to display insecure content from http://localhost:8800/service-workers/service-worker//resources/simple.html?referrerFull.
-
-CONSOLE MESSAGE: line 32: The page at https://localhost:9443/service-workers/service-worker/fetch-event-referrer-policy.https.html was allowed to display insecure content from http://localhost:8800/service-workers/service-worker//resources/simple.html?referrerFull.
-
-CONSOLE MESSAGE: line 54: The page at https://localhost:9443/service-workers/service-worker/fetch-event-referrer-policy.https.html was allowed to display insecure content from http://localhost:8800/service-workers/service-worker//resources/simple.html?referrerFull.
-
-CONSOLE MESSAGE: line 76: The page at https://localhost:9443/service-workers/service-worker/fetch-event-referrer-policy.https.html was allowed to display insecure content from http://localhost:8800/service-workers/service-worker//resources/simple.html?referrerFull.
-
-CONSOLE MESSAGE: line 98: The page at https://localhost:9443/service-workers/service-worker/fetch-event-referrer-policy.https.html was allowed to display insecure content from http://localhost:8800/service-workers/service-worker//resources/simple.html?referrerFull.
-
-CONSOLE MESSAGE: line 120: The page at https://localhost:9443/service-workers/service-worker/fetch-event-referrer-policy.https.html was allowed to display insecure content from http://localhost:8800/service-workers/service-worker//resources/simple.html?referrerFull.
-
-CONSOLE MESSAGE: line 132: The page at https://localhost:9443/service-workers/service-worker/fetch-event-referrer-policy.https.html was allowed to display insecure content from http://localhost:8800/service-workers/service-worker//resources/simple.html?referrerFull.
-
-CONSOLE MESSAGE: line 197: The page at https://localhost:9443/service-workers/service-worker/fetch-event-referrer-policy.https.html was allowed to display insecure content from http://localhost:8800/service-workers/service-worker//resources/simple.html?referrerFull.
-
-CONSOLE MESSAGE: line 231: The page at https://localhost:9443/service-workers/service-worker/fetch-event-referrer-policy.https.html was allowed to display insecure content from http://localhost:8800/service-workers/service-worker//resources/simple.html?referrerFull.
-
-
-PASS Service Worker responds to fetch event with the referrer policy 
+FAIL Service Worker responds to fetch event with the referrer policy promise_test: Unhandled rejection with value: object "TypeError: Not allowed to request resource"
 PASS Service Worker should respond to fetch with the default referrer policy 
 PASS Service Worker should respond to fetch with the referrer URL when a member of RequestInit is present - Default Referrer 
-PASS Service Worker should respond to fetch with no referrer when a member of RequestInit is present with an HTTP request - Default Referrer 
-PASS Service Worker should respond to fetch with the referrer with "" - Default Referrer 
-PASS Service Worker should respond to fetch with no referrer with "" - Default Referrer 
-PASS Service Worker should respond to fetch with the referrer origin with "origin" and a same origin request - Default Referrer 
-PASS Service Worker should respond to fetch with the referrer origin with "origin" and a cross origin request - Default Referrer 
-PASS Service Worker should respond to fetch with the referrer URL with "origin-when-cross-origin" and a same origin request - Default Referrer 
-PASS Service Worker should respond to fetch with the referrer origin with "origin-when-cross-origin" and a cross origin request - Default Referrer 
-PASS Service Worker should respond to fetch with no referrer with "no-referrer-when-downgrade" and a same origin request - Default Referrer 
-PASS Service Worker should respond to fetch with no referrer with "no-referrer-when-downgrade" and an HTTP request - Default Referrer 
-PASS Service Worker should respond to fetch with no referrer with "unsafe-url" - Default Referrer 
-PASS Service Worker should respond to fetch with no referrer URL with "no-referrer" - Default Referrer 
-PASS Service Worker should respond to fetch with referrer URL with "same-origin" and a same origin request - Default Referrer 
-PASS Service Worker should respond to fetch with no referrer with "same-origin" and cross origin request - Default Referrer 
-PASS Service Worker should respond to fetch with the referrer origin  with "strict-origin" and a HTTPS cross origin request - Default Referrer 
-PASS Service Worker should respond to fetch with the referrer origin with "strict-origin" and a same origin request - Default Referrer 
-PASS Service Worker should respond to fetch with no referrer with "strict-origin" and a HTTP request - Default Referrer 
-PASS Service Worker should respond to fetch with the referrer URL with "strict-origin-when-cross-origin" and a same origin request - Default Referrer 
-PASS Service Worker should respond to fetch with the referrer origin with "strict-origin-when-cross-origin" and a HTTPS cross origin request - Default Referrer 
-PASS Service Worker should respond to fetch with no referrer with "strict-origin-when-cross-origin" and a HTTP request - Default Referrer 
-PASS Service Worker should respond to fetch with the referrer URL when a member of RequestInit is present - Custom Referrer 
-PASS Service Worker should respond to fetch with no referrer when a member of RequestInit is present with an HTTP request - Custom Referrer 
-PASS Service Worker should respond to fetch with the referrer with "" - Custom Referrer 
-PASS Service Worker should respond to fetch with no referrer with "" - Custom Referrer 
-PASS Service Worker should respond to fetch with the referrer origin with "origin" and a same origin request - Custom Referrer 
-PASS Service Worker should respond to fetch with the referrer origin with "origin" and a cross origin request - Custom Referrer 
-PASS Service Worker should respond to fetch with the referrer URL with "origin-when-cross-origin" and a same origin request - Custom Referrer 
-PASS Service Worker should respond to fetch with the referrer origin with "origin-when-cross-origin" and a cross origin request - Custom Referrer 
-PASS Service Worker should respond to fetch with no referrer with "no-referrer-when-downgrade" and a same origin request - Custom Referrer 
-PASS Service Worker should respond to fetch with no referrer with "no-referrer-when-downgrade" and an HTTP request - Custom Referrer 
-PASS Service Worker should respond to fetch with no referrer with "unsafe-url" - Custom Referrer 
-PASS Service Worker should respond to fetch with no referrer URL with "no-referrer" - Custom Referrer 
-PASS Service Worker should respond to fetch with referrer URL with "same-origin" and a same origin request - Custom Referrer 
-PASS Service Worker should respond to fetch with no referrer with "same-origin" and cross origin request - Custom Referrer 
-PASS Service Worker should respond to fetch with the referrer origin  with "strict-origin" and a HTTPS cross origin request - Custom Referrer 
-PASS Service Worker should respond to fetch with the referrer origin with "strict-origin" and a same origin request - Custom Referrer 
-PASS Service Worker should respond to fetch with no referrer with "strict-origin" and a HTTP request - Custom Referrer 
-PASS Service Worker should respond to fetch with the referrer URL with "strict-origin-when-cross-origin" and a same origin request - Custom Referrer 
-PASS Service Worker should respond to fetch with the referrer origin with "strict-origin-when-cross-origin" and a HTTPS cross origin request - Custom Referrer 
-PASS Service Worker should respond to fetch with no referrer with "strict-origin-when-cross-origin" and a HTTP request - Custom Referrer 
 
index 3846c5b..804fd9b 100644 (file)
@@ -7,9 +7,6 @@
 <script>
 var worker = 'resources/fetch-event-test-worker.js';
 
-if (window.internals && window.internals.settings)
-    internals.settings.setAllowDisplayOfInsecureContent(true);
-
 function do_test(referrer, value, expected, name)
 {
     test(() => {
index c78fb78..05e2210 100644 (file)
@@ -22,6 +22,10 @@ promise_test(function(t) {
 
     return service_worker_unregister_and_register(t, script, scope)
       .then(function(registration) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return wait_for_state(t, registration.installing, 'activated');
         })
       .then(function() {
@@ -34,7 +38,6 @@ promise_test(function(t) {
       .then(function(result) {
           frame.remove();
           assert_equals(result, 'PASS');
-          return service_worker_unregister_and_done(t, scope);
         });
   }, 'respondWith() takes either a Response or a promise that resolves ' +
      'with a Response. Other values should raise a network error.');
index 824b6f3..932f903 100644 (file)
@@ -1,6 +1,7 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
 <title>respondWith with a response whose body is being loaded from the network by chunks</title>
+<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
index cd6861a..31fd616 100644 (file)
@@ -10,6 +10,10 @@ promise_test(function(t) {
 
     return service_worker_unregister_and_register(t, script, scope)
       .then(function(registration) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return wait_for_state(t, registration.installing, 'activated');
         })
       .then(function() {
@@ -28,7 +32,6 @@ promise_test(function(t) {
         })
       .then(function(message) {
           assert_equals(message, 'PASS');
-          return service_worker_unregister_and_done(t, scope);
         })
   }, 'respondWith() invokes stopImmediatePropagation()');
 </script>
index 969a3c9..d98fb22 100644 (file)
@@ -12,6 +12,10 @@ promise_test(function(t) {
     var iframe;
     return service_worker_unregister_and_register(t, workerscript, scope)
       .then(function(reg) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return wait_for_state(t, reg.installing, 'activated')
             .then(() => reg.active);
         })
@@ -27,7 +31,6 @@ promise_test(function(t) {
         })
       .then(function(frame) {
         assert_true(frame.contentDocument.body.innerHTML.includes("intercepted"));
-        service_worker_unregister_and_done(t, scope);
       })
   }, 'Fetch event handler throws after a successful respondWith()');
 
index 62aea66..2a731e4 100644 (file)
@@ -1,4 +1,6 @@
 
-
-FAIL CSS's base URL must be the request URL even when fetched from other URL. assert_equals: The base URL while loading the images referred from CSS must be the request URL of CSS. expected "https://localhost:9443/service-workers/service-worker/resources/dummy.png" but got "https://127.0.0.1:9443/service-workers/service-worker/resources/dummy.png"
+PASS global setup 
+FAIL base URL when service worker does respondWith(fetch(responseUrl)). assert_equals: referrer expected "https://localhost:9443/service-workers/service-worker/resources/fetch-request-css-base-url-style.css?fetch" but got "https://localhost:9443/service-workers/service-worker/resources/fetch-request-css-base-url-iframe.html?fetch"
+FAIL base URL when service worker does respondWith(new Response()). assert_equals: referrer expected "https://localhost:9443/service-workers/service-worker/resources/request-url-path/fetch-request-css-base-url-style.css?newResponse" but got "https://localhost:9443/service-workers/service-worker/resources/fetch-request-css-base-url-iframe.html?newResponse"
+PASS cleanup global state 
 
index 7feccfb..a08e0c7 100644 (file)
@@ -1,58 +1,87 @@
 <!DOCTYPE html>
-<title>Service Worker: CSS's base URL must be the request URL even when fetched from other URL</title>
+<title>Service Worker: CSS's base URL must be the response URL</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
-<script src="/common/get-host-info.sub.js"></script>
 <script src="resources/test-helpers.sub.js?pipe=sub"></script>
 <script>
-promise_test(function(t) {
-    var SCOPE = 'resources/fetch-request-css-base-url-iframe.html';
-    var SCRIPT = 'resources/fetch-request-css-base-url-worker.js';
-    var worker;
-    var testDonePromise;
-
-    return service_worker_unregister_and_register(t, SCRIPT, SCOPE)
-      .then(function(registration) {
-          t.add_cleanup(function() {
-              return service_worker_unregister(t, SCOPE);
-            });
-
-          worker = registration.installing;
-          return wait_for_state(t, worker, 'activated');
-        })
-      .then(function() {
-          return new Promise(function(resolve) {
-              var channel = new MessageChannel();
-              testDonePromise = new Promise(function(resolveTestDone) {
-                channel.port1.onmessage = t.step_func(function(msg) {
-                  if (msg.data.ready) {
-                    resolve();
-                    return;
-                  }
-                  var result = msg.data;
-                  var base = get_host_info()['HTTPS_ORIGIN'] + base_path();
-                  assert_equals(
-                    result.url,
-                    base + 'resources/dummy.png',
-                    'The base URL while loading the images referred from CSS ' +
-                    'must be the request URL of CSS.');
-                  assert_equals(
-                    result.referrer,
-                    base + 'resources/fetch-request-css-base-url-style.css',
-                    'While loading the image defined in CSS the referrer must ' +
-                    'be the request URL of CSS.');
-                  resolveTestDone();
-                });
-              });
-              worker.postMessage(
-                {port: channel.port2}, [channel.port2]);
-            });
-        })
-      .then(function() { return with_iframe(SCOPE); })
-      .then(function(f) {
-          return testDonePromise.then(function() {
-            f.remove();
-          });
-        });
-  }, 'CSS\'s base URL must be the request URL even when fetched from other URL.');
+const SCOPE = 'resources/fetch-request-css-base-url-iframe.html';
+const SCRIPT = 'resources/fetch-request-css-base-url-worker.js';
+let worker;
+
+var signalMessage;
+function getNextMessage() {
+  return new Promise(resolve => { signalMessage = resolve; });
+}
+
+promise_test(async (t) => {
+  const registration = await service_worker_unregister_and_register(
+      t, SCRIPT, SCOPE);
+  worker = registration.installing;
+  await wait_for_state(t, worker, 'activated');
+}, 'global setup');
+
+// Creates a test concerning the base URL of a stylesheet. It loads a
+// stylesheet from a controlled page. The stylesheet makes a subresource
+// request for an image. The service worker messages back the details of the
+// image request in order to test the base URL.
+//
+// The request URL for the stylesheet is under "resources/request-url-path/".
+// The service worker may respond in a way such that the response URL is
+// different to the request URL.
+function base_url_test(params) {
+  promise_test(async (t) => {
+    let frame;
+    t.add_cleanup(() => {
+      if (frame)
+        frame.remove();
+    });
+
+    // Ask the service worker to message this page once it gets the request
+    // for the image.
+    let channel = new MessageChannel();
+    const sawPong = getNextMessage();
+    channel.port1.onmessage = (event) => {
+      signalMessage(event.data);
+    };
+    worker.postMessage({port:channel.port2},[channel.port2]);
+
+    // It sends a pong back immediately. This ping/pong protocol helps deflake
+    // the test for browsers where message/fetch ordering isn't guaranteed.
+    assert_equals('pong', await sawPong);
+
+    // Load the frame which will load the stylesheet that makes the image
+    // request.
+    const sawResult = getNextMessage();
+    frame = await with_iframe(params.framePath);
+    const result = await sawResult;
+
+    // Test the image request.
+    const base = new URL('.', document.location).href;
+    assert_equals(result.url,
+                  base + params.expectImageRequestPath,
+                  'request');
+    assert_equals(result.referrer,
+                  base + params.expectImageRequestReferrer,
+                  'referrer');
+  }, params.description);
+}
+
+const cssFile = 'fetch-request-css-base-url-style.css';
+
+base_url_test({
+  framePath: SCOPE + '?fetch',
+  expectImageRequestPath: 'resources/dummy.png',
+  expectImageRequestReferrer: `resources/${cssFile}?fetch`,
+  description: 'base URL when service worker does respondWith(fetch(responseUrl)).'});
+
+base_url_test({
+  framePath: SCOPE + '?newResponse',
+  expectImageRequestPath: 'resources/request-url-path/dummy.png',
+  expectImageRequestReferrer: `resources/request-url-path/${cssFile}?newResponse`,
+  description: 'base URL when service worker does respondWith(new Response()).'});
+
+// Cleanup step: this must be the last promise_test.
+promise_test(async (t) => {
+  return service_worker_unregister(t, SCOPE);
+}, 'cleanup global state');
 </script>
index e8e90cf..57fb8eb 100644 (file)
@@ -74,6 +74,8 @@ promise_test(function(t) {
     var frame;
     return service_worker_unregister_and_register(t, SCRIPT, SCOPE)
       .then(function(registration) {
+          t.add_cleanup(() => service_worker_unregister(t, SCOPE));
+
           worker = registration.installing;
           return wait_for_state(t, worker, 'activated');
         })
@@ -181,7 +183,6 @@ promise_test(function(t) {
         })
       .then(function() {
           frame.remove();
-          service_worker_unregister_and_done(t, SCOPE);
         });
   }, 'Verify redirect mode of Fetch API and ServiceWorker FetchEvent.');
 
@@ -208,6 +209,8 @@ promise_test(function(t) {
     var frame;
     return service_worker_unregister_and_register(t, SCRIPT, SCOPE)
       .then(function(registration) {
+          t.add_cleanup(() => service_worker_unregister(t, SCOPE));
+
           worker = registration.installing;
           return wait_for_state(t, worker, 'activated');
         })
@@ -275,7 +278,6 @@ promise_test(function(t) {
         })
       .then(function() {
           frame.remove();
-          service_worker_unregister_and_done(t, SCOPE);
         });
   }, 'Verify redirected of Response(Fetch API) and ServiceWorker FetchEvent.');
 
@@ -302,6 +304,8 @@ promise_test(function(t) {
     var frame;
     return service_worker_unregister_and_register(t, SCRIPT, SCOPE)
       .then(function(registration) {
+          t.add_cleanup(() => service_worker_unregister(t, SCOPE));
+
           worker = registration.installing;
           return wait_for_state(t, worker, 'activated');
         })
@@ -375,7 +379,6 @@ promise_test(function(t) {
         })
       .then(function() {
           frame.remove();
-          service_worker_unregister_and_done(t, SCOPE);
         });
   }, 'Verify redirected of Response(Fetch API), Cache API and ServiceWorker ' +
      'FetchEvent.');
index 9396662..25135dd 100644 (file)
@@ -4,4 +4,5 @@ PASS Register then getRegistration
 PASS Register then getRegistration with a URL having a fragment 
 PASS getRegistration with a cross origin URL 
 PASS Register then Unregister then getRegistration 
+PASS Register then Unregister then getRegistration in controlled iframe 
 
index 72a2c25..634c2ef 100644 (file)
@@ -88,4 +88,21 @@ async_test(function(t) {
       .catch(unreached_rejection(t));
   }, 'Register then Unregister then getRegistration');
 
+
+promise_test(async function(t) {
+  const scope = 'resources/scope/getregistration/register-unregister';
+  const registration = await service_worker_unregister_and_register(
+    t, 'resources/empty-worker.js', scope
+  );
+
+  const frame = await with_iframe(scope);
+  t.add_cleanup(() => frame.remove());
+
+  const frameNav = frame.contentWindow.navigator;
+  await registration.unregister();
+  const value = await frameNav.serviceWorker.getRegistration(scope);
+
+  assert_equals(value, undefined, 'getRegistration should resolve with undefined');
+}, 'Register then Unregister then getRegistration in controlled iframe');
+
 </script>
index a5e2678..4742bd0 100644 (file)
@@ -1,23 +1,34 @@
 <!DOCTYPE html>
-<meta charset="utf-8">
+<meta charset="utf-8" />
 <title>Tests for importScripts: script resource map</title>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
 <body>
-<script>
-// This test registers a worker that imports a script multiple times. The
-// script should be stored on the first import and thereafter that stored
-// script should be loaded. The worker asserts that the stored script was
-// loaded; if the assert fails then registration fails.
-promise_test(t => {
-    const scope = 'resources/import-scripts-resource-map';
-    return service_worker_unregister(t, scope)
-      .then(() => {
-          return navigator.serviceWorker.register(
-              'resources/import-scripts-resource-map-worker.js', {scope: scope});
-        })
-      .then(r => r.unregister());
-  }, 'import the same script URL multiple times');
-</script>
+  <script>
+    // This test registers a worker that imports a script multiple times. The
+    // script should be stored on the first import and thereafter that stored
+    // script should be loaded. The worker asserts that the stored script was
+    // loaded; if the assert fails then registration fails.
+
+    promise_test(async t => {
+      const SCOPE = "resources/import-scripts-resource-map";
+      const SCRIPT = "resources/import-scripts-resource-map-worker.js";
+      await service_worker_unregister(t, SCOPE);
+      const registration = await navigator.serviceWorker.register(SCRIPT, {
+        scope: SCOPE
+      });
+      await registration.unregister();
+    }, "import the same script URL multiple times");
+
+    promise_test(async t => {
+      const SCOPE = "resources/import-scripts-diff-resource-map";
+      const SCRIPT = "resources/import-scripts-diff-resource-map-worker.js";
+      await service_worker_unregister(t, SCOPE);
+      const registration = await navigator.serviceWorker.register(SCRIPT, {
+        scope: SCOPE
+      });
+      await registration.unregister();
+    }, "call importScripts() with multiple arguments");
+  </script>
 </body>
index 2c131b3..f70cf40 100644 (file)
@@ -1,5 +1,6 @@
 <!DOCTYPE html>
 <title>Service Worker: Interfaces</title>
+<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="/resources/WebIDLParser.js"></script>
index 84aac95..6a83f73 100644 (file)
@@ -15,6 +15,10 @@ promise_test(function(t) {
 
     return service_worker_unregister_and_register(t, expected_url, scope)
       .then(function(r) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           registration = r;
           return wait_for_state(t, registration.installing, 'activated');
         })
@@ -85,8 +89,6 @@ promise_test(function(t) {
                         'waiting should be null after activated.');
           assert_equals(registration.active.scriptURL, expected_url,
                         'active should still exist after update found.');
-
-          return service_worker_unregister_and_done(t, scope);
         });
   }, 'Trigger multiple updates.');
 </script>
index e8b8e9a..d7d3d52 100644 (file)
@@ -668,6 +668,24 @@ redirect_test(
     'SW-fetched redirect to other-origin in-scope.');
 
 
+// SW responds with a fetch from a different url.
+// SW: event.respondWith(fetch(params['url']));
+url2 = SCOPE1;
+url1 = SCOPE1 + 'sw=fetch-url&url=' + encodeURIComponent(url2);
+redirect_test(
+    url1,
+    url1,
+    [
+      [
+        {url: url1, resultingClientIdTag: 'x'}
+      ],
+      [],
+      []
+    ],
+    'x',
+    'SW-fetched response from different URL, same-origin same-scope.');
+
+
 // Opaque redirect.
 // SW: event.respondWith(fetch(
 //         new Request(event.request.url, {redirect: 'manual'})));
index b66d4a8..1fe19da 100644 (file)
@@ -17,7 +17,11 @@ promise_test(t => {
   let slowURL = url + '&slow';
   let frame;
   return service_worker_unregister_and_register(t, script, scope)
-    .then(reg => wait_for_state(t, reg.installing, 'activated'))
+    .then(reg => {
+        t.add_cleanup(() => service_worker_unregister(t, scope));
+
+        return wait_for_state(t, reg.installing, 'activated');
+      })
     .then(_ => with_iframe(scope))
     .then(f => {
       frame = f;
@@ -39,7 +43,6 @@ promise_test(t => {
       assert_greater_than(slowURLTime, urlTime + 1000,
                   'Slow service worker request should measure increased delay.');
       frame.remove();
-      return service_worker_unregister_and_done(t, scope);
     })
 }, 'empty service worker fetch event included in performance timings');
 
index caa4f94..83e5f45 100644 (file)
@@ -141,12 +141,12 @@ function client_message_queue_enable_test(
     earliest_dispatch,
     description)
 {
-    function later_state(state1, state2) {
+    function assert_state_less_than_equal(state1, state2, explanation) {
         const states = ['init', 'install', 'start', 'finish', 'loaded'];
         const index1 = states.indexOf(state1);
         const index2 = states.indexOf(state2);
-        const max_index = Math.max(index1, index2);
-        return states[max_index];
+        if (index1 > index2)
+          assert_unreached(explanation);
     }
 
     client_message_queue_test('enable-client-message-queue.html', async t => {
@@ -161,12 +161,13 @@ function client_message_queue_enable_test(
 
         // Wait for all messages to get dispatched on the child's
         // ServiceWorkerContainer and then verify that each message
-        // was dispatched while the child was in the correct state.
+        // was dispatched after |earliest_dispatch|.
         const report = await t.frame.report;
         ['init', 'install', 'start'].forEach(state => {
-            const dispatch = later_state(state, earliest_dispatch);
-            assert_equals(report[state], dispatch,
-                          `Message sent in state '${state}' dispatched in state '${dispatch}'`);
+            const explanation = `Message sent in state '${state}' was dispatched in '${report[state]}', should be dispatched no earlier than '${earliest_dispatch}'`;
+            assert_state_less_than_equal(earliest_dispatch,
+                                         report[state],
+                                         explanation);
         });
     }, description);
 }
index 561541b..79abe42 100644 (file)
@@ -3,4 +3,5 @@ PASS postMessage to a ServiceWorker (and back via MessagePort)
 PASS postMessage a transferable ArrayBuffer between ServiceWorker and Client 
 PASS postMessage a transferable ArrayBuffer between ServiceWorker and Client over MessagePort 
 FAIL postMessage with dictionary a transferable ArrayBuffer between ServiceWorker and Client promise_test: Unhandled rejection with value: object "TypeError: Type error"
+FAIL postMessage to a redundant worker promise_test: Unhandled rejection with value: object "InvalidStateError: Service Worker state is redundant"
 
index b1f3342..7abb302 100644 (file)
@@ -39,15 +39,6 @@ promise_test(t => {
       .then(e => {
           assert_equals(e.data, 'quit');
           return registration.unregister(scope);
-        })
-      .then(() => { return wait_for_state(t, worker, 'redundant'); })
-      .then(() => {
-          assert_equals(worker.state, 'redundant');
-          assert_throws(
-            {name:'InvalidStateError'},
-            function() { worker.postMessage(''); },
-            'Calling postMessage on a redundant ServiceWorker should ' +
-                'throw InvalidStateError.');
         });
   }, 'postMessage to a ServiceWorker (and back via MessagePort)');
 
@@ -178,4 +169,34 @@ promise_test(t => {
         });
   }, 'postMessage with dictionary a transferable ArrayBuffer between ServiceWorker and Client');
 
+  promise_test(async t => {
+    const firstScript = 'resources/postmessage-echo-worker.js?one';
+    const secondScript = 'resources/postmessage-echo-worker.js?two';
+    const scope = 'resources/';
+
+    const registration = await service_worker_unregister_and_register(t, firstScript, scope);
+    t.add_cleanup(() => registration.unregister());
+    const firstWorker = registration.installing;
+
+    const messagePromise = new Promise(resolve => {
+      navigator.serviceWorker.addEventListener('message', (event) => {
+        resolve(event.data);
+      }, {once: true});
+    });
+
+    await wait_for_state(t, firstWorker, 'activated');
+    await navigator.serviceWorker.register(secondScript, {scope});
+    const secondWorker = registration.installing;
+    await wait_for_state(t, firstWorker, 'redundant');
+
+    // postMessage() to a redundant worker should be dropped silently.
+    // Historically, this threw an exception.
+    firstWorker.postMessage('firstWorker');
+
+    // To test somewhat that it was not received, send a message to another
+    // worker and check that we get a reply for that one.
+    secondWorker.postMessage('secondWorker');
+    const data = await messagePromise;
+    assert_equals(data, 'secondWorker');
+  }, 'postMessage to a redundant worker');
 </script>
index aaee3de..cd41363 100644 (file)
@@ -9,5 +9,6 @@ PASS ready on an iframe whose parent registers a new service worker
 PASS ready on an iframe that installs a new service worker 
 PASS ready after a longer matched registration registered 
 PASS access ready after it has been resolved 
-PASS access ready on uninstalling registration that is resurrected 
+FAIL resolve ready after unregistering and reregistering assert_not_equals: Registrations should be different got disallowed value object "[object ServiceWorkerRegistration]"
+FAIL resolve ready before unregistering and reregistering assert_equals: Resolves with the first registration expected "https://localhost:9443/service-workers/service-worker/resources/empty-worker.js" but got "https://localhost:9443/service-workers/service-worker/resources/empty-worker.js?2"
 
index ff5c793..6c1ed82 100644 (file)
@@ -250,51 +250,68 @@ promise_test(function(t) {
   }, 'access ready after it has been resolved');
 
 promise_test(async function(t) {
-    var url = 'resources/empty-worker.js';
-    var matched_scope = 'resources/blank.html?ready-after-resurrect';
-
-    let reg1 = await service_worker_unregister_and_register(t, url, matched_scope);
-    add_completion_callback(function() {
-        reg1.unregister();
-      });
-    await wait_for_state(t, reg1.installing, 'activated');
-
-    // Hold the worker alive with a controlled worker
-    let frame = await with_iframe(matched_scope);
-    add_completion_callback(function() {
-        frame.remove();
-      });
-
-    // Doom the registration as uninstalling.
-    await reg1.unregister();
-
-    // Access the ready promise while the registration is doomed.
-    let readyPromise = frame.contentWindow.navigator.serviceWorker.ready;
-
-    // Resurrect the doomed registration;
-    let reg2 = await service_worker_unregister_and_register(t, url, matched_scope);
-    assert_equals(reg1, reg2, 'existing registration should be resurrected');
-
-    // We are trying to test if the ready promise ever resolves here.  Use
-    // an explicit timeout check here rather than forcing a full infrastructure
-    // level timeout.
-    let timeoutId;
-    let timeoutPromise = new Promise(resolve => {
-      timeoutId = setTimeout(_ => {
-        timeoutId = null;
-        resolve();
-      }, 500);
-    });
-
-    // This should resolve immediately since there is an alive registration
-    // with an active promise for the matching scope.
-    await Promise.race([readyPromise, timeoutPromise]);
-
-    assert_not_equals(timeoutId, null,
-                      'ready promise should resolve before timeout');
-    clearTimeout(timeoutId);
-
-    // We should get here and not time out.
-
-  }, 'access ready on uninstalling registration that is resurrected');
+  const url1 = 'resources/empty-worker.js';
+  const url2 = url1 + '?2';
+  const matched_scope = 'resources/blank.html?ready-after-unregister';
+
+  const reg1 = await service_worker_unregister_and_register(t, url1, matched_scope);
+  t.add_cleanup(() => reg1.unregister());
+
+  await wait_for_state(t, reg1.installing, 'activating');
+  // This registration will resolve all ready promises in clients that match the scope.
+  // But there are no clients.
+
+  const frame = await with_iframe(matched_scope);
+  t.add_cleanup(() => frame.remove());
+
+  await reg1.unregister();
+
+  // Access the ready promise while the registration is unregistering.
+  const readyPromise = frame.contentWindow.navigator.serviceWorker.ready;
+
+  // Create a new registration.
+  const reg2 = await navigator.serviceWorker.register(url2, { scope: matched_scope });
+  t.add_cleanup(() => reg2.unregister());
+  // This registration will resolve all ready promises in clients that match the scope.
+  // That includes frame's client.
+
+  const readyReg = await readyPromise;
+
+  assert_equals(readyReg.active.scriptURL, reg2.active.scriptURL, 'Resolves with the second registration');
+  assert_not_equals(reg1, reg2, 'Registrations should be different');
+}, 'resolve ready after unregistering and reregistering');
+
+promise_test(async function(t) {
+  const url1 = 'resources/empty-worker.js';
+  const url2 = url1 + '?2';
+  const matched_scope = 'resources/blank.html?ready-after-unregister';
+
+  const frame = await with_iframe(matched_scope);
+  t.add_cleanup(() => frame.remove());
+
+  const reg1 = await service_worker_unregister_and_register(t, url1, matched_scope);
+  t.add_cleanup(() => reg1.unregister());
+
+  await wait_for_state(t, reg1.installing, 'activated');
+  // This registration will resolve all ready promises in clients that match the scope.
+  // That includes frame's client.
+
+  const reg1Active = reg1.active;
+
+  await reg1.unregister();
+
+  // Access the ready promise while the registration is unregistering.
+  const readyPromise = frame.contentWindow.navigator.serviceWorker.ready;
+
+  // Create a new registration.
+  const reg2 = await navigator.serviceWorker.register(url2, { scope: matched_scope });
+  t.add_cleanup(() => reg2.unregister());
+  // This registration will resolve all ready promises in clients that match the scope.
+  // That includes frame's client, but its ready promise has already resolved.
+
+  const readyReg = await readyPromise;
+
+  assert_equals(readyReg.active.scriptURL, reg1Active.scriptURL, 'Resolves with the first registration');
+  assert_not_equals(reg1, reg2, 'Registrations should be different');
+}, 'resolve ready before unregistering and reregistering');
 </script>
index dc136d4..1d86548 100644 (file)
@@ -52,8 +52,11 @@ promise_test(function(t) {
       })
       .then(
         function(registration) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, registration.scope);
+            });
+
           assert_unreached('register should fail');
-          service_worker_unregister_and_done(t, registration.scope);
         },
         function(error) {
           assert_equals(error.name, 'SecurityError',
index e23f9f4..0920b5c 100644 (file)
@@ -16,6 +16,10 @@ promise_test(function(t) {
 
     return navigator.serviceWorker.register(bad_script, {scope: scope})
       .then(function(r) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           registration = r;
           assert_equals(registration.installing.scriptURL,
                         normalizeURL(bad_script));
@@ -47,9 +51,6 @@ promise_test(function(t) {
                         normalizeURL(good_script));
           return wait_for_state(t, registration.installing, 'activated');
         })
-      .then(function() {
-          return service_worker_unregister_and_done(t, scope);
-        })
   }, 'register worker that calls waitUntil with a promise that never ' +
      'resolves in oninstall');
 
index e92b650..1af4582 100644 (file)
@@ -11,16 +11,11 @@ t.step(function() {
     var serviceWorkerStates = [];
     var lastServiceWorkerState = '';
     var receivedMessageFromPort = '';
-    var currentChangeCount = 0;
 
     assert_true(navigator.serviceWorker instanceof ServiceWorkerContainer);
     assert_equals(typeof navigator.serviceWorker.register, 'function');
     assert_equals(typeof navigator.serviceWorker.getRegistration, 'function');
 
-    navigator.serviceWorker.oncurrentchange = function() {
-        ++currentChangeCount;
-    };
-
     service_worker_unregister_and_register(
         t, 'resources/end-to-end-worker.js', scope)
       .then(onRegister)
@@ -75,9 +70,6 @@ t.step(function() {
                                 ['installing', 'installed', 'activating', 'activated'],
                                 'Service worker should pass through all states');
 
-            assert_equals(currentChangeCount, 0,
-                          'Should not see current changes since document is out of scope');
-
             assert_equals(receivedMessageFromPort, 'Ack for: registering doc');
 
             var sawRedundant = new Promise(t.step_func(function(resolve) {
index 9ae5f09..aa9d38c 100644 (file)
@@ -1,5 +1,6 @@
 <!DOCTYPE html>
 <title>Service Worker: Registration (MIME types)</title>
+<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/registration-schedule-job.https-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/registration-schedule-job.https-expected.txt
new file mode 100644 (file)
index 0000000..b169bcf
--- /dev/null
@@ -0,0 +1,4 @@
+
+FAIL different scriptURL and updateViaCache promise_test: Unhandled rejection with value: object "TypeError: null is not an object (evaluating 'registration.installing.scriptURL')"
+FAIL different type assert_equals: expected (string) "classic" but got (undefined) undefined
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/registration-schedule-job.https.html b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/registration-schedule-job.https.html
new file mode 100644 (file)
index 0000000..18589e0
--- /dev/null
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Service Worker: Schedule Job algorithm</title>
+<script src="/resources/testharness.js"></script>
+<script src="resources/testharness-helpers.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script>
+// Tests for https://w3c.github.io/ServiceWorker/#schedule-job-algorithm
+// Non-equivalent register jobs should not be coalesced.
+const scope = 'resources/';
+const script1 = 'resources/empty.js';
+const script2 = 'resources/empty.js?change';
+
+async function cleanup() {
+  const registration = await navigator.serviceWorker.getRegistration(scope);
+  if (registration)
+    await registration.unregister();
+}
+
+function absolute_url(url) {
+  return new URL(url, self.location).toString();
+}
+
+// Test scriptURL and updateViaCache.
+promise_test(async t => {
+  await cleanup();
+  t.add_cleanup(cleanup);
+
+  // Check defaults.
+  const registration = await
+      navigator.serviceWorker.register(script1, {scope});
+  assert_equals(registration.updateViaCache, 'imports');
+
+  // Schedule several register jobs.
+  navigator.serviceWorker.register(script1, {scope});
+  navigator.serviceWorker.register(script2, {scope});
+  await navigator.serviceWorker.register(script2,
+                                         {scope, updateViaCache: 'none'});
+
+  // None of the changes should have been coalesced.
+  assert_equals(registration.installing.scriptURL, absolute_url(script2));
+  assert_equals(registration.updateViaCache, 'none');
+}, 'different scriptURL and updateViaCache');
+
+// Test |type| in another test case because most browsers don't support it.
+promise_test(async t => {
+  const script1 = 'resources/empty.js';
+  const script2 = 'resources/empty.js?change';
+
+  await cleanup();
+  t.add_cleanup(cleanup);
+
+  // Check defaults.
+  const registration = await
+      navigator.serviceWorker.register(script1, {scope});
+  assert_equals(registration.installing.type, 'classic');
+
+  // Schedule several register jobs.
+  navigator.serviceWorker.register(script1, {scope});
+  navigator.serviceWorker.register(script2, {scope});
+  await navigator.serviceWorker.register(script2, {scope, type: 'module'});
+
+  // None of the changes should have been coalesced.
+  assert_equals(registration.installing.scriptURL, absolute_url(script2));
+  assert_equals(registration.installing.type, 'module');
+}, 'different type');
+</script>
index c90d094..c6e8675 100644 (file)
@@ -23,4 +23,5 @@ PASS access-updateViaCache-after-unregister-undefined
 PASS access-updateViaCache-after-unregister-imports 
 PASS access-updateViaCache-after-unregister-all 
 PASS access-updateViaCache-after-unregister-none 
+FAIL updateViaCache is not updated if register() rejects assert_equals: after update attempt expected "imports" but got "none"
 
index dbcc6ea..423908d 100644 (file)
     }, testName);
   }
 
+  promise_test(async t => {
+    await cleanup();
+    t.add_cleanup(cleanup);
+
+    const registration = await navigator.serviceWorker.register(
+        'resources/empty.js',
+        {scope: SCOPE});
+    assert_equals(registration.updateViaCache, 'imports',
+                  'before update attempt');
+
+    const fail = navigator.serviceWorker.register(
+        'resources/malformed-worker.py?parse-error',
+        {scope: SCOPE, updateViaCache: 'none'});
+    await promise_rejects(t, new TypeError(), fail);
+    assert_equals(registration.updateViaCache, 'imports',
+                  'after update attempt');
+  }, 'updateViaCache is not updated if register() rejects');
 </script>
index a9f89d3..f0502ca 100644 (file)
@@ -14,7 +14,7 @@ function crossOriginUrl(path) {
 function verify(options) {
     const url = options.mode === 'cross-origin' ? crossOriginUrl(options.resource)
                                       : resourceUrl(options.resource);
-    const entryList = options.performance.getEntriesByName(url);
+    const entryList = options.performance.getEntriesByName(url, 'resource');
     if (options.should_no_performance_entry) {
         // The performance timeline may not have an entry for a resource
         // which failed to load.
@@ -136,7 +136,7 @@ promise_test(function(t) {
 
 test(() => {
     const url = resourceUrl('resources/test-helpers.sub.js');
-    const entry = window.performance.getEntriesByName(url)[0];
+    const entry = window.performance.getEntriesByName(url, 'resource')[0];
     assert_equals(entry.workerStart, 0, 'Non-controlled');
 }, 'Non-controlled resource loads');
 
index 53f210c..1800407 100644 (file)
@@ -14,5 +14,6 @@ self.addEventListener('message', function(event) {
   });
 
 self.addEventListener('fetch', function(event) {
-    event.respondWith(new Response('Intercepted!'));
-});
+    if (!/404/.test(event.request.url))
+      event.respondWith(new Response('Intercepted!'));
+  });
index abf5493..8a975b0 100644 (file)
@@ -1,4 +1,12 @@
-// controlled by 'init'/'done' messages.
+// This worker calls waitUntil() and respondWith() asynchronously and
+// reports back to the test whether they threw.
+//
+// These test cases are confusing. Bear in mind that the event is active
+// (calling waitUntil() is allowed) if:
+// * The pending promise count is not 0, or
+// * The event dispatch flag is set.
+
+// Controlled by 'init'/'done' messages.
 var resolveLockPromise;
 var port;
 
@@ -14,34 +22,72 @@ self.addEventListener('message', function(event) {
       case 'done':
         resolveLockPromise();
         break;
+
+      // Throws because waitUntil() is called in a task after event dispatch
+      // finishes.
       case 'no-current-extension-different-task':
         async_task_waituntil(event).then(reportResultExpecting('InvalidStateError'));
         break;
+
+      // OK because waitUntil() is called in a microtask that runs after the
+      // event handler runs, while the event dispatch flag is still set.
       case 'no-current-extension-different-microtask':
-        async_microtask_waituntil(event).then(reportResultExpecting('InvalidStateError'));
+        async_microtask_waituntil(event).then(reportResultExpecting('OK'));
         break;
+
+      // OK because the second waitUntil() is called while the first waitUntil()
+      // promise is still pending.
       case 'current-extension-different-task':
         event.waitUntil(new Promise((res) => { resolveTestPromise = res; }));
         async_task_waituntil(event).then(reportResultExpecting('OK')).then(resolveTestPromise);
         break;
-      case 'current-extension-expired-same-microtask-turn':
+
+      // OK because all promises involved resolve "immediately", so the second
+      // waitUntil() is called during the microtask checkpoint at the end of
+      // event dispatching, when the event dispatch flag is still set.
+      case 'during-event-dispatch-current-extension-expired-same-microtask-turn':
         waitPromise = Promise.resolve();
         event.waitUntil(waitPromise);
         waitPromise.then(() => { return sync_waituntil(event); })
           .then(reportResultExpecting('OK'))
         break;
-      case 'current-extension-expired-same-microtask-turn-extra':
-        // The promise handler queues a new microtask *after* the check for new
-        // extensions was performed.
+
+      // OK for the same reason as above.
+      case 'during-event-dispatch-current-extension-expired-same-microtask-turn-extra':
         waitPromise = Promise.resolve();
         event.waitUntil(waitPromise);
         waitPromise.then(() => { return async_microtask_waituntil(event); })
+          .then(reportResultExpecting('OK'))
+        break;
+
+
+      // OK because the pending promise count is decremented in a microtask
+      // queued upon fulfillment of the first waitUntil() promise, so the second
+      // waitUntil() is called while the pending promise count is still
+      // positive.
+      case 'after-event-dispatch-current-extension-expired-same-microtask-turn':
+        waitPromise = makeNewTaskPromise();
+        event.waitUntil(waitPromise);
+        waitPromise.then(() => { return sync_waituntil(event); })
+          .then(reportResultExpecting('OK'))
+        break;
+
+      // Throws because the second waitUntil() is called after the pending
+      // promise count was decremented to 0.
+      case 'after-event-dispatch-current-extension-expired-same-microtask-turn-extra':
+        waitPromise = makeNewTaskPromise();
+        event.waitUntil(waitPromise);
+        waitPromise.then(() => { return async_microtask_waituntil(event); })
           .then(reportResultExpecting('InvalidStateError'))
         break;
+
+      // Throws because the second waitUntil() is called in a new task, after
+      // first waitUntil() promise settled and the event dispatch flag is unset.
       case 'current-extension-expired-different-task':
         event.waitUntil(Promise.resolve());
         async_task_waituntil(event).then(reportResultExpecting('InvalidStateError'));
         break;
+
       case 'script-extendable-event':
         self.dispatchEvent(new ExtendableEvent('nontrustedevent'));
         break;
@@ -51,25 +97,62 @@ self.addEventListener('message', function(event) {
   });
 
 self.addEventListener('fetch', function(event) {
-    if (event.request.url.indexOf('pending-respondwith-async-waituntil') != -1) {
+  const path = new URL(event.request.url).pathname;
+  const step = path.substring(path.lastIndexOf('/') + 1);
+  let response;
+  switch (step) {
+    // OK because waitUntil() is called while the respondWith() promise is still
+    // unsettled, so the pending promise count is positive.
+    case 'pending-respondwith-async-waituntil':
       var resolveFetch;
-      let response = new Promise((res) => { resolveFetch = res; });
+      response = new Promise((res) => { resolveFetch = res; });
       event.respondWith(response);
       async_task_waituntil(event)
         .then(reportResultExpecting('OK'))
         .then(() => { resolveFetch(new Response('OK')); });
-    } else if (event.request.url.indexOf('respondwith-microtask-sync-waituntil') != -1) {
+      break;
+
+    // OK because all promises involved resolve "immediately", so waitUntil() is
+    // called during the microtask checkpoint at the end of event dispatching,
+    // when the event dispatch flag is still set.
+    case 'during-event-dispatch-respondwith-microtask-sync-waituntil':
       response = Promise.resolve(new Response('RESP'));
       event.respondWith(response);
       response.then(() => { return sync_waituntil(event); })
-        .then(reportResultExpecting('OK'))
-    } else if (event.request.url.indexOf('respondwith-microtask-async-waituntil') != -1) {
+        .then(reportResultExpecting('OK'));
+      break;
+
+    // OK because all promises involved resolve "immediately", so waitUntil() is
+    // called during the microtask checkpoint at the end of event dispatching,
+    // when the event dispatch flag is still set.
+    case 'during-event-dispatch-respondwith-microtask-async-waituntil':
       response = Promise.resolve(new Response('RESP'));
       event.respondWith(response);
       response.then(() => { return async_microtask_waituntil(event); })
+        .then(reportResultExpecting('OK'));
+      break;
+
+    // OK because the pending promise count is decremented in a microtask queued
+    // upon fulfillment of the respondWith() promise, so waitUntil() is called
+    // while the pending promise count is still positive.
+    case 'after-event-dispatch-respondwith-microtask-sync-waituntil':
+      response = makeNewTaskPromise().then(() => {return new Response('RESP');});
+      event.respondWith(response);
+      response.then(() => { return sync_waituntil(event); })
+        .then(reportResultExpecting('OK'));
+      break;
+
+
+    // Throws because waitUntil() is called after the pending promise count was
+    // decremented to 0.
+    case 'after-event-dispatch-respondwith-microtask-async-waituntil':
+      response = makeNewTaskPromise().then(() => {return new Response('RESP');});
+      event.respondWith(response);
+      response.then(() => { return async_microtask_waituntil(event); })
         .then(reportResultExpecting('InvalidStateError'))
-    }
-  });
+      break;
+  }
+});
 
 self.addEventListener('nontrustedevent', function(event) {
     sync_waituntil(event).then(reportResultExpecting('InvalidStateError'));
@@ -118,3 +201,10 @@ function async_task_waituntil(event) {
     }, 0);
   });
 }
+
+// Returns a promise that settles in a separate task.
+function makeNewTaskPromise() {
+  return new Promise(resolve => {
+    setTimeout(resolve, 0);
+  });
+}
index 7f66d20..dc3f1a1 100644 (file)
@@ -1,19 +1,66 @@
-var result;
+// This worker attempts to call respondWith() asynchronously after the
+// fetch event handler finished. It reports back to the test whether
+// an exception was thrown.
 
-self.addEventListener('message', function(event) {
-    event.data.port.postMessage(result);
+// These get reset at the start of a test case.
+let reportResult;
+
+// The test page sends a message to tell us that a new test case is starting.
+// We expect a fetch event after this.
+self.addEventListener('message', (event) => {
+  // Ensure tests run mutually exclusive.
+  if (reportResult) {
+    event.source.postMessage('testAlreadyRunning');
+    return;
+  }
+
+  const resultPromise = new Promise((resolve) => {
+    reportResult = resolve;
+    // Tell the client that everything is initialized and that it's safe to
+    // proceed with the test without relying on the order of events (which some
+    // browsers like Chrome may not guarantee).
+    event.source.postMessage('messageHandlerInitialized');
   });
 
-self.addEventListener('fetch', function(event) {
-    setTimeout(function() {
-        try {
-          event.respondWith(new Response());
-          result = 'FAIL: did not throw';
-        } catch (error) {
-          if (error.name == 'InvalidStateError')
-            result = 'PASS';
-          else
-            result = 'FAIL: Unexpected exception: ' + error;
-        }
-      }, 0);
+  // Keep the worker alive until the test case finishes, and report
+  // back the result to the test page.
+  event.waitUntil(resultPromise.then(result => {
+    reportResult = null;
+    event.source.postMessage(result);
+  }));
+});
+
+// Calls respondWith() and reports back whether an exception occurred.
+function tryRespondWith(event) {
+  try {
+    event.respondWith(new Response());
+    reportResult({didThrow: false});
+  } catch (error) {
+    reportResult({didThrow: true, error: error.name});
+  }
+}
+
+function respondWithInTask(event) {
+  setTimeout(() => {
+    tryRespondWith(event);
+  }, 0);
+}
+
+function respondWithInMicrotask(event) {
+  Promise.resolve().then(() => {
+    tryRespondWith(event);
   });
+}
+
+self.addEventListener('fetch', function(event) {
+  const path = new URL(event.request.url).pathname;
+  const test = path.substring(path.lastIndexOf('/') + 1);
+
+  // If this is a test case, try respondWith() and report back to the test page
+  // the result.
+  if (test == 'respondWith-in-task') {
+    respondWithInTask(event);
+  } else if (test == 'respondWith-in-microtask') {
+    respondWithInMicrotask(event);
+  }
+});
index 0edf2e7..504e104 100644 (file)
@@ -1 +1,20 @@
-<link href="./fetch-request-css-base-url-style.css" rel="stylesheet" type="text/css">
+<html>
+<head>
+<title>iframe for css base url test</title>
+</head>
+<body>
+<script>
+// Load a stylesheet. Create it dynamically so we can construct the href URL
+// dynamically.
+const link = document.createElement('link');
+link.rel = 'stylesheet';
+link.type = 'text/css';
+// Add "request-url-path" to the path to help distinguish the request URL from
+// the response URL. Add |document.location.search| (chosen by the test main
+// page) to tell the service worker how to respond to the request.
+link.href = 'request-url-path/fetch-request-css-base-url-style.css' +
+    document.location.search;
+document.head.appendChild(link);
+</script>
+</body>
+</html>
index 91c3259..e8dbd27 100644 (file)
@@ -1,27 +1,45 @@
-importScripts('/common/get-host-info.sub.js');
-importScripts('test-helpers.sub.js');
+let source;
+let resolveDone;
+let done = new Promise(resolve => resolveDone = resolve);
 
-var port = undefined;
+// The page messages this worker to ask for the result. Keep the worker alive
+// via waitUntil() until the result is sent.
+self.addEventListener('message', event => {
+  source = event.data.port;
+  source.postMessage('pong');
+  event.waitUntil(done);
+});
 
-self.onmessage = function(e) {
-  var message = e.data;
-  if ('port' in message) {
-    port = message.port;
-    port.postMessage({ready: true});
-  }
-};
+self.addEventListener('fetch', event => {
+  const url = new URL(event.request.url);
 
-self.addEventListener('fetch', function(event) {
-    var url = event.request.url;
-    if (url.indexOf('fetch-request-css-base-url-style.css') != -1) {
-      event.respondWith(fetch(
-        get_host_info()['HTTPS_REMOTE_ORIGIN'] + base_path() +
-        'fetch-request-css-base-url-style.css',
-        {mode: 'no-cors'}));
-    } else if (url.indexOf('dummy.png') != -1) {
-      port.postMessage({
-          url: event.request.url,
-          referrer: event.request.referrer
-        });
+  // For the CSS file, respond in a way that may change the response URL,
+  // depending on |url.search|.
+  const cssPath = 'request-url-path/fetch-request-css-base-url-style.css';
+  if (url.pathname.indexOf(cssPath) != -1) {
+    // Respond with a different URL, deleting "request-url-path/".
+    if (url.search == '?fetch') {
+      event.respondWith(fetch('fetch-request-css-base-url-style.css'));
+    }
+    // Respond with new Response().
+    else if (url.search == '?newResponse') {
+      const styleString = 'body { background-image: url("./dummy.png");}';
+      const headers = {'content-type': 'text/css'};
+      event.respondWith(new Response(styleString, headers));
     }
-  });
+  }
+
+  // The image request indicates what the base URL of the CSS was. Message the
+  // result back to the test page.
+  else if (url.pathname.indexOf('dummy.png') != -1) {
+    // For some reason |source| is undefined here when running the test manually
+    // in Firefox. The test author experimented with both using Client
+    // (event.source) and MessagePort to try to get the test to pass, but
+    // failed.
+    source.postMessage({
+      url: event.request.url,
+      referrer: event.request.referrer
+    });
+    resolveDone();
+  }
+});
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/get-resultingClientId-worker.js b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/get-resultingClientId-worker.js
new file mode 100644 (file)
index 0000000..f0e6c7b
--- /dev/null
@@ -0,0 +1,107 @@
+// This worker expects a fetch event for a navigation and messages back the
+// result of clients.get(event.resultingClientId).
+
+// Resolves when the test finishes.
+let testFinishPromise;
+let resolveTestFinishPromise;
+let rejectTestFinishPromise;
+
+// Resolves to clients.get(event.resultingClientId) from the fetch event.
+let getPromise;
+let resolveGetPromise;
+let rejectGetPromise;
+
+let resultingClientId;
+
+function startTest() {
+  testFinishPromise = new Promise((resolve, reject) => {
+    resolveTestFinishPromise = resolve;
+    rejectTestFinishPromise = reject;
+  });
+
+  getPromise = new Promise((resolve, reject) => {
+    resolveGetPromise = resolve;
+    rejectGetPromise = reject;
+  });
+}
+
+async function describeGetPromiseResult(promise) {
+  const result = {};
+
+  await promise.then(
+    (client) => {
+      result.promiseState = 'fulfilled';
+      if (client === undefined) {
+        result.promiseValue = 'undefinedValue';
+      } else if (client instanceof Client) {
+        result.promiseValue = 'client';
+        result.client = {
+          id:  client.id,
+          url: client.url
+        };
+      } else {
+        result.promiseValue = 'unknown';
+      }
+    },
+    (error) => {
+      result.promiseState = 'rejected';
+    });
+
+  return result;
+}
+
+async function handleGetResultingClient(event) {
+  // Note that this message can arrive before |resultingClientId| is populated.
+  const result = await describeGetPromiseResult(getPromise);
+  // |resultingClientId| must be populated by now.
+  result.queriedId = resultingClientId;
+  event.source.postMessage(result);
+};
+
+async function handleGetClient(event) {
+  const id = event.data.id;
+  const result = await describeGetPromiseResult(self.clients.get(id));
+  result.queriedId = id;
+  event.source.postMessage(result);
+};
+
+self.addEventListener('message', (event) => {
+  if (event.data.command == 'startTest') {
+    startTest();
+    event.waitUntil(testFinishPromise);
+    event.source.postMessage('ok');
+    return;
+  }
+
+  if (event.data.command == 'finishTest') {
+    resolveTestFinishPromise();
+    event.source.postMessage('ok');
+    return;
+  }
+
+  if (event.data.command == 'getResultingClient') {
+    event.waitUntil(handleGetResultingClient(event));
+    return;
+  }
+
+  if (event.data.command == 'getClient') {
+    event.waitUntil(handleGetClient(event));
+    return;
+  }
+});
+
+async function handleFetch(event) {
+  try {
+    resultingClientId = event.resultingClientId;
+    const client = await self.clients.get(resultingClientId);
+    resolveGetPromise(client);
+  } catch (error) {
+    rejectGetPromise(error);
+  }
+}
+
+self.addEventListener('fetch', (event) => {
+  if (event.request.mode != 'navigate')
+    return;
+  event.waitUntil(handleFetch(event));
+});
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/import-relative.xsl b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/import-relative.xsl
new file mode 100644 (file)
index 0000000..063a62d
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+    <xsl:import href="xslt-pass.xsl"/>
+</xsl:stylesheet>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/import-scripts-diff-resource-map-worker.js b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/import-scripts-diff-resource-map-worker.js
new file mode 100644 (file)
index 0000000..0fdcb0f
--- /dev/null
@@ -0,0 +1,10 @@
+importScripts('/resources/testharness.js');
+
+let echo1 = null;
+let echo2 = null;
+let arg1 = 'import-scripts-get.py?output=echo1&msg=test1';
+let arg2 = 'import-scripts-get.py?output=echo2&msg=test2';
+
+importScripts(arg1, arg2);
+assert_equals(echo1, 'test1');
+assert_equals(echo2, 'test2');
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/import-scripts-get.py b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/import-scripts-get.py
new file mode 100644 (file)
index 0000000..9e376bc
--- /dev/null
@@ -0,0 +1,6 @@
+def main(req, res):
+    return ([
+        ('Cache-Control', 'no-cache, must-revalidate'),
+        ('Pragma', 'no-cache'),
+        ('Content-Type', 'application/javascript')],
+        '%s = "%s";\n' % (req.GET['output'], req.GET['msg']))
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/postmessage-echo-worker.js b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/postmessage-echo-worker.js
new file mode 100644 (file)
index 0000000..f088ad1
--- /dev/null
@@ -0,0 +1,3 @@
+self.addEventListener('message', event => {
+  event.source.postMessage(event.data);
+});
index 5f06454..9d2b1f2 100644 (file)
@@ -17,6 +17,15 @@ test(function() {
                 'Importing the other origins script should fail.');
   }, 'importScripts test for default-src');
 
+test(function() {
+    assert_throws(EvalError(),
+                  function() { eval('1 + 1'); },
+                  'eval() should throw EvalError.')
+    assert_throws(EvalError(),
+                  function() { new Function('1 + 1'); },
+                  'new Function() should throw EvalError.')
+  }, 'eval test for default-src');
+
 async_test(function(t) {
     fetch(host_info.HTTPS_REMOTE_ORIGIN +
           base_path() + 'fetch-access-control.py?ACAOrigin=*',
@@ -63,6 +72,15 @@ test(function() {
                 'Importing the other origins script should fail.');
   }, 'importScripts test for script-src');
 
+test(function() {
+    assert_throws(EvalError(),
+                  function() { eval('1 + 1'); },
+                  'eval() should throw EvalError.')
+    assert_throws(EvalError(),
+                  function() { new Function('1 + 1'); },
+                  'new Function() should throw EvalError.')
+  }, 'eval test for script-src');
+
 async_test(function(t) {
     fetch(host_info.HTTPS_REMOTE_ORIGIN +
           base_path() + 'fetch-access-control.py?ACAOrigin=*',
@@ -109,6 +127,18 @@ test(function() {
                  'Importing the other origins script should not fail.');
   }, 'importScripts test for connect-src');
 
+test(function() {
+    var eval_failed = false;
+    try {
+      eval('1 + 1');
+      new Function('1 + 1');
+    } catch(e) {
+      eval_failed = true;
+    }
+    assert_false(eval_failed,
+                 'connect-src without unsafe-eval should not block eval().');
+  }, 'eval test for connect-src');
+
 async_test(function(t) {
     fetch(host_info.HTTPS_REMOTE_ORIGIN +
           base_path() + 'fetch-access-control.py?ACAOrigin=*',
index 7efde35..af8dad3 100644 (file)
@@ -75,9 +75,11 @@ function wait_for_update(test, registration) {
   }
 
   return new Promise(test.step_func(function(resolve) {
-      registration.addEventListener('updatefound', test.step_func(function() {
-          resolve(registration.installing);
-        }));
+      var handler = test.step_func(function() {
+        registration.removeEventListener('updatefound', handler);
+        resolve(registration.installing);
+      });
+      registration.addEventListener('updatefound', handler);
     }));
 }
 
@@ -276,3 +278,33 @@ async function wait_for_activation_on_dummy_scope(t, window_or_workerglobalscope
   await wait_for_state(t, registration.installing, 'activated');
   await registration.unregister();
 }
+
+// This installs resources/appcache-ordering.manifest.
+function install_appcache_ordering_manifest() {
+  let resolve_install_appcache;
+  let reject_install_appcache;
+
+  // This is notified by the child iframe, i.e. appcache-ordering.install.html,
+  // that's to be created below.
+  window.notify_appcache_installed = success => {
+    if (success)
+      resolve_install_appcache();
+    else
+      reject_install_appcache();
+  };
+
+  return new Promise((resolve, reject) => {
+      const frame = document.createElement('iframe');
+      frame.src = 'resources/appcache-ordering.install.html';
+      document.body.appendChild(frame);
+      resolve_install_appcache = function() {
+          document.body.removeChild(frame);
+          resolve();
+        };
+      reject_install_appcache = function() {
+          document.body.removeChild(frame);
+          reject();
+        };
+  });
+}
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/test-request-headers-worker.js b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/test-request-headers-worker.js
new file mode 100644 (file)
index 0000000..71aff5e
--- /dev/null
@@ -0,0 +1,7 @@
+// The server injects the request headers here as a JSON string.
+const headersAsJson = `%HEADERS%`;
+const headers = JSON.parse(headersAsJson);
+
+self.addEventListener('message', async (e) => {
+  e.source.postMessage(headers);
+});
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/test-request-headers-worker.py b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/test-request-headers-worker.py
new file mode 100644 (file)
index 0000000..5666f19
--- /dev/null
@@ -0,0 +1,16 @@
+import json
+import os
+
+def main(request, response):
+  path = os.path.join(os.path.dirname(__file__),
+                      "test-request-headers-worker.js")
+  body = open(path, "rb").read()
+
+  data = {key:request.headers[key] for key,value in request.headers.iteritems()}
+  body = body.replace("%HEADERS%", json.dumps(data))
+
+  headers = []
+  headers.append(("ETag", "etag"))
+  headers.append(("Content-Type", 'text/javascript'))
+
+  return headers, body
index dabeec0..3f89881 100644 (file)
@@ -1,23 +1,57 @@
 'use strict';
 
-const installMayFinish = new Promise(resolve => {
-    self.finishInstall = resolve;
+const installEventFired = new Promise(resolve => {
+  self.fireInstallEvent = resolve;
 });
 
-let report = { installEventFired: false };
+const installFinished = new Promise(resolve => {
+  self.finishInstall = resolve;
+});
 
 addEventListener('install', event => {
-    report.installEventFired = true;
-    let attemptUpdate = registration.update().catch(exception => {
-        report.exception = exception.name;
-    });
-    event.waitUntil(Promise.all([installMayFinish, attemptUpdate]));
+  fireInstallEvent();
+  event.waitUntil(installFinished);
 });
 
 addEventListener('message', event => {
-    if (event.data === 'finishInstall') {
+  // Use a dedicated MessageChannel for every request so senders can wait for
+  // individual requests to finish, and concurrent requests (to different
+  // workers) don't cause race conditions.
+  const port = event.data;
+  port.onmessage = (event) => {
+    switch (event.data) {
+      case 'awaitInstallEvent':
+        installEventFired.then(() => {
+            port.postMessage('installEventFired');
+        });
+        break;
+
+      case 'finishInstall':
+        installFinished.then(() => {
+            port.postMessage('installFinished');
+        });
         finishInstall();
-    } else {
-        event.source.postMessage(report);
+        break;
+
+      case 'callUpdate': {
+        const channel = new MessageChannel();
+        registration.update().then(() => {
+            channel.port2.postMessage({
+                success: true,
+            });
+        }).catch((exception) => {
+            channel.port2.postMessage({
+                success: false,
+                exception: exception.name,
+            });
+        });
+        port.postMessage(channel.port1, [channel.port1]);
+        break;
+      }
+
+      default:
+        port.postMessage('Unexpected command ' + event.data);
+        break;
     }
+  };
 });
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/update-during-installation-worker.py b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/update-during-installation-worker.py
new file mode 100644 (file)
index 0000000..95e4522
--- /dev/null
@@ -0,0 +1,11 @@
+import time
+
+def main(request, response):
+    headers = [('Content-Type', 'application/javascript'),
+               ('Cache-Control', 'max-age=0')]
+    # Add timestamp to the worker so update() finds a new worker every time.
+    body = '''
+// %s
+importScripts('update-during-installation-worker.js');
+    '''.strip() % time.clock()
+    return headers, body
index c4028ea..9ebc8bc 100644 (file)
@@ -146,11 +146,15 @@ List of files:
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/fetch-rewrite-worker.js
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/fetch-waits-for-activate-worker.js
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/frame-for-getregistrations.html
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/get-resultingClientId-worker.js
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/http-to-https-redirect-and-register-iframe.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/iframe-with-image.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/immutable-prototype-serviceworker.js
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/import-mime-type-worker.py
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/import-relative.xsl
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/import-scripts-diff-resource-map-worker.js
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/import-scripts-echo.py
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/import-scripts-get.py
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/import-scripts-mime-types-worker.js
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/import-scripts-redirect-import.js
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/import-scripts-redirect-worker.js
@@ -221,6 +225,7 @@ List of files:
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/performance-timeline-worker.js
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/postmessage-blob-url.js
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/postmessage-dictionary-transferables-worker.js
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/postmessage-echo-worker.js
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/postmessage-msgport-to-client-worker.js
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/postmessage-to-client-worker.js
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/postmessage-transferables-worker.js
@@ -274,10 +279,15 @@ List of files:
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/stalling-service-worker.js
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/success.py
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/test-helpers.sub.js
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/test-request-headers-worker.js
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/test-request-headers-worker.py
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/testharness-helpers.js
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/trickle.py
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/unregister-controller-page.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/update-claim-worker.py
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/update-during-installation-worker.js
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/update-during-installation-worker.py
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/update-fetch-worker.py
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/update-max-aged-worker-imported-script.py
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/update-max-aged-worker.py
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/update-missing-import-scripts-imported-worker.py
@@ -300,3 +310,8 @@ List of files:
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/worker-load-interceptor.js
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/worker-testharness.js
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/worker_interception_redirect_webworker.py
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/xhr-iframe.html
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/xhr-response-url-worker.js
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/xsl-base-url-iframe.xml
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/xsl-base-url-worker.js
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/xslt-pass.xsl
index ab10a07..84204a3 100644 (file)
@@ -1,4 +1,5 @@
 <script src="/common/get-host-info.sub.js"></script>
+<script src="/resources/testharness.js"></script>
 <script src="test-helpers.sub.js?pipe=sub"></script>
 <script>
 var host_info = get_host_info();
@@ -11,7 +12,7 @@ function boilerplate_test(url, msg) {
           worker.postMessage(msg);
         })
       .then(function(data) {
-          window.parent.postMessage({results: data}, host_info['HTTPS_ORIGIN']);
+          assert_equals(data, "This load was successfully intercepted.");
         });
 }
 
index 695777a..a5f65c3 100644 (file)
@@ -8,6 +8,8 @@ self.onfetch = function(event) {
     if (url.indexOf("synthesized-response.txt") != -1) {
         event.respondWith(new Response(response_text));
     } else if (url.indexOf("synthesized-response.js") != -1) {
-        event.respondWith(new Response(response_script));
+      event.respondWith(new Response(
+          response_script,
+          {headers: {'Content-Type': 'application/javascript'}}));
     }
 };
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/xhr-iframe.html b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/xhr-iframe.html
new file mode 100644 (file)
index 0000000..4c57bbb
--- /dev/null
@@ -0,0 +1,23 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>iframe for xhr tests</title>
+<script>
+async function xhr(url, options) {
+  return new Promise((resolve, reject) => {
+    const xhr = new XMLHttpRequest();
+    const opts = options ? options : {};
+    xhr.onload = () => {
+      resolve(xhr);
+    };
+    xhr.onerror = () => {
+      reject('xhr failed');
+    };
+
+    xhr.open('GET', url);
+    if (opts.responseType) {
+      xhr.responseType = opts.responseType;
+    }
+    xhr.send();
+  });
+}
+</script>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/xhr-response-url-worker.js b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/xhr-response-url-worker.js
new file mode 100644 (file)
index 0000000..906ad50
--- /dev/null
@@ -0,0 +1,32 @@
+// Service worker for the xhr-response-url test.
+
+self.addEventListener('fetch', event => {
+  const url = new URL(event.request.url);
+  const respondWith = url.searchParams.get('respondWith');
+  if (!respondWith)
+    return;
+
+  if (respondWith == 'fetch') {
+    const target = url.searchParams.get('url');
+    event.respondWith(fetch(target));
+    return;
+  }
+
+  if (respondWith == 'string') {
+    const headers = {'content-type': 'text/plain'};
+    event.respondWith(new Response('hello', {headers}));
+    return;
+  }
+
+  if (respondWith == 'document') {
+    const doc = `
+        <!DOCTYPE html>
+        <html>
+        <title>hi</title>
+        <body>hello</body>
+        </html>`;
+    const headers = {'content-type': 'text/html'};
+    event.respondWith(new Response(doc, {headers}));
+    return;
+  }
+});
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/xsl-base-url-iframe.xml b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/xsl-base-url-iframe.xml
new file mode 100644 (file)
index 0000000..065a07a
--- /dev/null
@@ -0,0 +1,5 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl" href="resources/request-url-path/import-relative.xsl"?>
+<stylesheet-test>
+This tests a stylesheet which has a xsl:import with a relative URL.
+</stylesheet-test>
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/xsl-base-url-worker.js b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/xsl-base-url-worker.js
new file mode 100644 (file)
index 0000000..50e2b18
--- /dev/null
@@ -0,0 +1,12 @@
+self.addEventListener('fetch', event => {
+  const url = new URL(event.request.url);
+
+  // For the import-relative.xsl file, respond in a way that changes the
+  // response URL. This is expected to change the base URL and allow the import
+  // from the file to succeed.
+  const path = 'request-url-path/import-relative.xsl';
+  if (url.pathname.indexOf(path) != -1) {
+    // Respond with a different URL, deleting "request-url-path/".
+    event.respondWith(fetch('import-relative.xsl'));
+  }
+});
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/xslt-pass.xsl b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resources/xslt-pass.xsl
new file mode 100644 (file)
index 0000000..2cd7f2f
--- /dev/null
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+
+<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
+  <xsl:template match="/">
+    <html>
+      <body>
+           <p>PASS</p>
+      </body>
+    </html>
+  </xsl:template>
+</xsl:stylesheet>
index 2f780a6..fac8f20 100644 (file)
@@ -10,6 +10,10 @@ promise_test(function(t) {
     var url = 'resources/postmessage-to-client-worker.js';
     return service_worker_unregister_and_register(t, url, scope)
       .then(function(r) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return wait_for_state(t, r.installing, 'activated');
         })
       .then(function() {
@@ -35,9 +39,6 @@ promise_test(function(t) {
                 });
               worker.postMessage('PING');
             });
-        })
-      .then(function() {
-          return service_worker_unregister_and_done(t, scope);
         });
   }, 'Test MessageEvent supplants ServiceWorkerMessageEvent.');
 
index 33d52e0..0320c02 100644 (file)
@@ -12,6 +12,10 @@ promise_test(function(t) {
 
     return service_worker_unregister_and_register(t, service_worker, scope)
       .then(function(r) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return wait_for_state(t, r.installing, 'activated');
         })
       .then(function() {
@@ -24,7 +28,6 @@ promise_test(function(t) {
         })
       .then(function(data) {
           assert_equals(data, 'intercepted by service worker');
-          service_worker_unregister_and_done(t, scope);
         });
   }, 'Verify subresource loads in SharedWorker are controlled by a Service Worker');
 
@@ -35,6 +38,10 @@ promise_test(function(t) {
 
     return service_worker_unregister_and_register(t, service_worker, scope)
       .then(function(r) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return wait_for_state(t, r.installing, 'activated');
         })
       .then(function() {
@@ -47,7 +54,6 @@ promise_test(function(t) {
         })
       .then(function(data) {
           assert_equals(data, 'worker loading intercepted by service worker');
-          service_worker_unregister_and_done(t, scope);
         });
   }, 'Verify SharedWorker construction is controlled by a Service Worker');
 
@@ -58,6 +64,10 @@ promise_test(function(t) {
 
     return service_worker_unregister_and_register(t, service_worker, scope)
       .then(function(r) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return wait_for_state(t, r.installing, 'activated');
         })
       .then(function() {
@@ -70,7 +80,6 @@ promise_test(function(t) {
         })
       .then(function(data) {
           assert_equals(data, 'worker loading intercepted by service worker');
-          service_worker_unregister_and_done(t, scope);
         });
   }, 'Verify importScripts from SharedWorker is controlled by a Service Worker');
 </script>
index 21e26be..b604f65 100644 (file)
@@ -33,6 +33,10 @@ promise_test(function(t) {
       });
     return service_worker_unregister_and_register(t, url1, scope)
       .then(function(r) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return wait_for_state(t, r.installing, 'activated');
         })
       .then(function() {
@@ -60,7 +64,6 @@ promise_test(function(t) {
         })
       .then(function() {
           frame.remove();
-          return service_worker_unregister_and_done(t, scope);
         });
   }, 'Test skipWaiting when a installed worker is waiting');
 
index 67838ac..412ee2a 100644 (file)
@@ -1,5 +1,6 @@
 <!DOCTYPE html>
 <title>Service Worker: Skip waiting using registration</title>
+<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
@@ -58,7 +59,7 @@ promise_test(function(t) {
       .then(function() {
           assert_not_equals(sw_registration.active, null,
                             'Registration active worker should not be null');
-          fetch_tests_from_worker(sw_registration.active);
+          return fetch_tests_from_worker(sw_registration.active);
         });
   }, 'Test skipWaiting while a client is using the registration');
 
index 705fe83..ced64e5 100644 (file)
@@ -1,5 +1,6 @@
 <!DOCTYPE html>
 <title>Service Worker: Skip waiting without using registration</title>
+<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
@@ -36,7 +37,7 @@ promise_test(function(t) {
                         'Document controller should still be null');
           assert_not_equals(sw_registration.active, null,
                             'Registration active worker should not be null');
-          fetch_tests_from_worker(sw_registration.active);
+          return fetch_tests_from_worker(sw_registration.active);
         });
   }, 'Test skipWaiting while a client is not being controlled');
 
index 48b5a8c..f8392fc 100644 (file)
@@ -14,6 +14,10 @@ promise_test(function(t) {
     var sw_registration, activated_worker, waiting_worker;
     return service_worker_unregister_and_register(t, url1, scope)
       .then(function(registration) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           sw_registration = registration;
           return wait_for_state(t, registration.installing, 'activated');
         })
@@ -48,7 +52,6 @@ promise_test(function(t) {
                         'Worker with url2 should be redundant');
           assert_equals(sw_registration.active.scriptURL, normalizeURL(url3),
                         'Worker with url3 should be activated');
-          return service_worker_unregister_and_done(t, scope);
         });
   }, 'Test skipWaiting with both active and waiting workers');
 
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/svg-target-reftest.https-expected.html b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/svg-target-reftest.https-expected.html
new file mode 100644 (file)
index 0000000..9a93d3b
--- /dev/null
@@ -0,0 +1,5 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Green svg box reference file</title>
+<p>Pass if you see a green box below.</p>
+<iframe src="svg-target-reftest-001-frame.html">
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/svg-target-reftest.https.html b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/svg-target-reftest.https.html
new file mode 100644 (file)
index 0000000..3710ee6
--- /dev/null
@@ -0,0 +1,28 @@
+<!DOCTYPE html>
+<html class="reftest-wait">
+<meta charset="utf-8">
+<title>Service worker interception does not break SVG fragment targets</title>
+<meta name="assert" content="SVG with link fragment should render correctly when intercepted by a service worker.">
+<script src="resources/test-helpers.sub.js"></script>
+<link rel="match" href="resources/svg-target-reftest-001.html">
+<p>Pass if you see a green box below.</p>
+<script>
+// We want to use utility functions designed for testharness.js where
+// there is a test object.  We don't have a test object in reftests
+// so fake one for now.
+const fake_test = { step_func: f => f };
+
+async function runTest() {
+  const script = './resources/pass-through-worker.js';
+  const scope = './resources/svg-target-reftest-frame.html';
+  let reg = await navigator.serviceWorker.register(script, { scope });
+  await wait_for_state(fake_test, reg.installing, 'activated');
+  let f = await with_iframe(scope);
+  document.documentElement.classList.remove('reftest-wait');
+  await reg.unregister();
+  // Note, we cannot remove the frame explicitly because we can't
+  // tell when the reftest completes.
+}
+runTest();
+</script>
+</html>
index 90b7cae..44bc5c7 100644 (file)
@@ -1,5 +1,5 @@
 
 PASS Registering a new script URL while an unregistered registration is in use 
-PASS Registering a new script URL that 404s does resurrect an unregistered registration 
-PASS Registering a new script URL that fails to install does resurrect an unregistered registration 
+FAIL Registering a new script URL that 404s does not resurrect unregistered registration assert_equals: Document should not be controlled expected null but got object "[object ServiceWorker]"
+FAIL Registering a new script URL that fails to install does not resurrect unregistered registration assert_equals: registration.active expected null but got object "[object ServiceWorker]"
 
index 582132a..a07da7d 100644 (file)
 <script>
 var worker_url = 'resources/empty-worker.js';
 
-async_test(function(t) {
-    var scope = 'resources/scope/unregister-then-register-new-script-that-exists';
-    var new_worker_url = worker_url + '?new';
-    var iframe;
-    var registration;
-    var new_registration;
-
-    service_worker_unregister_and_register(t, worker_url, scope)
-      .then(function(r) {
-          registration = r;
-          return wait_for_state(t, r.installing, 'activated');
-        })
-      .then(function() {
-          return with_iframe(scope);
-        })
-      .then(function(frame) {
-          iframe = frame;
-          return registration.unregister();
-        })
-      .then(function() {
-          return navigator.serviceWorker.register(new_worker_url,
-                                                  { scope: scope });
-        })
-      .then(function(r) {
-          new_registration = r;
-          assert_equals(registration.installing.scriptURL,
-                        normalizeURL(new_worker_url),
-                        'before activated registration.installing');
-          assert_equals(registration.waiting, null,
-                        'before activated registration.waiting');
-          assert_equals(registration.active.scriptURL, normalizeURL(worker_url),
-                        'before activated registration.active');
-          assert_equals(new_registration.installing.scriptURL,
-                        normalizeURL(new_worker_url),
-                        'before activated new_registration.installing');
-          assert_equals(new_registration.waiting, null,
-                        'before activated new_registration.waiting');
-          assert_equals(new_registration.active.scriptURL,
-                        normalizeURL(worker_url),
-                        'before activated new_registration.active');
-          iframe.remove();
-          return wait_for_state(t, registration.installing, 'activated');
-        })
-      .then(function() {
-          assert_equals(new_registration.installing, null,
-                        'after activated new_registration.installing');
-          assert_equals(new_registration.waiting, null,
-                        'after activated new_registration.waiting');
-          assert_equals(new_registration.active.scriptURL,
-                        normalizeURL(new_worker_url),
-                        'after activated new_registration.active');
-          return with_iframe(scope);
-        })
-      .then(function(frame) {
-          assert_equals(
-              frame.contentWindow.navigator.serviceWorker.controller.scriptURL,
-              normalizeURL(new_worker_url),
-              'the new worker should control a new document');
-          frame.remove();
-          return registration.unregister();
-        })
-      .then(function() {
-          t.done();
-        })
-      .catch(unreached_rejection(t));
+promise_test(async function(t) {
+  const scope = 'resources/scope/unregister-then-register-new-script-that-exists';
+  const registration = await service_worker_unregister_and_register(t, worker_url, scope);
+  t.add_cleanup(() => registration.unregister());
+
+  const newWorkerURL = worker_url + '?new';
+  await wait_for_state(t, registration.installing, 'activated');
+
+  const iframe = await with_iframe(scope);
+  t.add_cleanup(() => iframe.remove());
+
+  await registration.unregister();
+
+  const newRegistration = await navigator.serviceWorker.register(newWorkerURL, { scope });
+  t.add_cleanup(() => newRegistration.unregister());
+
+  assert_equals(
+    registration.installing.scriptURL,
+    normalizeURL(newWorkerURL),
+    'before activated registration.installing'
+  );
+  assert_equals(
+    registration.waiting,
+    null,
+    'before activated registration.waiting'
+  );
+  assert_equals(
+    registration.active.scriptURL,
+    normalizeURL(worker_url),
+    'before activated registration.active'
+  );
+  assert_equals(
+    newRegistration.installing.scriptURL,
+    normalizeURL(newWorkerURL),
+    'before activated newRegistration.installing'
+  );
+  assert_equals(
+    newRegistration.waiting,
+    null,
+    'before activated newRegistration.waiting'
+  );
+  assert_equals(
+    newRegistration.active.scriptURL,
+    normalizeURL(worker_url),
+    'before activated newRegistration.active'
+  );
+  iframe.remove();
+
+  await wait_for_state(t, registration.installing, 'activated');
+
+  assert_equals(
+    newRegistration.installing,
+    null,
+    'after activated newRegistration.installing'
+  );
+  assert_equals(
+    newRegistration.waiting,
+    null,
+    'after activated newRegistration.waiting'
+  );
+  assert_equals(
+    newRegistration.active.scriptURL,
+    normalizeURL(newWorkerURL),
+    'after activated newRegistration.active'
+  );
+
+  const newIframe = await with_iframe(scope);
+  t.add_cleanup(() => newIframe.remove());
+
+  assert_equals(
+    newIframe.contentWindow.navigator.serviceWorker.controller.scriptURL,
+    normalizeURL(newWorkerURL),
+    'the new worker should control a new document'
+  );
 }, 'Registering a new script URL while an unregistered registration is in use');
 
-async_test(function(t) {
-    var scope = 'resources/scope/unregister-then-register-new-script-that-404s';
-    var iframe;
-    var registration;
-
-    service_worker_unregister_and_register(t, worker_url, scope)
-      .then(function(r) {
-          registration = r;
-          return wait_for_state(t, r.installing, 'activated');
-        })
-      .then(function() {
-          return with_iframe(scope);
-        })
-      .then(function(frame) {
-          iframe = frame;
-          return registration.unregister();
-        })
-      .then(function() {
-          // Step 5.1 of Register clears the uninstall flag before fetching
-          // the script:
-          //
-          //  https://w3c.github.io/ServiceWorker/#register-algorithm
-          var promise = navigator.serviceWorker.register('this-will-404',
-                                                         { scope: scope });
-          return promise;
-        })
-      .then(
-        function() {
-          assert_unreached('register should reject the promise');
-        },
-        function() {
-          assert_equals(registration.installing, null,
-                        'registration.installing');
-          assert_equals(registration.waiting, null,
-                        'registration.waiting');
-          assert_equals(registration.active.scriptURL, normalizeURL(worker_url),
-                        'registration.active');
-          iframe.remove();
-          return with_iframe(scope);
-        })
-      .then(function(frame) {
-          assert_equals(
-              frame.contentWindow.navigator.serviceWorker.controller.scriptURL,
-              normalizeURL(worker_url),
-              'the original worker should control a new document');
-          frame.remove();
-          return registration.unregister();
-        })
-      .then(function() {
-          t.done();
-        })
-      .catch(unreached_rejection(t));
-}, 'Registering a new script URL that 404s does resurrect an ' +
-       'unregistered registration');
-
-async_test(function(t) {
-    var scope = 'resources/scope/unregister-then-register-reject-install-worker';
-    var iframe;
-    var registration;
-
-    service_worker_unregister_and_register(t, worker_url, scope)
-      .then(function(r) {
-          registration = r;
-          return wait_for_state(t, r.installing, 'activated');
-        })
-      .then(function() {
-          return with_iframe(scope);
-        })
-      .then(function(frame) {
-          iframe = frame;
-          return registration.unregister();
-        })
-      .then(function() {
-          // Step 5.1 of Register clears the uninstall flag before firing
-          // the install event:
-          //
-          //  https://w3c.github.io/ServiceWorker/#register-algorithm
-          var promise = navigator.serviceWorker.register(
-              'resources/reject-install-worker.js', { scope: scope });
-          return promise;
-        })
-      .then(function(r) {
-          registration = r;
-          return wait_for_state(t, r.installing, 'redundant');
-        })
-      .then(function() {
-          assert_equals(registration.installing, null,
-                        'registration.installing');
-          assert_equals(registration.waiting, null,
-                        'registration.waiting');
-          assert_equals(registration.active.scriptURL, normalizeURL(worker_url),
-                        'registration.active');
-          iframe.remove();
-          return with_iframe(scope);
-        })
-      .then(function(frame) {
-          assert_equals(
-              frame.contentWindow.navigator.serviceWorker.controller.scriptURL,
-              normalizeURL(worker_url),
-              'the original worker should control a new document');
-          frame.remove();
-          return registration.unregister();
-        })
-      .then(function() {
-          t.done();
-        })
-      .catch(unreached_rejection(t));
-  }, 'Registering a new script URL that fails to install does resurrect ' +
-       'an unregistered registration');
+promise_test(async function(t) {
+  const scope = 'resources/scope/unregister-then-register-new-script-that-404s';
+  const registration = await service_worker_unregister_and_register(t, worker_url, scope);
+  t.add_cleanup(() => registration.unregister());
+
+  await wait_for_state(t, registration.installing, 'activated');
+
+  const iframe = await with_iframe(scope);
+  t.add_cleanup(() => iframe.remove());
+
+  await registration.unregister();
+
+  await promise_rejects(
+    t, new TypeError(),
+    navigator.serviceWorker.register('this-will-404', { scope })
+  );
+
+  assert_equals(registration.installing, null, 'registration.installing');
+  assert_equals(registration.waiting, null, 'registration.waiting');
+  assert_equals(registration.active.scriptURL, normalizeURL(worker_url), 'registration.active');
+
+  const newIframe = await with_iframe(scope);
+  t.add_cleanup(() => newIframe.remove());
+
+  assert_equals(newIframe.contentWindow.navigator.serviceWorker.controller, null, 'Document should not be controlled');
+}, 'Registering a new script URL that 404s does not resurrect unregistered registration');
+
+promise_test(async function(t) {
+  const scope = 'resources/scope/unregister-then-register-reject-install-worker';
+  const registration = await service_worker_unregister_and_register(t, worker_url, scope);
+  t.add_cleanup(() => registration.unregister());
+
+  await wait_for_state(t, registration.installing, 'activated');
+
+  const iframe = await with_iframe(scope);
+  t.add_cleanup(() => iframe.remove());
+
+  await registration.unregister();
+
+  const newRegistration = await navigator.serviceWorker.register(
+    'resources/reject-install-worker.js', { scope }
+  );
+  t.add_cleanup(() => newRegistration.unregister());
+
+  await wait_for_state(t, newRegistration.installing, 'redundant');
+
+  assert_equals(registration.installing, null, 'registration.installing');
+  assert_equals(registration.waiting, null, 'registration.waiting');
+  assert_equals(registration.active, null, 'registration.active');
+  assert_not_equals(registration, newRegistration, 'New registration is different');
+}, 'Registering a new script URL that fails to install does not resurrect unregistered registration');
 </script>
index 5e6c2be..e350cb0 100644 (file)
@@ -1,8 +1,6 @@
 
-
 PASS Unregister then register resolves to a new value 
-PASS Unregister then register resolves to the original value if the registration is in use. 
-PASS Reloading the last controlled iframe after unregistration should ensure the deletion of the registration 
+FAIL Unregister then register does not resolve to the original value even if the registration is in use. assert_not_equals: Unregister and register should always create a new registration got disallowed value object "[object ServiceWorkerRegistration]"
 PASS Unregister then register does not affect existing controllee 
-PASS Unregister then register resurrects the registration 
+FAIL Unregister then register does not resurrect the registration assert_equals: Registration is new expected null but got object "[object ServiceWorker]"
 
index 303b2be..5fd2cf9 100644 (file)
 <script>
 var worker_url = 'resources/empty-worker.js';
 
-promise_test(function(t) {
-    var scope = 'resources/scope/re-register-resolves-to-new-value';
-    var registration;
+promise_test(async function(t) {
+    const scope = 'resources/scope/re-register-resolves-to-new-value';
+    const registration = await service_worker_unregister_and_register(t, worker_url, scope);
+    t.add_cleanup(() => registration.unregister());
 
-    return service_worker_unregister_and_register(t, worker_url, scope)
-      .then(function(r) {
-          t.add_cleanup(function() {
-              return service_worker_unregister(t, scope);
-            });
+    await wait_for_state(t, registration.installing, 'activated');
+    await registration.unregister();
+    const newRegistration = await navigator.serviceWorker.register(worker_url, { scope });
+    t.add_cleanup(() => newRegistration.unregister());
 
-          registration = r;
-          return wait_for_state(t, r.installing, 'activated');
-        })
-      .then(function() {
-          return registration.unregister();
-        })
-      .then(function() {
-          return navigator.serviceWorker.register(worker_url, { scope: scope });
-        })
-      .then(function(new_registration) {
-          assert_not_equals(registration, new_registration,
-                            'register should resolve to a new value');
-        });
+    assert_not_equals(
+      registration, newRegistration,
+      'register should resolve to a new value'
+    );
   }, 'Unregister then register resolves to a new value');
 
-promise_test(function(t) {
-    var scope = 'resources/scope/re-register-while-old-registration-in-use';
-    var registration;
+promise_test(async function(t) {
+  const scope = 'resources/scope/re-register-while-old-registration-in-use';
+  const registration = await service_worker_unregister_and_register(t, worker_url, scope);
+  t.add_cleanup(() => registration.unregister());
 
-    return service_worker_unregister_and_register(t, worker_url, scope)
-      .then(function(r) {
-          t.add_cleanup(function() {
-              return service_worker_unregister(t, scope);
-            });
+  await wait_for_state(t, registration.installing, 'activated');
+  const frame = await with_iframe(scope);
+  t.add_cleanup(() => frame.remove());
 
-          registration = r;
-          return wait_for_state(t, r.installing, 'activated');
-        })
-      .then(function() {
-          return with_iframe(scope);
-        })
-      .then(function(frame) {
-          return registration.unregister();
-        })
-      .then(function() {
-          return navigator.serviceWorker.register(worker_url, { scope: scope });
-        })
-      .then(function(new_registration) {
-          assert_equals(registration, new_registration,
-                        'new registration should resolve to the same registration');
-        });
-  }, 'Unregister then register resolves to the original value if the ' +
-         'registration is in use.');
+  await registration.unregister();
+  const newRegistration = await navigator.serviceWorker.register(worker_url, { scope });
+  t.add_cleanup(() => newRegistration.unregister());
 
-promise_test(function(t) {
-    var scope = 'resources/scope/complete-unregistration-followed-by-' +
-                'reloading-controllee-iframe';
-    var registration;
-    var frame;
-    var service_worker;
-    return service_worker_unregister_and_register(t, worker_url, scope)
-      .then(function(r) {
-          t.add_cleanup(function() {
-              return service_worker_unregister(t, scope);
-            });
-
-          registration = r;
-          return wait_for_state(t, r.installing, 'activated');
-        })
-      .then(function() {
-          return with_iframe(scope);
-        })
-      .then(function(f) {
-          frame = f;
-          return registration.unregister();
-        })
-      .then(function() {
-          return new Promise(function(resolve) {
-              frame.onload = resolve;
-              frame.contentWindow.location.reload();
-            });
-        })
-      .then(function() {
-          var c = frame.contentWindow.navigator.serviceWorker.controller;
-          assert_equals(c, null, 'a page after unregistration should not be ' +
-                                 'controlled by service worker');
-          return navigator.serviceWorker.getRegistration(scope);
-        })
-      .then(function(r) {
-          assert_equals(r, undefined, 'getRegistration should return ' +
-                                      'undefined after unregistration');
-        });
-}, 'Reloading the last controlled iframe after unregistration should ensure ' +
-   'the deletion of the registration');
+  assert_not_equals(
+    registration, newRegistration,
+    'Unregister and register should always create a new registration'
+  );
+}, 'Unregister then register does not resolve to the original value even if the registration is in use.');
 
 promise_test(function(t) {
     var scope = 'resources/scope/re-register-does-not-affect-existing-controllee';
@@ -109,8 +49,8 @@ promise_test(function(t) {
     return service_worker_unregister_and_register(t, worker_url, scope)
       .then(function(r) {
           t.add_cleanup(function() {
-              return service_worker_unregister(t, scope);
-            });
+            return service_worker_unregister(t, scope);
+          });
 
           registration = r;
           return wait_for_state(t, r.installing, 'activated');
@@ -138,39 +78,30 @@ promise_test(function(t) {
         });
   }, 'Unregister then register does not affect existing controllee');
 
-promise_test(function(t) {
-    var scope = 'resources/scope/resurrection';
-    var iframe;
-    var registration;
+promise_test(async function(t) {
+  const scope = 'resources/scope/resurrection';
+  const altWorkerURL = worker_url + '?alt';
+  const registration = await service_worker_unregister_and_register(t, worker_url, scope);
+  t.add_cleanup(() => registration.unregister());
 
-    return service_worker_unregister_and_register(t, worker_url, scope)
-      .then(function(r) {
-          t.add_cleanup(function() {
-              return service_worker_unregister(t, scope);
-            });
+  await wait_for_state(t, registration.installing, 'activating');
+  const iframe = await with_iframe(scope);
+  t.add_cleanup(() => iframe.remove());
 
-          registration = r;
-          return wait_for_state(t, r.installing, 'activated');
-        })
-      .then(function() {
-          return with_iframe(scope);
-        })
-      .then(function(frame) {
-          iframe = frame;
-          return registration.unregister();
-        })
-      .then(function() {
-          return navigator.serviceWorker.register(worker_url, { scope: scope });
-        })
-      .then(function() {
-          iframe.remove();
-          return with_iframe(scope);
-        })
-      .then(function(frame) {
-          assert_not_equals(
-              frame.contentWindow.navigator.serviceWorker.controller, null,
-              'document should have a controller');
-          frame.remove();
-        });
-  }, 'Unregister then register resurrects the registration');
+  await registration.unregister();
+  const newRegistration = await navigator.serviceWorker.register(altWorkerURL, { scope });
+  t.add_cleanup(() => newRegistration.unregister());
+
+  assert_equals(newRegistration.active, null, 'Registration is new');
+
+  await wait_for_state(t, newRegistration.installing, 'activating');
+
+  const newIframe = await with_iframe(scope);
+  t.add_cleanup(() => newIframe.remove());
+
+  const iframeController = iframe.contentWindow.navigator.serviceWorker.controller;
+  const newIframeController = newIframe.contentWindow.navigator.serviceWorker.controller;
+
+  assert_not_equals(iframeController, newIframeController, 'iframes have different controllers');
+}, 'Unregister then register does not resurrect the registration');
 </script>
index 321e40c..6e821fe 100644 (file)
@@ -1,6 +1,7 @@
 <!DOCTYPE html>
 <meta charset="utf-8">
 <title>Service Worker: Update should be triggered after redirects during navigation</title>
+<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
index 08065d2..d9b9fcf 100644 (file)
@@ -17,6 +17,10 @@ promise_test(function(t) {
 
     return service_worker_unregister_and_register(t, expected_url, scope)
       .then(function(r) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           registration = r;
           return wait_for_state(t, registration.installing, 'activated');
         })
@@ -41,7 +45,6 @@ promise_test(function(t) {
        })
        .then(function() {
           frame.remove();
-          return service_worker_unregister_and_done(t, scope);
        })
   }, 'Update should be triggered after a functional event when last update time is over 24 hours');
 
index ec3d15a..6628dba 100644 (file)
@@ -1,6 +1,7 @@
 <!doctype html>
 <meta charset=utf-8>
 <title></title>
+<meta name="timeout" content="long">
 <script src="/resources/testharness.js"></script>
 <script src="resources/testharness-helpers.js"></script>
 <script src="/resources/testharnessreport.js"></script>
@@ -43,8 +44,11 @@ settings.reduce((p, s) => {
     return Promise.resolve()
       // Register a service worker.
       .then(_ => service_worker_unregister_and_register(t, script, scope))
-      .then(r => swr = r)
-      .then(_ => wait_for_update(t, swr))
+      .then(r => {
+        t.add_cleanup(() => service_worker_unregister(t, scope));
+        swr = r;
+        return wait_for_update(t, swr);
+      })
       .then(w => sw = w)
       .then(_ => wait_for_state(t, sw, 'activated'))
       .then(_ => assert_array_equals([swr.active,
@@ -64,10 +68,7 @@ settings.reduce((p, s) => {
                               swr.waiting,
                               swr.installing],
                              [sw, null, null]);
-      })
-
-      // Unregister the service worker.
-      .then(_ => service_worker_unregister_and_done(t, scope));
+      });
   }, `Test(cors: ${s.cors}, main: ${s.main}, imported: ${s.imported})`));
 }, Promise.resolve());
 
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-no-cache-request-headers.https-expected.txt b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-no-cache-request-headers.https-expected.txt
new file mode 100644 (file)
index 0000000..b5516d6
--- /dev/null
@@ -0,0 +1,3 @@
+
+PASS headers in no-cache mode 
+
diff --git a/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-no-cache-request-headers.https.html b/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-no-cache-request-headers.https.html
new file mode 100644 (file)
index 0000000..6ebad4b
--- /dev/null
@@ -0,0 +1,48 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>Test that cache is being bypassed/validated in no-cache mode on update</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<script src="resources/test-helpers.sub.js"></script>
+<script>
+// Tests a service worker script fetch during an update check which
+// bypasses/validates the browser cache. The fetch should have the
+// 'if-none-match' request header.
+//
+// This tests the Update step:
+//  "Set request’s cache mode to "no-cache" if any of the following are true..."
+// https://w3c.github.io/ServiceWorker/#update-algorithm
+//
+// The test works by registering a service worker with |updateViaCache|
+// set to "none". It then does an update. The test server responds with
+// an updated worker script that remembers the http request headers.
+// The updated worker reports back these headers to the test page.
+promise_test(async (t) => {
+  const script = "resources/test-request-headers-worker.py";
+  const scope = "resources/";
+
+  // Register the service worker.
+  await service_worker_unregister(t, scope);
+  const registration = await navigator.serviceWorker.register(
+      script, {scope, updateViaCache: 'none'});
+  await wait_for_state(t, registration.installing, 'activated');
+
+  // Do an update.
+  await registration.update();
+
+  // Ask the new worker what the request headers were.
+  const newWorker = registration.installing;
+  const sawMessage = new Promise((resolve) => {
+    navigator.serviceWorker.onmessage = (event) => {
+      resolve(event.data);
+    };
+  });
+  newWorker.postMessage('getHeaders');
+  const result = await sawMessage;
+
+  // Test the result.
+  assert_equals(result['service-worker'], 'script');
+  assert_equals(result['if-none-match'], 'etag');
+}, 'headers in no-cache mode');
+
+</script>
index 71fe173..0a54aa9 100644 (file)
 <script>
 'use strict';
 
+function send_message_to_worker_and_wait_for_response(worker, message) {
+  return new Promise(resolve => {
+    // Use a dedicated channel for every request to avoid race conditions on
+    // concurrent requests.
+    const channel = new MessageChannel();
+    worker.postMessage(channel.port1, [channel.port1]);
+
+    let messageReceived = false;
+    channel.port2.onmessage = event => {
+      assert_false(messageReceived, 'Already received response for ' + message);
+      messageReceived = true;
+      resolve(event.data);
+    };
+    channel.port2.postMessage(message);
+  });
+}
+
+async function ensure_install_event_fired(worker) {
+  const response = await send_message_to_worker_and_wait_for_response(worker, 'awaitInstallEvent');
+  assert_equals('installEventFired', response);
+  assert_equals('installing', worker.state, 'Expected worker to be installing.');
+}
+
+async function finish_install(worker) {
+  await ensure_install_event_fired(worker);
+  const response = await send_message_to_worker_and_wait_for_response(worker, 'finishInstall');
+  assert_equals('installFinished', response);
+}
+
+async function activate_service_worker(t, worker) {
+  await finish_install(worker);
+  // By waiting for both states at the same time, the test fails
+  // quickly if the installation fails, avoiding a timeout.
+  await Promise.race([wait_for_state(t, worker, 'activated'),
+                      wait_for_state(t, worker, 'redundant')]);
+  assert_equals('activated', worker.state, 'Service worker should be activated.');
+}
+
+async function update_within_service_worker(worker) {
+  // This function returns a Promise that resolves when update()
+  // has been called but is not necessarily finished yet.
+  // Call finish() on the returned object to wait for update() settle.
+  const port = await send_message_to_worker_and_wait_for_response(worker, 'callUpdate');
+  let messageReceived = false;
+  return {
+    finish: () => {
+      return new Promise(resolve => {
+        port.onmessage = event => {
+          assert_false(messageReceived, 'Update already finished.');
+          messageReceived = true;
+          resolve(event.data);
+        };
+      });
+    },
+  };
+}
+
+async function update_from_client_and_await_installing_version(test, registration) {
+  const updatefound = wait_for_update(test, registration);
+  registration.update();
+  await updatefound;
+  return registration.installing;
+}
+
 async function spin_up_service_worker(test) {
-    const script = 'resources/update-during-installation-worker.js';
-    const scope = 'resources/blank.html';
-
-    let registration = await service_worker_unregister_and_register(test, script, scope);
-    test.add_cleanup(() => {
-        if (registration.installing) {
-            registration.installing.postMessage('finishInstall');
-        }
-        registration.unregister();
-    });
-
-    return registration;
+  const script = 'resources/update-during-installation-worker.py';
+  const scope = 'resources/blank.html';
+
+  const registration = await service_worker_unregister_and_register(test, script, scope);
+  test.add_cleanup(async () => {
+    if (registration.installing) {
+      // If there is an installing worker, we need to finish installing it.
+      // Otherwise, the tests fails with an timeout because unregister() blocks
+      // until the install-event-handler finishes.
+      const worker = registration.installing;
+      await send_message_to_worker_and_wait_for_response(worker, 'awaitInstallEvent');
+      await send_message_to_worker_and_wait_for_response(worker, 'finishInstall');
+    }
+    return registration.unregister();
+  });
+
+  return registration;
 }
 
 promise_test(async t => {
-    const registration = await spin_up_service_worker(t);
-    const worker = registration.installing;
+  const registration = await spin_up_service_worker(t);
+  const worker = registration.installing;
+  await ensure_install_event_fired(worker);
 
-    // spin_up_service_worker installs a cleanup hook that ensures the
-    // worker finished its installation by sending it a
-    // 'finishInstall' message, thus making sure that the registration
-    // will be cleanly removed at the end of the test.
-    assert_equals(worker.state, 'installing');
-    promise_rejects(t, 'InvalidStateError', registration.update());
-}, 'ServiceWorkerRegistration.update() from client throws while installing service worker.')
+  const result = registration.update();
+  await activate_service_worker(t, worker);
+  return result;
+}, 'ServiceWorkerRegistration.update() from client succeeds while installing service worker.');
 
 promise_test(async t => {
-    const registration = await spin_up_service_worker(t);
-    const worker = registration.installing;
-    worker.postMessage('finishInstall');
-
-    // By waiting for both states at the same time, the test fails
-    // quickly if the installation fails, avoiding a timeout.
-    await Promise.race([wait_for_state(t, worker, 'activated'),
-                        wait_for_state(t, worker, 'redundant')]);
-    assert_equals(worker.state, 'activated', 'Service worker should be activated.');
-
-    const response = await new Promise(resolve => {
-        navigator.serviceWorker.onmessage = event => { resolve(event.data); };
-        worker.postMessage('PING');
-    });
-
-    // We check that the service worker instance that replied to the
-    // message is the same one that received the 'install' event since
-    // it's possible for them to be two distinct execution
-    // environments.
-    assert_true(response.installEventFired, 'Service worker should have been installed.');
-    assert_equals(response.exception, 'InvalidStateError', 'update() should have thrown.');
+  const registration = await spin_up_service_worker(t);
+  const worker = registration.installing;
+  await ensure_install_event_fired(worker);
+
+  // Add event listener to fail the test if update() succeeds.
+  const updatefound = t.step_func(async () => {
+    registration.removeEventListener('updatefound', updatefound);
+    // Activate new worker so non-compliant browsers don't fail with timeout.
+    await activate_service_worker(t, registration.installing);
+    assert_unreached("update() should have failed");
+  });
+  registration.addEventListener('updatefound', updatefound);
+
+  const update = await update_within_service_worker(worker);
+  // Activate worker to ensure update() finishes and the test doesn't timeout
+  // in non-compliant browsers.
+  await activate_service_worker(t, worker);
+
+  const response = await update.finish();
+  assert_false(response.success, 'update() should have failed.');
+  assert_equals('InvalidStateError', response.exception, 'update() should have thrown InvalidStateError.');
 }, 'ServiceWorkerRegistration.update() from installing service worker throws.');
+
+promise_test(async t => {
+  const registration = await spin_up_service_worker(t);
+  const worker1 = registration.installing;
+  await activate_service_worker(t, worker1);
+
+  const worker2 = await update_from_client_and_await_installing_version(t, registration);
+  await ensure_install_event_fired(worker2);
+
+  const update = await update_within_service_worker(worker1);
+  // Activate the new version so that update() finishes and the test doesn't timeout.
+  await activate_service_worker(t, worker2);
+  const response = await update.finish();
+  assert_true(response.success, 'update() from active service worker should have succeeded.');
+}, 'ServiceWorkerRegistration.update() from active service worker succeeds while installing service worker.');
 </script>
index c1cc737..327b770 100644 (file)
@@ -1,6 +1,6 @@
 
-FAIL Update the registration with a different script type (classic => module). promise_test: Unhandled rejection with value: object "ReferenceError: Can't find variable: guid"
-FAIL Update the registration with a different script type (module => classic). promise_test: Unhandled rejection with value: object "ReferenceError: Can't find variable: guid"
+FAIL Update the registration with a different script type (classic => module). promise_test: Unhandled rejection with value: object "TypeError: null is not an object (evaluating 'secondWorker.postMessage')"
+FAIL Update the registration with a different script type (module => classic). promise_test: Unhandled rejection with value: object "TypeError: SyntaxError: Unexpected token '*'. import call expects exactly one argument."
 PASS Update the registration with a different script type (classic => module) and with a same main script. 
 PASS Update the registration with a different script type (module => classic) and with a same main script. 
 PASS Does not update the registration with the same script type and the same main script. 
index b712c30..e7d3692 100644 (file)
@@ -2,7 +2,7 @@
 <meta charset="utf-8">
 <title>Service Worker: Update the registration with a different script type.</title>
 <!-- common.js is for guid() -->
-<script src="/mixed-content/generic/common.js"></script>
+<script src="/common/security-features/resources/common.js"></script>
 <script src="/resources/testharness.js"></script>
 <script src="/resources/testharnessreport.js"></script>
 <script src="resources/test-helpers.sub.js"></script>
index 185d577..a33ef05 100644 (file)
@@ -22,6 +22,7 @@ List of files:
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/active.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/appcache-ordering-main.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/claim-affect-other-registration.https.html
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/claim-fetch-with-appcache.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/claim-fetch.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/claim-not-using-registration.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/claim-shared-worker-fetch.https.html
@@ -32,6 +33,7 @@ List of files:
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/client-navigate.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/clients-get-client-types.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/clients-get-cross-origin.https.html
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/clients-get-resultingClientId.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/clients-get.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/clients-matchall-client-types.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/clients-matchall-exact-controller.https.html
@@ -43,6 +45,7 @@ List of files:
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/controller-on-load.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/controller-on-reload.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/controller-with-no-fetch-event-handler.https.html
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/data-transfer-files.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/dedicated-worker-service-worker-interception.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/detached-context.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/embed-and-object-are-not-intercepted.https.html
@@ -147,6 +150,7 @@ List of files:
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/registration-events.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/registration-iframe.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/registration-mime-types.https.html
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/registration-schedule-job.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/registration-scope.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/registration-script-url.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/registration-script.https.html
@@ -156,7 +160,7 @@ List of files:
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/rejections.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/request-end-to-end.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resource-timing-cross-origin.https.html
-/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resource-timing.https.html
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/resource-timing.sub.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/respond-with-body-accessed-response.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/sandboxed-iframe-fetch-event.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/sandboxed-iframe-navigator-serviceworker.https.html
@@ -186,7 +190,9 @@ List of files:
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-after-oneday.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-bytecheck.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-missing-import-scripts.https.html
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-no-cache-request-headers.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-not-allowed.https.html
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-on-navigation.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-recovery.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-registration-with-type.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/update-result.https.html
@@ -200,3 +206,5 @@ List of files:
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/worker-in-sandboxed-iframe-by-csp-fetch-event.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/worker-interception-redirect.https.html
 /LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/worker-interception.https.html
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/xhr-response-url.https.html
+/LayoutTests/imported/w3c/web-platform-tests/service-workers/service-worker/xsl-base-url.https.html
index f1af468..ccd376f 100644 (file)
@@ -2,5 +2,5 @@ CONSOLE MESSAGE: WebSocket network error: OSStatus Error -9807: Invalid certific
 CONSOLE MESSAGE: WebSocket network error: OSStatus Error -9807: Invalid certificate chain 
 
 
-FAIL Verify WebSocket handshake channel does not get intercepted assert_unreached: unexpected rejection: [object Event] Reached unreachable code
+FAIL Verify WebSocket handshake channel does not get intercepted promise_test: Unhandled rejection with value: object "[object Event]"
 
index 8ea279e..e62c1ac 100644 (file)
@@ -109,7 +109,7 @@ function navigate_test(override_parameters) {
         });
     }
 
-    var cleanup = function() {
+    test.add_cleanup(function() {
       if (client_frame && client_frame) {
         client_frame.remove();
       }
@@ -127,9 +127,9 @@ function navigate_test(override_parameters) {
       if (registration) {
         return registration.unregister();
       }
-    };
+    });
 
-    var test_body = with_iframe(parameters.src_url)
+    return with_iframe(parameters.src_url)
       .then(function(frame) {
           client_frame = frame;
           return service_worker_unregister_and_register(
@@ -161,17 +161,6 @@ function navigate_test(override_parameters) {
       .then(function(response) {
           assert_equals(response.data, parameters.expected);
         });
-
-    // Ensure that test "clean up" is deferred until after the test body
-    // executes. `Test#add_cleanup` cannot be used for this purpose because the
-    // operation is asynchronous, and `add_cleanup` does not support
-    // asynchronous operations at the time of this writing. See
-    // https://github.com/web-platform-tests/wpt/issues/6075
-    // Ensure also that test failure is not hidden by successful cleanup
-    // operation.
-    return test_body
-      .then(cleanup, cleanup)
-      .then(function() { return test_body; });
   }, parameters.description);
 }
 </script>
index 45e229e..b4ed4ee 100644 (file)
@@ -1,8 +1,8 @@
-
+CONSOLE MESSAGE: line 1: ReferenceError: Can't find variable: Worker
 
 FAIL Verify worker script from uncontrolled document is intercepted by Service Worker promise_test: Unhandled rejection with value: undefined
 FAIL Verify worker script intercepted by same-origin response succeeds promise_test: Unhandled rejection with value: undefined
 PASS Verify worker script intercepted by cors response fails 
 PASS Verify worker script intercepted by no-cors cross-origin response fails 
-PASS Verify worker loads from controlled document are intercepted by Service Worker 
+FAIL Verify worker loads from controlled document are intercepted by Service Worker assert_equals: expected "finish" but got "failure:[object ErrorEvent]"
 
index bf976a2..7b29412 100644 (file)
@@ -12,6 +12,10 @@ promise_test(function(t) {
 
     return service_worker_unregister_and_register(t, service_worker, scope)
       .then(function(r) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return wait_for_state(t, r.installing, 'activated');
         })
       .then(function() {
@@ -28,7 +32,6 @@ promise_test(function(t) {
         })
       .then(function(data) {
           assert_equals(data, 'worker loading intercepted by service worker');
-          service_worker_unregister_and_done(t, scope);
         });
   }, 'Verify worker script from uncontrolled document is intercepted by Service Worker');
 
@@ -39,6 +42,10 @@ promise_test(function(t) {
 
     return service_worker_unregister_and_register(t, service_worker, scope)
       .then(function(r) {
+          t.add_cleanup(function() {
+              return service_worker_unregister(t, scope);
+            });
+
           return wait_for_state(t, r.installing, 'activated');
         })
       .then(function() {
@@ -55,7