diff options
Diffstat (limited to 'app/scripts/contentscript.js')
-rw-r--r-- | app/scripts/contentscript.js | 96 |
1 files changed, 70 insertions, 26 deletions
diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 4d7e682d3..2ed7c87b6 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -1,12 +1,15 @@ +const fs = require('fs') +const path = require('path') +const pump = require('pump') const LocalMessageDuplexStream = require('post-message-stream') const PongStream = require('ping-pong-stream/pong') -const PortStream = require('./lib/port-stream.js') -const ObjectMultiplex = require('./lib/obj-multiplex') +const ObjectMultiplex = require('obj-multiplex') const extension = require('extensionizer') +const PortStream = require('./lib/port-stream.js') -const fs = require('fs') -const path = require('path') -const inpageText = fs.readFileSync(path.join(__dirname, 'inpage.js')).toString() +const inpageContent = fs.readFileSync(path.join(__dirname, '..', '..', 'dist', 'chrome', 'scripts', 'inpage.js')).toString() +const inpageSuffix = '//# sourceURL=' + extension.extension.getURL('scripts/inpage.js') + '\n' +const inpageBundle = inpageContent + inpageSuffix // Eventually this streaming injection could be replaced with: // https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.exportFunction @@ -24,8 +27,7 @@ function setupInjection () { try { // inject in-page script var scriptTag = document.createElement('script') - scriptTag.src = extension.extension.getURL('scripts/inpage.js') - scriptTag.textContent = inpageText + scriptTag.textContent = inpageBundle scriptTag.onload = function () { this.parentNode.removeChild(this) } var container = document.head || document.documentElement // append as first child @@ -37,35 +39,64 @@ function setupInjection () { function setupStreams () { // setup communication to page and plugin - var pageStream = new LocalMessageDuplexStream({ + const pageStream = new LocalMessageDuplexStream({ name: 'contentscript', target: 'inpage', }) - pageStream.on('error', console.error) - var pluginPort = extension.runtime.connect({name: 'contentscript'}) - var pluginStream = new PortStream(pluginPort) - pluginStream.on('error', console.error) + const pluginPort = extension.runtime.connect({ name: 'contentscript' }) + const pluginStream = new PortStream(pluginPort) // forward communication plugin->inpage - pageStream.pipe(pluginStream).pipe(pageStream) + pump( + pageStream, + pluginStream, + pageStream, + (err) => logStreamDisconnectWarning('MetaMask Contentscript Forwarding', err) + ) // setup local multistream channels - var mx = ObjectMultiplex() - mx.on('error', console.error) - mx.pipe(pageStream).pipe(mx) + const mux = new ObjectMultiplex() + mux.setMaxListeners(25) + + pump( + mux, + pageStream, + mux, + (err) => logStreamDisconnectWarning('MetaMask Inpage', err) + ) + pump( + mux, + pluginStream, + mux, + (err) => logStreamDisconnectWarning('MetaMask Background', err) + ) // connect ping stream - var pongStream = new PongStream({ objectMode: true }) - pongStream.pipe(mx.createStream('pingpong')).pipe(pongStream) + const pongStream = new PongStream({ objectMode: true }) + pump( + mux, + pongStream, + mux, + (err) => logStreamDisconnectWarning('MetaMask PingPongStream', err) + ) + + // connect phishing warning stream + const phishingStream = mux.createStream('phishing') + phishingStream.once('data', redirectToPhishingWarning) - // ignore unused channels (handled by background) - mx.ignoreStream('provider') - mx.ignoreStream('publicConfig') - mx.ignoreStream('reload') + // ignore unused channels (handled by background, inpage) + mux.ignoreStream('provider') + mux.ignoreStream('publicConfig') +} + +function logStreamDisconnectWarning (remoteLabel, err) { + let warningMsg = `MetamaskContentscript - lost connection to ${remoteLabel}` + if (err) warningMsg += '\n' + err.stack + console.warn(warningMsg) } function shouldInjectWeb3 () { - return doctypeCheck() || suffixCheck() + return doctypeCheck() && suffixCheck() && documentElementCheck() } function doctypeCheck () { @@ -73,19 +104,32 @@ function doctypeCheck () { if (doctype) { return doctype.name === 'html' } else { - return false + return true } } -function suffixCheck() { +function suffixCheck () { var prohibitedTypes = ['xml', 'pdf'] var currentUrl = window.location.href var currentRegex for (let i = 0; i < prohibitedTypes.length; i++) { - currentRegex = new RegExp(`\.${prohibitedTypes[i]}$`) + currentRegex = new RegExp(`\\.${prohibitedTypes[i]}$`) if (currentRegex.test(currentUrl)) { return false } } return true } + +function documentElementCheck () { + var documentElement = document.documentElement.nodeName + if (documentElement) { + return documentElement.toLowerCase() === 'html' + } + return true +} + +function redirectToPhishingWarning () { + console.log('MetaMask - redirecting to phishing warning') + window.location.href = 'https://metamask.io/phishing.html' +} |