feat: MessagePorts in the main process (#22404)

This commit is contained in:
Jeremy Apthorp 2020-03-11 18:07:54 -07:00 committed by GitHub
parent c4c0888972
commit b4d07f76d3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
34 changed files with 1316 additions and 113 deletions

View file

@ -15,10 +15,13 @@
#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/function_template_extensions.h"
#include "shell/common/gin_helper/promise.h"
#include "shell/common/node_bindings.h"
#include "shell/common/node_includes.h"
#include "shell/common/v8_value_serializer.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_message_port_converter.h"
using blink::WebLocalFrame;
using content::RenderFrame;
@ -57,7 +60,8 @@ class IPCRenderer : public gin::Wrappable<IPCRenderer> {
.SetMethod("sendSync", &IPCRenderer::SendSync)
.SetMethod("sendTo", &IPCRenderer::SendTo)
.SetMethod("sendToHost", &IPCRenderer::SendToHost)
.SetMethod("invoke", &IPCRenderer::Invoke);
.SetMethod("invoke", &IPCRenderer::Invoke)
.SetMethod("postMessage", &IPCRenderer::PostMessage);
}
const char* GetTypeName() override { return "IPCRenderer"; }
@ -68,7 +72,7 @@ class IPCRenderer : public gin::Wrappable<IPCRenderer> {
const std::string& channel,
v8::Local<v8::Value> arguments) {
blink::CloneableMessage message;
if (!gin::ConvertFromV8(isolate, arguments, &message)) {
if (!electron::SerializeV8Value(isolate, arguments, &message)) {
return;
}
electron_browser_ptr_->Message(internal, channel, std::move(message));
@ -79,7 +83,7 @@ class IPCRenderer : public gin::Wrappable<IPCRenderer> {
const std::string& channel,
v8::Local<v8::Value> arguments) {
blink::CloneableMessage message;
if (!gin::ConvertFromV8(isolate, arguments, &message)) {
if (!electron::SerializeV8Value(isolate, arguments, &message)) {
return v8::Local<v8::Promise>();
}
gin_helper::Promise<blink::CloneableMessage> p(isolate);
@ -95,6 +99,43 @@ class IPCRenderer : public gin::Wrappable<IPCRenderer> {
return handle;
}
void PostMessage(v8::Isolate* isolate,
gin_helper::ErrorThrower thrower,
const std::string& channel,
v8::Local<v8::Value> message_value,
base::Optional<v8::Local<v8::Value>> transfer) {
blink::TransferableMessage transferable_message;
if (!electron::SerializeV8Value(isolate, message_value,
&transferable_message)) {
// SerializeV8Value sets an exception.
return;
}
std::vector<v8::Local<v8::Object>> transferables;
if (transfer) {
if (!gin::ConvertFromV8(isolate, *transfer, &transferables)) {
thrower.ThrowTypeError("Invalid value for transfer");
return;
}
}
std::vector<blink::MessagePortChannel> ports;
for (auto& transferable : transferables) {
base::Optional<blink::MessagePortChannel> port =
blink::WebMessagePortConverter::
DisentangleAndExtractMessagePortChannel(isolate, transferable);
if (!port.has_value()) {
thrower.ThrowTypeError("Invalid value for transfer");
return;
}
ports.emplace_back(port.value());
}
transferable_message.ports = std::move(ports);
electron_browser_ptr_->ReceivePostMessage(channel,
std::move(transferable_message));
}
void SendTo(v8::Isolate* isolate,
bool internal,
bool send_to_all,
@ -102,7 +143,7 @@ class IPCRenderer : public gin::Wrappable<IPCRenderer> {
const std::string& channel,
v8::Local<v8::Value> arguments) {
blink::CloneableMessage message;
if (!gin::ConvertFromV8(isolate, arguments, &message)) {
if (!electron::SerializeV8Value(isolate, arguments, &message)) {
return;
}
electron_browser_ptr_->MessageTo(internal, send_to_all, web_contents_id,
@ -113,25 +154,25 @@ class IPCRenderer : public gin::Wrappable<IPCRenderer> {
const std::string& channel,
v8::Local<v8::Value> arguments) {
blink::CloneableMessage message;
if (!gin::ConvertFromV8(isolate, arguments, &message)) {
if (!electron::SerializeV8Value(isolate, arguments, &message)) {
return;
}
electron_browser_ptr_->MessageHost(channel, std::move(message));
}
blink::CloneableMessage SendSync(v8::Isolate* isolate,
bool internal,
const std::string& channel,
v8::Local<v8::Value> arguments) {
v8::Local<v8::Value> SendSync(v8::Isolate* isolate,
bool internal,
const std::string& channel,
v8::Local<v8::Value> arguments) {
blink::CloneableMessage message;
if (!gin::ConvertFromV8(isolate, arguments, &message)) {
return blink::CloneableMessage();
if (!electron::SerializeV8Value(isolate, arguments, &message)) {
return v8::Local<v8::Value>();
}
blink::CloneableMessage result;
electron_browser_ptr_->MessageSync(internal, channel, std::move(message),
&result);
return result;
return electron::DeserializeV8Value(isolate, result);
}
electron::mojom::ElectronBrowserPtr electron_browser_ptr_;

View file

@ -11,6 +11,7 @@
#include "base/environment.h"
#include "base/macros.h"
#include "base/threading/thread_restrictions.h"
#include "gin/data_object_builder.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "shell/common/electron_constants.h"
#include "shell/common/gin_converters/blink_converter.h"
@ -18,10 +19,12 @@
#include "shell/common/heap_snapshot.h"
#include "shell/common/node_includes.h"
#include "shell/common/options_switches.h"
#include "shell/common/v8_value_serializer.h"
#include "shell/renderer/electron_render_frame_observer.h"
#include "shell/renderer/renderer_client_base.h"
#include "third_party/blink/public/web/blink.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/public/web/web_message_port_converter.h"
namespace electron {
@ -74,6 +77,7 @@ void InvokeIpcCallback(v8::Local<v8::Context> context,
void EmitIPCEvent(v8::Local<v8::Context> context,
bool internal,
const std::string& channel,
std::vector<v8::Local<v8::Value>> ports,
v8::Local<v8::Value> args,
int32_t sender_id) {
auto* isolate = context->GetIsolate();
@ -85,7 +89,8 @@ void EmitIPCEvent(v8::Local<v8::Context> context,
std::vector<v8::Local<v8::Value>> argv = {
gin::ConvertToV8(isolate, internal), gin::ConvertToV8(isolate, channel),
args, gin::ConvertToV8(isolate, sender_id)};
gin::ConvertToV8(isolate, ports), args,
gin::ConvertToV8(isolate, sender_id)};
InvokeIpcCallback(context, "onMessage", argv);
}
@ -161,7 +166,7 @@ void ElectronApiServiceImpl::Message(bool internal,
v8::Local<v8::Value> args = gin::ConvertToV8(isolate, arguments);
EmitIPCEvent(context, internal, channel, args, sender_id);
EmitIPCEvent(context, internal, channel, {}, args, sender_id);
// Also send the message to all sub-frames.
// TODO(MarshallOfSound): Completely move this logic to the main process
@ -171,11 +176,39 @@ void ElectronApiServiceImpl::Message(bool internal,
if (child->IsWebLocalFrame()) {
v8::Local<v8::Context> child_context =
renderer_client_->GetContext(child->ToWebLocalFrame(), isolate);
EmitIPCEvent(child_context, internal, channel, args, sender_id);
EmitIPCEvent(child_context, internal, channel, {}, args, sender_id);
}
}
}
void ElectronApiServiceImpl::ReceivePostMessage(
const std::string& channel,
blink::TransferableMessage message) {
blink::WebLocalFrame* frame = render_frame()->GetWebFrame();
if (!frame)
return;
v8::Isolate* isolate = blink::MainThreadIsolate();
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = renderer_client_->GetContext(frame, isolate);
v8::Context::Scope context_scope(context);
v8::Local<v8::Value> message_value = DeserializeV8Value(isolate, message);
std::vector<v8::Local<v8::Value>> ports;
for (auto& port : message.ports) {
ports.emplace_back(
blink::WebMessagePortConverter::EntangleAndInjectMessagePortChannel(
context, std::move(port)));
}
std::vector<v8::Local<v8::Value>> args = {message_value};
EmitIPCEvent(context, false, channel, ports, gin::ConvertToV8(isolate, args),
0);
}
#if BUILDFLAG(ENABLE_REMOTE_MODULE)
void ElectronApiServiceImpl::DereferenceRemoteJSCallback(
const std::string& context_id,
@ -198,7 +231,7 @@ void ElectronApiServiceImpl::DereferenceRemoteJSCallback(
args.AppendInteger(object_id);
v8::Local<v8::Value> v8_args = gin::ConvertToV8(isolate, args);
EmitIPCEvent(context, true /* internal */, channel, v8_args,
EmitIPCEvent(context, true /* internal */, channel, {}, v8_args,
0 /* sender_id */);
}
#endif

View file

@ -33,6 +33,8 @@ class ElectronApiServiceImpl : public mojom::ElectronRenderer,
const std::string& channel,
blink::CloneableMessage arguments,
int32_t sender_id) override;
void ReceivePostMessage(const std::string& channel,
blink::TransferableMessage message) override;
#if BUILDFLAG(ENABLE_REMOTE_MODULE)
void DereferenceRemoteJSCallback(const std::string& context_id,
int32_t object_id) override;