@@ -208,13 +208,23 @@ export async function getSessionLock(onNewInstance: () => Promise<void>): Promis
208
208
// Now add a listener for other claimants to the lock.
209
209
window . addEventListener ( "storage" , onStorageEvent ) ;
210
210
211
- // also add a listener to clear our claims when our tab closes (provided we haven't released it already)
212
- window . document . addEventListener ( "visibilitychange" , ( event ) => {
213
- if ( window . document . visibilityState === "hidden" && lockServicer !== null ) {
214
- prefixedLogger . info ( "Unloading: clearing our claims" ) ;
211
+ // also add a listener to clear our claims when our tab closes or navigates away
212
+ window . addEventListener ( "pagehide" , ( event ) => {
213
+ // only remove the ping if we still think we're the owner. Otherwise we could be removing someone else's claim!
214
+ if ( lockServicer !== null ) {
215
+ prefixedLogger . info ( "page hide: clearing our claim" ) ;
215
216
window . localStorage . removeItem ( STORAGE_ITEM_PING ) ;
216
217
window . localStorage . removeItem ( STORAGE_ITEM_OWNER ) ;
217
218
}
219
+
220
+ // It's worth noting that, according to the spec, the page might come back to life again after a pagehide.
221
+ //
222
+ // In practice that's unlikely because Element is unlikely to qualify for the bfcache, but if it does,
223
+ // this is probably the best we can do: we certainly don't want to stop the user loading any new tabs because
224
+ // Element happens to be in a bfcache somewhere.
225
+ //
226
+ // So, we just hope that we aren't in the middle of any crypto operations, and rely on `onStorageEvent` kicking
227
+ // in soon enough after we resume to tell us if another tab woke up while we were asleep.
218
228
} ) ;
219
229
220
230
return true ;
0 commit comments