MV3: contentscript.js - re-activate streams when Service Worker terminates and then resets
Explanation
This PR disconnects and recreates the streams when the Service Worker resets. This PR reuses some patterns found here: https://github.com/MetaMask/metamask-extension/pull/14781.
The setup of the streams pretty much remains the same. The logic has been split into functions to be reused and to separate concerns. There is additional logic to destroy the streams and then reestablish them.
Todo:
- troubleshoot handshake between contentscript stream and inpage stream
- possibly reset streams created for inpage.js when Service Worker is re-activated
- Get feedback on current work
- Apply reset logic to
setupPhishingStream()
More Information
- Fixes #14845
Screenshots/Screencaps
Manual Testing Steps
- Run
yarn start:mv3 - Open test-dapp
- Check that streams work by using dapp
- Terminate the
app-init.jsservice worker - Check that dapp continues to work
Pre-Merge Checklist
- [ ] PR template is filled out
- [ ] IF this PR fixes a bug, a test that would have caught the bug has been added
- [ ] PR is linked to the appropriate GitHub issue
- [ ] PR has been added to the appropriate release Milestone
+ If there are functional changes:
- [ ] Manual testing complete & passed
- [ ] "Extension QA Board" label has been applied
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.
Builds ready [e0ee038]
- builds: chrome, firefox, opera
- builds (beta): chrome, firefox, opera
- builds (flask): chrome, firefox, opera
- build viz: Build System
- mv3: Background Module Init Stats
- mv3: UI Init Stats
- mv3: Module Load Stats
- mv3: Bundle Size Stats
- code coverage: Report
- storybook: Storybook
- all artifacts
Page Load Metrics (1682 ± 38 ms)
| Platform | Page | Metric | Min (ms) | Max (ms) | Average (ms) | StandardDeviation (ms) | MarginOfError (ms) |
|---|---|---|---|---|---|---|---|
| Chrome | Home | firstPaint | 89 | 333 | 115 | 51 | 25 |
| domContentLoaded | 1561 | 1842 | 1672 | 76 | 36 | ||
| load | 1574 | 1842 | 1682 | 79 | 38 | ||
| domInteractive | 1561 | 1842 | 1672 | 76 | 36 |
Builds ready [1e7ada7]
- builds: chrome, firefox, opera
- builds (beta): chrome, firefox, opera
- builds (flask): chrome, firefox, opera
- build viz: Build System
- mv3: Background Module Init Stats
- mv3: UI Init Stats
- mv3: Module Load Stats
- mv3: Bundle Size Stats
- mv2: E2e Actions Stats
- code coverage: Report
- storybook: Storybook
- typescript migration: Dashboard
- all artifacts
Page Load Metrics (1863 ± 46 ms)
| Platform | Page | Metric | Min (ms) | Max (ms) | Average (ms) | StandardDeviation (ms) | MarginOfError (ms) |
|---|---|---|---|---|---|---|---|
| Chrome | Home | firstPaint | 88 | 268 | 124 | 37 | 18 |
| domContentLoaded | 1730 | 2079 | 1847 | 94 | 45 | ||
| load | 1731 | 2079 | 1863 | 96 | 46 | ||
| domInteractive | 1730 | 2079 | 1847 | 94 | 45 |
Builds ready [a78f894]
- builds: chrome, firefox, opera
- builds (beta): chrome, firefox, opera
- builds (flask): chrome, firefox, opera
- build viz: Build System
- mv3: Background Module Init Stats
- mv3: UI Init Stats
- mv3: Module Load Stats
- mv3: Bundle Size Stats
- mv2: E2e Actions Stats
- code coverage: Report
- storybook: Storybook
- typescript migration: Dashboard
- all artifacts
Page Load Metrics (1950 ± 114 ms)
| Platform | Page | Metric | Min (ms) | Max (ms) | Average (ms) | StandardDeviation (ms) | MarginOfError (ms) |
|---|---|---|---|---|---|---|---|
| Chrome | Home | firstPaint | 93 | 157 | 114 | 15 | 7 |
| domContentLoaded | 1620 | 2520 | 1932 | 236 | 113 | ||
| load | 1655 | 2520 | 1950 | 238 | 114 | ||
| domInteractive | 1620 | 2520 | 1932 | 236 | 113 |
Builds ready [cf9d25d]
- builds: chrome, firefox, opera
- builds (beta): chrome, firefox, opera
- builds (flask): chrome, firefox, opera
- build viz: Build System
- mv3: Background Module Init Stats
- mv3: UI Init Stats
- mv3: Module Load Stats
- mv3: Bundle Size Stats
- mv2: E2e Actions Stats
- code coverage: Report
- storybook: Storybook
- typescript migration: Dashboard
- all artifacts
Page Load Metrics (1826 ± 85 ms)
| Platform | Page | Metric | Min (ms) | Max (ms) | Average (ms) | StandardDeviation (ms) | MarginOfError (ms) |
|---|---|---|---|---|---|---|---|
| Chrome | Home | firstPaint | 90 | 355 | 121 | 56 | 27 |
| domContentLoaded | 1564 | 2279 | 1821 | 179 | 86 | ||
| load | 1564 | 2279 | 1826 | 177 | 85 | ||
| domInteractive | 1564 | 2279 | 1821 | 179 | 86 |
Builds ready [2289602]
- builds: chrome, firefox, opera
- builds (beta): chrome, firefox, opera
- builds (flask): chrome, firefox, opera
- build viz: Build System
- mv3: Background Module Init Stats
- mv3: UI Init Stats
- mv3: Module Load Stats
- mv3: Bundle Size Stats
- mv2: E2e Actions Stats
- code coverage: Report
- storybook: Storybook
- typescript migration: Dashboard
- all artifacts
Page Load Metrics (2059 ± 131 ms)
| Platform | Page | Metric | Min (ms) | Max (ms) | Average (ms) | StandardDeviation (ms) | MarginOfError (ms) |
|---|---|---|---|---|---|---|---|
| Chrome | Home | firstPaint | 96 | 258 | 129 | 41 | 20 |
| domContentLoaded | 1677 | 2642 | 2022 | 282 | 135 | ||
| load | 1677 | 2642 | 2059 | 273 | 131 | ||
| domInteractive | 1677 | 2642 | 2022 | 282 | 135 |
Builds ready [23649db]
- builds: chrome, firefox, opera
- builds (beta): chrome, firefox, opera
- builds (flask): chrome, firefox, opera
- build viz: Build System
- mv3: Background Module Init Stats
- mv3: UI Init Stats
- mv3: Module Load Stats
- mv3: Bundle Size Stats
- mv2: E2e Actions Stats
- code coverage: Report
- storybook: Storybook
- typescript migration: Dashboard
- all artifacts
Page Load Metrics (2013 ± 101 ms)
| Platform | Page | Metric | Min (ms) | Max (ms) | Average (ms) | StandardDeviation (ms) | MarginOfError (ms) |
|---|---|---|---|---|---|---|---|
| Chrome | Home | firstPaint | 92 | 2142 | 231 | 442 | 212 |
| domContentLoaded | 1689 | 2555 | 1979 | 194 | 93 | ||
| load | 1689 | 2555 | 2013 | 211 | 101 | ||
| domInteractive | 1689 | 2555 | 1979 | 194 | 93 |
Builds ready [0e41b17]
- builds: chrome, firefox, opera
- builds (beta): chrome, firefox, opera
- builds (flask): chrome, firefox, opera
- build viz: Build System
- mv3: Background Module Init Stats
- mv3: UI Init Stats
- mv3: Module Load Stats
- mv3: Bundle Size Stats
- mv2: E2e Actions Stats
- code coverage: Report
- storybook: Storybook
- typescript migration: Dashboard
- all artifacts
Page Load Metrics (1768 ± 67 ms)
| Platform | Page | Metric | Min (ms) | Max (ms) | Average (ms) | StandardDeviation (ms) | MarginOfError (ms) |
|---|---|---|---|---|---|---|---|
| Chrome | Home | firstPaint | 90 | 1619 | 193 | 327 | 157 |
| domContentLoaded | 1557 | 2065 | 1746 | 131 | 63 | ||
| load | 1623 | 2123 | 1768 | 139 | 67 | ||
| domInteractive | 1557 | 2065 | 1746 | 131 | 63 |
Builds ready [3a09691]
- builds: chrome, firefox, opera
- builds (beta): chrome, firefox, opera
- builds (flask): chrome, firefox, opera
- build viz: Build System
- mv3: Background Module Init Stats
- mv3: UI Init Stats
- mv3: Module Load Stats
- mv3: Bundle Size Stats
- mv2: E2e Actions Stats
- code coverage: Report
- storybook: Storybook
- typescript migration: Dashboard
- all artifacts
Page Load Metrics (1817 ± 76 ms)
| Platform | Page | Metric | Min (ms) | Max (ms) | Average (ms) | StandardDeviation (ms) | MarginOfError (ms) |
|---|---|---|---|---|---|---|---|
| Chrome | Home | firstPaint | 90 | 162 | 118 | 19 | 9 |
| domContentLoaded | 1597 | 2173 | 1786 | 161 | 77 | ||
| load | 1619 | 2173 | 1817 | 159 | 76 | ||
| domInteractive | 1597 | 2173 | 1786 | 161 | 77 |
Builds ready [53eec15]
- builds: chrome, firefox, opera
- builds (beta): chrome, firefox, opera
- builds (flask): chrome, firefox, opera
- build viz: Build System
- mv3: Background Module Init Stats
- mv3: UI Init Stats
- mv3: Module Load Stats
- mv3: Bundle Size Stats
- mv2: E2e Actions Stats
- code coverage: Report
- storybook: Storybook
- typescript migration: Dashboard
- all artifacts
Page Load Metrics (1660 ± 36 ms)
| Platform | Page | Metric | Min (ms) | Max (ms) | Average (ms) | StandardDeviation (ms) | MarginOfError (ms) |
|---|---|---|---|---|---|---|---|
| Chrome | Home | firstPaint | 86 | 1707 | 257 | 464 | 223 |
| domContentLoaded | 1544 | 1785 | 1646 | 73 | 35 | ||
| load | 1547 | 1803 | 1660 | 74 | 36 | ||
| domInteractive | 1544 | 1785 | 1646 | 73 | 35 |
Builds ready [f3bcd73]
- builds: chrome, firefox, opera
- builds (beta): chrome, firefox, opera
- builds (flask): chrome, firefox, opera
- build viz: Build System
- mv3: Background Module Init Stats
- mv3: UI Init Stats
- mv3: Module Load Stats
- mv3: Bundle Size Stats
- mv2: E2e Actions Stats
- code coverage: Report
- storybook: Storybook
- typescript migration: Dashboard
- all artifacts
Page Load Metrics (2064 ± 84 ms)
| Platform | Page | Metric | Min (ms) | Max (ms) | Average (ms) | StandardDeviation (ms) | MarginOfError (ms) |
|---|---|---|---|---|---|---|---|
| Chrome | Home | firstPaint | 110 | 1954 | 230 | 396 | 190 |
| domContentLoaded | 1709 | 2318 | 2030 | 178 | 85 | ||
| load | 1709 | 2318 | 2064 | 175 | 84 | ||
| domInteractive | 1709 | 2318 | 2030 | 178 | 85 |
Builds ready [2550c01]
- builds: chrome, firefox, opera
- builds (beta): chrome, firefox, opera
- builds (flask): chrome, firefox, opera
- build viz: Build System
- mv3: Background Module Init Stats
- mv3: UI Init Stats
- mv3: Module Load Stats
- mv3: Bundle Size Stats
- mv2: E2e Actions Stats
- code coverage: Report
- storybook: Storybook
- typescript migration: Dashboard
- all artifacts
Page Load Metrics (1735 ± 58 ms)
| Platform | Page | Metric | Min (ms) | Max (ms) | Average (ms) | StandardDeviation (ms) | MarginOfError (ms) |
|---|---|---|---|---|---|---|---|
| Chrome | Home | firstPaint | 96 | 371 | 132 | 58 | 28 |
| domContentLoaded | 1534 | 1987 | 1718 | 120 | 57 | ||
| load | 1575 | 2092 | 1735 | 122 | 58 | ||
| domInteractive | 1534 | 1987 | 1717 | 120 | 57 |
Builds ready [290d2c5]
- builds: chrome, firefox, opera
- builds (beta): chrome, firefox, opera
- builds (flask): chrome, firefox, opera
- build viz: Build System
- mv3: Background Module Init Stats
- mv3: UI Init Stats
- mv3: Module Load Stats
- mv3: Bundle Size Stats
- mv2: E2e Actions Stats
- code coverage: Report
- storybook: Storybook
- typescript migration: Dashboard
- all artifacts
Page Load Metrics (1732 ± 44 ms)
| Platform | Page | Metric | Min (ms) | Max (ms) | Average (ms) | StandardDeviation (ms) | MarginOfError (ms) |
|---|---|---|---|---|---|---|---|
| Chrome | Home | firstPaint | 96 | 143 | 113 | 12 | 6 |
| domContentLoaded | 1595 | 1850 | 1716 | 76 | 37 | ||
| load | 1595 | 1924 | 1732 | 92 | 44 | ||
| domInteractive | 1595 | 1850 | 1716 | 76 | 37 |
Wow, this appears to be working great!
Builds ready [14db9cc]
- builds: chrome, firefox, opera
- builds (beta): chrome, firefox, opera
- builds (flask): chrome, firefox, opera
- build viz: Build System
- mv3: Background Module Init Stats
- mv3: UI Init Stats
- mv3: Module Load Stats
- mv3: Bundle Size Stats
- mv2: E2e Actions Stats
- code coverage: Report
- storybook: Storybook
- typescript migration: Dashboard
- all artifacts
Page Load Metrics (1863 ± 62 ms)
| Platform | Page | Metric | Min (ms) | Max (ms) | Average (ms) | StandardDeviation (ms) | MarginOfError (ms) |
|---|---|---|---|---|---|---|---|
| Chrome | Home | firstPaint | 100 | 174 | 128 | 18 | 9 |
| domContentLoaded | 1649 | 2056 | 1835 | 120 | 58 | ||
| load | 1670 | 2077 | 1863 | 129 | 62 | ||
| domInteractive | 1649 | 2056 | 1835 | 120 | 58 |
[out of scope] confirmed that the provider error is intermittent after seeing it pass here https://github.com/MetaMask/metamask-extension/pull/15494/commits/14db9cc4ff8a656f90bc2b96a08c38fc60d9feff
@jpuri @Gudahtt
Builds ready [af89556]
- builds: chrome, firefox, opera
- builds (beta): chrome, firefox, opera
- builds (flask): chrome, firefox, opera
- build viz: Build System
- mv3: Background Module Init Stats
- mv3: UI Init Stats
- mv3: Module Load Stats
- mv3: Bundle Size Stats
- mv2: E2e Actions Stats
- code coverage: Report
- storybook: Storybook
- typescript migration: Dashboard
- all artifacts
Page Load Metrics (1746 ± 45 ms)
| Platform | Page | Metric | Min (ms) | Max (ms) | Average (ms) | StandardDeviation (ms) | MarginOfError (ms) |
|---|---|---|---|---|---|---|---|
| Chrome | Home | firstPaint | 88 | 181 | 126 | 20 | 10 |
| domContentLoaded | 1592 | 2011 | 1724 | 88 | 42 | ||
| load | 1616 | 2030 | 1746 | 95 | 45 | ||
| domInteractive | 1592 | 2011 | 1724 | 88 | 42 |
Hey @digiwand : small suggestion using / in branch name creates trouble in running git commands. Try to avoid that.
Hey @jyoti, thanks very much for bringing this up! I didn't know it was causing difficulties to work with. I'll avoid adding / in the branch names from here on
Builds ready [23fe6e4]
- builds: chrome, firefox, opera
- builds (beta): chrome, firefox, opera
- builds (flask): chrome, firefox, opera
- build viz: Build System
- mv3: Background Module Init Stats
- mv3: UI Init Stats
- mv3: Module Load Stats
- mv3: Bundle Size Stats
- mv2: E2e Actions Stats
- code coverage: Report
- storybook: Storybook
- typescript migration: Dashboard
- all artifacts
Page Load Metrics (1832 ± 74 ms)
| Platform | Page | Metric | Min (ms) | Max (ms) | Average (ms) | StandardDeviation (ms) | MarginOfError (ms) |
|---|---|---|---|---|---|---|---|
| Chrome | Home | firstPaint | 99 | 1856 | 212 | 378 | 181 |
| domContentLoaded | 1635 | 2211 | 1807 | 155 | 75 | ||
| load | 1639 | 2238 | 1832 | 154 | 74 | ||
| domInteractive | 1635 | 2211 | 1807 | 155 | 75 |
@digiwand : service worker seems to always stay active after these changes even is extension is not used, do you plan to fix that.
I think we should keep service worker running only for connected dapps.
@jpuri I agree we should only keep the service worker running for connected dapps, when the pop-up is open, and when the home.html page is open.
Let me double-check this...
Hey @jpuri, good catch. I think this fixes it https://github.com/MetaMask/metamask-extension/commit/d259d04d8c5c9226c0b98bb7397fdb485dbdaa08 (merged commit)
Builds ready [420c7bb]
- builds: chrome, firefox, opera
- builds (beta): chrome, firefox, opera
- builds (flask): chrome, firefox, opera
- build viz: Build System
- mv3: Background Module Init Stats
- mv3: UI Init Stats
- mv3: Module Load Stats
- mv3: Bundle Size Stats
- mv2: E2e Actions Stats
- code coverage: Report
- storybook: Storybook
- typescript migration: Dashboard
- all artifacts
Page Load Metrics (1799 ± 79 ms)
| Platform | Page | Metric | Min (ms) | Max (ms) | Average (ms) | StandardDeviation (ms) | MarginOfError (ms) |
|---|---|---|---|---|---|---|---|
| Chrome | Home | firstPaint | 96 | 168 | 119 | 17 | 8 |
| domContentLoaded | 1591 | 2047 | 1772 | 142 | 68 | ||
| load | 1609 | 2175 | 1799 | 165 | 79 | ||
| domInteractive | 1591 | 2047 | 1772 | 142 | 68 |
Overall behavior looks fine :) . I have seen a couple of console errors that might be worth to double-check:
- On the dev console, I'm seeing the error
write after endonstream-utilsat the moment of loading the Extension
https://user-images.githubusercontent.com/54408225/188630588-6f5af261-f95a-4c5f-a29d-dddb404dd0b4.mp4
- After Importing a Wallet, I see the error
document is not definedon the dev console (this will also appear when I stop service worker and re-initiate - see point 4)

