Merge pull request #8956 from electron/expose-crash-reporter-to-sandbox

Expose crash reporter to sandbox
This commit is contained in:
Kevin Sawicki 2017-03-27 10:09:36 -07:00 committed by GitHub
commit 6a2cdcf32f
10 changed files with 114 additions and 83 deletions

View file

@ -115,7 +115,7 @@ class AtomRenderFrameObserver : public content::RenderFrameObserver {
// an argument.
std::string bundle(node::isolated_bundle_data,
node::isolated_bundle_data + sizeof(node::isolated_bundle_data));
std::string wrapper = "(function (binding) {\n" + bundle + "\n})";
std::string wrapper = "(function (binding, require) {\n" + bundle + "\n})";
auto script = v8::Script::Compile(
mate::ConvertToV8(isolate, wrapper)->ToString());
auto func = v8::Handle<v8::Function>::Cast(

View file

@ -9,6 +9,7 @@
#include "atom_natives.h" // NOLINT: This file is generated with js2c
#include "atom/common/api/api_messages.h"
#include "atom/common/api/atom_bindings.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "atom/common/native_mate_converters/v8_value_converter.h"
#include "atom/common/native_mate_converters/value_converter.h"
@ -85,6 +86,7 @@ void InitializeBindings(v8::Local<v8::Object> binding,
auto isolate = context->GetIsolate();
mate::Dictionary b(isolate, binding);
b.SetMethod("get", GetBinding);
b.SetMethod("crash", AtomBindings::Crash);
}
class AtomSandboxedRenderFrameObserver : public content::RenderFrameObserver {
@ -204,7 +206,7 @@ void AtomSandboxedRendererClient::DidCreateScriptContext(
std::string preload_bundle_native(node::preload_bundle_data,
node::preload_bundle_data + sizeof(node::preload_bundle_data));
std::stringstream ss;
ss << "(function(binding, preloadPath) {\n";
ss << "(function(binding, preloadPath, require) {\n";
ss << preload_bundle_native << "\n";
ss << "})";
std::string preload_wrapper = ss.str();

View file

@ -441,7 +441,13 @@
'sandbox_args': [
'./lib/sandboxed_renderer/init.js',
'-r',
'./lib/sandboxed_renderer/api/exports/electron.js:electron'
'./lib/sandboxed_renderer/api/exports/electron.js:electron',
'-r',
'./lib/sandboxed_renderer/api/exports/fs.js:fs',
'-r',
'./lib/sandboxed_renderer/api/exports/os.js:os',
'-r',
'./lib/sandboxed_renderer/api/exports/child_process.js:child_process'
],
'isolated_args': [
'lib/isolated_renderer/init.js',

View file

@ -0,0 +1 @@
module.exports = require('electron').remote.require('child_process')

View file

@ -11,6 +11,12 @@ Object.defineProperties(exports, {
return require('../../../renderer/api/remote')
}
},
crashReporter: {
enumerable: true,
get: function () {
return require('../../../common/api/crash-reporter')
}
},
CallbacksRegistry: {
get: function () {
return require('../../../common/api/callbacks-registry')

View file

@ -0,0 +1 @@
module.exports = require('electron').remote.require('fs')

View file

@ -0,0 +1 @@
module.exports = require('electron').remote.require('os')

View file

@ -21,23 +21,23 @@ for (let prop of Object.keys(events.EventEmitter.prototype)) {
Object.setPrototypeOf(process, events.EventEmitter.prototype)
const electron = require('electron')
const fs = require('fs')
const preloadModules = new Map([
['electron', electron]
['child_process', require('child_process')],
['electron', electron],
['fs', fs],
['os', require('os')],
['url', require('url')],
['timers', require('timers')]
])
const extraModules = [
'fs'
]
for (let extraModule of extraModules) {
preloadModules.set(extraModule, electron.remote.require(extraModule))
}
// Fetch the preload script using the "fs" module proxy.
let preloadSrc = preloadModules.get('fs').readFileSync(preloadPath).toString()
const preloadSrc = fs.readFileSync(preloadPath).toString()
// Pass different process object to the preload script(which should not have
// access to things like `process.atomBinding`).
const preloadProcess = new events.EventEmitter()
preloadProcess.platform = electron.remote.process.platform
preloadProcess.crash = () => binding.crash()
process.on('exit', () => preloadProcess.emit('exit'))
// This is the `require` function that will be visible to the preload script
@ -67,12 +67,13 @@ function preloadRequire (module) {
// and any `require('electron')` calls in `preload.js` will work as expected
// since browserify won't try to include `electron` in the bundle, falling back
// to the `preloadRequire` function above.
let preloadWrapperSrc = `(function(require, process, Buffer, global) {
const preloadWrapperSrc = `(function(require, process, Buffer, global, setImmediate) {
${preloadSrc}
})`
// eval in window scope:
// http://www.ecma-international.org/ecma-262/5.1/#sec-10.4.2
const geval = eval
let preloadFn = geval(preloadWrapperSrc)
preloadFn(preloadRequire, preloadProcess, Buffer, global)
const preloadFn = geval(preloadWrapperSrc)
const {setImmediate} = require('timers')
preloadFn(preloadRequire, preloadProcess, Buffer, global, setImmediate)

View file

@ -11,15 +11,20 @@ const {remote} = require('electron')
const {app, BrowserWindow, crashReporter} = remote.require('electron')
describe('crashReporter module', function () {
if (process.mas) {
return
}
var fixtures = path.resolve(__dirname, 'fixtures')
const generateSpecs = (description, browserWindowOpts) => {
describe(description, function () {
var w = null
var originalTempDirectory = null
var tempDirectory = null
beforeEach(function () {
w = new BrowserWindow({
w = new BrowserWindow(Object.assign({
show: false
})
}, browserWindowOpts))
tempDirectory = temp.mkdirSync('electronCrashReporterSpec-')
originalTempDirectory = app.getPath('temp')
app.setPath('temp', tempDirectory)
@ -30,10 +35,6 @@ describe('crashReporter module', function () {
return closeWindow(w).then(function () { w = null })
})
if (process.mas) {
return
}
it('should send minidump when renderer crashes', function (done) {
if (process.env.APPVEYOR === 'True') return done()
if (process.env.TRAVIS === 'true') return done()
@ -91,6 +92,16 @@ describe('crashReporter module', function () {
done: done
})
})
})
}
generateSpecs('without sandbox', {})
generateSpecs('with sandbox ', {
webPreferences: {
sandbox: true,
preload: path.join(fixtures, 'module', 'preload-sandbox.js')
}
})
describe('.start(options)', function () {
it('requires that the companyName and submitURL options be specified', function () {

View file

@ -1,6 +1,8 @@
(function () {
const {setImmediate} = require('timers')
const {ipcRenderer} = require('electron')
window.ipcRenderer = ipcRenderer
window.setImmediate = setImmediate
if (location.protocol === 'file:') {
window.test = 'preload'
window.require = require