From 913a9e85bd24a286c3399ab6e9a0c47fdfbeae0d Mon Sep 17 00:00:00 2001 From: Dan Finlay Date: Mon, 25 Jul 2016 16:34:29 -0700 Subject: [PATCH] Inject inpage script synchronously Huge thanks to the Firefox team, for their help on the issue of our long-standing inpage script race condition. http://stackoverflow.com/questions/38577656/how-can-i-make-a-firefox-add-on-contentscript-inject-and-run-a-script-before-oth The problem is that we were injecting a `script` tag and assigning its `src` attribute, which triggers an asynchronous fetch request, and does not guarantee execution order! (That was news to me!) Instead, I'm now assigning the `script` tag a `textContent` value of the script to inject, and it seems to fix the problem! There is also a Firefox-only API that could solve this whole problem in an even more elegant way, so we might want to expose a code path for that solution later on: https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.exportFunction Allows you to expose an object from one scope to another. There was even talk of creating a polyfill for it that does virtually what we do, message passing between contexts. --- app/scripts/contentscript.js | 13 ++++++++++++- gulpfile.js | 2 ++ package.json | 1 + 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index d85675e61..103ea5348 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -3,6 +3,17 @@ const PortStream = require('./lib/port-stream.js') const ObjectMultiplex = require('./lib/obj-multiplex') const extension = require('./lib/extension') +const fs = require('fs') +const path = require('path') +const inpageText = fs.readFileSync(__dirname + '/inpage.js').toString() + +// Eventually this streaming injection could be replaced with: +// https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.exportFunction +// +// But for now that is only Firefox +// If we create a FireFox-only code path using that API, +// MetaMask will be much faster loading and performant on Firefox. + if (shouldInjectWeb3()) { setupInjection() setupStreams() @@ -14,6 +25,7 @@ function setupInjection(){ // inject in-page script var scriptTag = document.createElement('script') scriptTag.src = extension.extension.getURL('scripts/inpage.js') + scriptTag.textContent = inpageText scriptTag.onload = function () { this.parentNode.removeChild(this) } var container = document.head || document.documentElement // append as first child @@ -50,7 +62,6 @@ function setupStreams(){ pluginStream.on('close', function () { reloadStream.write({ method: 'reset' }) }) - } function shouldInjectWeb3(){ diff --git a/gulpfile.js b/gulpfile.js index 941155ff4..e10a4eb7d 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -8,6 +8,7 @@ var watch = require('gulp-watch') var sourcemaps = require('gulp-sourcemaps') var assign = require('lodash.assign') var livereload = require('gulp-livereload') +var brfs = require('gulp-brfs') var del = require('del') var eslint = require('gulp-eslint') var fs = require('fs') @@ -144,6 +145,7 @@ function bundleTask(opts) { // log errors if they happen .on('error', gutil.log.bind(gutil, 'Browserify Error')) .pipe(source(opts.filename)) + .pipe(brfs()) // optional, remove if you don't need to buffer file contents .pipe(buffer()) // optional, remove if you dont want sourcemaps diff --git a/package.json b/package.json index ef570fb94..1691f769a 100644 --- a/package.json +++ b/package.json @@ -86,6 +86,7 @@ "deep-freeze-strict": "^1.1.1", "del": "^2.2.0", "gulp": "github:gulpjs/gulp#4.0", + "gulp-brfs": "^0.1.0", "gulp-livereload": "^3.8.1", "gulp-sourcemaps": "^1.6.0", "gulp-util": "^3.0.7",