From 3e3c275834597e70c9e77da9fc720a7227188bfd Mon Sep 17 00:00:00 2001 From: Paul J Thordarson Date: Tue, 15 Dec 2015 08:33:59 -0500 Subject: [PATCH] Fix #184: Add support for the Push API I did not include any of the following: * Any item marked deprecated in MDN. --- .../dom/experimental/push/PushManager.scala | 225 ++++++++++++++++++ .../dom/experimental/push/package.scala | 69 ++++++ 2 files changed, 294 insertions(+) create mode 100644 src/main/scala/org/scalajs/dom/experimental/push/PushManager.scala create mode 100644 src/main/scala/org/scalajs/dom/experimental/push/package.scala diff --git a/src/main/scala/org/scalajs/dom/experimental/push/PushManager.scala b/src/main/scala/org/scalajs/dom/experimental/push/PushManager.scala new file mode 100644 index 000000000..eb1c071f1 --- /dev/null +++ b/src/main/scala/org/scalajs/dom/experimental/push/PushManager.scala @@ -0,0 +1,225 @@ +package org.scalajs.dom.experimental.push + +import org.scalajs.dom.experimental.serviceworkers.ExtendableEvent +import org.scalajs.dom.raw.{Blob, Promise} + +import scala.scalajs.js +import scala.scalajs.js.typedarray.ArrayBuffer + +/** + * The PushManager interface of the Push API provides a way to receive notifications + * from third-party servers as well as request URLs for push notifications. + * + * This interface is accessed via the ServiceWorkerRegistration.pushManager property. + * + * MDN + * + * The Push API is currently specified here: [[http://www.w3.org/TR/2015/WD-push-api-20151215/]] + */ +@js.native +trait PushManager extends js.Object { + /** + * Retrieves an existing push subscription. It returns a Promise that resolves to a + * PushSubscription object containing details of an existing subscription. If no + * existing subscription exists, this resolves to a null value. + * + * MDN + */ + def getSubscription(): Promise[PushSubscription] = js.native + + /** + * The permissionState() method of the PushManager interface returns a Promise that + * resolves to a DOMString indicating the permission state of the push manager. + * Possible values are 'prompt', 'denied', or 'granted'. + * + * @param options An object containing optional configuration parameters. It can have + * the following properties: + * - userVisibleOnly: A boolean indicating that the returned push subscription will only + * be used for messages whose effect is made visible to the user. + * + * MDN + */ + def permissionState(options: PushSubscriptionOptions = js.native): Promise[PushPermissionState] = js.native + + /** + * The subscribe() method of the PushManager interface subscribes to a push service. + * + * It returns a Promise that resolves to a PushSubscription object containing details of a + * push subscription. A new push subscription is created if the current service worker + * does not have an existing subscription. + * + * MDN + */ + def subscribe(options: PushSubscriptionOptions = js.native): Promise[PushSubscription] = js.native +} + +/** + * The PushSubscription interface of the Push API provides a subcription's URL endpoint + * and allows unsubscription from a push service. + * + * An instance of this interface can be serialized. + * + * MDN + */ +@js.native +trait PushSubscription extends js.Object { + /** + * The endpoint read-only property of the PushSubscription interface returns a USVString + * containing the endpoint associated with the push subscription. The endpoint takes the + * form of a custom URL pointing to a push server, which can be used to send a push message + * to the particular service worker instance that subscribed to the push service. For this + * reason, it is a good idea to keep your endPoint a secret, so others do not hijack it and + * abuse the push functionality. + * + * MDN + */ + val endpoint: String = js.native + + /** + * The getKey method retrieves keying material that can be used for encrypting and authenticating messages. + */ + def getKey(name: PushEncryptionKeyName): ArrayBuffer = js.native + + /** + * The unsubscribe() method of the PushSubscription interface returns a Promise that + * resolves to a Boolean when the current subscription is successfully unsubscribed. + * + * MDN + */ + def unsubscribe(): Promise[Boolean] = js.native + + /** + * The toJSON() method of the PushSubscription interface is a standard serializer: it returns + * a JSON representation of the subscription properties, providing a useful shortcut. + * + * MDN + */ + def toJSON(): String = js.native +} + +/** + * The PushEvent interface of the Push API represents a push message that has been received. + * This event is sent to the global scope of a ServiceWorker. It contains the information + * sent from an application server to a PushSubscription. + * + * MDN + */ +@js.native +trait PushEvent extends ExtendableEvent { + + /** + * Returns a reference to a PushMessageData object containing data sent to the PushSubscription. + * Read-only. + * + * MDN + */ + val data: PushMessageData = js.native +} + +/** + * The PushMessageData interface of the Push API provides methods which let you retrieve the + * push data sent by a server in various formats. + * + * Unlike the similar methods in the Fetch API, which only allow the method to be invoked once, + * these methods can be called multiple times. + * + * MDN + */ +@js.native +trait PushMessageData extends js.Object { + /** + * Extracts the data as an ArrayBuffer object. + * + * MDN + */ + def arrayBuffer(): ArrayBuffer = js.native + + /** + * Extracts the data as a Blob object. + * + * MDN + */ + def blob(): Blob = js.native + + /** + * Extracts the data as a JSON object. + * + * MDN + */ + def json(): js.Any = js.native + + /** + * Extracts the data as a plain text string. + * + * MDN + */ + def text(): String = js.native +} + +/** + * A PushSubscriptionOptions object represents additional options associated with a push subscription. + * + * The userVisibleOnly option, when set to true, indicates that the push subscription will only be used + * for push messages whose effect is made visible to the user, for example by displaying a Web Notification. + */ +@js.native +trait PushSubscriptionOptions extends js.Object { + var userVisibleOnly: js.UndefOr[Boolean] = js.native +} + +/** Factory for [[PushSubscriptionOptions]] objects. */ +object PushSubscriptionOptions { + + /** + * Creates a new [[PushSubscriptionOptions]] object. Default value for userVisibleOnly is false. + */ + def apply(userVisibleOnly: Boolean = false): PushSubscriptionOptions = { + js.Dynamic.literal("userVisibleOnly" -> userVisibleOnly).asInstanceOf[PushSubscriptionOptions] + } +} + +/** + * This represents a JavaScript enumeration describing the state of permissions for + * pushing described here: [[http://www.w3.org/TR/push-api/#idl-def-PushPermissionState]] + */ +@js.native +sealed trait PushPermissionState extends js.Any + +/** Static definitions for [[PushPermissionState]] */ +object PushPermissionState { + /** + * The webapp has permission to use the Push API. + */ + val granted = "granted".asInstanceOf[PushPermissionState] + + /** + * The webapp has been denied permission to use the Push API. + */ + val denied = "denied".asInstanceOf[PushPermissionState] + + /** + * The webapp needs to ask for permission in order to use the Push API. + */ + val prompt = "prompt".asInstanceOf[PushPermissionState] +} + +/** + * This represents a JavaScript enumeration representing the various keys you an request from a + * [[PushSubscription]] as described here: [[http://www.w3.org/TR/push-api/#idl-def-PushEncryptionKeyName]] + */ +@js.native +sealed trait PushEncryptionKeyName extends js.Any + +/** Static definitions for [[PushEncryptionKeyName]] */ +object PushEncryptionKeyName { + /** + * used to retrieve the P-256 ECDH Diffie-Hellman public key described here: + * [[https://tools.ietf.org/html/draft-ietf-webpush-encryption-01]] + */ + val p256dh = "p256dh".asInstanceOf[PushEncryptionKeyName] + /** + * used to retrieve the authentication secret described here: + * [[https://tools.ietf.org/html/draft-ietf-webpush-encryption-01]] + */ + val auth = "auth".asInstanceOf[PushEncryptionKeyName] +} diff --git a/src/main/scala/org/scalajs/dom/experimental/push/package.scala b/src/main/scala/org/scalajs/dom/experimental/push/package.scala new file mode 100644 index 000000000..3351b02bf --- /dev/null +++ b/src/main/scala/org/scalajs/dom/experimental/push/package.scala @@ -0,0 +1,69 @@ +package org.scalajs.dom.experimental + +import scala.language.implicitConversions + +import org.scalajs.dom.experimental.serviceworkers.{ServiceWorkerGlobalScope, ServiceWorkerRegistration} + +import scala.scalajs.js + +/** + * The Push API is currently specified here: [[http://www.w3.org/TR/2015/WD-push-api-20151215/]] + */ +package object push { + /** + * Implicit function for patching Push API support onto ServiceWorkerRegistration. + */ + implicit def pushServiceWorkerRegistration(swr: ServiceWorkerRegistration): PushServiceWorkerRegistration = + swr.asInstanceOf[PushServiceWorkerRegistration] + + /** + * Implicit function for patching Push API support onto ServiceWorkerGlobalScope + */ + implicit def pushServiceWorkerGlobalScope(swgs: ServiceWorkerGlobalScope): PushServiceWorkerGlobalScope = + swgs.asInstanceOf[PushServiceWorkerGlobalScope] + + /** + * A trait used for patching Push API support onto ServiceWorkerRegistration. + */ + @js.native + trait PushServiceWorkerRegistration extends js.Any { + + /** + * The pushManager property of the ServiceWorkerRegistration interface returns + * a reference to the PushManager interface for managing push subscriptions; + * this includes support for subscribing, getting an active subscription, and + * accessing push permission status. + * + * MDN + */ + val pushManager: PushManager = js.native + } + + /** + * A trait used for patching Push API support onto ServiceWorkerGlobalScope. + */ + @js.native + trait PushServiceWorkerGlobalScope extends js.Any { + + /** + * The ServiceWorkerGlobalScope.onpush event of the ServiceWorkerGlobalScope + * interface is fired whenever a push message is received by a service worker + * via a push server. + * + * MDN + */ + var onpush: js.Function1[PushEvent, _] = js.native + + /** + * The ServiceWorkerGlobalScope.onpushsubscriptionchange event of the + * ServiceWorkerGlobalScope interface is fired whenever a push subscription has + * been invalidated (or is about to become so). This offers an opportunity to + * resubscribe in order to continue receiving push messages, if desired. This + * might happen if, for example, the push service sets an expiration time a + * subscription. + * + * MDN + */ + var onpushsubscriptionchange: js.Function1[PushEvent, _] = js.native + } +}