|  |  | @ -12,7 +12,7 @@ controlling the web browser's source code. Here named PROVIDER. An example of a | 
			
		
	
		
			
				
					|  |  |  | PROVIDER is FCM (Firebase Cloud Messaging) which is owned by Google. | 
			
		
	
		
			
				
					|  |  |  | 3) The Web Application that a user is visiting from their web browser. Let's | 
			
		
	
		
			
				
					|  |  |  | call this the SERVICE (short for Web Push application service) | 
			
		
	
		
			
				
					|  |  |  | [4) A Custom Web Push Intermediary Service, either third party or self-hosted. | 
			
		
	
		
			
				
					|  |  |  | 4) A Custom Web Push Intermediary Service, either third party or self-hosted. | 
			
		
	
		
			
				
					|  |  |  | Called INTERMEDIARY here. FCM also may fit in this category if the SERVICE | 
			
		
	
		
			
				
					|  |  |  | has an API key from FCM.] | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -105,7 +105,7 @@ Here's a version which can be used for testing locally.  Note there can be | 
			
		
	
		
			
				
					|  |  |  | caching issues in your browser!  Incognito is highly recommended. | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | sw-dev.ts | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | ``` | 
			
		
	
		
			
				
					|  |  |  | self.addEventListener('push', function(event: PushEvent) { | 
			
		
	
		
			
				
					|  |  |  |   console.log('Received a push message', event); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -122,10 +122,11 @@ self.addEventListener('push', function(event: PushEvent) { | 
			
		
	
		
			
				
					|  |  |  |     }) | 
			
		
	
		
			
				
					|  |  |  |   ); | 
			
		
	
		
			
				
					|  |  |  | }); | 
			
		
	
		
			
				
					|  |  |  | ``` | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | vue.config.js | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | ``` | 
			
		
	
		
			
				
					|  |  |  | module.exports = { | 
			
		
	
		
			
				
					|  |  |  |   pwa: { | 
			
		
	
		
			
				
					|  |  |  |     workboxOptions: { | 
			
		
	
	
		
			
				
					|  |  | @ -133,6 +134,7 @@ module.exports = { | 
			
		
	
		
			
				
					|  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |   } | 
			
		
	
		
			
				
					|  |  |  | } | 
			
		
	
		
			
				
					|  |  |  | ``` | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | Once we have the service worker registered and the ServiceWorkerRegistration is | 
			
		
	
		
			
				
					|  |  |  | returned, we then have access to a `pushManager` property object.  This property | 
			
		
	
	
		
			
				
					|  |  | @ -152,13 +154,13 @@ being used by the BROWSER in decrypting the messages coming from the SERVICE. | 
			
		
	
		
			
				
					|  |  |  | The VAPID (Voluntary Application Server Identification) key provides more | 
			
		
	
		
			
				
					|  |  |  | security and authenticity for web push notifications in the following ways: | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     Identifying the Application Server: | 
			
		
	
		
			
				
					|  |  |  | Identifying the Application Server: | 
			
		
	
		
			
				
					|  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |         The VAPID key is used to identify the application server that is sending | 
			
		
	
		
			
				
					|  |  |  | 	the push notifications. This ensures that the push notifications are | 
			
		
	
		
			
				
					|  |  |  | 	authentic and not sent by a malicious third party. | 
			
		
	
		
			
				
					|  |  |  | 	 | 
			
		
	
		
			
				
					|  |  |  |     Encrypting the Messages: | 
			
		
	
		
			
				
					|  |  |  | Encrypting the Messages: | 
			
		
	
		
			
				
					|  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |         The VAPID key is used to sign the push notifications sent by the | 
			
		
	
		
			
				
					|  |  |  | 	application server, ensuring that they are not tampered with during | 
			
		
	
	
		
			
				
					|  |  | @ -184,6 +186,7 @@ PROVIDER which creates and stores a special URL for that BROWSER. | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | Here's a bit of code describing the above process: | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | ``` | 
			
		
	
		
			
				
					|  |  |  | // b64 is the VAPID | 
			
		
	
		
			
				
					|  |  |  | b64 = 'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U'; | 
			
		
	
		
			
				
					|  |  |  | const applicationServerKey = urlBase64ToUint8Array(b64); | 
			
		
	
	
		
			
				
					|  |  | @ -199,6 +202,7 @@ registration.pushManager.subscribe(options) | 
			
		
	
		
			
				
					|  |  |  |   .catch(function(error) { | 
			
		
	
		
			
				
					|  |  |  |     console.error('Push subscription failed:', error); | 
			
		
	
		
			
				
					|  |  |  |   }); | 
			
		
	
		
			
				
					|  |  |  | ``` | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | In this example, the `applicationServerKey` variable contains the VAPID public | 
			
		
	
		
			
				
					|  |  |  | key, which is converted to a `Uint8Array` using a function such as this: | 
			
		
	
	
		
			
				
					|  |  | @ -221,6 +225,16 @@ export function toUint8Array(base64String: string, atobFn: typeof atob): Uint8Ar | 
			
		
	
		
			
				
					|  |  |  | The options object is of type `PushSubscriptionOptions`, which includes the | 
			
		
	
		
			
				
					|  |  |  | `userVisibleOnly` and `applicationServerKey` (ie VAPID public key) properties. | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     options: An object that contains the options used for creating the | 
			
		
	
		
			
				
					|  |  |  |     subscription. This object itself has the following sub-properties: | 
			
		
	
		
			
				
					|  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |       applicationServerKey: A public key your push service uses for application | 
			
		
	
		
			
				
					|  |  |  |       server identification. This is normally a Uint8Array. | 
			
		
	
		
			
				
					|  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |       userVisibleOnly: A boolean value indicating that the push messages that | 
			
		
	
		
			
				
					|  |  |  |       are sent should be made visible to the user through a notification. | 
			
		
	
		
			
				
					|  |  |  |       This is often set to true. | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | The subscribe() method returns a `Promise` that resolves to a `PushSubscription` | 
			
		
	
		
			
				
					|  |  |  | object containing details of the subscription, such as the endpoint URL and the | 
			
		
	
		
			
				
					|  |  |  | public key.  The returned data would have a form like this: | 
			
		
	
	
		
			
				
					|  |  | @ -242,16 +256,6 @@ public key.  The returned data would have a form like this: | 
			
		
	
		
			
				
					|  |  |  |     representing the subscription's expiration time in milliseconds since | 
			
		
	
		
			
				
					|  |  |  |     01 January, 1970 UTC. This can be null if the subscription never expires. | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |     options: An object that contains the options used for creating the | 
			
		
	
		
			
				
					|  |  |  |     subscription. This object itself has the following sub-properties: | 
			
		
	
		
			
				
					|  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |       applicationServerKey: A public key your push service uses for application | 
			
		
	
		
			
				
					|  |  |  |       server identification. This is normally a Uint8Array. | 
			
		
	
		
			
				
					|  |  |  |      | 
			
		
	
		
			
				
					|  |  |  |       userVisibleOnly: A boolean value indicating that the push messages that | 
			
		
	
		
			
				
					|  |  |  |       are sent should be made visible to the user through a notification. | 
			
		
	
		
			
				
					|  |  |  |       This is often set to true. | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | The BROWSER will, internally, then use that URL to check for incoming messages | 
			
		
	
		
			
				
					|  |  |  | by way of the service worker we described earlier. The BROWSER also sends this | 
			
		
	
		
			
				
					|  |  |  | URL back to SERVICE which will use that URL to send messages to the BROWSER via | 
			
		
	
	
		
			
				
					|  |  | @ -266,6 +270,7 @@ via the PROVIDER so that they reach the BROWSER service worker. | 
			
		
	
		
			
				
					|  |  |  | Just to remind us that in our service worker our code for receiving messages | 
			
		
	
		
			
				
					|  |  |  | will look something like this: | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | ``` | 
			
		
	
		
			
				
					|  |  |  | self.addEventListener('push', function(event: PushEvent) { | 
			
		
	
		
			
				
					|  |  |  |   console.log('Received a push message', event); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
	
		
			
				
					|  |  | @ -282,7 +287,7 @@ self.addEventListener('push', function(event: PushEvent) { | 
			
		
	
		
			
				
					|  |  |  |     }) | 
			
		
	
		
			
				
					|  |  |  |   ); | 
			
		
	
		
			
				
					|  |  |  | }); | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | ``` | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  | Now to address the issue of receiving notification messages on mobile devices. | 
			
		
	
	
		
			
				
					|  |  | 
 |