Skip to content

Commit 7ffe5c7

Browse files
committed
External controlling events
1 parent 27080cc commit 7ffe5c7

3 files changed

Lines changed: 43 additions & 17 deletions

File tree

packages/workbox-window/src/Workbox.ts

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -502,13 +502,20 @@ class Workbox extends WorkboxEventTarget {
502502
*/
503503
private readonly _onControllerChange = (originalEvent: Event) => {
504504
const sw = this._sw;
505-
if (sw === navigator.serviceWorker.controller) {
506-
this.dispatchEvent(new WorkboxEvent('controlling', {
507-
sw,
508-
originalEvent,
509-
isUpdate: this._isUpdate,
510-
}));
505+
const isExternal = sw !== navigator.serviceWorker.controller;
511506

507+
// Unconditionally dispatch the controlling event, with isExternal set
508+
// to distinguish between controller changes due to the initial registration
509+
// vs. an update-check or other tab's registration.
510+
// See https://github.com/GoogleChrome/workbox/issues/2786
511+
this.dispatchEvent(new WorkboxEvent('controlling', {
512+
isExternal,
513+
originalEvent,
514+
sw,
515+
isUpdate: this._isUpdate,
516+
}));
517+
518+
if (!isExternal) {
512519
if (process.env.NODE_ENV !== 'production') {
513520
logger.log('Registered service worker now controlling this page.');
514521
}
@@ -627,6 +634,8 @@ export {Workbox};
627634
* event.
628635
* @property {boolean|undefined} isUpdate True if a service worker was already
629636
* controlling when this service worker was registered.
637+
* @property {boolean|undefined} isExternal True if this event is associated
638+
* with an [external service worker]{@link https://developers.google.com/web/tools/workbox/modules/workbox-window#when_an_unexpected_version_of_the_service_worker_is_found}.
630639
* @property {string} type `controlling`.
631640
* @property {Workbox} target The `Workbox` instance.
632641
*/

test/workbox-window/integration/test-all.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ describe(`[workbox-window] Workbox`, function() {
8484
installedSpyCallCount: installedSpy.callCount,
8585
waitingSpyCallCount: waitingSpy.callCount,
8686
controllingSpyCallCount: controllingSpy.callCount,
87+
controllingIsExternal: controllingSpy.args[0][0].isExternal,
8788
activatedSpyCallCount: activatedSpy.callCount,
8889
});
8990
} catch (error) {
@@ -94,6 +95,7 @@ describe(`[workbox-window] Workbox`, function() {
9495
// Test for truthiness because some browsers structure clone
9596
// `undefined` to `null`.
9697
expect(result.isUpdate).to.not.be.ok;
98+
expect(result.controllingIsExternal).to.not.be.ok;
9799
expect(result.installedSpyCallCount).to.equal(1);
98100
expect(result.activatedSpyCallCount).to.equal(1);
99101
expect(result.controllingSpyCallCount).to.equal(1);
@@ -107,7 +109,9 @@ describe(`[workbox-window] Workbox`, function() {
107109
try {
108110
const wb1 = new Workbox('sw-clients-claim.js.njk?v=1');
109111
const redundantSpy = sinon.spy();
112+
const wb1ControllingSpy = sinon.spy();
110113
wb1.addEventListener('redundant', redundantSpy);
114+
wb1.addEventListener('controlling', wb1ControllingSpy);
111115

112116
await wb1.register();
113117
await window.activatedAndControlling(wb1);
@@ -117,12 +121,12 @@ describe(`[workbox-window] Workbox`, function() {
117121
const installedSpy = sinon.spy();
118122
const waitingSpy = sinon.spy();
119123
const activatedSpy = sinon.spy();
120-
const controllingSpy = sinon.spy();
124+
const wb2ControllingSpy = sinon.spy();
121125

122126
wb2.addEventListener('installed', installedSpy);
123127
wb2.addEventListener('waiting', waitingSpy);
124128
wb2.addEventListener('activated', activatedSpy);
125-
wb2.addEventListener('controlling', controllingSpy);
129+
wb2.addEventListener('controlling', wb2ControllingSpy);
126130

127131
await wb2.register();
128132

@@ -131,9 +135,11 @@ describe(`[workbox-window] Workbox`, function() {
131135
cb({
132136
wb1IsUpdate: redundantSpy.args[0][0].isUpdate,
133137
wb2IsUpdate: installedSpy.args[0][0].isUpdate,
138+
wb1ControllingIsExternal: wb1ControllingSpy.args[0][0].isExternal,
139+
wb2ControllingIsExternal: wb2ControllingSpy.args[0][0].isExternal,
134140
installedSpyCallCount: installedSpy.callCount,
135141
waitingSpyCallCount: waitingSpy.callCount,
136-
controllingSpyCallCount: controllingSpy.callCount,
142+
controllingSpyCallCount: wb2ControllingSpy.callCount,
137143
activatedSpyCallCount: activatedSpy.callCount,
138144
});
139145
} catch (error) {
@@ -145,6 +151,8 @@ describe(`[workbox-window] Workbox`, function() {
145151
// `undefined` to `null`.
146152
expect(result.wb1IsUpdate).to.not.be.ok;
147153
expect(result.wb2IsUpdate).to.equal(true);
154+
expect(result.wb1ControllingIsExternal).to.not.be.ok;
155+
expect(result.wb2ControllingIsExternal).to.not.be.ok;
148156
expect(result.installedSpyCallCount).to.equal(1);
149157
expect(result.waitingSpyCallCount).to.equal(0);
150158
expect(result.activatedSpyCallCount).to.equal(1);

test/workbox-window/window/test-Workbox.mjs

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -846,21 +846,30 @@ describe(`[workbox-window] Workbox`, function() {
846846

847847
expect(controlling1Spy.callCount).to.equal(1);
848848
assertMatchesWorkboxEvent(controlling1Spy.args[0][0], {
849-
type: 'controlling',
850-
target: wb1,
851-
sw: await wb1.getSW(),
852-
originalEvent: {type: 'controllerchange'},
849+
isExternal: false,
853850
isUpdate: true,
851+
originalEvent: {type: 'controllerchange'},
852+
sw: await wb1.getSW(),
853+
target: wb1,
854+
type: 'controlling',
854855
});
855856

856-
expect(controlling2Spy.callCount).to.equal(0);
857+
// This will be an "external" event, due to wb3's SW taking control.
858+
// wb2's SW never controls, because it's stuck in waiting.
859+
expect(controlling2Spy.callCount).to.equal(1);
860+
assertMatchesWorkboxEvent(controlling2Spy.args[0][0], {
861+
isExternal: true,
862+
isUpdate: true,
863+
type: 'controlling',
864+
});
857865

858866
expect(controlling3Spy.callCount).to.equal(1);
859867
assertMatchesWorkboxEvent(controlling3Spy.args[0][0], {
860-
type: 'controlling',
861-
target: wb3,
862-
sw: await wb3.getSW(),
868+
isExternal: false,
863869
originalEvent: {type: 'controllerchange'},
870+
sw: await wb3.getSW(),
871+
target: wb3,
872+
type: 'controlling',
864873
});
865874
});
866875
});

0 commit comments

Comments
 (0)