2016-03-12 02:13:48 +01:00
|
|
|
const createId = require('hat')
|
2016-06-25 02:22:27 +02:00
|
|
|
const extend = require('xtend')
|
2016-06-24 00:13:24 +02:00
|
|
|
const unmountComponentAtNode = require('react-dom').unmountComponentAtNode
|
|
|
|
const findDOMNode = require('react-dom').findDOMNode
|
|
|
|
const render = require('react-dom').render
|
|
|
|
const h = require('react-hyperscript')
|
2016-06-25 02:22:27 +02:00
|
|
|
const PendingTxDetails = require('../../../ui/app/components/pending-tx-details')
|
|
|
|
const PendingMsgDetails = require('../../../ui/app/components/pending-msg-details')
|
2016-06-24 00:13:24 +02:00
|
|
|
const MetaMaskUiCss = require('../../../ui/css')
|
2016-07-21 19:45:32 +02:00
|
|
|
const extension = require('./extension')
|
2016-03-12 02:13:48 +01:00
|
|
|
var notificationHandlers = {}
|
|
|
|
|
2016-07-12 05:53:26 +02:00
|
|
|
const notifications = {
|
2016-05-24 23:59:33 +02:00
|
|
|
createUnlockRequestNotification: createUnlockRequestNotification,
|
2016-04-28 23:16:24 +02:00
|
|
|
createTxNotification: createTxNotification,
|
|
|
|
createMsgNotification: createMsgNotification,
|
|
|
|
}
|
2016-07-12 00:45:57 +02:00
|
|
|
module.exports = notifications
|
|
|
|
window.METAMASK_NOTIFIER = notifications
|
2016-03-12 02:13:48 +01:00
|
|
|
|
2016-06-03 02:29:49 +02:00
|
|
|
setupListeners()
|
2016-06-03 01:59:02 +02:00
|
|
|
|
2016-06-21 22:18:32 +02:00
|
|
|
function setupListeners () {
|
2016-07-21 19:45:32 +02:00
|
|
|
// guard for extension bug https://github.com/MetaMask/metamask-plugin/issues/236
|
|
|
|
if (!extension.notifications) return console.error('Chrome notifications API missing...')
|
2016-03-12 02:13:48 +01:00
|
|
|
|
2016-06-03 02:29:49 +02:00
|
|
|
// notification button press
|
2016-07-21 19:45:32 +02:00
|
|
|
extension.notifications.onButtonClicked.addListener(function (notificationId, buttonIndex) {
|
2016-06-03 02:29:49 +02:00
|
|
|
var handlers = notificationHandlers[notificationId]
|
|
|
|
if (buttonIndex === 0) {
|
|
|
|
handlers.confirm()
|
|
|
|
} else {
|
|
|
|
handlers.cancel()
|
|
|
|
}
|
2016-07-21 19:45:32 +02:00
|
|
|
extension.notifications.clear(notificationId)
|
2016-06-03 02:29:49 +02:00
|
|
|
})
|
|
|
|
|
|
|
|
// notification teardown
|
2016-07-21 19:45:32 +02:00
|
|
|
extension.notifications.onClosed.addListener(function (notificationId) {
|
2016-06-03 02:29:49 +02:00
|
|
|
delete notificationHandlers[notificationId]
|
|
|
|
})
|
|
|
|
}
|
2016-03-12 02:13:48 +01:00
|
|
|
|
|
|
|
// creation helper
|
2016-06-21 22:18:32 +02:00
|
|
|
function createUnlockRequestNotification (opts) {
|
2016-07-21 19:45:32 +02:00
|
|
|
// guard for extension bug https://github.com/MetaMask/metamask-plugin/issues/236
|
|
|
|
if (!extension.notifications) return console.error('Chrome notifications API missing...')
|
2016-05-24 23:59:33 +02:00
|
|
|
var message = 'An Ethereum app has requested a signature. Please unlock your account.'
|
|
|
|
|
|
|
|
var id = createId()
|
2016-07-21 19:45:32 +02:00
|
|
|
extension.notifications.create(id, {
|
2016-05-24 23:59:33 +02:00
|
|
|
type: 'basic',
|
|
|
|
iconUrl: '/images/icon-128.png',
|
|
|
|
title: opts.title,
|
|
|
|
message: message,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-06-28 21:36:53 +02:00
|
|
|
function createTxNotification (state) {
|
2016-07-21 19:45:32 +02:00
|
|
|
// guard for extension bug https://github.com/MetaMask/metamask-plugin/issues/236
|
|
|
|
if (!extension.notifications) return console.error('Chrome notifications API missing...')
|
2016-03-12 02:13:48 +01:00
|
|
|
|
2016-07-12 05:53:26 +02:00
|
|
|
renderTxNotificationSVG(state, function (err, notificationSvgSource) {
|
2016-06-24 01:53:45 +02:00
|
|
|
if (err) throw err
|
2016-06-25 02:22:27 +02:00
|
|
|
|
|
|
|
showNotification(extend(state, {
|
2016-06-28 21:36:53 +02:00
|
|
|
title: 'New Unsigned Transaction',
|
2016-06-25 02:22:27 +02:00
|
|
|
imageUrl: toSvgUri(notificationSvgSource),
|
|
|
|
}))
|
2016-03-12 02:13:48 +01:00
|
|
|
})
|
2016-04-14 00:28:44 +02:00
|
|
|
}
|
2016-04-28 23:16:24 +02:00
|
|
|
|
2016-06-28 21:36:53 +02:00
|
|
|
function createMsgNotification (state) {
|
2016-07-21 19:45:32 +02:00
|
|
|
// guard for extension bug https://github.com/MetaMask/metamask-plugin/issues/236
|
|
|
|
if (!extension.notifications) return console.error('Chrome notifications API missing...')
|
2016-06-25 02:22:27 +02:00
|
|
|
|
2016-07-12 05:53:26 +02:00
|
|
|
renderMsgNotificationSVG(state, function (err, notificationSvgSource) {
|
2016-06-25 02:22:27 +02:00
|
|
|
if (err) throw err
|
|
|
|
|
|
|
|
showNotification(extend(state, {
|
2016-06-28 21:36:53 +02:00
|
|
|
title: 'New Unsigned Message',
|
2016-06-25 02:22:27 +02:00
|
|
|
imageUrl: toSvgUri(notificationSvgSource),
|
|
|
|
}))
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
function showNotification (state) {
|
2016-07-21 19:45:32 +02:00
|
|
|
// guard for extension bug https://github.com/MetaMask/metamask-plugin/issues/236
|
|
|
|
if (!extension.notifications) return console.error('Chrome notifications API missing...')
|
2016-04-28 23:16:24 +02:00
|
|
|
|
|
|
|
var id = createId()
|
2016-07-21 19:45:32 +02:00
|
|
|
extension.notifications.create(id, {
|
2016-06-25 02:22:27 +02:00
|
|
|
type: 'image',
|
2016-05-25 20:54:38 +02:00
|
|
|
requireInteraction: true,
|
2016-04-28 23:16:24 +02:00
|
|
|
iconUrl: '/images/icon-128.png',
|
2016-06-25 02:22:27 +02:00
|
|
|
imageUrl: state.imageUrl,
|
|
|
|
title: state.title,
|
|
|
|
message: '',
|
2016-04-28 23:16:24 +02:00
|
|
|
buttons: [{
|
2016-06-30 00:44:37 +02:00
|
|
|
title: 'Approve',
|
2016-06-21 22:18:32 +02:00
|
|
|
}, {
|
2016-06-30 00:44:37 +02:00
|
|
|
title: 'Reject',
|
2016-06-21 22:18:32 +02:00
|
|
|
}],
|
2016-04-28 23:16:24 +02:00
|
|
|
})
|
|
|
|
notificationHandlers[id] = {
|
2016-06-25 02:22:27 +02:00
|
|
|
confirm: state.onConfirm,
|
|
|
|
cancel: state.onCancel,
|
2016-04-28 23:16:24 +02:00
|
|
|
}
|
2016-06-25 02:22:27 +02:00
|
|
|
}
|
2016-06-23 04:28:11 +02:00
|
|
|
|
2016-07-12 05:53:26 +02:00
|
|
|
function renderTxNotificationSVG (state, cb) {
|
2016-06-25 02:22:27 +02:00
|
|
|
var content = h(PendingTxDetails, state)
|
|
|
|
renderNotificationSVG(content, cb)
|
|
|
|
}
|
2016-06-23 04:28:11 +02:00
|
|
|
|
2016-07-12 05:53:26 +02:00
|
|
|
function renderMsgNotificationSVG (state, cb) {
|
2016-06-25 02:22:27 +02:00
|
|
|
var content = h(PendingMsgDetails, state)
|
|
|
|
renderNotificationSVG(content, cb)
|
|
|
|
}
|
2016-06-23 04:28:11 +02:00
|
|
|
|
2016-07-12 05:53:26 +02:00
|
|
|
function renderNotificationSVG (content, cb) {
|
2016-06-23 04:28:11 +02:00
|
|
|
var container = document.createElement('div')
|
2016-06-24 00:13:24 +02:00
|
|
|
var confirmView = h('div.app-primary', {
|
|
|
|
style: {
|
2016-06-28 01:28:07 +02:00
|
|
|
width: '360px',
|
|
|
|
height: '240px',
|
2016-06-24 00:13:24 +02:00
|
|
|
padding: '16px',
|
|
|
|
// background: '#F7F7F7',
|
|
|
|
background: 'white',
|
|
|
|
},
|
|
|
|
}, [
|
|
|
|
h('style', MetaMaskUiCss()),
|
2016-06-25 02:22:27 +02:00
|
|
|
content,
|
2016-06-23 04:28:11 +02:00
|
|
|
])
|
|
|
|
|
2016-07-12 05:53:26 +02:00
|
|
|
render(confirmView, container, function ready() {
|
2016-06-23 04:28:11 +02:00
|
|
|
var rootElement = findDOMNode(this)
|
2016-06-24 00:13:24 +02:00
|
|
|
var viewSource = rootElement.outerHTML
|
2016-06-23 04:28:11 +02:00
|
|
|
unmountComponentAtNode(container)
|
2016-06-24 00:13:24 +02:00
|
|
|
var svgSource = svgWrapper(viewSource)
|
2016-06-23 04:28:11 +02:00
|
|
|
// insert content into svg wrapper
|
2016-06-24 00:13:24 +02:00
|
|
|
cb(null, svgSource)
|
2016-06-23 04:28:11 +02:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2016-07-12 05:53:26 +02:00
|
|
|
function svgWrapper (content) {
|
2016-06-28 20:57:33 +02:00
|
|
|
var wrapperSource = `
|
2016-06-28 22:21:25 +02:00
|
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="360" height="240">
|
2016-06-24 00:13:24 +02:00
|
|
|
<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)
|
2016-06-25 02:22:27 +02:00
|
|
|
}
|
|
|
|
|
2016-07-12 05:53:26 +02:00
|
|
|
function toSvgUri (content) {
|
2016-06-25 02:22:27 +02:00
|
|
|
return 'data:image/svg+xml;utf8,' + encodeURIComponent(content)
|
2016-06-28 20:57:33 +02:00
|
|
|
}
|