angular: Service worker requestSubscription() freezes and doesn't show native popup if serviceworker.controller is null
๐ bug report
Affected Package
Is this a regression?
No
Description
The problem is here
https://github.com/angular/angular/blob/a06824aef6e2e1c5b1c037d2c2e1dda544842000/packages/service-worker/src/low_level.ts#L74-L82
When controllerchange is triggered, the code access to serviceworker.controller and filters it if is null. After that, the registration is created from the previous pipes.
What happens if the serviceworker.controller is null in all controllerchange events? (At the moment you are thinking that couldnโt happen, but yes ๐it happens!!!๐.
Then if the app is started with serviceworker.controller = null and requestSubscription is called a few minutes later, the promise wonโt never be resolved.
https://github.com/angular/angular/blob/c0757d1d440d6f934436418add9755e7d630bbcf/packages/service-worker/src/push.ts#L93-L99
Possible solution
Merging registrationobservable with serviceworker.readybut Iโm not sure if breaks something.
https://github.com/angular/angular/blob/c0757d1d440d6f934436418add9755e7d630bbcf/packages/service-worker/src/low_level.ts#L81-L82
๐ฌ Minimal Reproduction
The problem reproduction is explained in the previous section. But if you want to get crazy to Chrome to test the bug, you can do the following:
You can test this on Chrome 72 Windows, the steps are not going to work on Chrome Mac. But I have logs that prove the bug happens in other Chrome version and platforms, maybe, doing different steps, but the state is the same, serviceworker.controller is null.
Steps Chrome Windows.
- Create a app with a checkbox or switch button to activate/descativate notifications.
- Check the switch in your app will call
requestSubscription() - When the popup is shown, press Block.
- Go to de addressbar, click in the lock ๐. Change the notifications state to Allow. Chrome will say you that the page should be reloaded.
- Reload the page.
- If you call
requestSubscription()again, you wonโt get the popup. Or if you write in the consoleserviceworker.controlleryou will getnull.
Here is an example image. The app is started, serviceworker.controller is null, but I can get the service worker registration and the push subscription, so serviceworker.controller is not needed to get it. (Keys are hidden in the image).

๐ Your Environment
Angular Version: Tested in angular 7.1.7 but I think all version are affected.
Anything else relevant?
I use this code with a timeout before I run into the issue to avoid freezing the function. Iโm getting logs Can't subscribe: Timeout ocurred from Chrome Windows but specially lots of entries for Chrome android.
this.swPush.requestSubscription({serverPublicKey: this.VAPID_PUBLIC_KEY}))
.pipe(
timeout(8000),
tap({
next: () => this.measuringDao.sendBackendEvent('activated_notifications').subscribe(),
error: err => this.logger.warn('Can\'t subscribe: ' + err.toString(), err)
}),
switchMap(sub => this.notificationsDao.registerPushSubscriber(sub))
);
About this issue
- Original URL
- State: closed
- Created 5 years ago
- Reactions: 1
- Comments: 16 (12 by maintainers)
From what I can tell, this is either a Chrome bug or if it is in Angular we donโt have a reliable reproduction. Thus this is issue is not actionable in its current state.
If you are still running into this problem and you have confirmed that this is not browser bug, please open a new issue with a minimal reproduction.
Not sure if same issue. I make the same call
navigator.serviceWorker.controllerisnull.Can I help investigate? Should I create a separate issue?