diff --git a/app/scripts/lib/createOnboardingMiddleware.js b/app/scripts/lib/createOnboardingMiddleware.js index 2dbac6b51..35d599308 100644 --- a/app/scripts/lib/createOnboardingMiddleware.js +++ b/app/scripts/lib/createOnboardingMiddleware.js @@ -3,18 +3,18 @@ import extension from 'extensionizer' /** * 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} */ -function createOnboardingMiddleware ({ location, tabId, registerOnboarding }) { +function createOnboardingMiddleware ({ location, registerOnboarding }) { return async function originMiddleware (req, res, next, end) { try { if (req.method !== 'wallet_registerOnboarding') { next() return } - if (tabId && tabId !== extension.tabs.TAB_ID_NONE) { - await registerOnboarding(location, tabId) + if (req.tabId && req.tabId !== extension.tabs.TAB_ID_NONE) { + await registerOnboarding(location, req.tabId) } else { log.debug(`'wallet_registerOnboarding' message from ${location} ignored due to missing tabId`) } diff --git a/app/scripts/lib/createTabIdMiddleware.js b/app/scripts/lib/createTabIdMiddleware.js new file mode 100644 index 000000000..0edfcb834 --- /dev/null +++ b/app/scripts/lib/createTabIdMiddleware.js @@ -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() + } +} diff --git a/app/scripts/metamask-controller.js b/app/scripts/metamask-controller.js index a4e9e852e..259bb09ee 100644 --- a/app/scripts/metamask-controller.js +++ b/app/scripts/metamask-controller.js @@ -20,6 +20,7 @@ import createFilterMiddleware from 'eth-json-rpc-filters' import createSubscriptionManager from 'eth-json-rpc-filters/subscriptionManager' import createLoggerMiddleware from './lib/createLoggerMiddleware' import createOriginMiddleware from './lib/createOriginMiddleware' +import createTabIdMiddleware from './lib/createTabIdMiddleware' import createOnboardingMiddleware from './lib/createOnboardingMiddleware' import providerAsMiddleware from 'eth-json-rpc-middleware/providerAsMiddleware' import { setupMultiplex } from './lib/stream-utils.js' @@ -1627,11 +1628,14 @@ export default class MetamaskController extends EventEmitter { // append origin to each request engine.push(createOriginMiddleware({ origin })) + // append tabId to each request if it exists + if (tabId) { + engine.push(createTabIdMiddleware({ tabId })) + } // logging engine.push(createLoggerMiddleware({ origin })) engine.push(createOnboardingMiddleware({ location, - tabId, registerOnboarding: this.onboardingController.registerOnboarding, })) // filter and subscription polyfills diff --git a/test/unit/app/controllers/metamask-controller-test.js b/test/unit/app/controllers/metamask-controller-test.js index 9d01c1549..ff92dbd20 100644 --- a/test/unit/app/controllers/metamask-controller-test.js +++ b/test/unit/app/controllers/metamask-controller-test.js @@ -102,6 +102,7 @@ describe('MetaMaskController', function () { // add sinon method spies sandbox.spy(metamaskController.keyringController, 'createNewVaultAndKeychain') sandbox.spy(metamaskController.keyringController, 'createNewVaultAndRestore') + sandbox.spy(metamaskController.txController, 'newUnapprovedTransaction') }) afterEach(function () { @@ -791,6 +792,88 @@ describe('MetaMaskController', function () { await promise 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 () {