Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
2020f68
Fix #15050 - MV3: Keep the user logged in when service worker restarts
darkwing Sep 20, 2022
21d4e76
Use WIP keyringcontroller
darkwing Sep 20, 2022
7a1196e
Update method name in encryption key call
darkwing Sep 22, 2022
d5dcbd0
Fix package location
darkwing Sep 27, 2022
aa03d75
Progress
darkwing Oct 3, 2022
82a2068
Prevent user from hitting login screen
darkwing Oct 4, 2022
8cfa72b
Provide encryption data from store, update encryption key during each…
darkwing Oct 12, 2022
772f7ce
Check for onboarding with encryption key submission
darkwing Oct 12, 2022
4e1261c
Install from correct keyringcontroller branch
darkwing Oct 13, 2022
111ebfc
Use async/await for storage, clear only loginToken on locked
darkwing Oct 17, 2022
78293b7
Change params to isAttemptingSessionLogin
darkwing Oct 26, 2022
04ad449
Use web extension polyfill instead of chrome storage directly
darkwing Oct 26, 2022
4666b52
Pin keyring controller version
darkwing Oct 27, 2022
a580bab
Avoid passing unncessary vault argument
darkwing Oct 28, 2022
e9a4d12
Fix login token variable
darkwing Oct 31, 2022
f4c0a8b
Set option to use encryption key in keyring controller
darkwing Nov 1, 2022
a72fdbc
Remove unnecessary state update since the value defaults to true
darkwing Nov 2, 2022
465157b
Update package.json keyring-controller version to use importKey
darkwing Nov 3, 2022
4656ffc
Store salt in storage for validation in the keyringcontroller
darkwing Nov 8, 2022
14bb1b3
Update keyringcontroller to current dev build
darkwing Nov 8, 2022
449489e
Update to official keyring-controller package
darkwing Nov 9, 2022
32fe5d0
Fix state sync with UI (#16393)
jpuri Nov 9, 2022
7caa6b2
Add encryptWithDetail to mock encryptor
darkwing Nov 9, 2022
2ffbe57
Only use cacheEncryptionKey if we're using manifest v3
darkwing Nov 9, 2022
88eb57e
Update lavamoat
darkwing Nov 10, 2022
f6de79f
fix ui loading
jpuri Nov 10, 2022
928d00f
Update lavamoat after rebase
darkwing Nov 10, 2022
6932159
Updaate keyringcontroller to 8.0.1
darkwing Nov 10, 2022
5c98aa4
Update warning text for duplicate account on e2e
seaona Nov 11, 2022
1d1ac51
lint
seaona Nov 11, 2022
f897267
Update verbiage of code comment
darkwing Nov 15, 2022
9914c72
Update app/scripts/ui.js
darkwing Nov 15, 2022
36a8965
snap policies
seaona Nov 17, 2022
5eb1cd1
Fix UI sync (#16612)
jpuri Nov 21, 2022
afcbd26
Fix policies
darkwing Nov 21, 2022
1947d65
Fix lint
darkwing Nov 21, 2022
1eaecc9
Fix policies
darkwing Nov 22, 2022
4a82542
lavamoat
seaona Nov 22, 2022
c6f6388
Restore policy overrides
darkwing Nov 22, 2022
a5f5a67
Merge branch 'mv3-login' of github.com:MetaMask/metamask-extension in…
darkwing Nov 22, 2022
71a087f
Regenerate policies
darkwing Nov 22, 2022
333b770
Warn of invalid salt
darkwing Nov 22, 2022
c2577d9
Add salt validation, move startUISync
darkwing Nov 22, 2022
3bcaf31
Add return
darkwing Nov 23, 2022
f09a411
Merge branch 'develop' into mv3-login
darkwing Nov 23, 2022
62fc4a2
Merge branch 'develop' into mv3-login
darkwing Nov 23, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions app/scripts/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -491,11 +491,6 @@ function setupController(initState, initLangCode, remoteSourcePort) {
controller.setupTrustedCommunication(portStream, remotePort.sender);

if (isManifestV3) {
// Message below if captured by UI code in app/scripts/ui.js which will trigger UI initialisation
// This ensures that UI is initialised only after background is ready
// It fixes the issue of blank screen coming when extension is loaded, the issue is very frequent in MV3
remotePort.postMessage({ name: EXTENSION_MESSAGES.CONNECTION_READY });

// If we get a WORKER_KEEP_ALIVE message, we respond with an ACK
remotePort.onMessage.addListener((message) => {
if (message.name === WORKER_KEEP_ALIVE_MESSAGE) {
Expand Down
104 changes: 99 additions & 5 deletions app/scripts/metamask-controller.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ import {
} from '@metamask/snaps-controllers';
///: END:ONLY_INCLUDE_IN

import browser from 'webextension-polyfill';
import {
ASSET_TYPES,
TRANSACTION_STATUSES,
Expand Down Expand Up @@ -140,6 +141,7 @@ import seedPhraseVerifier from './lib/seed-phrase-verifier';
import MetaMetricsController from './controllers/metametrics';
import { segment } from './lib/segment';
import createMetaRPCHandler from './lib/createMetaRPCHandler';

import {
CaveatMutatorFactories,
getCaveatSpecifications,
Expand Down Expand Up @@ -589,6 +591,7 @@ export default class MetamaskController extends EventEmitter {
keyringTypes: additionalKeyrings,
initState: initState.KeyringController,
encryptor: opts.encryptor || undefined,
cacheEncryptionKey: isManifestV3,
});
this.keyringController.memStore.subscribe((state) =>
this._onKeyringControllerUpdate(state),
Expand Down Expand Up @@ -1118,7 +1121,6 @@ export default class MetamaskController extends EventEmitter {
},
controllerMessenger: this.controllerMessenger,
});
this.memStore.subscribe(this.sendUpdate.bind(this));

// if this is the first time, clear the state of by calling these methods
const resetMethods = [
Expand All @@ -1144,13 +1146,14 @@ export default class MetamaskController extends EventEmitter {
this.resetStates(resetMethods);
}

const password = process.env.CONF?.PASSWORD;
// Automatic login via config password or loginToken
if (
password &&
!this.isUnlocked() &&
this.onboardingController.store.getState().completedOnboarding
) {
this.submitPassword(password);
this._loginUser();
} else {
this._startUISync();
}

// Lazily update the store with the current extension environment
Expand Down Expand Up @@ -2388,6 +2391,68 @@ export default class MetamaskController extends EventEmitter {
return this.keyringController.fullUpdate();
}

async _loginUser() {
try {
// Automatic login via config password
const password = process.env.CONF?.PASSWORD;
if (password) {
await this.submitPassword(password);
}
// Automatic login via storage encryption key
else if (isManifestV3) {
await this.submitEncryptionKey();
}
// Updating accounts in this.accountTracker before starting UI syncing ensure that
// state has account balance before it is synced with UI
await this.accountTracker._updateAccounts();
} finally {
this._startUISync();
}
}

_startUISync() {
// Message startUISync is used in MV3 to start syncing state with UI
// Sending this message after login is completed helps to ensure that incomplete state without
// account details are not flushed to UI.
this.emit('startUISync');
this.startUISync = true;
this.memStore.subscribe(this.sendUpdate.bind(this));
}

/**
* Submits a user's encryption key to log the user in via login token
*/
async submitEncryptionKey() {
try {
const { loginToken, loginSalt } = await browser.storage.session.get([
'loginToken',
'loginSalt',
]);
if (loginToken && loginSalt) {
const { vault } = this.keyringController.store.getState();

if (vault.salt !== loginSalt) {
console.warn(
'submitEncryptionKey: Stored salt and vault salt do not match',
);
await this.clearLoginArtifacts();
return;
}

await this.keyringController.submitEncryptionKey(loginToken, loginSalt);
}
} catch (e) {
// If somehow this login token doesn't work properly,
// remove it and the user will get shown back to the unlock screen
await this.clearLoginArtifacts();
throw e;
}
}

async clearLoginArtifacts() {
await browser.storage.session.remove(['loginToken', 'loginSalt']);
}

/**
* Submits a user's password to check its validity.
*
Expand Down Expand Up @@ -3526,6 +3591,23 @@ export default class MetamaskController extends EventEmitter {
});
};
this.on('update', handleUpdate);
const startUISync = () => {
if (outStream._writableState.ended) {
return;
}
// send notification to client-side
outStream.write({
jsonrpc: '2.0',
method: 'startUISync',
});
};

if (this.startUISync) {
startUISync();
} else {
this.once('startUISync', startUISync);
}

outStream.on('end', () => {
this.activeControllerConnections -= 1;
this.emit(
Expand Down Expand Up @@ -3969,12 +4051,20 @@ export default class MetamaskController extends EventEmitter {
* @private
*/
async _onKeyringControllerUpdate(state) {
const { keyrings } = state;
const {
keyrings,
encryptionKey: loginToken,
encryptionSalt: loginSalt,
} = state;
const addresses = keyrings.reduce(
(acc, { accounts }) => acc.concat(accounts),
[],
);

if (isManifestV3) {
await browser.storage.session.set({ loginToken, loginSalt });
}

if (!addresses.length) {
return;
}
Expand Down Expand Up @@ -4366,6 +4456,10 @@ export default class MetamaskController extends EventEmitter {
);
ledgerKeyring?.destroy?.();

if (isManifestV3) {
this.clearLoginArtifacts();
}

return this.keyringController.setLocked();
}

Expand Down
7 changes: 4 additions & 3 deletions app/scripts/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import launchMetaMaskUi, { updateBackgroundConnection } from '../../ui';
import {
ENVIRONMENT_TYPE_FULLSCREEN,
ENVIRONMENT_TYPE_POPUP,
EXTENSION_MESSAGES,
PLATFORM_FIREFOX,
} from '../../shared/constants/app';
import { isManifestV3 } from '../../shared/modules/mv3.utils';
Expand Down Expand Up @@ -117,11 +116,13 @@ async function start() {
if (isManifestV3) {
/*
* In case of MV3 the issue of blank screen was very frequent, it is caused by UI initialising before background is ready to send state.
* Code below ensures that UI is rendered only after CONNECTION_READY message is received thus background is ready.
* Code below ensures that UI is rendered only after "CONNECTION_READY" or "startUISync"
* messages are received thus the background is ready, and ensures that streams and
* phishing warning page load only after the "startUISync" message is received.
* In case the UI is already rendered, only update the streams.
*/
const messageListener = async (message) => {
if (message?.name === EXTENSION_MESSAGES.CONNECTION_READY) {
if (message?.data?.method === 'startUISync') {
if (isUIInitialised) {
// Currently when service worker is revived we create new streams
// in later version we might try to improve it by reviving same streams.
Expand Down
73 changes: 55 additions & 18 deletions lavamoat/browserify/beta/policy.json
Original file line number Diff line number Diff line change
Expand Up @@ -490,6 +490,7 @@
"@metamask/controllers>abort-controller": true,
"@metamask/controllers>async-mutex": true,
"@metamask/controllers>eth-json-rpc-infura": true,
"@metamask/controllers>eth-keyring-controller": true,
"@metamask/controllers>eth-method-registry": true,
"@metamask/controllers>eth-phishing-detect": true,
"@metamask/controllers>ethereumjs-wallet": true,
Expand All @@ -504,7 +505,6 @@
"deep-freeze-strict": true,
"eslint>fast-deep-equal": true,
"eth-ens-namehash": true,
"eth-keyring-controller": true,
"eth-query": true,
"eth-rpc-errors": true,
"eth-sig-util": true,
Expand Down Expand Up @@ -660,6 +660,37 @@
"safe-event-emitter": true
}
},
"@metamask/controllers>eth-keyring-controller": {
"packages": {
"@metamask/controllers>eth-keyring-controller>browser-passworder": true,
"browserify>buffer": true,
"browserify>events": true,
"eth-keyring-controller>@metamask/bip39": true,
"eth-keyring-controller>@metamask/eth-hd-keyring": true,
"eth-keyring-controller>eth-simple-keyring": true,
"eth-keyring-controller>obs-store": true,
"eth-sig-util": true
}
},
"@metamask/controllers>eth-keyring-controller>browser-passworder": {
"globals": {
"btoa": true,
"crypto.getRandomValues": true,
"crypto.subtle.decrypt": true,
"crypto.subtle.deriveKey": true,
"crypto.subtle.encrypt": true,
"crypto.subtle.importKey": true
},
"packages": {
"@metamask/controllers>eth-keyring-controller>browser-passworder>browserify-unibabel": true
}
},
"@metamask/controllers>eth-keyring-controller>browser-passworder>browserify-unibabel": {
"globals": {
"atob": true,
"btoa": true
}
},
"@metamask/controllers>eth-method-registry": {
"packages": {
"@metamask/controllers>eth-method-registry>ethjs": true
Expand Down Expand Up @@ -1274,6 +1305,7 @@
"@metamask/controllers>web3": true,
"@metamask/controllers>web3-provider-engine": true,
"@metamask/metamask-eth-abis": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-keyring-controller": true,
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry": true,
"@metamask/smart-transactions-controller>@metamask/controllers>ethereumjs-wallet": true,
"@metamask/smart-transactions-controller>@metamask/controllers>nanoid": true,
Expand All @@ -1282,7 +1314,6 @@
"deep-freeze-strict": true,
"eslint>fast-deep-equal": true,
"eth-ens-namehash": true,
"eth-keyring-controller": true,
"eth-query": true,
"eth-rpc-errors": true,
"eth-sig-util": true,
Expand All @@ -1296,6 +1327,18 @@
"uuid": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-keyring-controller": {
"packages": {
"@metamask/controllers>eth-keyring-controller>browser-passworder": true,
"browserify>buffer": true,
"browserify>events": true,
"eth-keyring-controller>@metamask/bip39": true,
"eth-keyring-controller>@metamask/eth-hd-keyring": true,
"eth-keyring-controller>eth-simple-keyring": true,
"eth-keyring-controller>obs-store": true,
"eth-sig-util": true
}
},
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry": {
"packages": {
"@metamask/smart-transactions-controller>@metamask/controllers>eth-method-registry>ethjs": true
Expand Down Expand Up @@ -2465,8 +2508,8 @@
"browserify>buffer": true,
"browserify>events": true,
"eth-keyring-controller>@metamask/bip39": true,
"eth-keyring-controller>@metamask/browser-passworder": true,
"eth-keyring-controller>@metamask/eth-hd-keyring": true,
"eth-keyring-controller>browser-passworder": true,
"eth-keyring-controller>eth-simple-keyring": true,
"eth-keyring-controller>obs-store": true,
"eth-sig-util": true
Expand All @@ -2480,6 +2523,15 @@
"ethereumjs-wallet>randombytes": true
}
},
"eth-keyring-controller>@metamask/browser-passworder": {
"globals": {
"btoa": true,
"crypto": true
},
"packages": {
"browserify>buffer": true
}
},
"eth-keyring-controller>@metamask/eth-hd-keyring": {
"packages": {
"browserify>buffer": true,
Expand Down Expand Up @@ -2509,21 +2561,6 @@
"msCrypto": true
}
},
"eth-keyring-controller>browser-passworder": {
"globals": {
"btoa": true,
"crypto": true
},
"packages": {
"eth-keyring-controller>browser-passworder>browserify-unibabel": true
}
},
"eth-keyring-controller>browser-passworder>browserify-unibabel": {
"globals": {
"atob": true,
"btoa": true
}
},
"eth-keyring-controller>eth-simple-keyring": {
"packages": {
"browserify>buffer": true,
Expand Down
Loading