Skip to content

Commit edc22aa

Browse files
authored
Merge branch 'master' into mmermerkaya-fix-types
2 parents 457f492 + 3110d6b commit edc22aa

File tree

5 files changed

+72
-111
lines changed

5 files changed

+72
-111
lines changed

packages/firebase/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
/firebase*.map
33
/firebase*.gz
44
/firebase*.tgz
5+
*/*.d.ts

packages/firebase/tsconfig.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
"extends": "../../config/tsconfig.base.json",
33
"compilerOptions": {
44
"outDir": "dist",
5-
"declaration": false
65
},
76
"exclude": [
87
"dist/**/*"

packages/messaging/src/controllers/controller-interface.ts

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -77,15 +77,11 @@ export abstract class ControllerInterface implements FirebaseMessaging {
7777
async getToken(): Promise<string | null> {
7878
// Check with permissions
7979
const currentPermission = this.getNotificationPermission_();
80-
if (currentPermission !== 'granted') {
81-
if (currentPermission === 'denied') {
82-
return Promise.reject(
83-
errorFactory.create(ERROR_CODES.NOTIFICATIONS_BLOCKED)
84-
);
85-
}
86-
80+
if (currentPermission === 'denied') {
81+
throw errorFactory.create(ERROR_CODES.NOTIFICATIONS_BLOCKED);
82+
} else if (currentPermission !== 'granted') {
8783
// We must wait for permission to be granted
88-
return Promise.resolve(null);
84+
return null;
8985
}
9086

9187
const swReg = await this.getSWRegistration_();
@@ -223,7 +219,6 @@ export abstract class ControllerInterface implements FirebaseMessaging {
223219
* unsubscribes the token from FCM and then unregisters the push
224220
* subscription if it exists. It returns a promise that indicates
225221
* whether or not the unsubscribe request was processed successfully.
226-
* @export
227222
*/
228223
async deleteToken(token: string): Promise<boolean> {
229224
// Delete the token details from the database.
@@ -371,6 +366,7 @@ function isTokenStillValid(
371366
tokenDetails: TokenDetails
372367
): boolean {
373368
if (
369+
!tokenDetails.vapidKey ||
374370
!isArrayBufferEqual(publicVapidKey.buffer, tokenDetails.vapidKey.buffer)
375371
) {
376372
return false;

packages/messaging/src/controllers/window-controller.ts

Lines changed: 56 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ import {
3636
} from '../models/worker-page-message';
3737
import { ControllerInterface } from './controller-interface';
3838

39+
interface ManifestContent {
40+
gcm_sender_id: string;
41+
}
42+
3943
export 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+
}

packages/messaging/test/window-controller.test.ts

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ import * as sinon from 'sinon';
1919
import { makeFakeApp } from './testing-utils/make-fake-app';
2020
import { makeFakeSWReg } from './testing-utils/make-fake-sw-reg';
2121

22-
import { WindowController } from '../src/controllers/window-controller';
22+
import {
23+
manifestCheck,
24+
WindowController
25+
} from '../src/controllers/window-controller';
2326
import { base64ToArrayBuffer } from '../src/helpers/base64-to-array-buffer';
2427
import { DEFAULT_PUBLIC_VAPID_KEY } from '../src/models/fcm-details';
2528

@@ -46,15 +49,14 @@ describe('Firebase Messaging > *WindowController', () => {
4649
return cleanup();
4750
});
4851

49-
describe('manifestCheck_()', () => {
52+
describe('manifestCheck()', () => {
5053
it("should resolve when the tag isn't defined", () => {
5154
sandbox
5255
.stub(document, 'querySelector')
5356
.withArgs('link[rel="manifest"]')
5457
.returns(null);
5558

56-
const controller = new WindowController(app);
57-
return controller.manifestCheck_();
59+
return manifestCheck();
5860
});
5961

6062
it('should fetch the manifest if defined and resolve when no gcm_sender_id', () => {
@@ -76,8 +78,7 @@ describe('Firebase Messaging > *WindowController', () => {
7678
})
7779
);
7880

79-
const controller = new WindowController(app);
80-
return controller.manifestCheck_();
81+
return manifestCheck();
8182
});
8283

8384
it('should fetch the manifest if defined and resolve with expected gcm_sender_id', () => {
@@ -101,8 +102,7 @@ describe('Firebase Messaging > *WindowController', () => {
101102
})
102103
);
103104

104-
const controller = new WindowController(app);
105-
return controller.manifestCheck_();
105+
return manifestCheck();
106106
});
107107

108108
it('should fetch the manifest if defined and reject when using wrong gcm_sender_id', () => {
@@ -126,8 +126,7 @@ describe('Firebase Messaging > *WindowController', () => {
126126
})
127127
);
128128

129-
const controller = new WindowController(app);
130-
return controller.manifestCheck_().then(
129+
return manifestCheck().then(
131130
() => {
132131
throw new Error('Expected error to be thrown.');
133132
},
@@ -150,8 +149,7 @@ describe('Firebase Messaging > *WindowController', () => {
150149
.withArgs('https://firebase.io/messaging/example')
151150
.returns(Promise.reject(new Error('Injected Failure.')));
152151

153-
const controller = new WindowController(app);
154-
return controller.manifestCheck_();
152+
return manifestCheck();
155153
});
156154
});
157155

@@ -206,16 +204,6 @@ describe('Firebase Messaging > *WindowController', () => {
206204
const controller = new WindowController(app);
207205
return controller.requestPermission();
208206
});
209-
210-
it('should resolve if the requestPermission() is granted using old callback API', () => {
211-
sandbox.stub(Notification as any, 'permission').value('default');
212-
sandbox.stub(Notification, 'requestPermission').callsFake(cb => {
213-
cb('granted');
214-
});
215-
216-
const controller = new WindowController(app);
217-
return controller.requestPermission();
218-
});
219207
});
220208

221209
describe('useServiceWorker()', () => {

0 commit comments

Comments
 (0)