diff options
author | kumavis <kumavis@users.noreply.github.com> | 2017-06-13 04:27:04 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-13 04:27:04 +0800 |
commit | 27220b7bcd5ea1ebdae3bc1b494d28d9c828918c (patch) | |
tree | c9385fba3d742ca9cbfb9f3b4c6c9ef29c4f4a1b /mascara/src | |
parent | 57d1a1f1860e50837104a10b7b9f86d398c795ec (diff) | |
parent | 8af41f1b0539e70cf4c6e1f4a9f4b10ad13656fc (diff) | |
download | tangerine-wallet-browser-27220b7bcd5ea1ebdae3bc1b494d28d9c828918c.tar tangerine-wallet-browser-27220b7bcd5ea1ebdae3bc1b494d28d9c828918c.tar.gz tangerine-wallet-browser-27220b7bcd5ea1ebdae3bc1b494d28d9c828918c.tar.bz2 tangerine-wallet-browser-27220b7bcd5ea1ebdae3bc1b494d28d9c828918c.tar.lz tangerine-wallet-browser-27220b7bcd5ea1ebdae3bc1b494d28d9c828918c.tar.xz tangerine-wallet-browser-27220b7bcd5ea1ebdae3bc1b494d28d9c828918c.tar.zst tangerine-wallet-browser-27220b7bcd5ea1ebdae3bc1b494d28d9c828918c.zip |
Merge branch 'master' into i#1203MainNetSwitch
Diffstat (limited to 'mascara/src')
-rw-r--r-- | mascara/src/background.js | 155 | ||||
-rw-r--r-- | mascara/src/lib/setup-iframe.js | 19 | ||||
-rw-r--r-- | mascara/src/lib/setup-provider.js | 22 | ||||
-rw-r--r-- | mascara/src/mascara.js | 47 | ||||
-rw-r--r-- | mascara/src/proxy.js | 26 | ||||
-rw-r--r-- | mascara/src/ui.js | 56 |
6 files changed, 325 insertions, 0 deletions
diff --git a/mascara/src/background.js b/mascara/src/background.js new file mode 100644 index 000000000..d9dbf593a --- /dev/null +++ b/mascara/src/background.js @@ -0,0 +1,155 @@ +global.window = global +const self = global +const pipe = require('pump') + +const SwGlobalListener = require('sw-stream/lib/sw-global-listener.js') +const connectionListener = new SwGlobalListener(self) +const setupMultiplex = require('../../app/scripts/lib/stream-utils.js').setupMultiplex +const PortStream = require('../../app/scripts/lib/port-stream.js') + +const DbController = require('idb-global') + +const SwPlatform = require('../../app/scripts/platforms/sw') +const MetamaskController = require('../../app/scripts/metamask-controller') +const extension = {} //require('../../app/scripts/lib/extension') + +const storeTransform = require('obs-store/lib/transform') +const Migrator = require('../../app/scripts/lib/migrator/') +const migrations = require('../../app/scripts/migrations/') +const firstTimeState = require('../../app/scripts/first-time-state') + +const STORAGE_KEY = 'metamask-config' +// const METAMASK_DEBUG = 'GULP_METAMASK_DEBUG' +const METAMASK_DEBUG = true +let popupIsOpen = false +let connectedClientCount = 0 + +const log = require('loglevel') +global.log = log +log.setDefaultLevel(METAMASK_DEBUG ? 'debug' : 'warn') + +self.addEventListener('install', function(event) { + event.waitUntil(self.skipWaiting()) +}) +self.addEventListener('activate', function(event) { + event.waitUntil(self.clients.claim()) +}) + +console.log('inside:open') + + +// // state persistence +let diskStore +const dbController = new DbController({ + key: STORAGE_KEY, +}) +loadStateFromPersistence() +.then((initState) => setupController(initState)) +.then(() => console.log('MetaMask initialization complete.')) +.catch((err) => console.error('WHILE SETTING UP:', err)) + +// initialization flow + +// +// State and Persistence +// +function loadStateFromPersistence() { + // migrations + let migrator = new Migrator({ migrations }) + const initialState = migrator.generateInitialState(firstTimeState) + dbController.initialState = initialState + return dbController.open() + .then((versionedData) => migrator.migrateData(versionedData)) + .then((versionedData) => { + dbController.put(versionedData) + return Promise.resolve(versionedData) + }) + .then((versionedData) => Promise.resolve(versionedData.data)) +} + +function setupController (initState, client) { + + // + // MetaMask Controller + // + + const platform = new SwPlatform() + + const controller = new MetamaskController({ + // platform specific implementation + platform, + // User confirmation callbacks: + showUnconfirmedMessage: noop, + unlockAccountMessage: noop, + showUnapprovedTx: noop, + // initial state + initState, + }) + global.metamaskController = controller + + controller.store.subscribe((state) => { + versionifyData(state) + .then((versionedData) => dbController.put(versionedData)) + .catch((err) => {console.error(err)}) + }) + function versionifyData(state) { + return dbController.get() + .then((rawData) => { + return Promise.resolve({ + data: state, + meta: rawData.meta, + })} + ) + } + + // + // connect to other contexts + // + + connectionListener.on('remote', (portStream, messageEvent) => { + console.log('REMOTE CONECTION FOUND***********') + connectedClientCount += 1 + connectRemote(portStream, messageEvent.data.context) + }) + + function connectRemote (connectionStream, context) { + var isMetaMaskInternalProcess = (context === 'popup') + if (isMetaMaskInternalProcess) { + // communication with popup + controller.setupTrustedCommunication(connectionStream, 'MetaMask') + popupIsOpen = true + } else { + // communication with page + setupUntrustedCommunication(connectionStream, context) + } + } + + 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 + controller.setupProviderConnection(mx.createStream('provider'), originDomain) + } + // + // User Interface setup + // + return Promise.resolve() + +} + +function sendMessageToAllClients (message) { + self.clients.matchAll().then(function(clients) { + clients.forEach(function(client) { + client.postMessage(message) + }) + }) +} +function noop () {} diff --git a/mascara/src/lib/setup-iframe.js b/mascara/src/lib/setup-iframe.js new file mode 100644 index 000000000..db67163df --- /dev/null +++ b/mascara/src/lib/setup-iframe.js @@ -0,0 +1,19 @@ +const Iframe = require('iframe') +const IframeStream = require('iframe-stream').IframeStream + +module.exports = setupIframe + + +function setupIframe(opts) { + opts = opts || {} + var frame = Iframe({ + src: opts.zeroClientProvider || 'https://zero.metamask.io/', + container: opts.container || document.head, + sandboxAttributes: opts.sandboxAttributes || ['allow-scripts', 'allow-popups'], + }) + var iframe = frame.iframe + iframe.style.setProperty('display', 'none') + var iframeStream = new IframeStream(iframe) + + return iframeStream +} diff --git a/mascara/src/lib/setup-provider.js b/mascara/src/lib/setup-provider.js new file mode 100644 index 000000000..62335b18d --- /dev/null +++ b/mascara/src/lib/setup-provider.js @@ -0,0 +1,22 @@ +const setupIframe = require('./setup-iframe.js') +const MetamaskInpageProvider = require('../../../app/scripts/lib/inpage-provider.js') + +module.exports = getProvider + + +function getProvider(opts){ + if (global.web3) { + console.log('MetaMask ZeroClient - using environmental web3 provider') + return global.web3.currentProvider + } + console.log('MetaMask ZeroClient - injecting zero-client iframe!') + var iframeStream = setupIframe({ + zeroClientProvider: opts.mascaraUrl, + sandboxAttributes: ['allow-scripts', 'allow-popups', 'allow-same-origin'], + container: document.body, + }) + + var inpageProvider = new MetamaskInpageProvider(iframeStream) + return inpageProvider + +} diff --git a/mascara/src/mascara.js b/mascara/src/mascara.js new file mode 100644 index 000000000..1655d1f64 --- /dev/null +++ b/mascara/src/mascara.js @@ -0,0 +1,47 @@ +const Web3 = require('web3') +const setupProvider = require('./lib/setup-provider.js') +const setupDappAutoReload = require('../../app/scripts/lib/auto-reload.js') +const MASCARA_ORIGIN = process.env.MASCARA_ORIGIN || 'http://localhost:9001' +console.log('MASCARA_ORIGIN:', MASCARA_ORIGIN) + +// +// setup web3 +// + +const provider = setupProvider({ + mascaraUrl: MASCARA_ORIGIN + '/proxy/', +}) +instrumentForUserInteractionTriggers(provider) + +const web3 = new Web3(provider) +setupDappAutoReload(web3, provider.publicConfigStore) +// +// ui stuff +// + +let shouldPop = false +window.addEventListener('click', maybeTriggerPopup) + +// +// util +// + +function maybeTriggerPopup(){ + if (!shouldPop) return + shouldPop = false + window.open(MASCARA_ORIGIN, '', 'width=360 height=500') + console.log('opening window...') +} + +function instrumentForUserInteractionTriggers(provider){ + const _super = provider.sendAsync.bind(provider) + provider.sendAsync = function(payload, cb){ + if (payload.method === 'eth_sendTransaction') { + console.log('saw send') + shouldPop = true + } + _super(payload, cb) + } +} + + diff --git a/mascara/src/proxy.js b/mascara/src/proxy.js new file mode 100644 index 000000000..eabc547b4 --- /dev/null +++ b/mascara/src/proxy.js @@ -0,0 +1,26 @@ +const ParentStream = require('iframe-stream').ParentStream +const SWcontroller = require('client-sw-ready-event/lib/sw-client.js') +const SwStream = require('sw-stream/lib/sw-stream.js') +const SetupUntrustedComunication = ('./lib/setup-untrusted-connection.js') + +let intervalDelay = Math.floor(Math.random() * (30000 - 1000)) + 1000 +const background = new SWcontroller({ + fileName: '/background.js', + letBeIdle: false, + wakeUpInterval: 30000, + intervalDelay, +}) + +const pageStream = new ParentStream() +background.on('ready', (_) => { + let swStream = SwStream({ + serviceWorker: background.controller, + context: 'dapp', + }) + pageStream.pipe(swStream).pipe(pageStream) + +}) +background.on('updatefound', () => window.location.reload()) + +background.on('error', console.error) +background.startWorker() diff --git a/mascara/src/ui.js b/mascara/src/ui.js new file mode 100644 index 000000000..5f9be542f --- /dev/null +++ b/mascara/src/ui.js @@ -0,0 +1,56 @@ +const injectCss = require('inject-css') +const SWcontroller = require('client-sw-ready-event/lib/sw-client.js') +const SwStream = require('sw-stream/lib/sw-stream.js') +const MetaMaskUiCss = require('../../ui/css') +const setupIframe = require('./lib/setup-iframe.js') +const MetamaskInpageProvider = require('../../app/scripts/lib/inpage-provider.js') +const MetamascaraPlatform = require('../../app/scripts/platforms/window') +const startPopup = require('../../app/scripts/popup-core') + +// create platform global +global.platform = new MetamascaraPlatform() + + +var css = MetaMaskUiCss() +injectCss(css) +const container = document.getElementById('app-content') + +var name = 'popup' +window.METAMASK_UI_TYPE = name + +let intervalDelay = Math.floor(Math.random() * (30000 - 1000)) + 1000 + +const background = new SWcontroller({ + fileName: '/background.js', + letBeIdle: false, + intervalDelay, + wakeUpInterval: 20000 +}) +// Setup listener for when the service worker is read +const connectApp = function (readSw) { + let connectionStream = SwStream({ + serviceWorker: background.controller, + context: name, + }) + startPopup({container, connectionStream}, (err, store) => { + if (err) return displayCriticalError(err) + store.subscribe(() => { + const state = store.getState() + if (state.appState.shouldClose) window.close() + }) + }) +} +background.on('ready', (sw) => { + background.removeListener('updatefound', connectApp) + connectApp(sw) +}) +background.on('updatefound', () => window.location.reload()) + +background.startWorker() +.then(() => { + setTimeout(() => { + const appContent = document.getElementById(`app-content`) + if (!appContent.children.length) window.location.reload() + }, 2000) +}) +console.log('hello from MetaMascara ui!') |