From 79248ae5cd3fb1314c5a7ff71c05f9dbe7b3a4cd Mon Sep 17 00:00:00 2001 From: frankiebee Date: Tue, 28 Mar 2017 18:02:08 -0700 Subject: [PATCH] WIP: Untrusted external connections eg: dapps --- library/controller.js | 190 ++++++++++++++++++++-- library/example/index.js | 4 +- library/index.js | 2 + library/lib/setup-provider.js | 1 - library/lib/setup-untrusted-connection.js | 27 +++ library/popup.js | 2 + library/sw-controller.js | 20 +-- library/sw-core.js | 25 +-- package.json | 2 +- 9 files changed, 220 insertions(+), 53 deletions(-) create mode 100644 library/lib/setup-untrusted-connection.js diff --git a/library/controller.js b/library/controller.js index f0aa7172c..cbba9584a 100644 --- a/library/controller.js +++ b/library/controller.js @@ -1,13 +1,181 @@ -// const SWcontroller = require('./sw-controller') -// const SwStream = require('sw-stream/lib/sw-stream.js') -// const startPopup = require('../app/scripts/popup-core') +const ParentStream = require('iframe-stream').ParentStream +const SWcontroller = require('./sw-controller') +const SwStream = require('sw-stream/lib/sw-stream.js') +const SetupUntrustedComunication = ('./lib/setup-untrusted-connection.js') +const background = new SWcontroller({ + fileName: '/popup/sw-build.js', +}) + +background.on('ready', (readSw) => { + // var inpageProvider = new MetamaskInpageProvider(SwStream(background.controller)) + let pageStream = new ParentStream() + let swStream = SwStream(background.controller) + pageStream.pipe(swStream).pipe(pageStream) +}) + +background.on('error', console.error) +background.startWorker() -// console.log('outside:open') -// const background = new SWcontroller({ -// fileName: 'sw-build.js', -// }) -// background.on('ready', (readSw) => { -// startPopup(SwStream(background.controller)) -// }) -// background.startWorker() console.log('hello from controller') +/* +const urlUtil = require('url') +const extend = require('xtend') +const Dnode = require('dnode') +const eos = require('end-of-stream') +const ParentStream = require('iframe-stream').ParentStream +const PortStream = require('../app/scripts/lib/port-stream.js') +const notification = require('../app/scripts/lib/notifications.js') +const messageManager = require('../app/scripts/lib/message-manager') +const setupMultiplex = require('../app/scripts/lib/stream-utils.js').setupMultiplex +const MetamaskController = require('../app/scripts/metamask-controller') +const extension = require('../app/scripts/lib/extension') + +const STORAGE_KEY = 'metamask-config' + + +initializeZeroClient() + +function initializeZeroClient() { + + const controller = new MetamaskController({ + // User confirmation callbacks: + showUnconfirmedMessage, + unlockAccountMessage, + showUnapprovedTx, + // Persistence Methods: + setData, + loadData, + }) + const idStore = controller.idStore + + function unlockAccountMessage () { + console.log('notif stub - unlockAccountMessage') + } + + function showUnconfirmedMessage (msgParams, msgId) { + console.log('notif stub - showUnconfirmedMessage') + } + + function showUnapprovedTx (txParams, txData, onTxDoneCb) { + console.log('notif stub - showUnapprovedTx') + } + + // + // connect to other contexts + // + + var connectionStream = new ParentStream() + + connectRemote(connectionStream, getParentHref()) + + function connectRemote (connectionStream, originDomain) { + var isMetaMaskInternalProcess = (originDomain === '127.0.0.1:9001') + if (isMetaMaskInternalProcess) { + // communication with popup + setupTrustedCommunication(connectionStream, 'MetaMask') + } else { + // communication with page + setupUntrustedCommunication(connectionStream, originDomain) + } + } + + function setupUntrustedCommunication (connectionStream, originDomain) { + // setup multiplexing + var mx = setupMultiplex(connectionStream) + // connect features + controller.setupProviderConnection(mx.createStream('provider'), originDomain) + controller.setupPublicConfig(mx.createStream('publicConfig')) + } + + function setupTrustedCommunication (connectionStream, originDomain) { + // setup multiplexing + var mx = setupMultiplex(connectionStream) + // connect features + setupControllerConnection(mx.createStream('controller')) + controller.setupProviderConnection(mx.createStream('provider'), originDomain) + } + + // + // remote features + // + + function setupControllerConnection (stream) { + controller.stream = stream + var api = controller.getApi() + var dnode = Dnode(api) + stream.pipe(dnode).pipe(stream) + dnode.on('remote', (remote) => { + // push updates to popup + controller.ethStore.on('update', controller.sendUpdate.bind(controller)) + controller.listeners.push(remote) + idStore.on('update', controller.sendUpdate.bind(controller)) + + // teardown on disconnect + eos(stream, () => { + controller.ethStore.removeListener('update', controller.sendUpdate.bind(controller)) + }) + }) + } + + function loadData () { + var oldData = getOldStyleData() + var newData + try { + newData = JSON.parse(window.localStorage[STORAGE_KEY]) + } catch (e) {} + + var data = extend({ + meta: { + version: 0, + }, + data: { + config: { + provider: { + type: 'testnet', + }, + }, + }, + }, oldData || null, newData || null) + return data + } + + function getOldStyleData () { + var config, wallet, seedWords + + var result = { + meta: { version: 0 }, + data: {}, + } + + try { + config = JSON.parse(window.localStorage['config']) + result.data.config = config + } catch (e) {} + try { + wallet = JSON.parse(window.localStorage['lightwallet']) + result.data.wallet = wallet + } catch (e) {} + try { + seedWords = window.localStorage['seedWords'] + result.data.seedWords = seedWords + } catch (e) {} + + return result + } + + function setData (data) { + window.localStorage[STORAGE_KEY] = JSON.stringify(data) + } + + function getParentHref(){ + try { + var parentLocation = window.parent.location + return parentLocation.hostname + ':' + parentLocation.port + } catch (err) { + return 'unknown' + } + } + +} + +*/ diff --git a/library/example/index.js b/library/example/index.js index 4a107df6a..329302a4d 100644 --- a/library/example/index.js +++ b/library/example/index.js @@ -1,4 +1,3 @@ - window.addEventListener('load', web3Detect) function web3Detect() { @@ -18,6 +17,7 @@ function startApp(){ web3.eth.getAccounts(function(err, addresses){ if (err) throw err console.log('set address', addresses[0]) + debugger primaryAccount = addresses[0] }) @@ -53,4 +53,4 @@ function startApp(){ function logToDom(message){ document.body.appendChild(document.createTextNode(message)) console.log(message) -} \ No newline at end of file +} diff --git a/library/index.js b/library/index.js index af82c6546..44ee401d8 100644 --- a/library/index.js +++ b/library/index.js @@ -41,3 +41,5 @@ function hijackProvider(provider){ _super(payload, cb) } } + + diff --git a/library/lib/setup-provider.js b/library/lib/setup-provider.js index 9efd209cb..68be99c9e 100644 --- a/library/lib/setup-provider.js +++ b/library/lib/setup-provider.js @@ -22,4 +22,3 @@ function getProvider(){ return inpageProvider } - diff --git a/library/lib/setup-untrusted-connection.js b/library/lib/setup-untrusted-connection.js new file mode 100644 index 000000000..b2aeb7905 --- /dev/null +++ b/library/lib/setup-untrusted-connection.js @@ -0,0 +1,27 @@ + +/* +IFRAME + var pageStream = new LocalMessageDuplexStream({ + name: 'contentscript', + target: 'inpage', + }) +SERVICEWORKER + pageStream.on('error', console.error) + var pluginPort = extension.runtime.connect({name: 'contentscript'}) + var pluginStream = new PortStream(pluginPort) + pluginStream.on('error', console.error) +IFRAME --> SW + // forward communication plugin->inpage + pageStream.pipe(pluginStream).pipe(pageStream) +*/ + +module.exports = SetupUntrustedComunicationWithSW + +function SetupUntrustedComunicationWithSW (connectionStream, readySwStream) { + pageStream.on('error', console.error) + var pluginPort = extension.runtime.connect({name: 'contentscript'}) + var pluginStream = new PortStream(pluginPort) + pluginStream.on('error', console.error) + // forward communication plugin->inpage + pageStream.pipe(pluginStream).pipe(pageStream) +} diff --git a/library/popup.js b/library/popup.js index 3825661cf..d956dc0b1 100644 --- a/library/popup.js +++ b/library/popup.js @@ -19,6 +19,7 @@ var iframeStream = setupIframe({ container: document.body, }) console.log('outside:open') + const background = new SWcontroller({ fileName: '/popup/sw-build.js', }) @@ -27,5 +28,6 @@ background.on('ready', (readSw) => { // startPopup(inpageProvider) startPopup(SwStream(background.controller)) }) +background.on('message', (messageEvent) => {debugger}) background.startWorker() console.log('hello from /library/popup.js') diff --git a/library/sw-controller.js b/library/sw-controller.js index 23d67026e..1a7b1cad3 100644 --- a/library/sw-controller.js +++ b/library/sw-controller.js @@ -7,22 +7,10 @@ module.exports = class ClientSideServiceWorker extends EventEmitter{ this.startDelay = opts.startDelay this.serviceWorkerApi = navigator.serviceWorker - this.serviceWorkerApi.onmessage = (event) => this.emit('message', event) - this.serviceWorkerApi.onerror = (event) => this.emit('error') - - // temporary function - this.askForId = (message) => { - this.sendMessage('check-in') - .then((data) => console.log(`${message}----${data}`)) - } - - // if (!!this.serviceWorkerApi) this.askForId('before') - + this.serviceWorkerApi.onmessage = (messageEvent) => this.emit('message', messageEvent) + this.serviceWorkerApi.onerror = (err) => this.emit('error', err) + this.on('message', (messageEvent) => {debugger}) if (opts.initStart) this.startWorker() - - this.on('ready', (sw) => { - this.askForId('ready') - }) } get controller () { @@ -34,7 +22,6 @@ module.exports = class ClientSideServiceWorker extends EventEmitter{ return this.registerWorker() .then((sw) => { this.sw = sw - this.askForId('after register:') this.sw.onerror = (err) => this.emit('error', err) this.sw = sw this.emit('ready', this.sw) @@ -46,7 +33,6 @@ module.exports = class ClientSideServiceWorker extends EventEmitter{ return this.serviceWorkerApi.register(this.fileName) .then((registerdWorker) => { return new Promise((resolve, reject) => { - this.askForId('after') let timeOutId = setTimeout(() => { if (this.serviceWorkerApi.controller) return resolve(this.serviceWorkerApi.controller) if (registerdWorker.active) return resolve(registerdWorker.active) diff --git a/library/sw-core.js b/library/sw-core.js index 46ef95e21..1d31b2acd 100644 --- a/library/sw-core.js +++ b/library/sw-core.js @@ -1,7 +1,4 @@ global.window = global -const SWGlobal = self -const urlUtil = require('url') -const endOfStream = require('end-of-stream') const asyncQ = require('async-q') const pipe = require('pump') @@ -14,7 +11,7 @@ const PortStream = require('../app/scripts/lib/port-stream.js') const DbController = require('./controllers/index-db-controller') const MetamaskController = require('../app/scripts/metamask-controller') -// const extension = require('../app/scripts/lib/extension') +const extension = {} //require('../app/scripts/lib/extension') // const LocalStorageStore = require('obs-store/lib/localStorage') const storeTransform = require('obs-store/lib/transform') const Migrator = require('../app/scripts/lib/migrator/') @@ -36,20 +33,6 @@ self.addEventListener('activate', function(event) { event.waitUntil(self.clients.claim()) }) -self.onsync = function (syncEvent) { -// What is done when a sync even is fired - console.log('inside:sync') - var focused - self.clients.matchAll() - .then(clients => { - clients.forEach(function(client) { - - }) - }) -} - - - console.log('inside:open') @@ -117,8 +100,6 @@ function setupController (initState, client) { .catch((err) => {console.error(err)}) }) function versionifyData(state) { - // let versionedData - // versionedData.data = state return dbController.get() .then((rawData) => { return Promise.resolve({ @@ -143,6 +124,7 @@ function setupController (initState, client) { if (isMetaMaskInternalProcess) { // communication with popup controller.setupTrustedCommunication(connectionStream, 'MetaMask') + popupIsOpen = true } else { // communication with page setupUntrustedCommunication(connectionStream, originDomain) @@ -175,6 +157,7 @@ function setupController (initState, client) { // // // // // // popup trigger + +/*send a message to the client that has focus and tell it to open a window*/ function triggerUi () { - if (!popupIsOpen) notification.show() } diff --git a/package.json b/package.json index c08d92339..cc51ef032 100644 --- a/package.json +++ b/package.json @@ -110,7 +110,7 @@ "valid-url": "^1.0.9", "vreme": "^3.0.2", "web3": "0.18.2", - "web3-provider-engine": "^11.0.0", + "web3-provider-engine": "^11.0.1", "web3-stream-provider": "^2.0.6", "xtend": "^4.0.1" },