mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-12-23 09:52:26 +01:00
wiring - trusted-untrusted features + remote-store
This commit is contained in:
parent
907e39e5ab
commit
d840e81a10
@ -9,8 +9,8 @@ const MetaMaskProvider = require('./lib/zero.js')
|
||||
const IdentityStore = require('./lib/idStore')
|
||||
const createTxNotification = require('./lib/tx-notification.js')
|
||||
const configManager = require('./lib/config-manager-singleton')
|
||||
const jsonParseStream = require('./lib/stream-utils.js').jsonParseStream
|
||||
const jsonStringifyStream = require('./lib/stream-utils.js').jsonStringifyStream
|
||||
const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex
|
||||
const HostStore = require('./lib/remote-store.js').HostStore
|
||||
|
||||
//
|
||||
// connect to other contexts
|
||||
@ -22,15 +22,27 @@ function connectRemote(remotePort){
|
||||
var portStream = new PortStream(remotePort)
|
||||
if (isMetaMaskInternalProcess) {
|
||||
// communication with popup
|
||||
handleInternalCommunication(portStream)
|
||||
setupTrustedCommunication(portStream)
|
||||
} else {
|
||||
// communication with page
|
||||
handleEthRpcRequestStream(portStream)
|
||||
setupUntrustedCommunication(portStream)
|
||||
}
|
||||
}
|
||||
|
||||
function handleEthRpcRequestStream(stream){
|
||||
stream.on('data', onRpcRequest.bind(null, stream))
|
||||
function setupUntrustedCommunication(connectionStream){
|
||||
// setup multiplexing
|
||||
var mx = setupMultiplex(connectionStream)
|
||||
// connect features
|
||||
setupProviderConnection(mx.createStream('provider'))
|
||||
setupPublicConfig(mx.createStream('publicConfig'))
|
||||
}
|
||||
|
||||
function setupTrustedCommunication(connectionStream){
|
||||
// setup multiplexing
|
||||
var mx = setupMultiplex(connectionStream)
|
||||
// connect features
|
||||
setupControllerConnection(mx.createStream('controller'))
|
||||
setupProviderConnection(mx.createStream('provider'))
|
||||
}
|
||||
|
||||
//
|
||||
@ -59,6 +71,13 @@ provider.on('block', function(block){
|
||||
var ethStore = new EthStore(provider)
|
||||
idStore.setStore(ethStore)
|
||||
|
||||
// copy idStore substate into public store
|
||||
var publicConfigStore = new HostStore()
|
||||
idStore.on('update', function(state){
|
||||
publicConfigStore.set('selectedAddress', state.selectedAddress)
|
||||
})
|
||||
|
||||
|
||||
function getState(){
|
||||
var state = extend(
|
||||
ethStore.getState(),
|
||||
@ -84,27 +103,20 @@ function onRpcRequest(remoteStream, payload){
|
||||
|
||||
|
||||
//
|
||||
// popup integration
|
||||
// remote features
|
||||
//
|
||||
|
||||
function handleInternalCommunication(portStream){
|
||||
// setup multiplexing
|
||||
var mx = ObjectMultiplex()
|
||||
portStream.pipe(mx).pipe(portStream)
|
||||
mx.on('error', function(err) {
|
||||
console.error(err)
|
||||
// portStream.destroy()
|
||||
})
|
||||
portStream.on('error', function(err) {
|
||||
console.error(err)
|
||||
mx.destroy()
|
||||
})
|
||||
linkDnode(mx.createStream('dnode'))
|
||||
handleEthRpcRequestStream(mx.createStream('provider'))
|
||||
function setupPublicConfig(stream){
|
||||
var storeStream = publicConfigStore.createStream()
|
||||
stream.pipe(storeStream).pipe(stream)
|
||||
}
|
||||
|
||||
function linkDnode(stream){
|
||||
var connection = Dnode({
|
||||
function setupProviderConnection(stream){
|
||||
stream.on('data', onRpcRequest.bind(null, stream))
|
||||
}
|
||||
|
||||
function setupControllerConnection(stream){
|
||||
var dnode = Dnode({
|
||||
getState: function(cb){ cb(null, getState()) },
|
||||
setRpcTarget: setRpcTarget,
|
||||
useEtherscanProvider: useEtherscanProvider,
|
||||
@ -119,8 +131,8 @@ function linkDnode(stream){
|
||||
clearSeedWordCache: idStore.clearSeedWordCache.bind(idStore),
|
||||
exportAccount: idStore.exportAccount.bind(idStore),
|
||||
})
|
||||
stream.pipe(connection).pipe(stream)
|
||||
connection.on('remote', function(remote){
|
||||
stream.pipe(dnode).pipe(stream)
|
||||
dnode.on('remote', function(remote){
|
||||
|
||||
// push updates to popup
|
||||
ethStore.on('update', sendUpdate)
|
||||
|
@ -1,13 +1,13 @@
|
||||
const XHR = window.XMLHttpRequest
|
||||
|
||||
// bring in web3 but rename on window
|
||||
const Web3 = require('web3')
|
||||
delete window.Web3
|
||||
window.MetamaskWeb3 = Web3
|
||||
|
||||
const createPayload = require('web3-provider-engine/util/create-payload')
|
||||
const StreamProvider = require('./lib/stream-provider.js')
|
||||
const LocalMessageDuplexStream = require('./lib/local-message-stream.js')
|
||||
const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex
|
||||
const RemoteStore = require('./lib/remote-store.js').RemoteStore
|
||||
const Web3 = require('web3')
|
||||
|
||||
// rename on window
|
||||
delete window.Web3
|
||||
window.MetamaskWeb3 = Web3
|
||||
|
||||
const RPC_URL = 'https://testrpc.metamask.io/'
|
||||
|
||||
@ -16,16 +16,26 @@ const RPC_URL = 'https://testrpc.metamask.io/'
|
||||
// setup plugin communication
|
||||
//
|
||||
|
||||
// setup background connection
|
||||
var pluginStream = new LocalMessageDuplexStream({
|
||||
name: 'inpage',
|
||||
target: 'contentscript',
|
||||
})
|
||||
var mx = setupMultiplex(pluginStream)
|
||||
// connect features
|
||||
var remoteProvider = new StreamProvider()
|
||||
remoteProvider.pipe(pluginStream).pipe(remoteProvider)
|
||||
|
||||
pluginStream.on('error', console.error.bind(console))
|
||||
remoteProvider.pipe(mx.createStream('provider')).pipe(remoteProvider)
|
||||
remoteProvider.on('error', console.error.bind(console))
|
||||
|
||||
var publicConfigStore = new RemoteStore()
|
||||
var storeStream = publicConfigStore.createStream()
|
||||
storeStream.pipe(mx.createStream('publicConfig')).pipe(storeStream)
|
||||
|
||||
publicConfigStore.subscribe(function(state){
|
||||
console.log('store updated:', state)
|
||||
})
|
||||
|
||||
|
||||
//
|
||||
// global web3
|
||||
//
|
||||
|
@ -11,7 +11,7 @@ function ObjectMultiplex(opts){
|
||||
var data = chunk.data
|
||||
var substream = mx.streams[name]
|
||||
if (!substream) {
|
||||
console.warn("orphaned data for stream " + name)
|
||||
console.warn('orphaned data for stream ' + name)
|
||||
} else {
|
||||
substream.push(data)
|
||||
}
|
||||
|
97
app/scripts/lib/remote-store.js
Normal file
97
app/scripts/lib/remote-store.js
Normal file
@ -0,0 +1,97 @@
|
||||
const Dnode = require('dnode')
|
||||
const inherits = require('util').inherits
|
||||
|
||||
module.exports = {
|
||||
HostStore: HostStore,
|
||||
RemoteStore: RemoteStore,
|
||||
}
|
||||
|
||||
function BaseStore(initState){
|
||||
this._state = initState || {}
|
||||
this._subs = []
|
||||
}
|
||||
|
||||
BaseStore.prototype.set = function(key, value){
|
||||
throw Error('Not implemented.')
|
||||
}
|
||||
|
||||
BaseStore.prototype.get = function(key){
|
||||
return this._state[key]
|
||||
}
|
||||
|
||||
BaseStore.prototype.subscribe = function(fn){
|
||||
this._subs.push(fn)
|
||||
var unsubscribe = this.unsubscribe.bind(this, fn)
|
||||
return unsubscribe
|
||||
}
|
||||
|
||||
BaseStore.prototype.unsubscribe = function(fn){
|
||||
var index = this._subs.indexOf(fn)
|
||||
if (index !== -1) this._subs.splice(index, 1)
|
||||
}
|
||||
|
||||
BaseStore.prototype._emitUpdates = function(state){
|
||||
this._subs.forEach(function(handler){
|
||||
handler(state)
|
||||
})
|
||||
}
|
||||
|
||||
//
|
||||
// host
|
||||
//
|
||||
|
||||
inherits(HostStore, BaseStore)
|
||||
function HostStore(initState, opts){
|
||||
BaseStore.call(this, initState)
|
||||
}
|
||||
|
||||
HostStore.prototype.set = function(key, value){
|
||||
this._state[key] = value
|
||||
process.nextTick(this._emitUpdates.bind(this, this._state))
|
||||
}
|
||||
|
||||
HostStore.prototype.createStream = function(){
|
||||
var dnode = Dnode({
|
||||
// update: this._didUpdate.bind(this),
|
||||
})
|
||||
dnode.on('remote', this._didConnect.bind(this))
|
||||
return dnode
|
||||
}
|
||||
|
||||
HostStore.prototype._didConnect = function(remote){
|
||||
this.subscribe(function(state){
|
||||
remote.update(state)
|
||||
})
|
||||
remote.update(this._state)
|
||||
}
|
||||
|
||||
//
|
||||
// remote
|
||||
//
|
||||
|
||||
inherits(RemoteStore, BaseStore)
|
||||
function RemoteStore(initState, opts){
|
||||
BaseStore.call(this, initState)
|
||||
this._remote = null
|
||||
}
|
||||
|
||||
RemoteStore.prototype.set = function(key, value){
|
||||
this._remote.set(key, value)
|
||||
}
|
||||
|
||||
RemoteStore.prototype.createStream = function(){
|
||||
var dnode = Dnode({
|
||||
update: this._didUpdate.bind(this),
|
||||
})
|
||||
dnode.once('remote', this._didConnect.bind(this))
|
||||
return dnode
|
||||
}
|
||||
|
||||
RemoteStore.prototype._didConnect = function(remote){
|
||||
this._remote = remote
|
||||
}
|
||||
|
||||
RemoteStore.prototype._didUpdate = function(state){
|
||||
this._state = state
|
||||
this._emitUpdates(state)
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
const Through = require('through2')
|
||||
const ObjectMultiplex = require('./obj-multiplex')
|
||||
|
||||
|
||||
module.exports = {
|
||||
jsonParseStream: jsonParseStream,
|
||||
jsonStringifyStream: jsonStringifyStream,
|
||||
setupMultiplex: setupMultiplex,
|
||||
}
|
||||
|
||||
function jsonParseStream(){
|
||||
@ -19,3 +21,17 @@ function jsonStringifyStream(){
|
||||
cb()
|
||||
})
|
||||
}
|
||||
|
||||
function setupMultiplex(connectionStream){
|
||||
var mx = ObjectMultiplex()
|
||||
connectionStream.pipe(mx).pipe(connectionStream)
|
||||
mx.on('error', function(err) {
|
||||
console.error(err)
|
||||
// connectionStream.destroy()
|
||||
})
|
||||
connectionStream.on('error', function(err) {
|
||||
console.error(err)
|
||||
mx.destroy()
|
||||
})
|
||||
return mx
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
const url = require('url')
|
||||
const EventEmitter = require('events').EventEmitter
|
||||
const async = require('async')
|
||||
const ObjectMultiplex = require('./lib/obj-multiplex')
|
||||
const Dnode = require('dnode')
|
||||
const Web3 = require('web3')
|
||||
const MetaMaskUi = require('../../ui')
|
||||
@ -9,6 +8,7 @@ const MetaMaskUiCss = require('../../ui/css')
|
||||
const injectCss = require('inject-css')
|
||||
const PortStream = require('./lib/port-stream.js')
|
||||
const StreamProvider = require('./lib/stream-provider.js')
|
||||
const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex
|
||||
|
||||
// setup app
|
||||
var css = MetaMaskUiCss()
|
||||
@ -24,21 +24,13 @@ function connectToAccountManager(cb){
|
||||
var pluginPort = chrome.runtime.connect({name: 'popup'})
|
||||
var portStream = new PortStream(pluginPort)
|
||||
// setup multiplexing
|
||||
var mx = ObjectMultiplex()
|
||||
portStream.pipe(mx).pipe(portStream)
|
||||
mx.on('error', function(err) {
|
||||
console.error(err)
|
||||
portStream.destroy()
|
||||
})
|
||||
portStream.on('error', function(err) {
|
||||
console.error(err)
|
||||
mx.destroy()
|
||||
})
|
||||
linkDnode(mx.createStream('dnode'), cb)
|
||||
linkWeb3(mx.createStream('provider'))
|
||||
var mx = setupMultiplex(portStream)
|
||||
// connect features
|
||||
setupControllerConnection(mx.createStream('controller'), cb)
|
||||
setupWeb3Connection(mx.createStream('provider'))
|
||||
}
|
||||
|
||||
function linkWeb3(stream){
|
||||
function setupWeb3Connection(stream){
|
||||
var remoteProvider = new StreamProvider()
|
||||
remoteProvider.pipe(stream).pipe(remoteProvider)
|
||||
stream.on('error', console.error.bind(console))
|
||||
@ -46,7 +38,7 @@ function linkWeb3(stream){
|
||||
global.web3 = new Web3(remoteProvider)
|
||||
}
|
||||
|
||||
function linkDnode(stream, cb){
|
||||
function setupControllerConnection(stream, cb){
|
||||
var eventEmitter = new EventEmitter()
|
||||
var background = Dnode({
|
||||
sendUpdate: function(state){
|
||||
|
Loading…
Reference in New Issue
Block a user