diff options
author | Dan Finlay <dan@danfinlay.com> | 2016-08-17 06:39:40 +0800 |
---|---|---|
committer | Dan Finlay <dan@danfinlay.com> | 2016-08-17 06:39:40 +0800 |
commit | 5479509618e601391586d0851acee4e408523c4f (patch) | |
tree | 68a26e9fe5589f7d5ad8b9b649a88f87d7e26585 /app | |
parent | f1986d7a3757aea50fba798b295397e69739b891 (diff) | |
download | tangerine-wallet-browser-5479509618e601391586d0851acee4e408523c4f.tar tangerine-wallet-browser-5479509618e601391586d0851acee4e408523c4f.tar.gz tangerine-wallet-browser-5479509618e601391586d0851acee4e408523c4f.tar.bz2 tangerine-wallet-browser-5479509618e601391586d0851acee4e408523c4f.tar.lz tangerine-wallet-browser-5479509618e601391586d0851acee4e408523c4f.tar.xz tangerine-wallet-browser-5479509618e601391586d0851acee4e408523c4f.tar.zst tangerine-wallet-browser-5479509618e601391586d0851acee4e408523c4f.zip |
Set up MVP for popup-based notifications.
Diffstat (limited to 'app')
-rw-r--r-- | app/notification.html | 11 | ||||
-rw-r--r-- | app/scripts/background.js | 2 | ||||
-rw-r--r-- | app/scripts/lib/notifications.js | 136 | ||||
-rw-r--r-- | app/scripts/notification.js | 85 |
4 files changed, 106 insertions, 128 deletions
diff --git a/app/notification.html b/app/notification.html new file mode 100644 index 000000000..927f1634c --- /dev/null +++ b/app/notification.html @@ -0,0 +1,11 @@ +<!doctype html> +<html> + <head> + <meta charset="utf-8"> + <title>MetaMask Notification</title> + </head> + <body> + <div id="app-content"></div> + <script src="./scripts/notification.js" type="text/javascript" charset="utf-8"></script> + </body> +</html> diff --git a/app/scripts/background.js b/app/scripts/background.js index e04309e74..79f8f9fd9 100644 --- a/app/scripts/background.js +++ b/app/scripts/background.js @@ -69,7 +69,7 @@ function showUnconfirmedTx (txParams, txData, onTxDoneCb) { extension.runtime.onConnect.addListener(connectRemote) function connectRemote (remotePort) { - var isMetaMaskInternalProcess = (remotePort.name === 'popup') + var isMetaMaskInternalProcess = remotePort.name === 'popup' || remotePort.name === 'notification' var portStream = new PortStream(remotePort) if (isMetaMaskInternalProcess) { // communication with popup diff --git a/app/scripts/lib/notifications.js b/app/scripts/lib/notifications.js index 6c1601df1..75fb60dd0 100644 --- a/app/scripts/lib/notifications.js +++ b/app/scripts/lib/notifications.js @@ -18,142 +18,24 @@ const notifications = { module.exports = notifications window.METAMASK_NOTIFIER = notifications -setupListeners() - -function setupListeners () { - // guard for extension bug https://github.com/MetaMask/metamask-plugin/issues/236 - if (!extension.notifications) return console.error('Chrome notifications API missing...') - - // notification button press - extension.notifications.onButtonClicked.addListener(function (notificationId, buttonIndex) { - var handlers = notificationHandlers[notificationId] - if (buttonIndex === 0) { - handlers.confirm() - } else { - handlers.cancel() - } - extension.notifications.clear(notificationId) - }) - - // notification teardown - extension.notifications.onClosed.addListener(function (notificationId) { - delete notificationHandlers[notificationId] - }) -} - -// creation helper function createUnlockRequestNotification (opts) { - // guard for extension bug https://github.com/MetaMask/metamask-plugin/issues/236 - if (!extension.notifications) return console.error('Chrome notifications API missing...') - var message = 'An Ethereum app has requested a signature. Please unlock your account.' - - var id = createId() - extension.notifications.create(id, { - type: 'basic', - iconUrl: '/images/icon-128.png', - title: opts.title, - message: message, - }) + showNotification() } function createTxNotification (state) { - // guard for extension bug https://github.com/MetaMask/metamask-plugin/issues/236 - if (!extension.notifications) return console.error('Chrome notifications API missing...') - - renderTxNotificationSVG(state, function (err, notificationSvgSource) { - if (err) throw err - - showNotification(extend(state, { - title: 'New Unsigned Transaction', - imageUrl: toSvgUri(notificationSvgSource), - })) - }) + showNotification() } function createMsgNotification (state) { - // guard for extension bug https://github.com/MetaMask/metamask-plugin/issues/236 - if (!extension.notifications) return console.error('Chrome notifications API missing...') - - renderMsgNotificationSVG(state, function (err, notificationSvgSource) { - if (err) throw err - - showNotification(extend(state, { - title: 'New Unsigned Message', - imageUrl: toSvgUri(notificationSvgSource), - })) - }) + showNotification() } -function showNotification (state) { - // guard for extension bug https://github.com/MetaMask/metamask-plugin/issues/236 - if (!extension.notifications) return console.error('Chrome notifications API missing...') - - var id = createId() - extension.notifications.create(id, { - type: 'image', - requireInteraction: true, - iconUrl: '/images/icon-128.png', - imageUrl: state.imageUrl, - title: state.title, - message: '', - buttons: [{ - title: 'Approve', - }, { - title: 'Reject', - }], +function showNotification() { + chrome.windows.create({ + url:"notification.html", + type:"panel", + width:360, + height:500, }) - notificationHandlers[id] = { - confirm: state.onConfirm, - cancel: state.onCancel, - } -} - -function renderTxNotificationSVG (state, cb) { - var content = h(PendingTxDetails, state) - renderNotificationSVG(content, cb) } -function renderMsgNotificationSVG (state, cb) { - var content = h(PendingMsgDetails, state) - renderNotificationSVG(content, cb) -} - -function renderNotificationSVG (content, cb) { - var container = document.createElement('div') - var confirmView = h('div.app-primary', { - style: { - width: '360px', - height: '240px', - padding: '16px', - // background: '#F7F7F7', - background: 'white', - }, - }, [ - h('style', MetaMaskUiCss()), - content, - ]) - - render(confirmView, container, function ready() { - var rootElement = findDOMNode(this) - var viewSource = rootElement.outerHTML - unmountComponentAtNode(container) - var svgSource = svgWrapper(viewSource) - // insert content into svg wrapper - cb(null, svgSource) - }) -} - -function svgWrapper (content) { - var wrapperSource = ` - <svg xmlns="http://www.w3.org/2000/svg" width="360" height="240"> - <foreignObject x="0" y="0" width="100%" height="100%"> - <body xmlns="http://www.w3.org/1999/xhtml" height="100%">{{content}}</body> - </foreignObject> - </svg> - ` - return wrapperSource.split('{{content}}').join(content) -} - -function toSvgUri (content) { - return 'data:image/svg+xml;utf8,' + encodeURIComponent(content) -} diff --git a/app/scripts/notification.js b/app/scripts/notification.js new file mode 100644 index 000000000..90c00b32d --- /dev/null +++ b/app/scripts/notification.js @@ -0,0 +1,85 @@ +const url = require('url') +const EventEmitter = require('events').EventEmitter +const async = require('async') +const Dnode = require('dnode') +const Web3 = require('web3') +const MetaMaskNotification = require('../../ui/notification') +const MetaMaskUiCss = require('../../ui/css') +const injectCss = require('inject-css') +const PortStream = require('./lib/port-stream.js') +const StreamProvider = require('web3-stream-provider') +const setupMultiplex = require('./lib/stream-utils.js').setupMultiplex +const extension = require('./lib/extension') + +// setup app +var css = MetaMaskUiCss() +injectCss(css) + +async.parallel({ + currentDomain: getCurrentDomain, + accountManager: connectToAccountManager, +}, setupApp) + +function connectToAccountManager (cb) { + // setup communication with background + var pluginPort = extension.runtime.connect({name: 'notification'}) + var portStream = new PortStream(pluginPort) + // setup multiplexing + var mx = setupMultiplex(portStream) + // connect features + setupControllerConnection(mx.createStream('controller'), cb) + setupWeb3Connection(mx.createStream('provider')) +} + +function setupWeb3Connection (stream) { + var remoteProvider = new StreamProvider() + remoteProvider.pipe(stream).pipe(remoteProvider) + stream.on('error', console.error.bind(console)) + remoteProvider.on('error', console.error.bind(console)) + global.web3 = new Web3(remoteProvider) +} + +function setupControllerConnection (stream, cb) { + var eventEmitter = new EventEmitter() + var background = Dnode({ + sendUpdate: function (state) { + eventEmitter.emit('update', state) + }, + }) + stream.pipe(background).pipe(stream) + background.once('remote', function (accountManager) { + // setup push events + accountManager.on = eventEmitter.on.bind(eventEmitter) + cb(null, accountManager) + }) +} + +function getCurrentDomain (cb) { + const unknown = '<unknown>' + if (!extension.tabs) return cb(null, unknown) + extension.tabs.query({active: true, currentWindow: true}, function (results) { + var activeTab = results[0] + var currentUrl = activeTab && activeTab.url + var currentDomain = url.parse(currentUrl).host + if (!currentUrl) { + return cb(null, unknown) + } + cb(null, currentDomain) + }) +} + +function setupApp (err, opts) { + if (err) { + alert(err.stack) + throw err + } + + var container = document.getElementById('app-content') + + MetaMaskNotification({ + container: container, + accountManager: opts.accountManager, + currentDomain: opts.currentDomain, + networkVersion: opts.networkVersion, + }) +} |