fix contextIsolation issue while webPreference sandbox is on

contextIsolation didn't work while sandbox is on. The fix is contextIsolation picked up while sandbox on
This commit is contained in:
sungpark 2017-07-27 17:08:24 -07:00
parent 485b9099f1
commit bf07c5aebd
8 changed files with 63 additions and 22 deletions

View file

@ -41,8 +41,6 @@ AtomRendererClient::AtomRendererClient()
: node_integration_initialized_(false), : node_integration_initialized_(false),
node_bindings_(NodeBindings::Create(NodeBindings::RENDERER)), node_bindings_(NodeBindings::Create(NodeBindings::RENDERER)),
atom_bindings_(new AtomBindings(uv_default_loop())) { atom_bindings_(new AtomBindings(uv_default_loop())) {
isolated_world_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kContextIsolation);
} }
AtomRendererClient::~AtomRendererClient() { AtomRendererClient::~AtomRendererClient() {
@ -171,14 +169,6 @@ void AtomRendererClient::WillDestroyWorkerContextOnWorkerThread(
} }
} }
v8::Local<v8::Context> AtomRendererClient::GetContext(
blink::WebFrame* frame, v8::Isolate* isolate) {
if (isolated_world())
return frame->WorldScriptContext(isolate, World::ISOLATED_WORLD);
else
return frame->MainWorldScriptContext();
}
void AtomRendererClient::SetupMainWorldOverrides( void AtomRendererClient::SetupMainWorldOverrides(
v8::Handle<v8::Context> context) { v8::Handle<v8::Context> context) {
// Setup window overrides in the main world context // Setup window overrides in the main world context

View file

@ -20,10 +20,6 @@ class AtomRendererClient : public RendererClientBase {
AtomRendererClient(); AtomRendererClient();
virtual ~AtomRendererClient(); virtual ~AtomRendererClient();
// Get the context that the Electron API is running in.
v8::Local<v8::Context> GetContext(
blink::WebFrame* frame, v8::Isolate* isolate);
// atom::RendererClientBase: // atom::RendererClientBase:
void DidCreateScriptContext( void DidCreateScriptContext(
v8::Handle<v8::Context> context, v8::Handle<v8::Context> context,
@ -32,7 +28,6 @@ class AtomRendererClient : public RendererClientBase {
v8::Handle<v8::Context> context, v8::Handle<v8::Context> context,
content::RenderFrame* render_frame) override; content::RenderFrame* render_frame) override;
void SetupMainWorldOverrides(v8::Handle<v8::Context> context) override; void SetupMainWorldOverrides(v8::Handle<v8::Context> context) override;
bool isolated_world() override { return isolated_world_; }
private: private:
enum NodeIntegration { enum NodeIntegration {
@ -64,7 +59,6 @@ class AtomRendererClient : public RendererClientBase {
std::unique_ptr<NodeBindings> node_bindings_; std::unique_ptr<NodeBindings> node_bindings_;
std::unique_ptr<AtomBindings> atom_bindings_; std::unique_ptr<AtomBindings> atom_bindings_;
bool isolated_world_;
DISALLOW_COPY_AND_ASSIGN(AtomRendererClient); DISALLOW_COPY_AND_ASSIGN(AtomRendererClient);
}; };

View file

@ -27,7 +27,6 @@ class AtomSandboxedRendererClient : public RendererClientBase {
v8::Handle<v8::Context> context, v8::Handle<v8::Context> context,
content::RenderFrame* render_frame) override; content::RenderFrame* render_frame) override;
void SetupMainWorldOverrides(v8::Handle<v8::Context> context) override { } void SetupMainWorldOverrides(v8::Handle<v8::Context> context) override { }
bool isolated_world() override { return false; }
// content::ContentRendererClient: // content::ContentRendererClient:
void RenderFrameCreated(content::RenderFrame*) override; void RenderFrameCreated(content::RenderFrame*) override;
void RenderViewCreated(content::RenderView*) override; void RenderViewCreated(content::RenderView*) override;

View file

@ -69,6 +69,8 @@ RendererClientBase::RendererClientBase() {
ParseSchemesCLISwitch(switches::kStandardSchemes); ParseSchemesCLISwitch(switches::kStandardSchemes);
for (const std::string& scheme : standard_schemes_list) for (const std::string& scheme : standard_schemes_list)
url::AddStandardScheme(scheme.c_str(), url::SCHEME_WITHOUT_PORT); url::AddStandardScheme(scheme.c_str(), url::SCHEME_WITHOUT_PORT);
isolated_world_ = base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kContextIsolation);
} }
RendererClientBase::~RendererClientBase() { RendererClientBase::~RendererClientBase() {
@ -197,4 +199,12 @@ void RendererClientBase::AddSupportedKeySystems(
AddChromeKeySystems(key_systems); AddChromeKeySystems(key_systems);
} }
v8::Local<v8::Context> RendererClientBase::GetContext(
blink::WebFrame* frame, v8::Isolate* isolate) {
if (isolated_world())
return frame->worldScriptContext(isolate, World::ISOLATED_WORLD);
else
return frame->mainWorldScriptContext();
}
} // namespace atom } // namespace atom

View file

@ -25,7 +25,12 @@ class RendererClientBase : public content::ContentRendererClient {
v8::Handle<v8::Context> context, content::RenderFrame* render_frame) = 0; v8::Handle<v8::Context> context, content::RenderFrame* render_frame) = 0;
virtual void DidClearWindowObject(content::RenderFrame* render_frame); virtual void DidClearWindowObject(content::RenderFrame* render_frame);
virtual void SetupMainWorldOverrides(v8::Handle<v8::Context> context) = 0; virtual void SetupMainWorldOverrides(v8::Handle<v8::Context> context) = 0;
virtual bool isolated_world() = 0;
bool isolated_world() { return isolated_world_; }
// Get the context that the Electron API is running in.
v8::Local<v8::Context> GetContext(
blink::WebFrame* frame, v8::Isolate* isolate);
protected: protected:
void AddRenderBindings(v8::Isolate* isolate, void AddRenderBindings(v8::Isolate* isolate,
@ -51,6 +56,7 @@ class RendererClientBase : public content::ContentRendererClient {
private: private:
std::unique_ptr<PreferencesManager> preferences_manager_; std::unique_ptr<PreferencesManager> preferences_manager_;
bool isolated_world_;
}; };
} // namespace atom } // namespace atom

View file

@ -17,6 +17,7 @@ const nativeModulesEnabled = remote.getGlobal('nativeModulesEnabled')
describe('BrowserWindow module', function () { describe('BrowserWindow module', function () {
var fixtures = path.resolve(__dirname, 'fixtures') var fixtures = path.resolve(__dirname, 'fixtures')
var w = null var w = null
var ws = null
var server, postData var server, postData
before(function (done) { before(function (done) {
@ -2643,7 +2644,7 @@ describe('BrowserWindow module', function () {
}) })
}) })
describe('contextIsolation option', () => { describe('contextIsolation option with and without sandbox option', () => {
const expectedContextData = { const expectedContextData = {
preloadContext: { preloadContext: {
preloadProperty: 'number', preloadProperty: 'number',
@ -2674,6 +2675,19 @@ describe('BrowserWindow module', function () {
preload: path.join(fixtures, 'api', 'isolated-preload.js') preload: path.join(fixtures, 'api', 'isolated-preload.js')
} }
}) })
if (ws != null) ws.destroy()
ws = new BrowserWindow({
show: false,
webPreferences: {
sandbox: true,
contextIsolation: true,
preload: path.join(fixtures, 'api', 'isolated-preload.js')
}
})
})
afterEach(() => {
if (ws != null) ws.destroy()
}) })
it('separates the page context from the Electron/preload context', (done) => { it('separates the page context from the Electron/preload context', (done) => {
@ -2702,6 +2716,25 @@ describe('BrowserWindow module', function () {
}) })
w.loadURL('file://' + fixtures + '/pages/window-open.html') w.loadURL('file://' + fixtures + '/pages/window-open.html')
}) })
it('separates the page context from the Electron/preload context with sandbox on', (done) => {
ipcMain.once('isolated-sandbox-world', (event, data) => {
assert.deepEqual(data, expectedContextData)
done()
})
w.loadURL('file://' + fixtures + '/api/isolated.html')
})
it('recreates the contexts on reload with sandbox on', (done) => {
w.webContents.once('did-finish-load', () => {
ipcMain.once('isolated-sandbox-world', (event, data) => {
assert.deepEqual(data, expectedContextData)
done()
})
w.webContents.reload()
})
w.loadURL('file://' + fixtures + '/api/isolated.html')
})
}) })
describe('offscreen rendering', function () { describe('offscreen rendering', function () {

View file

@ -1,14 +1,11 @@
// Ensure fetch works from isolated world origin // Ensure fetch works from isolated world origin
fetch('http://localhost:1234') fetch('http://localhost:1234')
fetch('https://localhost:1234') fetch('https://localhost:1234')
fetch(`file://${__filename}`)
const {ipcRenderer, webFrame} = require('electron') const {ipcRenderer, webFrame} = require('electron')
window.foo = 3 window.foo = 3
webFrame.executeJavaScript('window.preloadExecuteJavaScriptProperty = 1234;')
window.addEventListener('message', (event) => { window.addEventListener('message', (event) => {
ipcRenderer.send('isolated-world', { ipcRenderer.send('isolated-world', {
preloadContext: { preloadContext: {
@ -21,4 +18,15 @@ window.addEventListener('message', (event) => {
}, },
pageContext: event.data pageContext: event.data
}) })
ipcRenderer.send('isolated-sandbox-world', {
preloadContext: {
preloadProperty: typeof window.foo,
pageProperty: typeof window.hello,
typeofRequire: typeof require,
typeofProcess: typeof process,
typeofArrayPush: typeof Array.prototype.push,
typeofFunctionApply: typeof Function.prototype.apply
},
pageContext: event.data
})
}) })

View file

@ -7,6 +7,7 @@
window.hello = 'world' window.hello = 'world'
Array.prototype.push = 3 Array.prototype.push = 3
Function.prototype.apply = true Function.prototype.apply = true
window.preloadExecuteJavaScriptProperty = 1234;
const opened = window.open() const opened = window.open()
opened.close() opened.close()