Assign `tabId` to middleware request, if provided (#7695)

The `tabId` of the message sender is now added to the middleware
request object. This step is omitted if the `tabId` is not provided.
This is done early in the middleware stack, so the `tabId` should be
available for any subsequent middleware to use.

The Onboarding Middleware has also been modified to get the `tabId`
from the request object, rather than expecting it as a parameter upon
creation.

This refactor will enable further uses of the `tabId`.
feature/default_network_editable
Dan J Miller 5 years ago committed by GitHub
parent ef98e876a7
commit 1d2c57a2f3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      app/scripts/lib/createOnboardingMiddleware.js
  2. 14
      app/scripts/lib/createTabIdMiddleware.js
  3. 6
      app/scripts/metamask-controller.js
  4. 83
      test/unit/app/controllers/metamask-controller-test.js

@ -3,18 +3,18 @@ import extension from 'extensionizer'
/** /**
* Returns a middleware that intercepts `wallet_registerOnboarding` messages * Returns a middleware that intercepts `wallet_registerOnboarding` messages
* @param {{ location: string, tabId: number, registerOnboarding: Function }} opts - The middleware options * @param {{ location: string, registerOnboarding: Function }} opts - The middleware options
* @returns {(req: any, res: any, next: Function, end: Function) => void} * @returns {(req: any, res: any, next: Function, end: Function) => void}
*/ */
function createOnboardingMiddleware ({ location, tabId, registerOnboarding }) { function createOnboardingMiddleware ({ location, registerOnboarding }) {
return async function originMiddleware (req, res, next, end) { return async function originMiddleware (req, res, next, end) {
try { try {
if (req.method !== 'wallet_registerOnboarding') { if (req.method !== 'wallet_registerOnboarding') {
next() next()
return return
} }
if (tabId && tabId !== extension.tabs.TAB_ID_NONE) { if (req.tabId && req.tabId !== extension.tabs.TAB_ID_NONE) {
await registerOnboarding(location, tabId) await registerOnboarding(location, req.tabId)
} else { } else {
log.debug(`'wallet_registerOnboarding' message from ${location} ignored due to missing tabId`) log.debug(`'wallet_registerOnboarding' message from ${location} ignored due to missing tabId`)
} }

@ -0,0 +1,14 @@
module.exports = createTabIdMiddleware
/**
* Returns a middleware that appends the DApp TabId to the request
* @param {{ tabId: number }} opts - The middleware options
* @returns {Function}
*/
function createTabIdMiddleware (opts) {
return function tabIdMiddleware (/** @type {any} */ req, /** @type {any} */ _, /** @type {Function} */ next) {
req.tabId = opts.tabId
next()
}
}

@ -20,6 +20,7 @@ import createFilterMiddleware from 'eth-json-rpc-filters'
import createSubscriptionManager from 'eth-json-rpc-filters/subscriptionManager' import createSubscriptionManager from 'eth-json-rpc-filters/subscriptionManager'
import createLoggerMiddleware from './lib/createLoggerMiddleware' import createLoggerMiddleware from './lib/createLoggerMiddleware'
import createOriginMiddleware from './lib/createOriginMiddleware' import createOriginMiddleware from './lib/createOriginMiddleware'
import createTabIdMiddleware from './lib/createTabIdMiddleware'
import createOnboardingMiddleware from './lib/createOnboardingMiddleware' import createOnboardingMiddleware from './lib/createOnboardingMiddleware'
import providerAsMiddleware from 'eth-json-rpc-middleware/providerAsMiddleware' import providerAsMiddleware from 'eth-json-rpc-middleware/providerAsMiddleware'
import { setupMultiplex } from './lib/stream-utils.js' import { setupMultiplex } from './lib/stream-utils.js'
@ -1627,11 +1628,14 @@ export default class MetamaskController extends EventEmitter {
// append origin to each request // append origin to each request
engine.push(createOriginMiddleware({ origin })) engine.push(createOriginMiddleware({ origin }))
// append tabId to each request if it exists
if (tabId) {
engine.push(createTabIdMiddleware({ tabId }))
}
// logging // logging
engine.push(createLoggerMiddleware({ origin })) engine.push(createLoggerMiddleware({ origin }))
engine.push(createOnboardingMiddleware({ engine.push(createOnboardingMiddleware({
location, location,
tabId,
registerOnboarding: this.onboardingController.registerOnboarding, registerOnboarding: this.onboardingController.registerOnboarding,
})) }))
// filter and subscription polyfills // filter and subscription polyfills

@ -102,6 +102,7 @@ describe('MetaMaskController', function () {
// add sinon method spies // add sinon method spies
sandbox.spy(metamaskController.keyringController, 'createNewVaultAndKeychain') sandbox.spy(metamaskController.keyringController, 'createNewVaultAndKeychain')
sandbox.spy(metamaskController.keyringController, 'createNewVaultAndRestore') sandbox.spy(metamaskController.keyringController, 'createNewVaultAndRestore')
sandbox.spy(metamaskController.txController, 'newUnapprovedTransaction')
}) })
afterEach(function () { afterEach(function () {
@ -791,6 +792,88 @@ describe('MetaMaskController', function () {
await promise await promise
streamTest.end() streamTest.end()
}) })
it('adds a tabId and origin to requests', function (done) {
const messageSender = {
url: 'http://mycrypto.com',
tab: { id: 456 },
}
const streamTest = createThoughStream((chunk, _, cb) => {
if (chunk.data && chunk.data.method) {
cb(null, chunk)
} else {
cb()
}
})
metamaskController.setupUntrustedCommunication(streamTest, messageSender)
const message = {
id: 1999133338649204,
jsonrpc: '2.0',
params: ['mock tx params'],
method: 'eth_sendTransaction',
}
streamTest.write({
name: 'provider',
data: message,
}, null, () => {
setTimeout(() => {
assert.deepStrictEqual(
metamaskController.txController.newUnapprovedTransaction.getCall(0).args,
[
'mock tx params',
{
...message,
origin: 'mycrypto.com',
tabId: 456,
},
]
)
done()
})
})
})
it('should add only origin to request if tabId not provided', function (done) {
const messageSender = {
url: 'http://mycrypto.com',
}
const streamTest = createThoughStream((chunk, _, cb) => {
if (chunk.data && chunk.data.method) {
cb(null, chunk)
} else {
cb()
}
})
metamaskController.setupUntrustedCommunication(streamTest, messageSender)
const message = {
id: 1999133338649204,
jsonrpc: '2.0',
params: ['mock tx params'],
method: 'eth_sendTransaction',
}
streamTest.write({
name: 'provider',
data: message,
}, null, () => {
setTimeout(() => {
assert.deepStrictEqual(
metamaskController.txController.newUnapprovedTransaction.getCall(0).args,
[
'mock tx params',
{
...message,
origin: 'mycrypto.com',
},
]
)
done()
})
})
})
}) })
describe('#setupTrustedCommunication', function () { describe('#setupTrustedCommunication', function () {

Loading…
Cancel
Save