-
Notifications
You must be signed in to change notification settings - Fork 4.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: Reset streams on BFCache events #24950
Conversation
CLA Signature Action: All authors have signed the CLA. You may need to manually re-run the blocking PR check if it doesn't pass in a few minutes. |
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## develop #24950 +/- ##
===========================================
+ Coverage 65.61% 65.65% +0.04%
===========================================
Files 1372 1376 +4
Lines 54519 54569 +50
Branches 14282 14293 +11
===========================================
+ Hits 35770 35822 +52
+ Misses 18749 18747 -2 ☔ View full report in Codecov by Sentry. |
Builds ready [dec9f77]
Page Load Metrics (137 ± 170 ms)
|
Builds ready [7ae24c3]
Page Load Metrics (51 ± 5 ms)
Bundle size diffs
|
…show' into jl/reset-streams-on-bfcache-pageshow
Builds ready [6592fe6]
Page Load Metrics (1933 ± 66 ms)
Bundle size diffs
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. I also ran the new E2E test on the develop
version of the Extension, and it failed as expected.
Builds ready [2f1000c]
Page Load Metrics (1850 ± 60 ms)
Bundle size diffs
|
…show' into jl/reset-streams-on-bfcache-pageshow
Builds ready [e4d55a5]
Page Load Metrics (2086 ± 116 ms)
Bundle size diffs
|
Builds ready [149c240]
Page Load Metrics (1907 ± 78 ms)
Bundle size diffs
|
Description
Previously, Chrome's BFCache (Back Forward) strategy was to evict a page from cache if it received a message over any connected port streams. The port stream would remain open and the background script would NOT receive an onDisconnect. As long as the cached page did not receive a message, the port would still function when the page became active again. This was problematic because MetaMask was likely to send a message to the still connected cached page at some point due to the nature of notifications, which would evict the page from cache, neutralizing the performance benefit of the BFCache for the end user.
Now, Chrome's BFCache strategy is to trigger an onDisconnect for the background script, but NOT the cached page. The port stream is invalid despite not being closed on the cached page side. This is problematic because we do not listen for events relevant to when a BFCached page becomes active and thus do not reset the invalid stream.
To address both strategies, we now listen for the
pageshow
andpagehide
events. When a page is entering a BFCached state, we preemptively end the port stream connection (even if the user is on an older version of chrome that would have kept it alive). When a BFCached page is restored to an active state, we establish a port stream connection. We know the port stream must be restored/reset because we were the ones responsible for preemptively ending it earlier in the lifecycle. Combining these two changes allows us to handle both the old and new BFCache strategies without having to target them by versions separately.Related issues
See: https://developer.chrome.com/blog/bfcache-extension-messaging-changes?hl=en
See: #13373
See: https://web.dev/articles/bfcache (useful links at bottom)
See: w3c/webextensions#474
Fixes: https://github.com/MetaMask/MetaMask-planning/issues/2582
Manual testing steps
Steps are for macOS. Using chrome 123 or newer
Testing with old BFCache strategy
open /Applications/Google\ Chrome.app --args --disable-features=DisconnectExtensionMessagePortWhenPageEntersBFCache
http://www.brainjar.com/java/host/test.html
await window.ethereum.request({method: 'eth_chainId'})
, which should be responsivechrome://terms/
await window.ethereum.request({method: 'eth_chainId'})
, which should be responsiveTesting with the new BFCache strategy
Repeat the steps above, but use
--enable-features
instead ofdisable
MetaMask Behavior should look the same regardless of browser's BFCache strategy
Screenshots/Recordings
BFCache Behavior
bfcache.new.behavior.mov
Prerender Behavior (to show affected chromium browsers still reset streams correctly)
targeted.prerender.still.working.correctly.mov
Pre-merge author checklist
Pre-merge reviewer checklist