feat: add ContextBridgeMutability feature (#27348)
This commit is contained in:
parent
fa320eeb90
commit
e99893df22
6 changed files with 88 additions and 0 deletions
|
@ -11,6 +11,7 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "base/feature_list.h"
|
||||||
#include "base/no_destructor.h"
|
#include "base/no_destructor.h"
|
||||||
#include "base/strings/string_number_conversions.h"
|
#include "base/strings/string_number_conversions.h"
|
||||||
#include "content/public/renderer/render_frame.h"
|
#include "content/public/renderer/render_frame.h"
|
||||||
|
@ -25,6 +26,12 @@
|
||||||
#include "third_party/blink/public/web/web_element.h"
|
#include "third_party/blink/public/web/web_element.h"
|
||||||
#include "third_party/blink/public/web/web_local_frame.h"
|
#include "third_party/blink/public/web/web_local_frame.h"
|
||||||
|
|
||||||
|
namespace features {
|
||||||
|
|
||||||
|
const base::Feature kContextBridgeMutability{"ContextBridgeMutability",
|
||||||
|
base::FEATURE_DISABLED_BY_DEFAULT};
|
||||||
|
}
|
||||||
|
|
||||||
namespace electron {
|
namespace electron {
|
||||||
|
|
||||||
namespace api {
|
namespace api {
|
||||||
|
@ -554,6 +561,12 @@ void ExposeAPIInMainWorld(v8::Isolate* isolate,
|
||||||
if (maybe_proxy.IsEmpty())
|
if (maybe_proxy.IsEmpty())
|
||||||
return;
|
return;
|
||||||
auto proxy = maybe_proxy.ToLocalChecked();
|
auto proxy = maybe_proxy.ToLocalChecked();
|
||||||
|
|
||||||
|
if (base::FeatureList::IsEnabled(features::kContextBridgeMutability)) {
|
||||||
|
global.Set(key, proxy);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (proxy->IsObject() && !proxy->IsTypedArray() &&
|
if (proxy->IsObject() && !proxy->IsTypedArray() &&
|
||||||
!DeepFreeze(v8::Local<v8::Object>::Cast(proxy), main_context))
|
!DeepFreeze(v8::Local<v8::Object>::Cast(proxy), main_context))
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -5,6 +5,7 @@ import * as fs from 'fs-extra';
|
||||||
import * as http from 'http';
|
import * as http from 'http';
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import * as path from 'path';
|
import * as path from 'path';
|
||||||
|
import * as cp from 'child_process';
|
||||||
|
|
||||||
import { closeWindow } from './window-helpers';
|
import { closeWindow } from './window-helpers';
|
||||||
import { emittedOnce } from './events-helpers';
|
import { emittedOnce } from './events-helpers';
|
||||||
|
@ -1165,3 +1166,31 @@ describe('contextBridge', () => {
|
||||||
generateTests(true);
|
generateTests(true);
|
||||||
generateTests(false);
|
generateTests(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('ContextBridgeMutability', () => {
|
||||||
|
it('should not make properties unwriteable and read-only if ContextBridgeMutability is on', async () => {
|
||||||
|
const appPath = path.join(fixturesPath, 'context-bridge-mutability');
|
||||||
|
const appProcess = cp.spawn(process.execPath, ['--enable-logging', '--enable-features=ContextBridgeMutability', appPath]);
|
||||||
|
|
||||||
|
let output = '';
|
||||||
|
appProcess.stdout.on('data', data => { output += data; });
|
||||||
|
await emittedOnce(appProcess, 'exit');
|
||||||
|
|
||||||
|
expect(output).to.include('some-modified-text');
|
||||||
|
expect(output).to.include('obj-modified-prop');
|
||||||
|
expect(output).to.include('1,2,5,3,4');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should make properties unwriteable and read-only if ContextBridgeMutability is off', async () => {
|
||||||
|
const appPath = path.join(fixturesPath, 'context-bridge-mutability');
|
||||||
|
const appProcess = cp.spawn(process.execPath, ['--enable-logging', appPath]);
|
||||||
|
|
||||||
|
let output = '';
|
||||||
|
appProcess.stdout.on('data', data => { output += data; });
|
||||||
|
await emittedOnce(appProcess, 'exit');
|
||||||
|
|
||||||
|
expect(output).to.include('some-text');
|
||||||
|
expect(output).to.include('obj-prop');
|
||||||
|
expect(output).to.include('1,2,3,4');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<script>
|
||||||
|
try {
|
||||||
|
window.str = 'some-modified-text';
|
||||||
|
window.obj.prop = 'obj-modified-prop';
|
||||||
|
window.arr.splice(2, 0, 5);
|
||||||
|
} catch (e) { }
|
||||||
|
console.log(window.str);
|
||||||
|
console.log(window.obj.prop);
|
||||||
|
console.log(window.arr);
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
|
@ -0,0 +1,20 @@
|
||||||
|
const { app, BrowserWindow } = require('electron');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
let win;
|
||||||
|
app.whenReady().then(function () {
|
||||||
|
win = new BrowserWindow({
|
||||||
|
webPreferences: {
|
||||||
|
contextIsolation: true,
|
||||||
|
preload: path.join(__dirname, 'preload.js')
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
win.loadFile('index.html');
|
||||||
|
|
||||||
|
win.webContents.on('console-message', (event, level, message) => {
|
||||||
|
console.log(message);
|
||||||
|
});
|
||||||
|
|
||||||
|
win.webContents.on('did-finish-load', () => app.quit());
|
||||||
|
});
|
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"name": "context-bridge-mutability",
|
||||||
|
"main": "main.js"
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
const { contextBridge, ipcRenderer } = require('electron');
|
||||||
|
|
||||||
|
contextBridge.exposeInMainWorld('str', 'some-text');
|
||||||
|
contextBridge.exposeInMainWorld('obj', { prop: 'obj-prop' });
|
||||||
|
contextBridge.exposeInMainWorld('arr', [1, 2, 3, 4]);
|
Loading…
Reference in a new issue