| // Copyright 2014 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| 'use strict'; |
| |
| // The ResultQueue is a mechanism for passing messages back to the test |
| // framework. |
| var resultQueue = new ResultQueue(); |
| |
| // Waits for the given ServiceWorkerRegistration to become ready. |
| // Shim for https://github.com/w3c/ServiceWorker/issues/770. |
| function swRegistrationReady(reg) { |
| return new Promise((resolve, reject) => { |
| if (reg.active) { |
| resolve(); |
| return; |
| } |
| |
| if (!reg.installing && !reg.waiting) { |
| reject(Error('Install failed')); |
| return; |
| } |
| |
| (reg.installing || reg.waiting).addEventListener('statechange', function() { |
| if (this.state == 'redundant') { |
| reject(Error('Install failed')); |
| } else if (this.state == 'activated') { |
| resolve(); |
| } |
| }); |
| }); |
| } |
| |
| // Notification permission has been coalesced with Push permission. After |
| // this is granted, Push API subscription can succeed. |
| function requestNotificationPermission() { |
| return new Promise(resolve => { |
| Notification.requestPermission(resolve); |
| }).then((permission) => 'permission status - ' + permission); |
| } |
| |
| function registerServiceWorker() { |
| // The base dir used to resolve service_worker.js and the scope depends on |
| // whether this script is included from an html file in ./, subscope1/, or |
| // subscope2/. |
| return navigator.serviceWorker.register( |
| 'service_worker.js' + window.location.search, { |
| scope: './' |
| }).then(swRegistrationReady).then(() => { |
| return 'ok - service worker registered'; |
| }).catch(formatError); |
| } |
| |
| function unregisterServiceWorker() { |
| return navigator.serviceWorker.getRegistration() |
| .then(function(swRegistration) { |
| return swRegistration.unregister(); |
| }).then(function(result) { |
| return 'service worker unregistration status: ' + result; |
| }) |
| .catch(formatError); |
| } |
| |
| function replaceServiceWorker() { |
| return navigator.serviceWorker.register( |
| 'service_worker_with_skipWaiting_claim.js', { |
| scope: './' |
| }).then(swRegistrationReady).then(() => { |
| return 'ok - service worker replaced'; |
| }).catch(formatError); |
| } |
| |
| function removeManifest() { |
| var element = document.querySelector('link[rel="manifest"]'); |
| if (element) |
| element.parentNode.removeChild(element); |
| return 'manifest removed'; |
| } |
| |
| function swapManifestNoSenderId() { |
| var element = document.querySelector('link[rel="manifest"]'); |
| if (element) { |
| element.href = 'manifest_no_sender_id.json'; |
| return 'sender id removed from manifest'; |
| } else { |
| return 'unable to find manifest element'; |
| } |
| } |
| |
| // This is the old style of push subscriptions which we are phasing away |
| // from, where the subscription used a sender ID instead of public key. |
| function documentSubscribePushWithoutKey() { |
| return navigator.serviceWorker.ready.then(function(swRegistration) { |
| return swRegistration.pushManager.subscribe({userVisibleOnly: true}); |
| }).then(function(subscription) { |
| return subscription.endpoint; |
| }).catch(formatError); |
| } |
| |
| function documentSubscribePushWithEmptyOptions() { |
| return navigator.serviceWorker.ready.then(function(swRegistration) { |
| return swRegistration.pushManager.subscribe(); |
| }).then(function(subscription) { |
| return subscription.endpoint; |
| }).catch(formatError); |
| } |
| |
| function documentSubscribePush() { |
| return navigator.serviceWorker.ready.then(function(swRegistration) { |
| return swRegistration.pushManager.subscribe({ |
| userVisibleOnly: true, |
| applicationServerKey: kApplicationServerKey.buffer |
| }); |
| }).then(function(subscription) { |
| return subscription.endpoint; |
| }).catch(formatError); |
| } |
| |
| function documentSubscribePushWithNumericKey() { |
| return navigator.serviceWorker.ready.then(function(swRegistration) { |
| return swRegistration.pushManager.subscribe({ |
| userVisibleOnly: true, |
| applicationServerKey: new TextEncoder().encode('1234567890') |
| }); |
| }).then(function(subscription) { |
| return subscription.endpoint; |
| }).catch(formatError); |
| } |
| |
| function documentSubscribePushWithBase64URLEncodedString() { |
| return navigator.serviceWorker.ready.then(function(swRegistration) { |
| return swRegistration.pushManager.subscribe({ |
| userVisibleOnly: true, |
| applicationServerKey: kBase64URLEncodedKey |
| }); |
| }).then(function(subscription) { |
| return subscription.endpoint; |
| }).catch(formatError); |
| } |
| |
| function documentSubscribePushGetExpirationTime() { |
| return navigator.serviceWorker.ready.then(function(swRegistration) { |
| return swRegistration.pushManager.subscribe({ |
| userVisibleOnly: true, |
| applicationServerKey: kApplicationServerKey.buffer |
| }); |
| }).then(function(subscription) { |
| return String(subscription.expirationTime); |
| }).catch(formatError); |
| } |
| |
| function workerSubscribePush() { |
| // Send the message to the worker for it to subscribe |
| return new Promise(resolve => { |
| navigator.serviceWorker.addEventListener('message', resolve, false); |
| navigator.serviceWorker.controller.postMessage( |
| {command: 'workerSubscribe'}); |
| }).then((event) => JSON.parse(event.data).data); |
| } |
| |
| function workerSubscribePushNoKey() { |
| // The worker will try to subscribe without providing a key. This should |
| // succeed if the worker was previously subscribed with a numeric key |
| // and fail otherwise. |
| return new Promise(resolve => { |
| navigator.serviceWorker.addEventListener('message', resolve, false); |
| navigator.serviceWorker.controller.postMessage( |
| {command: 'workerSubscribeNoKey'}); |
| }).then((event) => JSON.parse(event.data).data); |
| } |
| |
| function workerSubscribePushWithNumericKey(numericKey = '1234567890') { |
| // Send the message to the worker for it to subscribe with the given numeric key |
| return new Promise(resolve => { |
| navigator.serviceWorker.addEventListener('message', resolve, false); |
| navigator.serviceWorker.controller.postMessage( |
| {command: 'workerSubscribeWithNumericKey', key: numericKey}); |
| }).then((event) => JSON.parse(event.data).data); |
| } |
| |
| function workerSubscribePushWithBase64URLEncodedString() { |
| // Send the message to the worker for it to subscribe with the given Base64URLEncoded key |
| return new Promise(resolve => { |
| navigator.serviceWorker.addEventListener('message', resolve, false); |
| navigator.serviceWorker.controller.postMessage( |
| {command: 'workerSubscribePushWithBase64URLEncodedString', |
| key: kBase64URLEncodedKey}); |
| }).then((event) => JSON.parse(event.data).data); |
| } |
| |
| function GetP256dh() { |
| return navigator.serviceWorker.ready.then(function(swRegistration) { |
| return swRegistration.pushManager.getSubscription(); |
| }).then(function(subscription) { |
| return btoa(String.fromCharCode.apply(null, |
| new Uint8Array(subscription.getKey('p256dh')))); |
| }).catch(formatError); |
| } |
| |
| function GetSubscriptionExpirationTime() { |
| return navigator.serviceWorker.ready.then(function(swRegistration) { |
| return swRegistration.pushManager.getSubscription(); |
| }).then(function(subscription) { |
| return String(subscription.expirationTime); |
| }).catch(formatError); |
| } |
| |
| function pushManagerPermissionState() { |
| return navigator.serviceWorker.ready.then(function(swRegistration) { |
| return swRegistration.pushManager.permissionState({userVisibleOnly: true}); |
| }).then(function(permission) { |
| return 'permission status - ' + permission; |
| }).catch(formatError); |
| } |
| |
| function notificationPermissionState() { |
| return 'permission status - ' + Notification.permission; |
| } |
| |
| function notificationPermissionAPIState() { |
| return navigator.permissions.query({name: 'notifications'}).then( |
| permission_status => { |
| return 'permission status - ' + permission_status.state; |
| }).catch(formatError); |
| } |
| |
| function isControlled() { |
| if (navigator.serviceWorker.controller) { |
| return 'true - is controlled'; |
| } else { |
| return 'false - is not controlled'; |
| } |
| } |
| |
| async function unsubscribePush() { |
| const swRegistration = await navigator.serviceWorker.ready; |
| if (!swRegistration) { |
| return 'unsubscribe result: false'; |
| } |
| const pushSubscription = await swRegistration.pushManager.getSubscription(); |
| if (!pushSubscription) { |
| return 'unsubscribe result: false'; |
| } |
| try { |
| const result = await pushSubscription.unsubscribe(); |
| return 'unsubscribe result: ' + result; |
| } catch(error) { |
| return 'unsubscribe error: ' + error.message; |
| } |
| } |
| |
| function storePushSubscription() { |
| return navigator.serviceWorker.ready.then(swRegistration => { |
| return swRegistration.pushManager.getSubscription(); |
| }).then(pushSubscription => { |
| window.storedPushSubscription = pushSubscription; |
| return 'ok - stored'; |
| }) |
| .catch(formatError); |
| } |
| |
| function unsubscribeStoredPushSubscription() { |
| return window.storedPushSubscription.unsubscribe().then(function(result) { |
| return 'unsubscribe result: ' + result; |
| }, function(error) { |
| return 'unsubscribe error: ' + error.message; |
| }); |
| } |
| |
| function hasSubscription() { |
| return navigator.serviceWorker.ready.then(function(swRegistration) { |
| return swRegistration.pushManager.getSubscription(); |
| }).then(function(subscription) { |
| return subscription ? 'true - subscribed' |
| : 'false - not subscribed'; |
| }).catch(formatError); |
| } |
| |
| navigator.serviceWorker.addEventListener('message', function(event) { |
| var message = JSON.parse(event.data); |
| if (message.type === 'push') { |
| resultQueue.push(message.data); |
| } else if (message.type === 'pushsubscriptionchange') { |
| resultQueue.push(message.data.oldEndpoint); |
| resultQueue.push(message.data.newEndpoint); |
| } else if (message.type === 'autoresubscribe') { |
| resultQueue.push(message.data.endpoint); |
| } |
| }, false); |