From fc7f2042ecb6bd43b39dd93649de0de736d4829a Mon Sep 17 00:00:00 2001 From: Milan Burda Date: Wed, 17 Mar 2021 19:23:29 +0100 Subject: [PATCH] feat: add process.contextIsolation property (#28030) --- docs/api/process.md | 6 ++++++ shell/renderer/electron_renderer_client.cc | 3 +-- .../renderer/electron_sandboxed_renderer_client.cc | 7 +++---- .../renderer/electron_sandboxed_renderer_client.h | 2 +- shell/renderer/renderer_client_base.cc | 10 +++++++--- shell/renderer/renderer_client_base.h | 6 ++++-- spec-main/api-browser-window-spec.ts | 14 ++++++++++++++ spec-main/fixtures/module/preload-sandbox.js | 1 + spec/fixtures/api/isolated-process.js | 3 +++ 9 files changed, 40 insertions(+), 12 deletions(-) create mode 100644 spec/fixtures/api/isolated-process.js diff --git a/docs/api/process.md b/docs/api/process.md index e4b5c26d550d..43a72f62ddfd 100644 --- a/docs/api/process.md +++ b/docs/api/process.md @@ -30,6 +30,7 @@ In sandboxed renderers the `process` object contains only a subset of the APIs: * `arch` * `platform` * `sandboxed` +* `contextIsolation` * `type` * `version` * `versions` @@ -94,6 +95,11 @@ A `String` representing the path to the resources directory. A `Boolean`. When the renderer process is sandboxed, this property is `true`, otherwise it is `undefined`. +### `process.contextIsolation` _Readonly_ + +A `Boolean` that indicates whether the current renderer context has `contextIsolation` enabled. +It is `undefined` in the main process. + ### `process.throwDeprecation` A `Boolean` that controls whether or not deprecation warnings will be thrown as diff --git a/shell/renderer/electron_renderer_client.cc b/shell/renderer/electron_renderer_client.cc index a577a34e4a09..74284e41285c 100644 --- a/shell/renderer/electron_renderer_client.cc +++ b/shell/renderer/electron_renderer_client.cc @@ -146,9 +146,8 @@ void ElectronRendererClient::DidCreateScriptContext( // Add Electron extended APIs. electron_bindings_->BindTo(env->isolate(), env->process_object()); - AddRenderBindings(env->isolate(), env->process_object()); gin_helper::Dictionary process_dict(env->isolate(), env->process_object()); - process_dict.SetReadOnly("isMainFrame", render_frame->IsMainFrame()); + BindProcess(env->isolate(), &process_dict, render_frame); // Load everything. node_bindings_->LoadEnvironment(env); diff --git a/shell/renderer/electron_sandboxed_renderer_client.cc b/shell/renderer/electron_sandboxed_renderer_client.cc index c6b58c06f72a..96d6eccb34af 100644 --- a/shell/renderer/electron_sandboxed_renderer_client.cc +++ b/shell/renderer/electron_sandboxed_renderer_client.cc @@ -131,7 +131,7 @@ ElectronSandboxedRendererClient::~ElectronSandboxedRendererClient() = default; void ElectronSandboxedRendererClient::InitializeBindings( v8::Local binding, v8::Local context, - bool is_main_frame) { + content::RenderFrame* render_frame) { auto* isolate = context->GetIsolate(); gin_helper::Dictionary b(isolate, binding); b.SetMethod("get", GetBinding); @@ -141,13 +141,13 @@ void ElectronSandboxedRendererClient::InitializeBindings( b.Set("process", process); ElectronBindings::BindProcess(isolate, &process, metrics_.get()); + BindProcess(isolate, &process, render_frame); process.SetMethod("uptime", Uptime); process.Set("argv", base::CommandLine::ForCurrentProcess()->argv()); process.SetReadOnly("pid", base::GetCurrentProcId()); process.SetReadOnly("sandboxed", true); process.SetReadOnly("type", "renderer"); - process.SetReadOnly("isMainFrame", is_main_frame); } void ElectronSandboxedRendererClient::RenderFrameCreated( @@ -218,8 +218,7 @@ void ElectronSandboxedRendererClient::DidCreateScriptContext( // argument. auto* isolate = context->GetIsolate(); auto binding = v8::Object::New(isolate); - InitializeBindings(binding, context, render_frame->IsMainFrame()); - AddRenderBindings(isolate, binding); + InitializeBindings(binding, context, render_frame); std::vector> sandbox_preload_bundle_params = { node::FIXED_ONE_BYTE_STRING(isolate, "binding")}; diff --git a/shell/renderer/electron_sandboxed_renderer_client.h b/shell/renderer/electron_sandboxed_renderer_client.h index ab481b422f6a..623896ff8f1c 100644 --- a/shell/renderer/electron_sandboxed_renderer_client.h +++ b/shell/renderer/electron_sandboxed_renderer_client.h @@ -21,7 +21,7 @@ class ElectronSandboxedRendererClient : public RendererClientBase { void InitializeBindings(v8::Local binding, v8::Local context, - bool is_main_frame); + content::RenderFrame* render_frame); // electron::RendererClientBase: void DidCreateScriptContext(v8::Handle context, content::RenderFrame* render_frame) override; diff --git a/shell/renderer/renderer_client_base.cc b/shell/renderer/renderer_client_base.cc index e1fde902b1d6..ef09ca770460 100644 --- a/shell/renderer/renderer_client_base.cc +++ b/shell/renderer/renderer_client_base.cc @@ -137,9 +137,13 @@ void RendererClientBase::DidCreateScriptContext( global.SetHidden("contextId", context_id); } -void RendererClientBase::AddRenderBindings( - v8::Isolate* isolate, - v8::Local binding_object) {} +void RendererClientBase::BindProcess(v8::Isolate* isolate, + gin_helper::Dictionary* process, + content::RenderFrame* render_frame) { + process->SetReadOnly("isMainFrame", render_frame->IsMainFrame()); + process->SetReadOnly("contextIsolation", + render_frame->GetBlinkPreferences().context_isolation); +} void RendererClientBase::RenderThreadStarted() { auto* command_line = base::CommandLine::ForCurrentProcess(); diff --git a/shell/renderer/renderer_client_base.h b/shell/renderer/renderer_client_base.h index 14b766b8cfdd..e0a6d4016cb1 100644 --- a/shell/renderer/renderer_client_base.h +++ b/shell/renderer/renderer_client_base.h @@ -13,6 +13,7 @@ #include "content/public/renderer/content_renderer_client.h" #include "electron/buildflags/buildflags.h" #include "printing/buildflags/buildflags.h" +#include "shell/common/gin_helper/dictionary.h" #include "third_party/blink/public/web/web_local_frame.h" // In SHARED_INTERMEDIATE_DIR. #include "widevine_cdm_version.h" // NOLINT(build/include_directory) @@ -92,8 +93,9 @@ class RendererClientBase : public content::ContentRendererClient #endif protected: - void AddRenderBindings(v8::Isolate* isolate, - v8::Local binding_object); + void BindProcess(v8::Isolate* isolate, + gin_helper::Dictionary* process, + content::RenderFrame* render_frame); // content::ContentRendererClient: void RenderThreadStarted() override; diff --git a/spec-main/api-browser-window-spec.ts b/spec-main/api-browser-window-spec.ts index 957607b85552..a62087843cfc 100644 --- a/spec-main/api-browser-window-spec.ts +++ b/spec-main/api-browser-window-spec.ts @@ -2487,6 +2487,7 @@ describe('BrowserWindow module', () => { expect(test.env).to.deep.equal(process.env); expect(test.execPath).to.equal(process.helperExecPath); expect(test.sandboxed).to.be.true('sandboxed'); + expect(test.contextIsolation).to.be.false('contextIsolation'); expect(test.type).to.equal('renderer'); expect(test.version).to.equal(process.version); expect(test.versions).to.deep.equal(process.versions); @@ -4305,6 +4306,19 @@ describe('BrowserWindow module', () => { const [, data] = await p; expect(data.pageContext.openedLocation).to.equal('about:blank'); }); + it('reports process.contextIsolation', async () => { + const iw = new BrowserWindow({ + show: false, + webPreferences: { + contextIsolation: true, + preload: path.join(fixtures, 'api', 'isolated-process.js') + } + }); + const p = emittedOnce(ipcMain, 'context-isolation'); + iw.loadURL('about:blank'); + const [, contextIsolation] = await p; + expect(contextIsolation).to.be.true('contextIsolation'); + }); }); describe('reloading with allowRendererProcessReuse enabled', () => { diff --git a/spec-main/fixtures/module/preload-sandbox.js b/spec-main/fixtures/module/preload-sandbox.js index 816b26be2497..e72aac520c5a 100644 --- a/spec-main/fixtures/module/preload-sandbox.js +++ b/spec-main/fixtures/module/preload-sandbox.js @@ -40,6 +40,7 @@ arch: process.arch, platform: process.platform, sandboxed: process.sandboxed, + contextIsolation: process.contextIsolation, type: process.type, version: process.version, versions: process.versions, diff --git a/spec/fixtures/api/isolated-process.js b/spec/fixtures/api/isolated-process.js new file mode 100644 index 000000000000..370436bfe0a0 --- /dev/null +++ b/spec/fixtures/api/isolated-process.js @@ -0,0 +1,3 @@ +const { ipcRenderer } = require('electron'); + +ipcRenderer.send('context-isolation', process.contextIsolation);