mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 18:00:18 +01:00
Add hostname and extensionId to site metadata (#7218)
If the extension ID is set, an alternate title and subtitle are used for the Connect Request screen. The title is always `External Extension`, and the subtitle is `Extension ID: [id]` instead of the origin (which would just be `[extension-scheme]://[id]` anyway). The hostname for the site is used as a fallback in case it has no title. The artificial hostname set for internal connections has been renamed from 'MetaMask' to 'metamask' because URL objects automatically normalize hostnames to be all lower-case, and it was more convenient to use a URL object so that the parameter would be the same type as used for an untrusted connection.
This commit is contained in:
parent
7181779576
commit
8dfb0e8154
@ -10,7 +10,6 @@ require('./lib/setupFetchDebugging')()
|
|||||||
// polyfills
|
// polyfills
|
||||||
import 'abortcontroller-polyfill/dist/polyfill-patch-fetch'
|
import 'abortcontroller-polyfill/dist/polyfill-patch-fetch'
|
||||||
|
|
||||||
const urlUtil = require('url')
|
|
||||||
const endOfStream = require('end-of-stream')
|
const endOfStream = require('end-of-stream')
|
||||||
const pump = require('pump')
|
const pump = require('pump')
|
||||||
const debounce = require('debounce-stream')
|
const debounce = require('debounce-stream')
|
||||||
@ -352,7 +351,10 @@ function setupController (initState, initLangCode) {
|
|||||||
const portStream = new PortStream(remotePort)
|
const portStream = new PortStream(remotePort)
|
||||||
// communication with popup
|
// communication with popup
|
||||||
controller.isClientOpen = true
|
controller.isClientOpen = true
|
||||||
controller.setupTrustedCommunication(portStream, 'MetaMask')
|
// construct fake URL for identifying internal messages
|
||||||
|
const metamaskUrl = new URL(window.location)
|
||||||
|
metamaskUrl.hostname = 'metamask'
|
||||||
|
controller.setupTrustedCommunication(portStream, metamaskUrl)
|
||||||
|
|
||||||
if (processName === ENVIRONMENT_TYPE_POPUP) {
|
if (processName === ENVIRONMENT_TYPE_POPUP) {
|
||||||
popupIsOpen = true
|
popupIsOpen = true
|
||||||
@ -388,9 +390,10 @@ function setupController (initState, initLangCode) {
|
|||||||
|
|
||||||
// communication with page or other extension
|
// communication with page or other extension
|
||||||
function connectExternal (remotePort) {
|
function connectExternal (remotePort) {
|
||||||
const originDomain = urlUtil.parse(remotePort.sender.url).hostname
|
const senderUrl = new URL(remotePort.sender.url)
|
||||||
|
const extensionId = remotePort.sender.id
|
||||||
const portStream = new PortStream(remotePort)
|
const portStream = new PortStream(remotePort)
|
||||||
controller.setupUntrustedCommunication(portStream, originDomain)
|
controller.setupUntrustedCommunication(portStream, senderUrl, extensionId)
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -31,19 +31,25 @@ class ProviderApprovalController extends SafeEventEmitter {
|
|||||||
*
|
*
|
||||||
* @param {object} opts - opts for the middleware contains the origin for the middleware
|
* @param {object} opts - opts for the middleware contains the origin for the middleware
|
||||||
*/
|
*/
|
||||||
createMiddleware ({ origin, getSiteMetadata }) {
|
createMiddleware ({ senderUrl, extensionId, getSiteMetadata }) {
|
||||||
return createAsyncMiddleware(async (req, res, next) => {
|
return createAsyncMiddleware(async (req, res, next) => {
|
||||||
// only handle requestAccounts
|
// only handle requestAccounts
|
||||||
if (req.method !== 'eth_requestAccounts') return next()
|
if (req.method !== 'eth_requestAccounts') return next()
|
||||||
// if already approved or privacy mode disabled, return early
|
// if already approved or privacy mode disabled, return early
|
||||||
const isUnlocked = this.keyringController.memStore.getState().isUnlocked
|
const isUnlocked = this.keyringController.memStore.getState().isUnlocked
|
||||||
|
const origin = senderUrl.hostname
|
||||||
if (this.shouldExposeAccounts(origin) && isUnlocked) {
|
if (this.shouldExposeAccounts(origin) && isUnlocked) {
|
||||||
res.result = [this.preferencesController.getSelectedAddress()]
|
res.result = [this.preferencesController.getSelectedAddress()]
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// register the provider request
|
// register the provider request
|
||||||
const metadata = await getSiteMetadata(origin)
|
const metadata = { hostname: senderUrl.hostname, origin }
|
||||||
this._handleProviderRequest(origin, metadata.name, metadata.icon)
|
if (extensionId) {
|
||||||
|
metadata.extensionId = extensionId
|
||||||
|
} else {
|
||||||
|
Object.assign(metadata, await getSiteMetadata(origin))
|
||||||
|
}
|
||||||
|
this._handleProviderRequest(metadata)
|
||||||
// wait for resolution of request
|
// wait for resolution of request
|
||||||
const approved = await new Promise(resolve => this.once(`resolvedRequest:${origin}`, ({ approved }) => resolve(approved)))
|
const approved = await new Promise(resolve => this.once(`resolvedRequest:${origin}`, ({ approved }) => resolve(approved)))
|
||||||
if (approved) {
|
if (approved) {
|
||||||
@ -54,19 +60,26 @@ class ProviderApprovalController extends SafeEventEmitter {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} SiteMetadata
|
||||||
|
* @param {string} hostname - The hostname of the site
|
||||||
|
* @param {string} origin - The origin of the site
|
||||||
|
* @param {string} [siteTitle] - The title of the site
|
||||||
|
* @param {string} [siteImage] - The icon for the site
|
||||||
|
* @param {string} [extensionId] - The extension ID of the extension
|
||||||
|
*/
|
||||||
/**
|
/**
|
||||||
* Called when a tab requests access to a full Ethereum provider API
|
* Called when a tab requests access to a full Ethereum provider API
|
||||||
*
|
*
|
||||||
* @param {string} origin - Origin of the window requesting full provider access
|
* @param {SiteMetadata} siteMetadata - The metadata for the site requesting full provider access
|
||||||
* @param {string} siteTitle - The title of the document requesting full provider access
|
|
||||||
* @param {string} siteImage - The icon of the window requesting full provider access
|
|
||||||
*/
|
*/
|
||||||
_handleProviderRequest (origin, siteTitle, siteImage) {
|
_handleProviderRequest (siteMetadata) {
|
||||||
const { providerRequests } = this.memStore.getState()
|
const { providerRequests } = this.memStore.getState()
|
||||||
|
const origin = siteMetadata.origin
|
||||||
this.memStore.updateState({
|
this.memStore.updateState({
|
||||||
providerRequests: [
|
providerRequests: [
|
||||||
...providerRequests,
|
...providerRequests,
|
||||||
{ origin, siteTitle, siteImage },
|
siteMetadata,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
const isUnlocked = this.keyringController.memStore.getState().isUnlocked
|
const isUnlocked = this.keyringController.memStore.getState().isUnlocked
|
||||||
@ -98,6 +111,7 @@ class ProviderApprovalController extends SafeEventEmitter {
|
|||||||
[origin]: {
|
[origin]: {
|
||||||
siteTitle: providerRequest ? providerRequest.siteTitle : null,
|
siteTitle: providerRequest ? providerRequest.siteTitle : null,
|
||||||
siteImage: providerRequest ? providerRequest.siteImage : null,
|
siteImage: providerRequest ? providerRequest.siteImage : null,
|
||||||
|
hostname: providerRequest ? providerRequest.hostname : null,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -334,7 +334,7 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
// Expose no accounts if this origin has not been approved, preventing
|
// Expose no accounts if this origin has not been approved, preventing
|
||||||
// account-requring RPC methods from completing successfully
|
// account-requring RPC methods from completing successfully
|
||||||
const exposeAccounts = this.providerApprovalController.shouldExposeAccounts(origin)
|
const exposeAccounts = this.providerApprovalController.shouldExposeAccounts(origin)
|
||||||
if (origin !== 'MetaMask' && !exposeAccounts) { return [] }
|
if (origin !== 'metamask' && !exposeAccounts) { return [] }
|
||||||
const isUnlocked = this.keyringController.memStore.getState().isUnlocked
|
const isUnlocked = this.keyringController.memStore.getState().isUnlocked
|
||||||
const selectedAddress = this.preferencesController.getSelectedAddress()
|
const selectedAddress = this.preferencesController.getSelectedAddress()
|
||||||
// only show address if account is unlocked
|
// only show address if account is unlocked
|
||||||
@ -1318,23 +1318,25 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
* Used to create a multiplexed stream for connecting to an untrusted context
|
* Used to create a multiplexed stream for connecting to an untrusted context
|
||||||
* like a Dapp or other extension.
|
* like a Dapp or other extension.
|
||||||
* @param {*} connectionStream - The Duplex stream to connect to.
|
* @param {*} connectionStream - The Duplex stream to connect to.
|
||||||
* @param {string} originDomain - The domain requesting the stream, which
|
* @param {URL} senderUrl - The URL of the resource requesting the stream,
|
||||||
* may trigger a blacklist reload.
|
* which may trigger a blacklist reload.
|
||||||
|
* @param {string} extensionId - The extension id of the sender, if the sender
|
||||||
|
* is an extension
|
||||||
*/
|
*/
|
||||||
setupUntrustedCommunication (connectionStream, originDomain) {
|
setupUntrustedCommunication (connectionStream, senderUrl, extensionId) {
|
||||||
// Check if new connection is blacklisted
|
// Check if new connection is blacklisted
|
||||||
if (this.phishingController.test(originDomain)) {
|
if (this.phishingController.test(senderUrl.hostname)) {
|
||||||
log.debug('MetaMask - sending phishing warning for', originDomain)
|
log.debug('MetaMask - sending phishing warning for', senderUrl.hostname)
|
||||||
this.sendPhishingWarning(connectionStream, originDomain)
|
this.sendPhishingWarning(connectionStream, senderUrl.hostname)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// setup multiplexing
|
// setup multiplexing
|
||||||
const mux = setupMultiplex(connectionStream)
|
const mux = setupMultiplex(connectionStream)
|
||||||
// connect features
|
// connect features
|
||||||
const publicApi = this.setupPublicApi(mux.createStream('publicApi'), originDomain)
|
const publicApi = this.setupPublicApi(mux.createStream('publicApi'))
|
||||||
this.setupProviderConnection(mux.createStream('provider'), originDomain, publicApi)
|
this.setupProviderConnection(mux.createStream('provider'), senderUrl, extensionId, publicApi)
|
||||||
this.setupPublicConfig(mux.createStream('publicConfig'), originDomain)
|
this.setupPublicConfig(mux.createStream('publicConfig'), senderUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1344,15 +1346,15 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
* functions, like the ability to approve transactions or sign messages.
|
* functions, like the ability to approve transactions or sign messages.
|
||||||
*
|
*
|
||||||
* @param {*} connectionStream - The duplex stream to connect to.
|
* @param {*} connectionStream - The duplex stream to connect to.
|
||||||
* @param {string} originDomain - The domain requesting the connection,
|
* @param {URL} senderUrl - The URL requesting the connection,
|
||||||
* used in logging and error reporting.
|
* used in logging and error reporting.
|
||||||
*/
|
*/
|
||||||
setupTrustedCommunication (connectionStream, originDomain) {
|
setupTrustedCommunication (connectionStream, senderUrl) {
|
||||||
// setup multiplexing
|
// setup multiplexing
|
||||||
const mux = setupMultiplex(connectionStream)
|
const mux = setupMultiplex(connectionStream)
|
||||||
// connect features
|
// connect features
|
||||||
this.setupControllerConnection(mux.createStream('controller'))
|
this.setupControllerConnection(mux.createStream('controller'))
|
||||||
this.setupProviderConnection(mux.createStream('provider'), originDomain)
|
this.setupProviderConnection(mux.createStream('provider'), senderUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1405,11 +1407,14 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
/**
|
/**
|
||||||
* A method for serving our ethereum provider over a given stream.
|
* A method for serving our ethereum provider over a given stream.
|
||||||
* @param {*} outStream - The stream to provide over.
|
* @param {*} outStream - The stream to provide over.
|
||||||
* @param {string} origin - The URI of the requesting resource.
|
* @param {URL} senderUrl - The URI of the requesting resource.
|
||||||
|
* @param {string} extensionId - The id of the extension, if the requesting
|
||||||
|
* resource is an extension.
|
||||||
|
* @param {object} publicApi - The public API
|
||||||
*/
|
*/
|
||||||
setupProviderConnection (outStream, origin, publicApi) {
|
setupProviderConnection (outStream, senderUrl, extensionId, publicApi) {
|
||||||
const getSiteMetadata = publicApi && publicApi.getSiteMetadata
|
const getSiteMetadata = publicApi && publicApi.getSiteMetadata
|
||||||
const engine = this.setupProviderEngine(origin, getSiteMetadata)
|
const engine = this.setupProviderEngine(senderUrl, extensionId, getSiteMetadata)
|
||||||
|
|
||||||
// setup connection
|
// setup connection
|
||||||
const providerStream = createEngineStream({ engine })
|
const providerStream = createEngineStream({ engine })
|
||||||
@ -1433,7 +1438,8 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
/**
|
/**
|
||||||
* A method for creating a provider that is safely restricted for the requesting domain.
|
* A method for creating a provider that is safely restricted for the requesting domain.
|
||||||
**/
|
**/
|
||||||
setupProviderEngine (origin, getSiteMetadata) {
|
setupProviderEngine (senderUrl, extensionId, getSiteMetadata) {
|
||||||
|
const origin = senderUrl.hostname
|
||||||
// setup json rpc engine stack
|
// setup json rpc engine stack
|
||||||
const engine = new RpcEngine()
|
const engine = new RpcEngine()
|
||||||
const provider = this.provider
|
const provider = this.provider
|
||||||
@ -1456,7 +1462,8 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
engine.push(this.preferencesController.requestWatchAsset.bind(this.preferencesController))
|
engine.push(this.preferencesController.requestWatchAsset.bind(this.preferencesController))
|
||||||
// requestAccounts
|
// requestAccounts
|
||||||
engine.push(this.providerApprovalController.createMiddleware({
|
engine.push(this.providerApprovalController.createMiddleware({
|
||||||
origin,
|
senderUrl,
|
||||||
|
extensionId,
|
||||||
getSiteMetadata,
|
getSiteMetadata,
|
||||||
}))
|
}))
|
||||||
// forward to metamask primary provider
|
// forward to metamask primary provider
|
||||||
@ -1473,11 +1480,12 @@ module.exports = class MetamaskController extends EventEmitter {
|
|||||||
* this is a good candidate for deprecation.
|
* this is a good candidate for deprecation.
|
||||||
*
|
*
|
||||||
* @param {*} outStream - The stream to provide public config over.
|
* @param {*} outStream - The stream to provide public config over.
|
||||||
|
* @param {URL} senderUrl - The URL of requesting resource
|
||||||
*/
|
*/
|
||||||
setupPublicConfig (outStream, originDomain) {
|
setupPublicConfig (outStream, senderUrl) {
|
||||||
const configStore = this.createPublicConfigStore({
|
const configStore = this.createPublicConfigStore({
|
||||||
// check the providerApprovalController's approvedOrigins
|
// check the providerApprovalController's approvedOrigins
|
||||||
checkIsEnabled: () => this.providerApprovalController.shouldExposeAccounts(originDomain),
|
checkIsEnabled: () => this.providerApprovalController.shouldExposeAccounts(senderUrl.hostname),
|
||||||
})
|
})
|
||||||
const configStream = asStream(configStore)
|
const configStream = asStream(configStore)
|
||||||
|
|
||||||
|
@ -797,7 +797,7 @@ describe('MetaMaskController', function () {
|
|||||||
describe('#setupUntrustedCommunication', function () {
|
describe('#setupUntrustedCommunication', function () {
|
||||||
let streamTest
|
let streamTest
|
||||||
|
|
||||||
const phishingUrl = 'myethereumwalletntw.com'
|
const phishingUrl = new URL('http://myethereumwalletntw.com')
|
||||||
|
|
||||||
afterEach(function () {
|
afterEach(function () {
|
||||||
streamTest.end()
|
streamTest.end()
|
||||||
@ -810,7 +810,7 @@ describe('MetaMaskController', function () {
|
|||||||
|
|
||||||
streamTest = createThoughStream((chunk, _, cb) => {
|
streamTest = createThoughStream((chunk, _, cb) => {
|
||||||
if (chunk.name !== 'phishing') return cb()
|
if (chunk.name !== 'phishing') return cb()
|
||||||
assert.equal(chunk.data.hostname, phishingUrl)
|
assert.equal(chunk.data.hostname, phishingUrl.hostname)
|
||||||
resolve()
|
resolve()
|
||||||
cb()
|
cb()
|
||||||
})
|
})
|
||||||
|
@ -25,14 +25,17 @@ describe('ProviderApprovalController', () => {
|
|||||||
keyringController: mockUnlockedKeyringController,
|
keyringController: mockUnlockedKeyringController,
|
||||||
})
|
})
|
||||||
|
|
||||||
controller._handleProviderRequest('example.com', 'Example', 'https://example.com/logo.svg')
|
const metadata = {
|
||||||
|
hostname: 'https://example.com',
|
||||||
|
origin: 'example.com',
|
||||||
|
siteTitle: 'Example',
|
||||||
|
siteImage: 'https://example.com/logo.svg',
|
||||||
|
}
|
||||||
|
|
||||||
|
controller._handleProviderRequest(metadata)
|
||||||
assert.deepEqual(controller._getMergedState(), {
|
assert.deepEqual(controller._getMergedState(), {
|
||||||
approvedOrigins: {},
|
approvedOrigins: {},
|
||||||
providerRequests: [{
|
providerRequests: [metadata],
|
||||||
origin: 'example.com',
|
|
||||||
siteTitle: 'Example',
|
|
||||||
siteImage: 'https://example.com/logo.svg',
|
|
||||||
}],
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -41,14 +44,16 @@ describe('ProviderApprovalController', () => {
|
|||||||
keyringController: mockLockedKeyringController,
|
keyringController: mockLockedKeyringController,
|
||||||
})
|
})
|
||||||
|
|
||||||
controller._handleProviderRequest('example.com', 'Example', 'https://example.com/logo.svg')
|
const metadata = {
|
||||||
|
hostname: 'https://example.com',
|
||||||
|
origin: 'example.com',
|
||||||
|
siteTitle: 'Example',
|
||||||
|
siteImage: 'https://example.com/logo.svg',
|
||||||
|
}
|
||||||
|
controller._handleProviderRequest(metadata)
|
||||||
assert.deepEqual(controller._getMergedState(), {
|
assert.deepEqual(controller._getMergedState(), {
|
||||||
approvedOrigins: {},
|
approvedOrigins: {},
|
||||||
providerRequests: [{
|
providerRequests: [metadata],
|
||||||
origin: 'example.com',
|
|
||||||
siteTitle: 'Example',
|
|
||||||
siteImage: 'https://example.com/logo.svg',
|
|
||||||
}],
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -57,19 +62,23 @@ describe('ProviderApprovalController', () => {
|
|||||||
keyringController: mockUnlockedKeyringController,
|
keyringController: mockUnlockedKeyringController,
|
||||||
})
|
})
|
||||||
|
|
||||||
controller._handleProviderRequest('example1.com', 'Example 1', 'https://example1.com/logo.svg')
|
const metadata = [{
|
||||||
controller._handleProviderRequest('example2.com', 'Example 2', 'https://example2.com/logo.svg')
|
hostname: 'https://example1.com',
|
||||||
|
origin: 'example1.com',
|
||||||
|
siteTitle: 'Example 1',
|
||||||
|
siteImage: 'https://example1.com/logo.svg',
|
||||||
|
}, {
|
||||||
|
hostname: 'https://example2.com',
|
||||||
|
origin: 'example2.com',
|
||||||
|
siteTitle: 'Example 2',
|
||||||
|
siteImage: 'https://example2.com/logo.svg',
|
||||||
|
}]
|
||||||
|
|
||||||
|
controller._handleProviderRequest(metadata[0])
|
||||||
|
controller._handleProviderRequest(metadata[1])
|
||||||
assert.deepEqual(controller._getMergedState(), {
|
assert.deepEqual(controller._getMergedState(), {
|
||||||
approvedOrigins: {},
|
approvedOrigins: {},
|
||||||
providerRequests: [{
|
providerRequests: metadata,
|
||||||
origin: 'example1.com',
|
|
||||||
siteTitle: 'Example 1',
|
|
||||||
siteImage: 'https://example1.com/logo.svg',
|
|
||||||
}, {
|
|
||||||
origin: 'example2.com',
|
|
||||||
siteTitle: 'Example 2',
|
|
||||||
siteImage: 'https://example2.com/logo.svg',
|
|
||||||
}],
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -78,19 +87,23 @@ describe('ProviderApprovalController', () => {
|
|||||||
keyringController: mockLockedKeyringController,
|
keyringController: mockLockedKeyringController,
|
||||||
})
|
})
|
||||||
|
|
||||||
controller._handleProviderRequest('example1.com', 'Example 1', 'https://example1.com/logo.svg')
|
const metadata = [{
|
||||||
controller._handleProviderRequest('example2.com', 'Example 2', 'https://example2.com/logo.svg')
|
hostname: 'https://example1.com',
|
||||||
|
origin: 'example1.com',
|
||||||
|
siteTitle: 'Example 1',
|
||||||
|
siteImage: 'https://example1.com/logo.svg',
|
||||||
|
}, {
|
||||||
|
hostname: 'https://example2.com',
|
||||||
|
origin: 'example2.com',
|
||||||
|
siteTitle: 'Example 2',
|
||||||
|
siteImage: 'https://example2.com/logo.svg',
|
||||||
|
}]
|
||||||
|
|
||||||
|
controller._handleProviderRequest(metadata[0])
|
||||||
|
controller._handleProviderRequest(metadata[1])
|
||||||
assert.deepEqual(controller._getMergedState(), {
|
assert.deepEqual(controller._getMergedState(), {
|
||||||
approvedOrigins: {},
|
approvedOrigins: {},
|
||||||
providerRequests: [{
|
providerRequests: metadata,
|
||||||
origin: 'example1.com',
|
|
||||||
siteTitle: 'Example 1',
|
|
||||||
siteImage: 'https://example1.com/logo.svg',
|
|
||||||
}, {
|
|
||||||
origin: 'example2.com',
|
|
||||||
siteTitle: 'Example 2',
|
|
||||||
siteImage: 'https://example2.com/logo.svg',
|
|
||||||
}],
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -101,7 +114,13 @@ describe('ProviderApprovalController', () => {
|
|||||||
keyringController: mockUnlockedKeyringController,
|
keyringController: mockUnlockedKeyringController,
|
||||||
})
|
})
|
||||||
|
|
||||||
controller._handleProviderRequest('example.com', 'Example', 'https://example.com/logo.svg')
|
const metadata = {
|
||||||
|
hostname: 'https://example.com',
|
||||||
|
origin: 'example.com',
|
||||||
|
siteTitle: 'Example',
|
||||||
|
siteImage: 'https://example.com/logo.svg',
|
||||||
|
}
|
||||||
|
controller._handleProviderRequest(metadata)
|
||||||
assert.ok(openPopup.calledOnce)
|
assert.ok(openPopup.calledOnce)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -112,7 +131,13 @@ describe('ProviderApprovalController', () => {
|
|||||||
keyringController: mockLockedKeyringController,
|
keyringController: mockLockedKeyringController,
|
||||||
})
|
})
|
||||||
|
|
||||||
controller._handleProviderRequest('example.com', 'Example', 'https://example.com/logo.svg')
|
const metadata = {
|
||||||
|
hostname: 'https://example.com',
|
||||||
|
origin: 'example.com',
|
||||||
|
siteTitle: 'Example',
|
||||||
|
siteImage: 'https://example.com/logo.svg',
|
||||||
|
}
|
||||||
|
controller._handleProviderRequest(metadata)
|
||||||
assert.ok(openPopup.calledOnce)
|
assert.ok(openPopup.calledOnce)
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -131,7 +156,13 @@ describe('ProviderApprovalController', () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
controller._handleProviderRequest('example.com', 'Example', 'https://example.com/logo.svg')
|
const metadata = {
|
||||||
|
hostname: 'https://example.com',
|
||||||
|
origin: 'example.com',
|
||||||
|
siteTitle: 'Example',
|
||||||
|
siteImage: 'https://example.com/logo.svg',
|
||||||
|
}
|
||||||
|
controller._handleProviderRequest(metadata)
|
||||||
assert.ok(openPopup.notCalled)
|
assert.ok(openPopup.notCalled)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -142,12 +173,19 @@ describe('ProviderApprovalController', () => {
|
|||||||
keyringController: mockUnlockedKeyringController,
|
keyringController: mockUnlockedKeyringController,
|
||||||
})
|
})
|
||||||
|
|
||||||
controller._handleProviderRequest('example.com', 'Example', 'https://example.com/logo.svg')
|
const metadata = {
|
||||||
|
hostname: 'https://example.com',
|
||||||
|
origin: 'example.com',
|
||||||
|
siteTitle: 'Example',
|
||||||
|
siteImage: 'https://example.com/logo.svg',
|
||||||
|
}
|
||||||
|
controller._handleProviderRequest(metadata)
|
||||||
controller.approveProviderRequestByOrigin('example.com')
|
controller.approveProviderRequestByOrigin('example.com')
|
||||||
assert.deepEqual(controller._getMergedState(), {
|
assert.deepEqual(controller._getMergedState(), {
|
||||||
providerRequests: [],
|
providerRequests: [],
|
||||||
approvedOrigins: {
|
approvedOrigins: {
|
||||||
'example.com': {
|
'example.com': {
|
||||||
|
hostname: 'https://example.com',
|
||||||
siteTitle: 'Example',
|
siteTitle: 'Example',
|
||||||
siteImage: 'https://example.com/logo.svg',
|
siteImage: 'https://example.com/logo.svg',
|
||||||
},
|
},
|
||||||
@ -160,13 +198,20 @@ describe('ProviderApprovalController', () => {
|
|||||||
keyringController: mockUnlockedKeyringController,
|
keyringController: mockUnlockedKeyringController,
|
||||||
})
|
})
|
||||||
|
|
||||||
controller._handleProviderRequest('example.com', 'Example', 'https://example.com/logo.svg')
|
const metadata = {
|
||||||
controller._handleProviderRequest('example.com', 'Example', 'https://example.com/logo.svg')
|
hostname: 'https://example.com',
|
||||||
|
origin: 'example.com',
|
||||||
|
siteTitle: 'Example',
|
||||||
|
siteImage: 'https://example.com/logo.svg',
|
||||||
|
}
|
||||||
|
controller._handleProviderRequest(metadata)
|
||||||
|
controller._handleProviderRequest(metadata)
|
||||||
controller.approveProviderRequestByOrigin('example.com')
|
controller.approveProviderRequestByOrigin('example.com')
|
||||||
assert.deepEqual(controller._getMergedState(), {
|
assert.deepEqual(controller._getMergedState(), {
|
||||||
providerRequests: [],
|
providerRequests: [],
|
||||||
approvedOrigins: {
|
approvedOrigins: {
|
||||||
'example.com': {
|
'example.com': {
|
||||||
|
hostname: 'https://example.com',
|
||||||
siteTitle: 'Example',
|
siteTitle: 'Example',
|
||||||
siteImage: 'https://example.com/logo.svg',
|
siteImage: 'https://example.com/logo.svg',
|
||||||
},
|
},
|
||||||
@ -184,6 +229,7 @@ describe('ProviderApprovalController', () => {
|
|||||||
providerRequests: [],
|
providerRequests: [],
|
||||||
approvedOrigins: {
|
approvedOrigins: {
|
||||||
'example.com': {
|
'example.com': {
|
||||||
|
hostname: null,
|
||||||
siteTitle: null,
|
siteTitle: null,
|
||||||
siteImage: null,
|
siteImage: null,
|
||||||
},
|
},
|
||||||
@ -198,7 +244,13 @@ describe('ProviderApprovalController', () => {
|
|||||||
keyringController: mockUnlockedKeyringController,
|
keyringController: mockUnlockedKeyringController,
|
||||||
})
|
})
|
||||||
|
|
||||||
controller._handleProviderRequest('example.com', 'Example', 'https://example.com/logo.svg')
|
const metadata = {
|
||||||
|
hostname: 'https://example.com',
|
||||||
|
origin: 'example.com',
|
||||||
|
siteTitle: 'Example',
|
||||||
|
siteImage: 'https://example.com/logo.svg',
|
||||||
|
}
|
||||||
|
controller._handleProviderRequest(metadata)
|
||||||
controller.approveProviderRequestByOrigin('example.com')
|
controller.approveProviderRequestByOrigin('example.com')
|
||||||
controller.rejectProviderRequestByOrigin('example.com')
|
controller.rejectProviderRequestByOrigin('example.com')
|
||||||
assert.deepEqual(controller._getMergedState(), {
|
assert.deepEqual(controller._getMergedState(), {
|
||||||
@ -226,7 +278,13 @@ describe('ProviderApprovalController', () => {
|
|||||||
keyringController: mockUnlockedKeyringController,
|
keyringController: mockUnlockedKeyringController,
|
||||||
})
|
})
|
||||||
|
|
||||||
controller._handleProviderRequest('example.com', 'Example', 'https://example.com/logo.svg')
|
const metadata = {
|
||||||
|
hostname: 'https://example.com',
|
||||||
|
origin: 'example.com',
|
||||||
|
siteTitle: 'Example',
|
||||||
|
siteImage: 'https://example.com/logo.svg',
|
||||||
|
}
|
||||||
|
controller._handleProviderRequest(metadata)
|
||||||
controller.approveProviderRequestByOrigin('example.com')
|
controller.approveProviderRequestByOrigin('example.com')
|
||||||
controller.clearApprovedOrigins()
|
controller.clearApprovedOrigins()
|
||||||
assert.deepEqual(controller._getMergedState(), {
|
assert.deepEqual(controller._getMergedState(), {
|
||||||
@ -242,7 +300,13 @@ describe('ProviderApprovalController', () => {
|
|||||||
keyringController: mockUnlockedKeyringController,
|
keyringController: mockUnlockedKeyringController,
|
||||||
})
|
})
|
||||||
|
|
||||||
controller._handleProviderRequest('example.com', 'Example', 'https://example.com/logo.svg')
|
const metadata = {
|
||||||
|
hostname: 'https://example.com',
|
||||||
|
origin: 'example.com',
|
||||||
|
siteTitle: 'Example',
|
||||||
|
siteImage: 'https://example.com/logo.svg',
|
||||||
|
}
|
||||||
|
controller._handleProviderRequest(metadata)
|
||||||
controller.approveProviderRequestByOrigin('example.com')
|
controller.approveProviderRequestByOrigin('example.com')
|
||||||
assert.ok(controller.shouldExposeAccounts('example.com'))
|
assert.ok(controller.shouldExposeAccounts('example.com'))
|
||||||
})
|
})
|
||||||
@ -252,7 +316,13 @@ describe('ProviderApprovalController', () => {
|
|||||||
keyringController: mockUnlockedKeyringController,
|
keyringController: mockUnlockedKeyringController,
|
||||||
})
|
})
|
||||||
|
|
||||||
controller._handleProviderRequest('example.com', 'Example', 'https://example.com/logo.svg')
|
const metadata = {
|
||||||
|
hostname: 'https://example.com',
|
||||||
|
origin: 'example.com',
|
||||||
|
siteTitle: 'Example',
|
||||||
|
siteImage: 'https://example.com/logo.svg',
|
||||||
|
}
|
||||||
|
controller._handleProviderRequest(metadata)
|
||||||
controller.approveProviderRequestByOrigin('example.com')
|
controller.approveProviderRequestByOrigin('example.com')
|
||||||
assert.ok(!controller.shouldExposeAccounts('bad.website'))
|
assert.ok(!controller.shouldExposeAccounts('bad.website'))
|
||||||
})
|
})
|
||||||
|
@ -7,15 +7,17 @@ export default class ProviderPageContainerContent extends PureComponent {
|
|||||||
origin: PropTypes.string.isRequired,
|
origin: PropTypes.string.isRequired,
|
||||||
selectedIdentity: PropTypes.object.isRequired,
|
selectedIdentity: PropTypes.object.isRequired,
|
||||||
siteImage: PropTypes.string,
|
siteImage: PropTypes.string,
|
||||||
siteTitle: PropTypes.string.isRequired,
|
siteTitle: PropTypes.string,
|
||||||
|
hostname: PropTypes.string,
|
||||||
|
extensionId: PropTypes.string,
|
||||||
}
|
}
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
t: PropTypes.func,
|
t: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
renderConnectVisual = () => {
|
renderConnectVisual = (title, identifier) => {
|
||||||
const { origin, selectedIdentity, siteImage, siteTitle } = this.props
|
const { selectedIdentity, siteImage } = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="provider-approval-visual">
|
<div className="provider-approval-visual">
|
||||||
@ -27,11 +29,11 @@ export default class ProviderPageContainerContent extends PureComponent {
|
|||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<i className="provider-approval-visual__identicon--default">
|
<i className="provider-approval-visual__identicon--default">
|
||||||
{siteTitle.charAt(0).toUpperCase()}
|
{title.charAt(0).toUpperCase()}
|
||||||
</i>
|
</i>
|
||||||
)}
|
)}
|
||||||
<h1>{siteTitle}</h1>
|
<h1>{title}</h1>
|
||||||
<h2>{origin}</h2>
|
<h2>{identifier}</h2>
|
||||||
</section>
|
</section>
|
||||||
<span className="provider-approval-visual__check" />
|
<span className="provider-approval-visual__check" />
|
||||||
<section>
|
<section>
|
||||||
@ -47,15 +49,23 @@ export default class ProviderPageContainerContent extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const { siteTitle } = this.props
|
const { siteTitle, hostname, extensionId } = this.props
|
||||||
const { t } = this.context
|
const { t } = this.context
|
||||||
|
|
||||||
|
const title = extensionId ?
|
||||||
|
'External Extension' :
|
||||||
|
siteTitle || hostname
|
||||||
|
|
||||||
|
const identifier = extensionId ?
|
||||||
|
`Extension ID: '${extensionId}'` :
|
||||||
|
hostname
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="provider-approval-container__content">
|
<div className="provider-approval-container__content">
|
||||||
<section>
|
<section>
|
||||||
<h2>{t('connectRequest')}</h2>
|
<h2>{t('connectRequest')}</h2>
|
||||||
{this.renderConnectVisual()}
|
{this.renderConnectVisual(title, identifier)}
|
||||||
<h1>{t('providerRequest', [siteTitle])}</h1>
|
<h1>{t('providerRequest', [title])}</h1>
|
||||||
<p>
|
<p>
|
||||||
{t('providerRequestInfo')}
|
{t('providerRequestInfo')}
|
||||||
<br/>
|
<br/>
|
||||||
|
@ -9,7 +9,9 @@ export default class ProviderPageContainer extends PureComponent {
|
|||||||
rejectProviderRequestByOrigin: PropTypes.func.isRequired,
|
rejectProviderRequestByOrigin: PropTypes.func.isRequired,
|
||||||
origin: PropTypes.string.isRequired,
|
origin: PropTypes.string.isRequired,
|
||||||
siteImage: PropTypes.string,
|
siteImage: PropTypes.string,
|
||||||
siteTitle: PropTypes.string.isRequired,
|
siteTitle: PropTypes.string,
|
||||||
|
hostname: PropTypes.string,
|
||||||
|
extensionId: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
@ -52,7 +54,7 @@ export default class ProviderPageContainer extends PureComponent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render () {
|
render () {
|
||||||
const {origin, siteImage, siteTitle} = this.props
|
const {origin, siteImage, siteTitle, hostname, extensionId} = this.props
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="page-container provider-approval-container">
|
<div className="page-container provider-approval-container">
|
||||||
@ -61,6 +63,8 @@ export default class ProviderPageContainer extends PureComponent {
|
|||||||
origin={origin}
|
origin={origin}
|
||||||
siteImage={siteImage}
|
siteImage={siteImage}
|
||||||
siteTitle={siteTitle}
|
siteTitle={siteTitle}
|
||||||
|
hostname={hostname}
|
||||||
|
extensionId={extensionId}
|
||||||
/>
|
/>
|
||||||
<PageContainerFooter
|
<PageContainerFooter
|
||||||
onCancel={() => this.onCancel()}
|
onCancel={() => this.onCancel()}
|
||||||
|
@ -67,7 +67,7 @@ const customDimensionsNameIdMap = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function composeUrlRefParamAddition (previousPath, confirmTransactionOrigin) {
|
function composeUrlRefParamAddition (previousPath, confirmTransactionOrigin) {
|
||||||
const externalOrigin = confirmTransactionOrigin && confirmTransactionOrigin !== 'MetaMask'
|
const externalOrigin = confirmTransactionOrigin && confirmTransactionOrigin !== 'metamask'
|
||||||
return `&urlref=${externalOrigin ? 'EXTERNAL' : encodeURIComponent(previousPath.replace(/chrome-extension:\/\/\w+/, METAMETRICS_TRACKING_URL))}`
|
return `&urlref=${externalOrigin ? 'EXTERNAL' : encodeURIComponent(previousPath.replace(/chrome-extension:\/\/\w+/, METAMETRICS_TRACKING_URL))}`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,8 @@ export default class ProviderApproval extends Component {
|
|||||||
tabID={providerRequest.tabID}
|
tabID={providerRequest.tabID}
|
||||||
siteImage={providerRequest.siteImage}
|
siteImage={providerRequest.siteImage}
|
||||||
siteTitle={providerRequest.siteTitle}
|
siteTitle={providerRequest.siteTitle}
|
||||||
|
hostname={providerRequest.hostname}
|
||||||
|
extensionId={providerRequest.extensionId}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user