- When I Connect to Test Dapp and try to perfom a Send tx or to Deploy Contract, I see the error
failed to parse tx data. This also happens when I Submit a tx.
https://user-images.githubusercontent.com/54408225/188631337-19c965cc-40dc-4e44-968a-e64427d10407.mp4
- When I stop the Service Worker, I see the following errors:
Duplicate script ID 'inpage'Incorrect passwordReferenceError: document is not defined
https://user-images.githubusercontent.com/54408225/188632278-86412277-5403-4188-ab69-8ab0e71ff661.mp4
In this case, when I stop service worker MM is logged out and I need to log in again with the password. Is this the expected behaviour?
@seaona Thank you for the thorough testing! I think there is some crossover testing of https://github.com/MetaMask/metamask-extension/pull/14781 and this PR, which is actually great you tested both. I believe none of these are blockers to this PR. This caught some out-of-scope issues, and I created one follow-up issue: https://github.com/MetaMask/metamask-extension/issues/15775
-
[related to other service worker PR] This is actually testing service worker behavior for the home.html page and not the dapp pages. This PR re-activates streams for
script/contentscript.jswhich is loaded in dapp pages which summons popup.html. Then https://github.com/MetaMask/metamask-extension/pull/14781 re-activates streams forscript/ui.jswhich is loaded on our extension home.html page cc: @jpuri -
[unrelated] This
document is not definedbug appears to be related to the Ledger iframe which will be supported in another PR https://github.com/MetaMask/metamask-extension/issues/14183. For now, I've been loading a wallet with no hard wallets associated with it. -
[I think out of scope] Nice catch. I'm seeing this issue on both home.html and popup.html. This may or may not be related to the service worker and streams. I created an issue ticket to handle this separately from this PR: https://github.com/MetaMask/metamask-extension/issues/15775
-
When I stop the Service Worker, I see the following errors:
- [non-blocker] Duplicate script ID 'inpage': I've also observed this on both home.html and dapp pages. I don't believe this is a blocker. This error appears to be more related to the service worker implementation than this PR - though, in a way, it may be related
- [unrelated] Incorrect password: I believe this is being supported by https://github.com/MetaMask/metamask-extension/issues/15050
- [unrelated] ReferenceError: document is not defined Please refer to # 2 relating to hard wallet support
Builds ready [0d05cfc]
- builds: chrome, firefox, opera
- builds (beta): chrome, firefox, opera
- builds (flask): chrome, firefox, opera
- build viz: Build System
- mv3: Background Module Init Stats
- mv3: UI Init Stats
- mv3: Module Load Stats
- mv3: Bundle Size Stats
- mv2: E2e Actions Stats
- code coverage: Report
- storybook: Storybook
- typescript migration: Dashboard
- all artifacts
Page Load Metrics (1763 ± 89 ms)
| Platform | Page | Metric | Min (ms) | Max (ms) | Average (ms) | StandardDeviation (ms) | MarginOfError (ms) |
|---|---|---|---|---|---|---|---|
| Chrome | Home | firstPaint | 91 | 170 | 117 | 18 | 9 |
| domContentLoaded | 1542 | 2083 | 1733 | 176 | 84 | ||
| load | 1542 | 2085 | 1763 | 186 | 89 | ||
| domInteractive | 1542 | 2083 | 1733 | 176 | 84 |
Hey @digiwand , I found an issue while working on task of retrying DAPP requests, if I add a bit of delay in resetStreamAndListeners method by adding a timeout, stream re-connection does not happen.
Reconnection should always happen irrespective of delay.
I add a bit of delay in resetStreamAndListeners method by adding a timeout, stream re-connection does not happen.
To follow up from the call we just had discussing this: I suspect that this method of simulating a delayed startup is flawed. I would expect the method resetStreamAndListeners to execute synchronously without any delay even if the service worker was slow to start up - just that we'd see a timeout disconnect event after the fact. But I'm not confident in that guess.
Needs further testing. Suggested next steps for testing that was to add an artificial delay during service worker initialization, before streams were setup. No need to block this PR though.