fix: throw instead of crash when using ipcRenderer after context released (#23977)

Co-authored-by: Jeremy Apthorp <nornagon@nornagon.net>
This commit is contained in:
trop[bot]
2020-06-08 11:36:32 -07:00
committed by GitHub
parent 656d9e7490
commit 1f0d2594bd
2 changed files with 55 additions and 1 deletions

View File

@@ -16,6 +16,7 @@
#include "shell/common/api/api.mojom.h"
#include "shell/common/gin_converters/blink_converter.h"
#include "shell/common/gin_converters/value_converter.h"
#include "shell/common/gin_helper/error_thrower.h"
#include "shell/common/gin_helper/function_template_extensions.h"
#include "shell/common/gin_helper/promise.h"
#include "shell/common/node_bindings.h"
@@ -29,6 +30,9 @@ using content::RenderFrame;
namespace {
const char kIPCMethodCalledAfterContextReleasedError[] =
"IPC method called after context was released";
RenderFrame* GetCurrentRenderFrame() {
WebLocalFrame* frame = WebLocalFrame::FrameForCurrentContext();
if (!frame)
@@ -83,9 +87,14 @@ class IPCRenderer : public gin::Wrappable<IPCRenderer>,
private:
void SendMessage(v8::Isolate* isolate,
gin_helper::ErrorThrower thrower,
bool internal,
const std::string& channel,
v8::Local<v8::Value> arguments) {
if (!electron_browser_ptr_) {
thrower.ThrowError(kIPCMethodCalledAfterContextReleasedError);
return;
}
blink::CloneableMessage message;
if (!electron::SerializeV8Value(isolate, arguments, &message)) {
return;
@@ -94,9 +103,14 @@ class IPCRenderer : public gin::Wrappable<IPCRenderer>,
}
v8::Local<v8::Promise> Invoke(v8::Isolate* isolate,
gin_helper::ErrorThrower thrower,
bool internal,
const std::string& channel,
v8::Local<v8::Value> arguments) {
if (!electron_browser_ptr_) {
thrower.ThrowError(kIPCMethodCalledAfterContextReleasedError);
return v8::Local<v8::Promise>();
}
blink::CloneableMessage message;
if (!electron::SerializeV8Value(isolate, arguments, &message)) {
return v8::Local<v8::Promise>();
@@ -119,6 +133,10 @@ class IPCRenderer : public gin::Wrappable<IPCRenderer>,
const std::string& channel,
v8::Local<v8::Value> message_value,
base::Optional<v8::Local<v8::Value>> transfer) {
if (!electron_browser_ptr_) {
thrower.ThrowError(kIPCMethodCalledAfterContextReleasedError);
return;
}
blink::TransferableMessage transferable_message;
if (!electron::SerializeV8Value(isolate, message_value,
&transferable_message)) {
@@ -152,11 +170,16 @@ class IPCRenderer : public gin::Wrappable<IPCRenderer>,
}
void SendTo(v8::Isolate* isolate,
gin_helper::ErrorThrower thrower,
bool internal,
bool send_to_all,
int32_t web_contents_id,
const std::string& channel,
v8::Local<v8::Value> arguments) {
if (!electron_browser_ptr_) {
thrower.ThrowError(kIPCMethodCalledAfterContextReleasedError);
return;
}
blink::CloneableMessage message;
if (!electron::SerializeV8Value(isolate, arguments, &message)) {
return;
@@ -166,8 +189,13 @@ class IPCRenderer : public gin::Wrappable<IPCRenderer>,
}
void SendToHost(v8::Isolate* isolate,
gin_helper::ErrorThrower thrower,
const std::string& channel,
v8::Local<v8::Value> arguments) {
if (!electron_browser_ptr_) {
thrower.ThrowError(kIPCMethodCalledAfterContextReleasedError);
return;
}
blink::CloneableMessage message;
if (!electron::SerializeV8Value(isolate, arguments, &message)) {
return;
@@ -176,9 +204,14 @@ class IPCRenderer : public gin::Wrappable<IPCRenderer>,
}
v8::Local<v8::Value> SendSync(v8::Isolate* isolate,
gin_helper::ErrorThrower thrower,
bool internal,
const std::string& channel,
v8::Local<v8::Value> arguments) {
if (!electron_browser_ptr_) {
thrower.ThrowError(kIPCMethodCalledAfterContextReleasedError);
return v8::Local<v8::Value>();
}
blink::CloneableMessage message;
if (!electron::SerializeV8Value(isolate, arguments, &message)) {
return v8::Local<v8::Value>();

View File

@@ -9,7 +9,7 @@ describe('ipcRenderer module', () => {
let w: BrowserWindow;
before(async () => {
w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true } });
w = new BrowserWindow({ show: false, webPreferences: { nodeIntegration: true, nativeWindowOpen: true } });
await w.loadURL('about:blank');
});
after(async () => {
@@ -182,4 +182,25 @@ describe('ipcRenderer module', () => {
expect(result).to.deep.equal([]);
});
});
describe('after context is released', () => {
it('throws an exception', async () => {
const error = await w.webContents.executeJavaScript(`(${() => {
const child = window.open('', 'child', 'show=no,nodeIntegration=yes')! as any;
const childIpc = child.require('electron').ipcRenderer;
child.close();
return new Promise(resolve => {
setTimeout(() => {
try {
childIpc.send('hello');
} catch (e) {
resolve(e);
}
resolve(false);
}, 100);
});
}})()`);
expect(error).to.have.property('message', 'IPC method called after context was released');
});
});
});