@@ -36,6 +36,10 @@ import {
3636} from '../models/worker-page-message' ;
3737import { ControllerInterface } from './controller-interface' ;
3838
39+ interface ManifestContent {
40+ gcm_sender_id : string ;
41+ }
42+
3943export class WindowController extends ControllerInterface {
4044 private registrationToUse : ServiceWorkerRegistration | null = null ;
4145 private publicVapidKeyToUse : Uint8Array | null = null ;
@@ -75,55 +79,12 @@ export class WindowController extends ControllerInterface {
7579 * @return Returns a promise that resolves to an FCM token or null if
7680 * permission isn't granted.
7781 */
78- getToken ( ) : Promise < string | null > {
79- return this . manifestCheck_ ( ) . then ( ( ) => {
80- return super . getToken ( ) ;
81- } ) ;
82- }
83-
84- /**
85- * The method checks that a manifest is defined and has the correct GCM
86- * sender ID.
87- * @return Returns a promise that resolves if the manifest matches
88- * our required sender ID
89- */
90- // Visible for testing
91- // TODO: make private
92- manifestCheck_ ( ) : Promise < void > {
93- if ( this . manifestCheckPromise ) {
94- return this . manifestCheckPromise ;
95- }
96-
97- const manifestTag = document . querySelector < HTMLAnchorElement > (
98- 'link[rel="manifest"]'
99- ) ;
100- if ( ! manifestTag ) {
101- this . manifestCheckPromise = Promise . resolve ( ) ;
102- } else {
103- this . manifestCheckPromise = fetch ( manifestTag . href )
104- . then ( response => {
105- return response . json ( ) ;
106- } )
107- . catch ( ( ) => {
108- // If the download or parsing fails allow check.
109- // We only want to error if we KNOW that the gcm_sender_id is incorrect.
110- } )
111- . then ( manifestContent => {
112- if ( ! manifestContent ) {
113- return ;
114- }
115-
116- if ( ! manifestContent [ 'gcm_sender_id' ] ) {
117- return ;
118- }
119-
120- if ( manifestContent [ 'gcm_sender_id' ] !== '103953800507' ) {
121- throw errorFactory . create ( ERROR_CODES . INCORRECT_GCM_SENDER_ID ) ;
122- }
123- } ) ;
82+ async getToken ( ) : Promise < string | null > {
83+ if ( ! this . manifestCheckPromise ) {
84+ this . manifestCheckPromise = manifestCheck ( ) ;
12485 }
125-
126- return this . manifestCheckPromise ;
86+ await this . manifestCheckPromise ;
87+ return super . getToken ( ) ;
12788 }
12889
12990 /**
@@ -132,37 +93,18 @@ export class WindowController extends ControllerInterface {
13293 * @return Resolves if the permission was granted, otherwise rejects
13394 */
13495 async requestPermission ( ) : Promise < void > {
135- if (
136- // TODO: Remove the cast when this issue is fixed:
137- // https://github.com/Microsoft/TypeScript/issues/14701
138- // tslint:disable-next-line no-any
139- ( ( Notification as any ) . permission as NotificationPermission ) === 'granted'
140- ) {
96+ if ( this . getNotificationPermission_ ( ) === 'granted' ) {
14197 return ;
14298 }
14399
144- return new Promise < void > ( ( resolve , reject ) => {
145- const managePermissionResult = ( result : NotificationPermission ) => {
146- if ( result === 'granted' ) {
147- return resolve ( ) ;
148- } else if ( result === 'denied' ) {
149- return reject ( errorFactory . create ( ERROR_CODES . PERMISSION_BLOCKED ) ) ;
150- } else {
151- return reject ( errorFactory . create ( ERROR_CODES . PERMISSION_DEFAULT ) ) ;
152- }
153- } ;
154-
155- // The Notification.requestPermission API was changed to
156- // return a promise so now have to handle both in case
157- // browsers stop support callbacks for promised version
158- const permissionPromise = Notification . requestPermission (
159- managePermissionResult
160- ) ;
161- if ( permissionPromise ) {
162- // Prefer the promise version as it's the future API.
163- permissionPromise . then ( managePermissionResult ) ;
164- }
165- } ) ;
100+ const permissionResult = await Notification . requestPermission ( ) ;
101+ if ( permissionResult === 'granted' ) {
102+ return ;
103+ } else if ( permissionResult === 'denied' ) {
104+ throw errorFactory . create ( ERROR_CODES . PERMISSION_BLOCKED ) ;
105+ } else {
106+ throw errorFactory . create ( ERROR_CODES . PERMISSION_DEFAULT ) ;
107+ }
166108 }
167109
168110 /**
@@ -334,12 +276,12 @@ export class WindowController extends ControllerInterface {
334276 * This will return the default VAPID key or the uint8array version of the public VAPID key
335277 * provided by the developer.
336278 */
337- getPublicVapidKey_ ( ) : Promise < Uint8Array > {
279+ async getPublicVapidKey_ ( ) : Promise < Uint8Array > {
338280 if ( this . publicVapidKeyToUse ) {
339- return Promise . resolve ( this . publicVapidKeyToUse ) ;
281+ return this . publicVapidKeyToUse ;
340282 }
341283
342- return Promise . resolve ( DEFAULT_PUBLIC_VAPID_KEY ) ;
284+ return DEFAULT_PUBLIC_VAPID_KEY ;
343285 }
344286
345287 /**
@@ -376,3 +318,38 @@ export class WindowController extends ControllerInterface {
376318 ) ;
377319 }
378320}
321+
322+ /**
323+ * The method checks that a manifest is defined and has the correct GCM
324+ * sender ID.
325+ * @return Returns a promise that resolves if the manifest matches
326+ * our required sender ID
327+ */
328+ // Exported for testing
329+ export async function manifestCheck ( ) : Promise < void > {
330+ const manifestTag = document . querySelector < HTMLAnchorElement > (
331+ 'link[rel="manifest"]'
332+ ) ;
333+
334+ if ( ! manifestTag ) {
335+ return ;
336+ }
337+
338+ let manifestContent : ManifestContent ;
339+ try {
340+ const response = await fetch ( manifestTag . href ) ;
341+ manifestContent = await response . json ( ) ;
342+ } catch ( e ) {
343+ // If the download or parsing fails allow check.
344+ // We only want to error if we KNOW that the gcm_sender_id is incorrect.
345+ return ;
346+ }
347+
348+ if ( ! manifestContent || ! manifestContent . gcm_sender_id ) {
349+ return ;
350+ }
351+
352+ if ( manifestContent . gcm_sender_id !== '103953800507' ) {
353+ throw errorFactory . create ( ERROR_CODES . INCORRECT_GCM_SENDER_ID ) ;
354+ }
355+ }
0 commit comments