diff --git a/.circleci/config.yml b/.circleci/config.yml index ae6f44c8a..98f27030e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -98,6 +98,32 @@ jobs: key: build-cache-{{ .Revision }} paths: - dist + - store_artifacts: + path: dist/mascara + destination: builds/mascara + - store_artifacts: + path: builds + destination: builds + - run: + name: build:announce + command: | + CIRCLE_PR_NUMBER="${CIRCLE_PR_NUMBER:-${CIRCLE_PULL_REQUEST##*/}}" + SHORT_SHA1=$(echo $CIRCLE_SHA1 | cut -c 1-7) + BUILD_LINK_BASE="https://$CIRCLE_BUILD_NUM-42009758-gh.circle-artifacts.com/0/builds" + VERSION=$(node -p 'require("./dist/chrome/manifest.json").version') + MASCARA="$BUILD_LINK_BASE/mascara/home.html" + CHROME="$BUILD_LINK_BASE/metamask-chrome-$VERSION.zip" + FIREFOX="$BUILD_LINK_BASE/metamask-firefox-$VERSION.zip" + OPERA="$BUILD_LINK_BASE/metamask-opera-$VERSION.zip" + EDGE="$BUILD_LINK_BASE/metamask-edge-$VERSION.zip" + COMMENT_MAIN="Builds ready [$SHORT_SHA1]: [mascara][mascara], [chrome][chrome], [firefox][firefox], [edge][edge], [opera][opera]" + COMMENT_LINKS="[mascara]:$MASCARA\n[chrome]:$CHROME\n[firefox]:$FIREFOX\n[opera]:$OPERA\n[edge]:$EDGE\n" + COMMENT_BODY="$COMMENT_MAIN\n\n$COMMENT_LINKS" + JSON_PAYLOAD="{\"body\":\"$COMMENT_BODY\"}" + POST_COMMENT_URI="https://api.github.com/repos/metamask/metamask-extension/issues/$CIRCLE_PR_NUMBER/comments" + echo "Announcement:\n$COMMENT_BODY" + echo "Posting to $POST_COMMENT_URI" + curl -d "$JSON_PAYLOAD" -H "Authorization: token $GITHUB_COMMENT_TOKEN" $POST_COMMENT_URI prep-scss: docker: diff --git a/app/home.html b/app/home.html index cfb4b00a0..4fad0f993 100644 --- a/app/home.html +++ b/app/home.html @@ -3,10 +3,10 @@ - MetaMask Plugin + MetaMask
- + diff --git a/app/manifest.json b/app/manifest.json index a20f9b976..1982b4820 100644 --- a/app/manifest.json +++ b/app/manifest.json @@ -27,8 +27,8 @@ "default_locale": "en", "background": { "scripts": [ - "scripts/chromereload.js", - "scripts/background.js" + "chromereload.js", + "background.js" ], "persistent": true }, @@ -48,7 +48,7 @@ "https://*/*" ], "js": [ - "scripts/contentscript.js" + "contentscript.js" ], "run_at": "document_start", "all_frames": true @@ -62,11 +62,11 @@ "https://*.infura.io/" ], "web_accessible_resources": [ - "scripts/inpage.js" + "inpage.js" ], "externally_connectable": { "matches": [ "https://metamask.io/*" ] } -} \ No newline at end of file +} diff --git a/app/notification.html b/app/notification.html index f10cbbf41..457ba7137 100644 --- a/app/notification.html +++ b/app/notification.html @@ -11,6 +11,6 @@
- + diff --git a/app/popup.html b/app/popup.html index bf09b97ca..3acfd8c55 100644 --- a/app/popup.html +++ b/app/popup.html @@ -3,10 +3,10 @@ - MetaMask Plugin + MetaMask
- + diff --git a/app/scripts/contentscript.js b/app/scripts/contentscript.js index 7abbc60e7..2098fae27 100644 --- a/app/scripts/contentscript.js +++ b/app/scripts/contentscript.js @@ -7,8 +7,8 @@ const ObjectMultiplex = require('obj-multiplex') const extension = require('extensionizer') const PortStream = require('./lib/port-stream.js') -const inpageContent = fs.readFileSync(path.join(__dirname, '..', '..', 'dist', 'chrome', 'scripts', 'inpage.js')).toString() -const inpageSuffix = '//# sourceURL=' + extension.extension.getURL('scripts/inpage.js') + '\n' +const inpageContent = fs.readFileSync(path.join(__dirname, '..', '..', 'dist', 'chrome', 'inpage.js')).toString() +const inpageSuffix = '//# sourceURL=' + extension.extension.getURL('inpage.js') + '\n' const inpageBundle = inpageContent + inpageSuffix // Eventually this streaming injection could be replaced with: @@ -96,7 +96,7 @@ function logStreamDisconnectWarning (remoteLabel, err) { } function shouldInjectWeb3 () { - return doctypeCheck() && suffixCheck() + return doctypeCheck() && suffixCheck() && documentElementCheck() && !blacklistedDomainCheck() } diff --git a/app/scripts/popup.js b/app/scripts/ui.js similarity index 100% rename from app/scripts/popup.js rename to app/scripts/ui.js diff --git a/gulpfile.js b/gulpfile.js index f57ea6206..3ca0c65de 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -1,37 +1,51 @@ -var watchify = require('watchify') -var browserify = require('browserify') -var disc = require('disc') -var gulp = require('gulp') -var source = require('vinyl-source-stream') -var buffer = require('vinyl-buffer') -var gutil = require('gulp-util') -var watch = require('gulp-watch') -var sourcemaps = require('gulp-sourcemaps') -var jsoneditor = require('gulp-json-editor') -var zip = require('gulp-zip') -var assign = require('lodash.assign') -var livereload = require('gulp-livereload') -var del = require('del') -var eslint = require('gulp-eslint') -var fs = require('fs') -var path = require('path') -var manifest = require('./app/manifest.json') -var gulpif = require('gulp-if') -var replace = require('gulp-replace') -var mkdirp = require('mkdirp') -var asyncEach = require('async/each') -var exec = require('child_process').exec -var sass = require('gulp-sass') -var autoprefixer = require('gulp-autoprefixer') -var gulpStylelint = require('gulp-stylelint') -var stylefmt = require('gulp-stylefmt') -var uglify = require('gulp-uglify-es').default -var babel = require('gulp-babel') +const watchify = require('watchify') +const browserify = require('browserify') +const disc = require('disc') +const gulp = require('gulp') +const source = require('vinyl-source-stream') +const buffer = require('vinyl-buffer') +const gutil = require('gulp-util') +const watch = require('gulp-watch') +const sourcemaps = require('gulp-sourcemaps') +const jsoneditor = require('gulp-json-editor') +const zip = require('gulp-zip') +const assign = require('lodash.assign') +const livereload = require('gulp-livereload') +const del = require('del') +const eslint = require('gulp-eslint') +const fs = require('fs') +const path = require('path') +const manifest = require('./app/manifest.json') +const gulpif = require('gulp-if') +const replace = require('gulp-replace') +const mkdirp = require('mkdirp') +const asyncEach = require('async/each') +const exec = require('child_process').exec +const sass = require('gulp-sass') +const autoprefixer = require('gulp-autoprefixer') +const gulpStylelint = require('gulp-stylelint') +const stylefmt = require('gulp-stylefmt') +const uglify = require('gulp-uglify-es').default +const babel = require('gulp-babel') +const debug = require('gulp-debug') +const pify = require('pify') +const endOfStream = pify(require('end-of-stream')) +const disableDebugTools = gutil.env.disableDebugTools +const debugMode = gutil.env.debug -var disableDebugTools = gutil.env.disableDebugTools -var debug = gutil.env.debug - +const browserPlatforms = [ + 'firefox', + 'chrome', + 'edge', + 'opera', +] +const commonPlatforms = [ + // browser webapp + 'mascara', + // browser extensions + ...browserPlatforms +] // browser reload @@ -41,65 +55,98 @@ gulp.task('dev:reload', function() { }) }) +// copy universal -// copy static +const copyTaskNames = [] +const copyDevTaskNames = [] -gulp.task('copy:locales', copyTask({ +createCopyTasks('locales', { source: './app/_locales/', - destinations: [ - './dist/firefox/_locales', - './dist/chrome/_locales', - './dist/edge/_locales', - './dist/opera/_locales', - ] -})) -gulp.task('copy:images', copyTask({ + destinations: commonPlatforms.map(platform => `./dist/${platform}/_locales`), +}) +createCopyTasks('images', { source: './app/images/', - destinations: [ - './dist/firefox/images', - './dist/chrome/images', - './dist/edge/images', - './dist/opera/images', - ], -})) -gulp.task('copy:contractImages', copyTask({ + destinations: commonPlatforms.map(platform => `./dist/${platform}/images`), +}) +createCopyTasks('contractImages', { source: './node_modules/eth-contract-metadata/images/', - destinations: [ - './dist/firefox/images/contract', - './dist/chrome/images/contract', - './dist/edge/images/contract', - './dist/opera/images/contract', - ], -})) -gulp.task('copy:fonts', copyTask({ + destinations: commonPlatforms.map(platform => `./dist/${platform}/images/contract`), +}) +createCopyTasks('fonts', { source: './app/fonts/', - destinations: [ - './dist/firefox/fonts', - './dist/chrome/fonts', - './dist/edge/fonts', - './dist/opera/fonts', - ], -})) -gulp.task('copy:reload', copyTask({ + destinations: commonPlatforms.map(platform => `./dist/${platform}/fonts`), +}) +createCopyTasks('reload', { + devOnly: true, source: './app/scripts/', - destinations: [ - './dist/firefox/scripts', - './dist/chrome/scripts', - './dist/edge/scripts', - './dist/opera/scripts', - ], pattern: '/chromereload.js', -})) -gulp.task('copy:root', copyTask({ + destinations: commonPlatforms.map(platform => `./dist/${platform}`), +}) +createCopyTasks('html', { source: './app/', - destinations: [ - './dist/firefox', - './dist/chrome', - './dist/edge', - './dist/opera', - ], - pattern: '/*', -})) + pattern: '/*.html', + destinations: commonPlatforms.map(platform => `./dist/${platform}`), +}) + +// copy extension + +createCopyTasks('manifest', { + source: './app/', + pattern: '/*.json', + destinations: browserPlatforms.map(platform => `./dist/${platform}`), +}) + +// copy mascara + +createCopyTasks('html:mascara', { + source: './mascara/', + pattern: 'proxy/index.html', + destinations: [`./dist/mascara/`], +}) + +function createCopyTasks(label, opts) { + if (!opts.devOnly) { + const copyTaskName = `copy:${label}` + copyTask(copyTaskName, opts) + copyTaskNames.push(copyTaskName) + } + const copyDevTaskName = `dev:copy:${label}` + copyTask(copyDevTaskName, Object.assign({ devMode: true }, opts)) + copyDevTaskNames.push(copyDevTaskName) +} + +function copyTask(taskName, opts){ + const source = opts.source + const destination = opts.destination + const destinations = opts.destinations || [destination] + const pattern = opts.pattern || '/**/*' + const devMode = opts.devMode + + return gulp.task(taskName, function () { + if (devMode) { + watch(source + pattern, (event) => { + livereload.changed(event.path) + performCopy() + }) + } + + return performCopy() + }) + + function performCopy() { + // stream from source + let stream = gulp.src(source + pattern, { base: source }) + + // copy to destinations + destinations.forEach(function(destination) { + stream = stream.pipe(gulp.dest(destination)) + }) + + return stream + } +} + +// manifest tinkering gulp.task('manifest:chrome', function() { return gulp.src('./dist/chrome/manifest.json') @@ -134,7 +181,7 @@ gulp.task('manifest:production', function() { ],{base: './dist/'}) // Exclude chromereload script in production: - .pipe(gulpif(!debug,jsoneditor(function(json) { + .pipe(gulpif(!debugMode,jsoneditor(function(json) { json.background.scripts = json.background.scripts.filter((script) => { return !script.includes('chromereload') }) @@ -144,36 +191,22 @@ gulp.task('manifest:production', function() { .pipe(gulp.dest('./dist/', { overwrite: true })) }) -const staticFiles = [ - 'locales', - 'images', - 'fonts', - 'root' -] +gulp.task('copy', + gulp.series( + gulp.parallel(...copyTaskNames), + 'manifest:production', + 'manifest:chrome', + 'manifest:opera' + ) +) -var copyStrings = staticFiles.map(staticFile => `copy:${staticFile}`) -copyStrings.push('copy:contractImages') - -if (debug) { - copyStrings.push('copy:reload') -} - -gulp.task('copy', gulp.series(gulp.parallel(...copyStrings), 'manifest:production', 'manifest:chrome', 'manifest:opera')) -gulp.task('copy:watch', function(){ - gulp.watch(['./app/{_locales,images}/*', './app/scripts/chromereload.js', './app/*.{html,json}'], gulp.series('copy')) -}) - -// record deps - -gulp.task('deps', function (cb) { - exec('npm ls', (err, stdoutOutput, stderrOutput) => { - if (err) return cb(err) - const browsers = ['firefox','chrome','edge','opera'] - asyncEach(browsers, (target, done) => { - fs.writeFile(`./dist/${target}/deps.txt`, stdoutOutput, done) - }, cb) - }) -}) +gulp.task('dev:copy', + gulp.series( + gulp.parallel(...copyDevTaskNames), + 'manifest:chrome', + 'manifest:opera' + ) +) // lint js @@ -196,41 +229,49 @@ gulp.task('lint:fix', function () { .pipe(eslint.failAfterError()) }); -/* -gulp.task('default', ['lint'], function () { - // This will only run if the lint task is successful... -}); -*/ - -// build js - -const jsFiles = [ - 'inpage', - 'contentscript', - 'background', - 'popup', -] - // scss compilation and autoprefixing tasks -gulp.task('build:scss', function () { - return gulp.src('ui/app/css/index.scss') - .pipe(sourcemaps.init()) - .pipe(sass().on('error', sass.logError)) - .pipe(sourcemaps.write()) - .pipe(autoprefixer()) - .pipe(gulp.dest('ui/app/css/output')) -}) -gulp.task('watch:scss', function() { - gulp.watch(['ui/app/css/**/*.scss'], gulp.series(['build:scss'])) -}) +gulp.task('build:scss', createScssBuildTask({ + src: 'ui/app/css/index.scss', + dest: 'ui/app/css/output', + devMode: false, +})) + +gulp.task('dev:scss', createScssBuildTask({ + src: 'ui/app/css/index.scss', + dest: 'ui/app/css/output', + devMode: true, + pattern: 'ui/app/css/**/*.scss', +})) + +function createScssBuildTask({ src, dest, devMode, pattern }) { + return function () { + if (devMode) { + watch(pattern, async (event) => { + const stream = buildScss() + await endOfStream(stream) + livereload.changed(event.path) + }) + } + return buildScss() + } + + function buildScss() { + return gulp.src(src) + .pipe(sourcemaps.init()) + .pipe(sass().on('error', sass.logError)) + .pipe(sourcemaps.write()) + .pipe(autoprefixer()) + .pipe(gulp.dest(dest)) + } +} gulp.task('lint-scss', function() { return gulp .src('ui/app/css/itcss/**/*.scss') .pipe(gulpStylelint({ reporters: [ - {formatter: 'string', console: true} + { formatter: 'string', console: true } ], fix: true, })); @@ -242,46 +283,82 @@ gulp.task('fmt-scss', function () { .pipe(gulp.dest('ui/app/css/itcss')); }); +// build js + +const buildJsFiles = [ + 'inpage', + 'contentscript', + 'background', + 'ui', +] + // bundle tasks +createTasksForBuildJsExtension({ buildJsFiles, taskPrefix: 'dev:extension:js', devMode: true }) +createTasksForBuildJsExtension({ buildJsFiles, taskPrefix: 'build:extension:js' }) +createTasksForBuildJsMascara({ taskPrefix: 'build:mascara:js' }) +createTasksForBuildJsMascara({ taskPrefix: 'dev:mascara:js', devMode: true }) -var jsDevStrings = jsFiles.map(jsFile => `dev:js:${jsFile}`) -var jsBuildStrings = jsFiles.map(jsFile => `build:js:${jsFile}`) +function createTasksForBuildJsExtension({ buildJsFiles, taskPrefix, devMode, bundleTaskOpts = {} }) { + // inpage must be built before all other scripts: + const rootDir = './app/scripts' + const nonInpageFiles = buildJsFiles.filter(file => file !== 'inpage') + const buildPhase1 = ['inpage'] + const buildPhase2 = nonInpageFiles + const destinations = browserPlatforms.map(platform => `./dist/${platform}`) + bundleTaskOpts = Object.assign({ + buildSourceMaps: true, + sourceMapDir: devMode ? './' : '../sourcemaps', + minifyBuild: !devMode, + buildWithFullPaths: devMode, + watch: devMode, + }, bundleTaskOpts) + createTasksForBuildJs({ rootDir, taskPrefix, bundleTaskOpts, destinations, buildPhase1, buildPhase2 }) +} -jsFiles.forEach((jsFile) => { - gulp.task(`dev:js:${jsFile}`, bundleTask({ - watch: true, - label: jsFile, - filename: `${jsFile}.js`, - isBuild: false - })) - gulp.task(`build:js:${jsFile}`, bundleTask({ - watch: false, - label: jsFile, - filename: `${jsFile}.js`, - isBuild: true - })) -}) +function createTasksForBuildJsMascara({ taskPrefix, devMode, bundleTaskOpts = {} }) { + // inpage must be built before all other scripts: + const rootDir = './mascara/src/' + const buildPhase1 = ['ui', 'proxy', 'background', 'metamascara'] + const destinations = ['./dist/mascara'] + bundleTaskOpts = Object.assign({ + buildSourceMaps: true, + sourceMapDir: './', + minifyBuild: !devMode, + buildWithFullPaths: devMode, + watch: devMode, + }, bundleTaskOpts) + createTasksForBuildJs({ rootDir, taskPrefix, bundleTaskOpts, destinations, buildPhase1 }) +} -// inpage must be built before all other scripts: -const firstDevString = jsDevStrings.shift() -gulp.task('dev:js', gulp.series(firstDevString, gulp.parallel(...jsDevStrings))) +function createTasksForBuildJs({ rootDir, taskPrefix, bundleTaskOpts, destinations, buildPhase1 = [], buildPhase2 = [] }) { + // bundle task for each file + const jsFiles = [].concat(buildPhase1, buildPhase2) + jsFiles.forEach((jsFile) => { + gulp.task(`${taskPrefix}:${jsFile}`, bundleTask(Object.assign({ + label: jsFile, + filename: `${jsFile}.js`, + filepath: `${rootDir}/${jsFile}.js`, + destinations, + }, bundleTaskOpts))) + }) + // compose into larger task + const subtasks = [] + subtasks.push(gulp.parallel(buildPhase1.map(file => `${taskPrefix}:${file}`))) + if (buildPhase2.length) subtasks.push(gulp.parallel(buildPhase2.map(file => `${taskPrefix}:${file}`))) -// inpage must be built before all other scripts: -const firstBuildString = jsBuildStrings.shift() -gulp.task('build:js', gulp.series(firstBuildString, gulp.parallel(...jsBuildStrings))) + gulp.task(taskPrefix, gulp.series(subtasks)) +} // disc bundle analyzer tasks -jsFiles.forEach((jsFile) => { - gulp.task(`disc:${jsFile}`, discTask({ label: jsFile, filename: `${jsFile}.js` })) +buildJsFiles.forEach((jsFile) => { + gulp.task(`disc:${jsFile}`, discTask({ label: jsFile, filename: `${jsFile}.js` })) }) -gulp.task('disc', gulp.parallel(jsFiles.map(jsFile => `disc:${jsFile}`))) - +gulp.task('disc', gulp.parallel(buildJsFiles.map(jsFile => `disc:${jsFile}`))) // clean dist - gulp.task('clean', function clean() { return del(['./dist/*']) }) @@ -293,40 +370,95 @@ gulp.task('zip:edge', zipTask('edge')) gulp.task('zip:opera', zipTask('opera')) gulp.task('zip', gulp.parallel('zip:chrome', 'zip:firefox', 'zip:edge', 'zip:opera')) -// set env var for production +// set env for production gulp.task('apply-prod-environment', function(done) { - process.env.NODE_ENV = 'production' - done() + process.env.NODE_ENV = 'production' + done() }); // high level tasks -gulp.task('dev', gulp.series('build:scss', 'dev:js', 'copy', gulp.parallel('watch:scss', 'copy:watch', 'dev:reload'))) +gulp.task('dev', + gulp.series( + 'clean', + 'dev:scss', + gulp.parallel( + 'dev:extension:js', + 'dev:mascara:js', + 'dev:copy', + 'dev:reload' + ) + ) +) -gulp.task('build', gulp.series('clean', 'build:scss', gulp.parallel('build:js', 'copy'))) -gulp.task('dist', gulp.series('apply-prod-environment', 'build', 'zip')) +gulp.task('dev:extension', + gulp.series( + 'clean', + 'dev:scss', + gulp.parallel( + 'dev:extension:js', + 'dev:copy', + 'dev:reload' + ) + ) +) + +gulp.task('dev:mascara', + gulp.series( + 'clean', + 'dev:scss', + gulp.parallel( + 'dev:mascara:js', + 'dev:copy', + 'dev:reload' + ) + ) +) + +gulp.task('build', + gulp.series( + 'clean', + 'build:scss', + gulp.parallel( + 'build:extension:js', + 'build:mascara:js', + 'copy' + ) + ) +) + +gulp.task('build:extension', + gulp.series( + 'clean', + 'build:scss', + gulp.parallel( + 'build:extension:js', + 'copy' + ) + ) +) + +gulp.task('build:mascara', + gulp.series( + 'clean', + 'build:scss', + gulp.parallel( + 'build:mascara:js', + 'copy' + ) + ) +) + +gulp.task('dist', + gulp.series( + 'apply-prod-environment', + 'build', + 'zip' + ) +) // task generators -function copyTask(opts){ - var source = opts.source - var destination = opts.destination - var destinations = opts.destinations || [ destination ] - var pattern = opts.pattern || '/**/*' - - return performCopy - - function performCopy(){ - let stream = gulp.src(source + pattern, { base: source }) - destinations.forEach(function(destination) { - stream = stream.pipe(gulp.dest(destination)) - }) - stream.pipe(gulpif(debug,livereload())) - - return stream - } -} - function zipTask(target) { return () => { return gulp.src(`dist/${target}/**`) @@ -337,10 +469,10 @@ function zipTask(target) { function generateBundler(opts, performBundle) { const browserifyOpts = assign({}, watchify.args, { - entries: ['./app/scripts/'+opts.filename], + entries: [opts.filepath], plugin: 'browserify-derequire', - debug: true, - fullPaths: debug, + debug: opts.buildSourceMaps, + fullPaths: opts.buildWithFullPaths, }) let bundler = browserify(browserifyOpts) @@ -348,13 +480,21 @@ function generateBundler(opts, performBundle) { if (opts.watch) { bundler = watchify(bundler) // on any file update, re-runs the bundler - bundler.on('update', performBundle) + bundler.on('update', async (ids) => { + const stream = performBundle() + await endOfStream(stream) + livereload.changed(`${ids}`) + }) } return bundler } function discTask(opts) { + opts = Object.assign({ + buildWithFullPaths: true, + }, opts) + const bundler = generateBundler(opts, performBundle) // output build logs to terminal bundler.on('log', gutil.log) @@ -363,9 +503,9 @@ function discTask(opts) { function performBundle(){ // start "disc" build - let discDir = path.join(__dirname, 'disc') + const discDir = path.join(__dirname, 'disc') mkdirp.sync(discDir) - let discPath = path.join(discDir, `${opts.label}.html`) + const discPath = path.join(discDir, `${opts.label}.html`) return ( bundler.bundle() @@ -384,43 +524,58 @@ function bundleTask(opts) { return performBundle function performBundle(){ - return ( + let buildStream = bundler.bundle() - bundler.bundle() + // handle errors + buildStream.on('error', (err) => { + beep() + if (opts.watch) { + console.warn(err.stack) + } else { + throw err + } + }) - // handle errors - .on('error', (err) => { - beep() - if (opts.watch) { - console.warn(err.stack) - } else { - throw err - } - }) + // process bundles + buildStream = buildStream // convert bundle stream to gulp vinyl stream .pipe(source(opts.filename)) // inject variables into bundle - .pipe(replace('\'GULP_METAMASK_DEBUG\'', debug)) + .pipe(replace('\'GULP_METAMASK_DEBUG\'', debugMode)) // buffer file contents (?) .pipe(buffer()) - // sourcemaps - // loads map from browserify file - .pipe(sourcemaps.init({ loadMaps: true })) - // Minification - .pipe(gulpif(opts.isBuild, uglify({ - mangle: { reserved: [ 'MetamaskInpageProvider' ] }, - }))) - // writes .map file - .pipe(sourcemaps.write(debug ? './' : '../../sourcemaps')) - // write completed bundles - .pipe(gulp.dest('./dist/firefox/scripts')) - .pipe(gulp.dest('./dist/chrome/scripts')) - .pipe(gulp.dest('./dist/edge/scripts')) - .pipe(gulp.dest('./dist/opera/scripts')) - // finally, trigger live reload - .pipe(gulpif(debug, livereload())) - ) + + // Initialize Source Maps + if (opts.buildSourceMaps) { + buildStream = buildStream + // loads map from browserify file + .pipe(sourcemaps.init({ loadMaps: true })) + } + + // Minification + if (opts.minifyBuild) { + buildStream = buildStream + .pipe(uglify({ + mangle: { + reserved: [ 'MetamaskInpageProvider' ] + }, + })) + } + + // Finalize Source Maps (writes .map file) + if (opts.buildSourceMaps) { + buildStream = buildStream + .pipe(sourcemaps.write(opts.sourceMapDir)) + } + + // write completed bundles + opts.destinations.forEach((dest) => { + buildStream = buildStream.pipe(gulp.dest(dest)) + }) + + return buildStream + } } diff --git a/mascara/proxy/index.html b/mascara/proxy/index.html index b83fc41af..4e167db72 100644 --- a/mascara/proxy/index.html +++ b/mascara/proxy/index.html @@ -17,4 +17,4 @@ Hello! I am the MetaMask iframe. - \ No newline at end of file + diff --git a/mascara/server/index.js b/mascara/server/index.js index 6fb1287cc..a30120438 100644 --- a/mascara/server/index.js +++ b/mascara/server/index.js @@ -1,7 +1,5 @@ const path = require('path') const express = require('express') -const createBundle = require('./util').createBundle -const serveBundle = require('./util').serveBundle const compression = require('compression') module.exports = createMetamascaraServer @@ -9,27 +7,14 @@ module.exports = createMetamascaraServer function createMetamascaraServer () { - // start bundlers - const metamascaraBundle = createBundle(path.join(__dirname, '/../src/mascara.js')) - const proxyBundle = createBundle(path.join(__dirname, '/../src/proxy.js')) - const uiBundle = createBundle(path.join(__dirname, '/../src/ui.js')) - const backgroundBuild = createBundle(path.join(__dirname, '/../src/background.js')) - - // serve bundles + // setup server const server = express() server.use(compression()) - // ui window - serveBundle(server, '/ui.js', uiBundle) + // serve assets server.use(express.static(path.join(__dirname, '/../ui/'), { setHeaders: (res) => res.set('X-Frame-Options', 'DENY') })) - server.use(express.static(path.join(__dirname, '/../../dist/chrome'))) - // metamascara - serveBundle(server, '/metamascara.js', metamascaraBundle) - // proxy - serveBundle(server, '/proxy/proxy.js', proxyBundle) - server.use('/proxy/', express.static(path.join(__dirname, '/../proxy'))) - // background - serveBundle(server, '/background.js', backgroundBuild) + server.use(express.static(path.join(__dirname, '/../../dist/mascara'))) + server.use(express.static(path.join(__dirname, '/../proxy'))) return server diff --git a/mascara/src/background.js b/mascara/src/background.js index 8aa1d8fe2..40a684f3d 100644 --- a/mascara/src/background.js +++ b/mascara/src/background.js @@ -30,15 +30,19 @@ global.addEventListener('activate', function (event) { log.debug('inside:open') - -// // state persistence +// state persistence const dbController = new DbController({ key: STORAGE_KEY, }) -loadStateFromPersistence() -.then((initState) => setupController(initState)) -.then(() => log.debug('MetaMask initialization complete.')) -.catch((err) => console.error('WHILE SETTING UP:', err)) + +start().catch(log.error) + +async function start() { + log.debug('MetaMask initializing...') + const initState = await loadStateFromPersistence() + await setupController(initState) + log.debug('MetaMask initialization complete.') +} // // State and Persistence diff --git a/mascara/src/mascara.js b/mascara/src/metamascara.js similarity index 100% rename from mascara/src/mascara.js rename to mascara/src/metamascara.js diff --git a/mascara/src/proxy.js b/mascara/src/proxy.js index 54c5d5cf4..80b4dc516 100644 --- a/mascara/src/proxy.js +++ b/mascara/src/proxy.js @@ -1,13 +1,13 @@ const createParentStream = require('iframe-stream').ParentStream -const SWcontroller = require('client-sw-ready-event/lib/sw-client.js') +const SwController = require('sw-controller') const SwStream = require('sw-stream/lib/sw-stream.js') -const intervalDelay = Math.floor(Math.random() * (30000 - 1000)) + 1000 -const background = new SWcontroller({ - fileName: '/background.js', - letBeIdle: false, - wakeUpInterval: 30000, - intervalDelay, +const keepAliveDelay = Math.floor(Math.random() * (30000 - 1000)) + 1000 +const background = new SwController({ + fileName: './scripts/background.js', + keepAlive: true, + keepAliveInterval: 30000, + keepAliveDelay, }) const pageStream = createParentStream() diff --git a/mascara/src/ui.js b/mascara/src/ui.js index b272a2e06..f35a11fc4 100644 --- a/mascara/src/ui.js +++ b/mascara/src/ui.js @@ -1,6 +1,6 @@ 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 SwController = require('sw-controller') +const SwStream = require('sw-stream') const MetaMaskUiCss = require('../../ui/css') const MetamascaraPlatform = require('../../app/scripts/platforms/window') const startPopup = require('../../app/scripts/popup-core') @@ -8,27 +8,44 @@ 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' +const name = 'popup' window.METAMASK_UI_TYPE = name window.METAMASK_PLATFORM_TYPE = 'mascara' -const intervalDelay = Math.floor(Math.random() * (30000 - 1000)) + 1000 +const keepAliveDelay = Math.floor(Math.random() * (30000 - 1000)) + 1000 -const background = new SWcontroller({ - fileName: '/background.js', - letBeIdle: false, - intervalDelay, - wakeUpInterval: 20000, +const swController = new SwController({ + fileName: './background.js', + keepAlive: true, + keepAliveDelay, + keepAliveInterval: 20000, }) + +swController.once('updatefound', windowReload) +swController.once('ready', async () => { + try { + swController.removeListener('updatefound', windowReload) + console.log('swController ready') + await timeout(1000) + console.log('connecting to app') + await connectApp() + console.log('app connected') + } catch (err) { + console.error(err) + } +}) + +console.log('starting service worker') +swController.startWorker() + // Setup listener for when the service worker is read -const connectApp = function (readSw) { +function connectApp() { const connectionStream = SwStream({ - serviceWorker: background.controller, + serviceWorker: swController.getWorker(), context: name, }) return new Promise((resolve, reject) => { @@ -43,19 +60,6 @@ const connectApp = function (readSw) { }) }) } -background.on('ready', async (sw) => { - try { - background.removeListener('updatefound', connectApp) - await timeout(1000) - await connectApp(sw) - console.log('hello from cb ready event!') - } catch (e) { - console.error(e) - } -}) -background.on('updatefound', windowReload) - -background.startWorker() function windowReload () { if (window.METAMASK_SKIP_RELOAD) return diff --git a/mascara/ui/index.html b/mascara/ui/index.html index eac8e4898..dbc445891 100644 --- a/mascara/ui/index.html +++ b/mascara/ui/index.html @@ -7,6 +7,6 @@
- + - \ No newline at end of file + diff --git a/old-ui/app/app.js b/old-ui/app/app.js index c79ac633a..e9ab185f3 100644 --- a/old-ui/app/app.js +++ b/old-ui/app/app.js @@ -171,7 +171,7 @@ App.prototype.renderAppBar = function () { h('img', { height: 24, width: 24, - src: '/images/icon-128.png', + src: './images/icon-128.png', }), h(NetworkIndicator, { diff --git a/package-lock.json b/package-lock.json index f0f76919a..504f2f1d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3125,11 +3125,6 @@ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=" }, - "client-sw-ready-event": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/client-sw-ready-event/-/client-sw-ready-event-3.4.0.tgz", - "integrity": "sha1-/0hkYXaQVed0hXDxrvECuGdbZtA=" - }, "cliui": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", @@ -8192,6 +8187,11 @@ "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", "dev": true }, + "get-own-enumerable-property-symbols": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-2.0.1.tgz", + "integrity": "sha512-TtY/sbOemiMKPRUDDanGCSgBYe7Mf0vbRsWnBZ+9yghpZ1MvcpSpuZFjHdEeY/LZjZy0vdLjS77L6HosisFiug==" + }, "get-stdin": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-3.0.2.tgz", @@ -8628,6 +8628,52 @@ } } }, + "gulp-debug": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/gulp-debug/-/gulp-debug-3.2.0.tgz", + "integrity": "sha512-2LZzP+ydczqz1rhqq/NYxvVvYTmOa0IgBl2B1sQTdkQgku9ayOUM/KHuGPjF4QA5aO1VcG+Sskw7iCcRUqHKkA==", + "requires": { + "chalk": "2.3.2", + "fancy-log": "1.3.2", + "plur": "2.1.2", + "stringify-object": "3.2.2", + "through2": "2.0.3", + "tildify": "1.2.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "1.9.1" + } + }, + "chalk": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.3.2.tgz", + "integrity": "sha512-ZM4j2/ld/YZDc3Ma8PgN7gyAk+kHMMMyzLNryCPGhWrsfAuDVeuid5bpRFTDgMH9JBK2lA4dyyAkkZYF/WcqDQ==", + "requires": { + "ansi-styles": "3.2.1", + "escape-string-regexp": "1.0.5", + "supports-color": "5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "supports-color": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.3.0.tgz", + "integrity": "sha512-0aP01LLIskjKs3lq52EC0aGBAJhLq7B2Rd8HC/DR/PtNNpcLilNmHC12O+hu0usQpo7wtHNRqtrhBwtDb0+dNg==", + "requires": { + "has-flag": "3.0.0" + } + } + } + }, "gulp-eslint": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/gulp-eslint/-/gulp-eslint-4.0.0.tgz", @@ -9204,7 +9250,7 @@ "dev": true, "requires": { "anymatch": "1.3.2", - "chokidar": "2.0.1", + "chokidar": "2.0.3", "glob-parent": "3.1.0", "gulp-util": "3.0.8", "object-assign": "4.1.1", @@ -9228,9 +9274,9 @@ "dev": true }, "braces": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.0.tgz", - "integrity": "sha512-P4O8UQRdGiMLWSizsApmXVQDBS6KCt7dSexgLKBmH5Hr1CZq7vsnscFh8oR1sP1ab1Zj0uCHCEzZeV6SfUf3rA==", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.1.tgz", + "integrity": "sha512-SO5lYHA3vO6gz66erVvedSCkp7AKWdv6VcQ2N4ysXfPxdAlxAMMAdwegGGcv1Bqwm7naF1hNdk5d6AAIEHV2nQ==", "dev": true, "requires": { "arr-flatten": "1.1.0", @@ -9239,22 +9285,43 @@ "extend-shallow": "2.0.1", "fill-range": "4.0.0", "isobject": "3.0.1", + "kind-of": "6.0.2", "repeat-element": "1.1.2", "snapdragon": "0.8.1", "snapdragon-node": "2.1.1", "split-string": "3.1.0", - "to-regex": "3.0.1" + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } } }, "chokidar": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.1.tgz", - "integrity": "sha512-rv5iP8ENhpqvDWr677rAXcB+SMoPQ1urd4ch79+PhM4lQwbATdJUQK69t0lJIKNB+VXpqxt5V1gvqs59XEPKnw==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.0.3.tgz", + "integrity": "sha512-zW8iXYZtXMx4kux/nuZVXjkLP+CyIK5Al5FHnj1OgTKGZfp4Oy6/ymtMSKFv3GD8DviEmUPmJg9eFdJ/JzudMg==", "dev": true, "requires": { "anymatch": "2.0.0", "async-each": "1.0.1", - "braces": "2.3.0", + "braces": "2.3.1", "fsevents": "1.1.3", "glob-parent": "3.1.0", "inherits": "2.0.3", @@ -9263,7 +9330,7 @@ "normalize-path": "2.1.1", "path-is-absolute": "1.0.1", "readdirp": "2.1.0", - "upath": "1.0.0" + "upath": "1.0.4" }, "dependencies": { "anymatch": { @@ -9272,12 +9339,22 @@ "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", "dev": true, "requires": { - "micromatch": "3.1.5", + "micromatch": "3.1.10", "normalize-path": "2.1.1" } } } }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + } + }, "expand-brackets": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", @@ -9290,7 +9367,7 @@ "posix-character-classes": "0.1.1", "regex-not": "1.0.0", "snapdragon": "0.8.1", - "to-regex": "3.0.1" + "to-regex": "3.0.2" }, "dependencies": { "define-property": { @@ -9301,6 +9378,53 @@ "requires": { "is-descriptor": "0.1.6" } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + }, + "is-descriptor": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", + "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", + "dev": true, + "requires": { + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" + } + }, + "kind-of": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", + "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "dev": true + } + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + }, + "dependencies": { + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } } } }, @@ -9317,7 +9441,27 @@ "fragment-cache": "0.2.1", "regex-not": "1.0.0", "snapdragon": "0.8.1", - "to-regex": "3.0.1" + "to-regex": "3.0.2" + }, + "dependencies": { + "define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", + "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", + "dev": true, + "requires": { + "is-descriptor": "1.0.2" + } + }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } } }, "fill-range": { @@ -9330,6 +9474,17 @@ "is-number": "3.0.0", "repeat-string": "1.6.1", "to-regex-range": "2.1.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "0.1.1" + } + } } }, "glob-parent": { @@ -9393,25 +9548,6 @@ } } }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true - } - } - }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -9460,24 +9596,48 @@ "dev": true }, "micromatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.5.tgz", - "integrity": "sha512-ykttrLPQrz1PUJcXjwsTUjGoPJ64StIGNE2lGVD1c9CuguJ+L7/navsE8IcDNndOoCMvYV0qc/exfVbMHkUhvA==", + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", "dev": true, "requires": { "arr-diff": "4.0.0", "array-unique": "0.3.2", - "braces": "2.3.0", - "define-property": "1.0.0", - "extend-shallow": "2.0.1", + "braces": "2.3.1", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", "extglob": "2.0.4", "fragment-cache": "0.2.1", "kind-of": "6.0.2", - "nanomatch": "1.2.7", + "nanomatch": "1.2.9", "object.pick": "1.3.0", "regex-not": "1.0.0", "snapdragon": "0.8.1", - "to-regex": "3.0.1" + "to-regex": "3.0.2" + } + }, + "to-regex": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", + "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", + "dev": true, + "requires": { + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" + }, + "dependencies": { + "regex-not": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", + "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", + "dev": true, + "requires": { + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" + } + } } } } @@ -10374,8 +10534,7 @@ "irregular-plurals": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-1.4.0.tgz", - "integrity": "sha1-LKmwM2UREYVUEvFr5dd8YqRYp2Y=", - "dev": true + "integrity": "sha1-LKmwM2UREYVUEvFr5dd8YqRYp2Y=" }, "is-absolute": { "version": "1.0.0", @@ -10603,23 +10762,25 @@ "integrity": "sha1-8mWrian0RQNO9q/xWo8AsA9VF5k=", "dev": true }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=" + }, "is-odd": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-1.0.0.tgz", - "integrity": "sha1-O4qTLrAos3dcObsJ6RdnrM22kIg=", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", + "integrity": "sha512-OTiixgpZAT1M4NHgS5IguFp/Vz2VI3U7Goh4/HA1adtwyLtSBrxYlcSYkhpAE07s4fKEcjrFxyvtQBND4vFQyQ==", "dev": true, "requires": { - "is-number": "3.0.0" + "is-number": "4.0.0" }, "dependencies": { "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "requires": { - "kind-of": "3.2.2" - } + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true } } }, @@ -10695,8 +10856,7 @@ "is-regexp": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=", - "dev": true + "integrity": "sha1-/S2INUXEa6xaYz57mgnof6LLUGk=" }, "is-relative": { "version": "1.0.0", @@ -13589,18 +13749,19 @@ "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=" }, "nanomatch": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.7.tgz", - "integrity": "sha512-/5ldsnyurvEw7wNpxLFgjVvBLMta43niEYOy0CJ4ntcYSbx6bugRUTQeFb4BR/WanEL1o3aQgHuVLHQaB6tOqg==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", + "integrity": "sha512-n8R9bS8yQ6eSXaV6jHUpKzD8gLsin02w1HSFiegwrs9E098Ylhw5jdyKPaYqvHknHaSCKTPp7C8dGCQ0q9koXA==", "dev": true, "requires": { "arr-diff": "4.0.0", "array-unique": "0.3.2", - "define-property": "1.0.0", - "extend-shallow": "2.0.1", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", "fragment-cache": "0.2.1", - "is-odd": "1.0.0", - "kind-of": "5.1.0", + "is-odd": "2.0.0", + "is-windows": "1.0.2", + "kind-of": "6.0.2", "object.pick": "1.3.0", "regex-not": "1.0.0", "snapdragon": "0.8.1", @@ -13619,10 +13780,45 @@ "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", "dev": true }, + "define-property": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", + "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", + "dev": true, + "requires": { + "is-descriptor": "1.0.2", + "isobject": "3.0.1" + } + }, + "extend-shallow": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", + "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", + "dev": true, + "requires": { + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" + } + }, + "is-extendable": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", + "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", + "dev": true, + "requires": { + "is-plain-object": "2.0.4" + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true + }, "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", "dev": true } } @@ -16675,7 +16871,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/plur/-/plur-2.1.2.tgz", "integrity": "sha1-dIJFLBoPUI4+NE6uwxLJHCncZVo=", - "dev": true, "requires": { "irregular-plurals": "1.4.0" } @@ -18334,6 +18529,15 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" }, + "safe-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", + "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", + "dev": true, + "requires": { + "ret": "0.1.15" + } + }, "samsam": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/samsam/-/samsam-1.3.0.tgz", @@ -19727,6 +19931,16 @@ "safe-buffer": "5.1.1" } }, + "stringify-object": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.2.2.tgz", + "integrity": "sha512-O696NF21oLiDy8PhpWu8AEqoZHw++QW6mUv0UvKZe8gWSdSvMXkiLufK7OmnP27Dro4GU5kb9U7JIO0mBuCRQg==", + "requires": { + "get-own-enumerable-property-symbols": "2.0.1", + "is-obj": "1.0.1", + "is-regexp": "1.0.0" + } + }, "stringstream": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz", @@ -20333,6 +20547,27 @@ "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=", "dev": true }, + "sw-controller": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sw-controller/-/sw-controller-1.0.3.tgz", + "integrity": "sha512-q+rS4v7kj1MPDxFRyl8GAICw/BbQzewd5HhVDNIPLnyvKtcpxi26fVXReUeUMRl4CRL/fX56PvKKqxtKhAaMpg==", + "requires": { + "babel-preset-es2015": "6.24.1", + "babel-runtime": "6.26.0", + "babelify": "7.3.0" + }, + "dependencies": { + "babelify": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/babelify/-/babelify-7.3.0.tgz", + "integrity": "sha1-qlau3nBn/XvVSWZu4W3ChQh+iOU=", + "requires": { + "babel-core": "6.26.0", + "object-assign": "4.1.1" + } + } + } + }, "sw-stream": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/sw-stream/-/sw-stream-2.0.2.tgz", @@ -20797,6 +21032,14 @@ "dev": true, "optional": true }, + "tildify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", + "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", + "requires": { + "os-homedir": "1.0.2" + } + }, "time-stamp": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz", @@ -21244,12 +21487,6 @@ "integrity": "sha1-YaajIBBiKvoHljvzJSA88SI51gQ=", "dev": true }, - "underscore.string": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/underscore.string/-/underscore.string-2.3.3.tgz", - "integrity": "sha1-ccCL9rQosRM/N+ePo6Icgvcymw0=", - "dev": true - }, "undertaker": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/undertaker/-/undertaker-1.2.0.tgz", @@ -21410,22 +21647,10 @@ } }, "upath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.0.0.tgz", - "integrity": "sha1-tHBrlGHKhHOt+JEz0jVonKF/NlY=", - "dev": true, - "requires": { - "lodash": "3.10.1", - "underscore.string": "2.3.3" - }, - "dependencies": { - "lodash": { - "version": "3.10.1", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.10.1.tgz", - "integrity": "sha1-W/Rejkm6QYnhfUgnid/RW9FAt7Y=", - "dev": true - } - } + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.0.4.tgz", + "integrity": "sha512-d4SJySNBXDaQp+DPrziv3xGS6w3d2Xt69FijJr86zMPBy23JEloMCEOUBBzuN7xCtjLCnmB9tI/z7SBCahHBOw==", + "dev": true }, "urix": { "version": "0.1.0", @@ -21713,9 +21938,9 @@ }, "dependencies": { "clone": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.3.tgz", - "integrity": "sha1-KY1+IjFmD0DAA8LtMUDezz9TCF8=", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", "dev": true }, "clone-stats": { @@ -21742,7 +21967,7 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "1.0.3", + "clone": "1.0.4", "clone-stats": "0.0.1", "replace-ext": "0.0.1" } diff --git a/package.json b/package.json index 6cd8f7f4e..a852395b3 100644 --- a/package.json +++ b/package.json @@ -4,14 +4,9 @@ "public": false, "private": true, "scripts": { - "start": "npm run dev", - "dev": "gulp dev --debug", - "ui": "npm run test:flat:build:states && beefy development/ui-dev.js:bundle.js --live --open --index=./development/index.html --cwd ./", - "mock": "beefy development/mock-dev.js:bundle.js --live --open --index=./development/index.html --cwd ./", - "watch": "mocha watch --recursive \"test/unit/**/*.js\"", - "mascara": "gulp build && cross-env METAMASK_DEBUG=true node ./mascara/example/server", - "dist": "npm run dist:clear && npm install && gulp dist", - "dist:clear": "rm -rf node_modules/eth-contract-metadata && rm -rf node_modules/eth-phishing-detect", + "start": "gulp dev:extension", + "mascara": "gulp dev:mascara & cross-env METAMASK_DEBUG=true node ./mascara/example/server", + "dist": "gulp dist", "test": "npm run test:unit && npm run test:integration && npm run lint", "test:unit": "cross-env METAMASK_ENV=test mocha --exit --require babel-core/register --require test/helper.js --recursive \"test/unit/**/*.js\"", "test:single": "cross-env METAMASK_ENV=test mocha --require test/helper.js", @@ -41,6 +36,9 @@ "sentry:upload:maps": "sentry-cli releases --org 'metamask' --project 'metamask' files $RELEASE upload-sourcemaps ./dist/sourcemaps/ --url-prefix 'sourcemaps' --rewrite", "lint": "gulp lint", "lint:fix": "gulp lint:fix", + "ui": "npm run test:flat:build:states && beefy development/ui-dev.js:bundle.js --live --open --index=./development/index.html --cwd ./", + "mock": "beefy development/mock-dev.js:bundle.js --live --open --index=./development/index.html --cwd ./", + "watch": "mocha watch --recursive \"test/unit/**/*.js\"", "disc": "gulp disc --debug", "announce": "node development/announcer.js", "version:bump": "node development/run-version-bump.js", @@ -78,7 +76,6 @@ "browserify-derequire": "^0.9.4", "browserify-unibabel": "^3.0.0", "classnames": "^2.2.5", - "client-sw-ready-event": "^3.3.0", "clone": "^2.1.1", "copy-to-clipboard": "^3.0.8", "debounce": "^1.0.0", @@ -118,6 +115,7 @@ "fuse.js": "^3.2.0", "gulp": "github:gulpjs/gulp#4.0", "gulp-autoprefixer": "^5.0.0", + "gulp-debug": "^3.2.0", "gulp-eslint": "^4.0.0", "gulp-sass": "^3.1.0", "hat": "0.0.3", @@ -180,7 +178,8 @@ "semaphore": "^1.0.5", "semver": "^5.4.1", "shallow-copy": "0.0.1", - "sw-stream": "^2.0.0", + "sw-controller": "^1.0.3", + "sw-stream": "^2.0.2", "textarea-caret": "^3.0.1", "through2": "^2.0.3", "valid-url": "^1.0.9", @@ -258,8 +257,8 @@ "react-addons-test-utils": "^15.5.1", "react-test-renderer": "^15.6.2", "react-testutils-additions": "^15.2.0", - "selenium-webdriver": "^3.5.0", "redux-test-utils": "^0.2.2", + "selenium-webdriver": "^3.5.0", "sinon": "^5.0.0", "stylelint-config-standard": "^18.2.0", "tape": "^4.5.1", diff --git a/test/e2e/metamask.spec.js b/test/e2e/metamask.spec.js index ff5bdb51b..d2ffa041e 100644 --- a/test/e2e/metamask.spec.js +++ b/test/e2e/metamask.spec.js @@ -42,7 +42,7 @@ describe('Metamask popup page', function () { it('should match title', async () => { const title = await driver.getTitle() - assert.equal(title, 'MetaMask Plugin', 'title matches MetaMask Plugin') + assert.equal(title, 'MetaMask', 'title matches MetaMask') }) it('should show privacy notice', async () => { diff --git a/ui/app/app.js b/ui/app/app.js index ea88f3039..0b7a7a1e0 100644 --- a/ui/app/app.js +++ b/ui/app/app.js @@ -294,7 +294,7 @@ App.prototype.renderAppBar = function () { h('img.metafox-icon', { height: 42, width: 42, - src: '/images/metamask-fox.svg', + src: './images/metamask-fox.svg', }), // metamask name diff --git a/ui/app/components/identicon.js b/ui/app/components/identicon.js index b803b7ceb..7cc5a4de0 100644 --- a/ui/app/components/identicon.js +++ b/ui/app/components/identicon.js @@ -47,7 +47,7 @@ IdenticonComponent.prototype.render = function () { ) : ( h('img.balance-icon', { - src: '../images/eth_logo.svg', + src: './images/eth_logo.svg', style: { height: diameter, width: diameter, diff --git a/ui/app/components/modals/deposit-ether-modal.js b/ui/app/components/modals/deposit-ether-modal.js index 8854d258f..0dc611f50 100644 --- a/ui/app/components/modals/deposit-ether-modal.js +++ b/ui/app/components/modals/deposit-ether-modal.js @@ -150,7 +150,7 @@ DepositEtherModal.prototype.render = function () { this.renderRow({ logo: h('img.deposit-ether-modal__logo', { - src: '../../../images/deposit-eth.svg', + src: './images/deposit-eth.svg', }), title: DIRECT_DEPOSIT_ROW_TITLE, text: DIRECT_DEPOSIT_ROW_TEXT, @@ -171,7 +171,7 @@ DepositEtherModal.prototype.render = function () { this.renderRow({ logo: h('div.deposit-ether-modal__logo', { style: { - backgroundImage: 'url(\'../../../images/coinbase logo.png\')', + backgroundImage: 'url(\'./images/coinbase logo.png\')', height: '40px', }, }), @@ -185,7 +185,7 @@ DepositEtherModal.prototype.render = function () { this.renderRow({ logo: h('div.deposit-ether-modal__logo', { style: { - backgroundImage: 'url(\'../../../images/shapeshift logo.png\')', + backgroundImage: 'url(\'./images/shapeshift logo.png\')', }, }), title: SHAPESHIFT_ROW_TITLE, diff --git a/ui/app/components/sender-to-recipient.js b/ui/app/components/sender-to-recipient.js index 6b9cd32ea..9cef8e401 100644 --- a/ui/app/components/sender-to-recipient.js +++ b/ui/app/components/sender-to-recipient.js @@ -46,7 +46,7 @@ class SenderToRecipient extends Component { h('img', { height: 15, width: 15, - src: '/images/arrow-right.svg', + src: './images/arrow-right.svg', }), ]), ]), diff --git a/ui/app/css/itcss/settings/typography.scss b/ui/app/css/itcss/settings/typography.scss index 8a56d9c6c..18c444c8a 100644 --- a/ui/app/css/itcss/settings/typography.scss +++ b/ui/app/css/itcss/settings/typography.scss @@ -1,4 +1,4 @@ -@import url('/fonts/Font_Awesome/font-awesome.min.css'); +@import url('./fonts/Font_Awesome/font-awesome.min.css'); @font-face { font-family: 'Roboto'; @@ -338,8 +338,8 @@ @font-face { font-family: 'Montserrat Regular'; - src: url('/fonts/Montserrat/Montserrat-Regular.woff') format('woff'); - src: url('/fonts/Montserrat/Montserrat-Regular.ttf') format('truetype'); + src: url('./fonts/Montserrat/Montserrat-Regular.woff') format('woff'); + src: url('./fonts/Montserrat/Montserrat-Regular.ttf') format('truetype'); font-weight: 400; font-style: normal; font-size: 'small'; @@ -347,59 +347,59 @@ @font-face { font-family: 'Montserrat Bold'; - src: url('/fonts/Montserrat/Montserrat-Bold.woff') format('woff'); - src: url('/fonts/Montserrat/Montserrat-Bold.ttf') format('truetype'); + src: url('./fonts/Montserrat/Montserrat-Bold.woff') format('woff'); + src: url('./fonts/Montserrat/Montserrat-Bold.ttf') format('truetype'); font-weight: 400; font-style: normal; } @font-face { font-family: 'Montserrat Light'; - src: url('/fonts/Montserrat/Montserrat-Light.woff') format('woff'); - src: url('/fonts/Montserrat/Montserrat-Light.ttf') format('truetype'); + src: url('./fonts/Montserrat/Montserrat-Light.woff') format('woff'); + src: url('./fonts/Montserrat/Montserrat-Light.ttf') format('truetype'); font-weight: 400; font-style: normal; } @font-face { font-family: 'Montserrat UltraLight'; - src: url('/fonts/Montserrat/Montserrat-UltraLight.woff') format('woff'); - src: url('/fonts/Montserrat/Montserrat-UltraLight.ttf') format('truetype'); + src: url('./fonts/Montserrat/Montserrat-UltraLight.woff') format('woff'); + src: url('./fonts/Montserrat/Montserrat-UltraLight.ttf') format('truetype'); font-weight: 400; font-style: normal; } @font-face { font-family: 'DIN OT'; - src: url('/fonts/DIN_OT/DINOT-2.otf') format('opentype'); + src: url('./fonts/DIN_OT/DINOT-2.otf') format('opentype'); font-weight: 400; font-style: normal; } @font-face { font-family: 'DIN OT Light'; - src: url('/fonts/DIN_OT/DINOT-2.otf') format('opentype'); + src: url('./fonts/DIN_OT/DINOT-2.otf') format('opentype'); font-weight: 200; font-style: normal; } @font-face { font-family: 'DIN NEXT'; - src: url('/fonts/DIN Next/DIN Next W01 Regular.otf') format('opentype'); + src: url('./fonts/DIN Next/DIN Next W01 Regular.otf') format('opentype'); font-weight: 400; font-style: normal; } @font-face { font-family: 'DIN NEXT Light'; - src: url('/fonts/DIN Next/DIN Next W10 Light.otf') format('opentype'); + src: url('./fonts/DIN Next/DIN Next W10 Light.otf') format('opentype'); font-weight: 400; font-style: normal; } @font-face { font-family: 'Lato'; - src: url('/fonts/Lato/Lato-Regular.ttf') format('truetype'); + src: url('./fonts/Lato/Lato-Regular.ttf') format('truetype'); font-weight: 400; font-style: normal; } diff --git a/ui/app/settings.js b/ui/app/settings.js index e91ac7340..3aa7b9c6b 100644 --- a/ui/app/settings.js +++ b/ui/app/settings.js @@ -108,11 +108,12 @@ class Settings extends Component { renderCurrentLocale () { const { updateCurrentLocale, currentLocale } = this.props const currentLocaleMeta = locales.find(locale => locale.code === currentLocale) + const currentLocaleName = currentLocaleMeta ? currentLocaleMeta.name : '' return h('div.settings__content-row', [ h('div.settings__content-item', [ h('span', 'Current Language'), - h('span.settings__content-description', `${currentLocaleMeta.name}`), + h('span.settings__content-description', `${currentLocaleName}`), ]), h('div.settings__content-item', [ h('div.settings__content-item-col', [ diff --git a/ui/i18n-helper.js b/ui/i18n-helper.js index 3ce24ddfb..db2fd2dc4 100644 --- a/ui/i18n-helper.js +++ b/ui/i18n-helper.js @@ -27,7 +27,7 @@ const getMessage = (locale, key, substitutions) => { function fetchLocale (localeName) { return new Promise((resolve, reject) => { - return fetch(`/_locales/${localeName}/messages.json`) + return fetch(`./_locales/${localeName}/messages.json`) .then(response => response.json()) .then( locale => resolve(locale),