Skip to content

Commit e2ee513

Browse files
committed
Added a timeout
1 parent 2035fe8 commit e2ee513

File tree

11 files changed

+69
-13
lines changed

11 files changed

+69
-13
lines changed

.changeset/neat-beans-rescue.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
'@firebase/messaging': patch
2+
'@firebase/messaging': minor
33
---
44

55
Fix an issue where PushManager.subscribe() is called too soon after registering the default service worker.

common/api-review/messaging-sw.api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ export function getMessaging(app?: FirebaseApp): Messaging;
2424
// @public
2525
export interface GetTokenOptions {
2626
serviceWorkerRegistration?: ServiceWorkerRegistration;
27+
serviceWorkerRegistrationTimeout?: number;
2728
vapidKey?: string;
2829
}
2930

common/api-review/messaging.api.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export function getToken(messaging: Messaging, options?: GetTokenOptions): Promi
2727
// @public
2828
export interface GetTokenOptions {
2929
serviceWorkerRegistration?: ServiceWorkerRegistration;
30+
serviceWorkerRegistrationTimeout?: number;
3031
vapidKey?: string;
3132
}
3233

docs-devsite/messaging_.gettokenoptions.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export interface GetTokenOptions
2323
| Property | Type | Description |
2424
| --- | --- | --- |
2525
| [serviceWorkerRegistration](./messaging_.gettokenoptions.md#gettokenoptionsserviceworkerregistration) | ServiceWorkerRegistration | The service worker registration for receiving push messaging. If the registration is not provided explicitly, you need to have a <code>firebase-messaging-sw.js</code> at your root location. See [Access the registration token](https://firebase.google.com/docs/cloud-messaging/js/client#access_the_registration_token) for more details. |
26+
| [serviceWorkerRegistrationTimeout](./messaging_.gettokenoptions.md#gettokenoptionsserviceworkerregistrationtimeout) | number | Milliseconds to wait for service worker registration to complete before rejecting and throwing an error. Defaults to 10000. |
2627
| [vapidKey](./messaging_.gettokenoptions.md#gettokenoptionsvapidkey) | string | The public server key provided to push services. The key is used to authenticate push subscribers to receive push messages only from sending servers that hold the corresponding private key. If it is not provided, a default VAPID key is used. Note that some push services (Chrome Push Service) require a non-default VAPID key. Therefore, it is recommended to generate and import a VAPID key for your project with [Configure Web Credentials with FCM](https://firebase.google.com/docs/cloud-messaging/js/client#configure_web_credentials_in_your_app)<!-- -->. See [The Web Push Protocol](https://developers.google.com/web/fundamentals/push-notifications/web-push-protocol) for details on web push services. |
2728

2829
## GetTokenOptions.serviceWorkerRegistration
@@ -35,6 +36,16 @@ The service worker registration for receiving push messaging. If the registratio
3536
serviceWorkerRegistration?: ServiceWorkerRegistration;
3637
```
3738

39+
## GetTokenOptions.serviceWorkerRegistrationTimeout
40+
41+
Milliseconds to wait for service worker registration to complete before rejecting and throwing an error. Defaults to 10000.
42+
43+
<b>Signature:</b>
44+
45+
```typescript
46+
serviceWorkerRegistrationTimeout?: number;
47+
```
48+
3849
## GetTokenOptions.vapidKey
3950

4051
The public server key provided to push services. The key is used to authenticate push subscribers to receive push messages only from sending servers that hold the corresponding private key. If it is not provided, a default VAPID key is used. Note that some push services (Chrome Push Service) require a non-default VAPID key. Therefore, it is recommended to generate and import a VAPID key for your project with [Configure Web Credentials with FCM](https://firebase.google.com/docs/cloud-messaging/js/client#configure_web_credentials_in_your_app)<!-- -->. See [The Web Push Protocol](https://developers.google.com/web/fundamentals/push-notifications/web-push-protocol) for details on web push services.

docs-devsite/messaging_sw.gettokenoptions.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export interface GetTokenOptions
2323
| Property | Type | Description |
2424
| --- | --- | --- |
2525
| [serviceWorkerRegistration](./messaging_sw.gettokenoptions.md#gettokenoptionsserviceworkerregistration) | ServiceWorkerRegistration | The service worker registration for receiving push messaging. If the registration is not provided explicitly, you need to have a <code>firebase-messaging-sw.js</code> at your root location. See [Access the registration token](https://firebase.google.com/docs/cloud-messaging/js/client#access_the_registration_token) for more details. |
26+
| [serviceWorkerRegistrationTimeout](./messaging_sw.gettokenoptions.md#gettokenoptionsserviceworkerregistrationtimeout) | number | Milliseconds to wait for service worker registration to complete before rejecting and throwing an error. Defaults to 10000. |
2627
| [vapidKey](./messaging_sw.gettokenoptions.md#gettokenoptionsvapidkey) | string | The public server key provided to push services. The key is used to authenticate push subscribers to receive push messages only from sending servers that hold the corresponding private key. If it is not provided, a default VAPID key is used. Note that some push services (Chrome Push Service) require a non-default VAPID key. Therefore, it is recommended to generate and import a VAPID key for your project with [Configure Web Credentials with FCM](https://firebase.google.com/docs/cloud-messaging/js/client#configure_web_credentials_in_your_app)<!-- -->. See [The Web Push Protocol](https://developers.google.com/web/fundamentals/push-notifications/web-push-protocol) for details on web push services. |
2728

2829
## GetTokenOptions.serviceWorkerRegistration
@@ -35,6 +36,16 @@ The service worker registration for receiving push messaging. If the registratio
3536
serviceWorkerRegistration?: ServiceWorkerRegistration;
3637
```
3738

39+
## GetTokenOptions.serviceWorkerRegistrationTimeout
40+
41+
Milliseconds to wait for service worker registration to complete before rejecting and throwing an error. Defaults to 10000.
42+
43+
<b>Signature:</b>
44+
45+
```typescript
46+
serviceWorkerRegistrationTimeout?: number;
47+
```
48+
3849
## GetTokenOptions.vapidKey
3950

4051
The public server key provided to push services. The key is used to authenticate push subscribers to receive push messages only from sending servers that hold the corresponding private key. If it is not provided, a default VAPID key is used. Note that some push services (Chrome Push Service) require a non-default VAPID key. Therefore, it is recommended to generate and import a VAPID key for your project with [Configure Web Credentials with FCM](https://firebase.google.com/docs/cloud-messaging/js/client#configure_web_credentials_in_your_app)<!-- -->. See [The Web Push Protocol](https://developers.google.com/web/fundamentals/push-notifications/web-push-protocol) for details on web push services.

packages/messaging/src/api/deleteToken.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,15 @@ import { deleteTokenInternal } from '../internals/token-manager';
2222
import { registerDefaultSw } from '../helpers/registerDefaultSw';
2323

2424
export async function deleteToken(
25-
messaging: MessagingService
25+
messaging: MessagingService,
26+
swRegistrationTimeoutMillis?: number
2627
): Promise<boolean> {
2728
if (!navigator) {
2829
throw ERROR_FACTORY.create(ErrorCode.AVAILABLE_IN_WINDOW);
2930
}
3031

3132
if (!messaging.swRegistration) {
32-
await registerDefaultSw(messaging);
33+
await registerDefaultSw(messaging, swRegistrationTimeoutMillis);
3334
}
3435

3536
return deleteTokenInternal(messaging);

packages/messaging/src/api/getToken.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,11 @@ export async function getToken(
4040
}
4141

4242
await updateVapidKey(messaging, options?.vapidKey);
43-
await updateSwReg(messaging, options?.serviceWorkerRegistration);
43+
await updateSwReg(
44+
messaging,
45+
options?.serviceWorkerRegistration,
46+
options?.serviceWorkerRegistrationTimeout
47+
);
4448

4549
return getTokenInternal(messaging);
4650
}

packages/messaging/src/helpers/registerDefaultSw.ts

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,18 @@
1515
* limitations under the License.
1616
*/
1717

18-
import { DEFAULT_SW_PATH, DEFAULT_SW_SCOPE } from '../util/constants';
18+
import {
19+
DEFAULT_REGISTRATION_TIMEOUT,
20+
DEFAULT_SW_PATH,
21+
DEFAULT_SW_SCOPE
22+
} from '../util/constants';
1923
import { ERROR_FACTORY, ErrorCode } from '../util/errors';
2024

2125
import { MessagingService } from '../messaging-service';
2226

2327
export async function registerDefaultSw(
24-
messaging: MessagingService
28+
messaging: MessagingService,
29+
swRegistrationTimeoutMillis?: number
2530
): Promise<void> {
2631
try {
2732
messaging.swRegistration = await navigator.serviceWorker.register(
@@ -39,7 +44,10 @@ export async function registerDefaultSw(
3944
messaging.swRegistration.update().catch(() => {
4045
/* it is non blocking and we don't care if it failed */
4146
});
42-
await waitForRegistrationActive(messaging.swRegistration);
47+
await waitForRegistrationActive(
48+
messaging.swRegistration,
49+
swRegistrationTimeoutMillis
50+
);
4351
} catch (e) {
4452
throw ERROR_FACTORY.create(ErrorCode.FAILED_DEFAULT_REGISTRATION, {
4553
browserErrorMessage: (e as Error)?.message
@@ -57,21 +65,33 @@ export async function registerDefaultSw(
5765
* to become "active".
5866
*/
5967
async function waitForRegistrationActive(
60-
registration: ServiceWorkerRegistration
68+
registration: ServiceWorkerRegistration,
69+
swRegistrationTimeoutMillis: number = DEFAULT_REGISTRATION_TIMEOUT
6170
): Promise<void> {
6271
return new Promise<void>((resolve, reject) => {
72+
const rejectTimeout = setTimeout(
73+
() =>
74+
reject(
75+
new Error(
76+
`Service worker not registered after ${swRegistrationTimeoutMillis} ms`
77+
)
78+
),
79+
swRegistrationTimeoutMillis
80+
);
81+
const incomingSw = registration.installing || registration.waiting;
6382
if (registration.active) {
83+
clearTimeout(rejectTimeout);
6484
resolve();
65-
}
66-
const incomingSw = registration.installing || registration.waiting;
67-
if (incomingSw) {
85+
} else if (incomingSw) {
6886
incomingSw.onstatechange = ev => {
6987
if ((ev.target as ServiceWorker)?.state === 'activated') {
7088
incomingSw.onstatechange = null;
89+
clearTimeout(rejectTimeout);
7190
resolve();
7291
}
7392
};
7493
} else {
94+
clearTimeout(rejectTimeout);
7595
reject(new Error('No incoming service worker found.'));
7696
}
7797
});

packages/messaging/src/helpers/updateSwReg.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,11 @@ import { registerDefaultSw } from './registerDefaultSw';
2222

2323
export async function updateSwReg(
2424
messaging: MessagingService,
25-
swRegistration?: ServiceWorkerRegistration | undefined
25+
swRegistration?: ServiceWorkerRegistration | undefined,
26+
swRegistrationTimeoutMillis?: number
2627
): Promise<void> {
2728
if (!swRegistration && !messaging.swRegistration) {
28-
await registerDefaultSw(messaging);
29+
await registerDefaultSw(messaging, swRegistrationTimeoutMillis);
2930
}
3031

3132
if (!swRegistration && !!messaging.swRegistration) {

packages/messaging/src/interfaces/public-types.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@ export interface GetTokenOptions {
132132
* for more details.
133133
*/
134134
serviceWorkerRegistration?: ServiceWorkerRegistration;
135+
/**
136+
* Milliseconds to wait for service worker registration to complete before
137+
* rejecting and throwing an error. Defaults to 10000.
138+
*/
139+
serviceWorkerRegistrationTimeout?: number;
135140
}
136141

137142
/**

0 commit comments

Comments
 (0)