| 
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -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. | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
						
					 | 
				
				 | 
				
					
  |