1
0
mirror of https://github.com/kremalicious/metamask-extension.git synced 2024-12-02 14:15:06 +01:00
metamask-extension/app/scripts/controllers/permissions/methodMiddleware.js
Erik Marks 2301d9980e
Wait for extension unlock before processing eth_requestAccounts (#8149)
* eth_requestAccounts: wait on unlock

return error on duplicate eth_requestAccounts
add getUnlockPromise mock to permissions unit tests

* only await unlock if already permitted

* add notification badge for wait on unlock

* fixup

* more fixup

* cleanup

* update keyring controller, us its unlock event

* move keyring update unlock logic to unlock event handler

* fix unit tests

* delete onUnlock handler

* fix eth-keyring-controller resolution

* update eth-keyring-controller
2020-03-23 09:25:55 -07:00

110 lines
2.8 KiB
JavaScript

import createAsyncMiddleware from 'json-rpc-engine/src/createAsyncMiddleware'
import { ethErrors } from 'eth-json-rpc-errors'
/**
* Create middleware for handling certain methods and preprocessing permissions requests.
*/
export default function createMethodMiddleware ({
getAccounts,
getUnlockPromise,
hasPermission,
requestAccountsPermission,
store,
storeKey,
}) {
let isProcessingRequestAccounts = false
return createAsyncMiddleware(async (req, res, next) => {
switch (req.method) {
// Intercepting eth_accounts requests for backwards compatibility:
// The getAccounts call below wraps the rpc-cap middleware, and returns
// an empty array in case of errors (such as 4100:unauthorized)
case 'eth_accounts':
res.result = await getAccounts()
return
case 'eth_requestAccounts':
if (isProcessingRequestAccounts) {
res.error = ethErrors.rpc.resourceUnavailable(
'Already processing eth_requestAccounts. Please wait.'
)
return
}
if (hasPermission('eth_accounts')) {
isProcessingRequestAccounts = true
await getUnlockPromise()
isProcessingRequestAccounts = false
}
// first, just try to get accounts
let accounts = await getAccounts()
if (accounts.length > 0) {
res.result = accounts
return
}
// if no accounts, request the accounts permission
try {
await requestAccountsPermission()
} catch (err) {
res.error = err
return
}
// get the accounts again
accounts = await getAccounts()
/* istanbul ignore else: too hard to induce, see below comment */
if (accounts.length > 0) {
res.result = accounts
} else {
// this should never happen, because it should be caught in the
// above catch clause
res.error = ethErrors.rpc.internal(
'Accounts unexpectedly unavailable. Please report this bug.'
)
}
return
// custom method for getting metadata from the requesting domain,
// sent automatically by the inpage provider
case 'wallet_sendDomainMetadata':
const storeState = store.getState()[storeKey]
const extensionId = storeState[req.origin]
? storeState[req.origin].extensionId
: undefined
if (
req.domainMetadata &&
typeof req.domainMetadata.name === 'string'
) {
store.updateState({
[storeKey]: {
...storeState,
[req.origin]: {
extensionId,
...req.domainMetadata,
},
},
})
}
res.result = true
return
default:
break
}
next()
})
}