refactor: simplify events (#37099)

This commit is contained in:
Jeremy Rose 2023-02-13 13:39:18 -08:00 committed by GitHub
parent 8b3e498436
commit 71944f2c3b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 290 additions and 409 deletions

View file

@ -1812,6 +1812,81 @@ void WebContents::OnFirstNonEmptyLayout(
}
}
// This object wraps the InvokeCallback so that if it gets GC'd by V8, we can
// still call the callback and send an error. Not doing so causes a Mojo DCHECK,
// since Mojo requires callbacks to be called before they are destroyed.
class ReplyChannel : public gin::Wrappable<ReplyChannel> {
public:
using InvokeCallback = electron::mojom::ElectronApiIPC::InvokeCallback;
static gin::Handle<ReplyChannel> Create(v8::Isolate* isolate,
InvokeCallback callback) {
return gin::CreateHandle(isolate, new ReplyChannel(std::move(callback)));
}
// gin::Wrappable
static gin::WrapperInfo kWrapperInfo;
gin::ObjectTemplateBuilder GetObjectTemplateBuilder(
v8::Isolate* isolate) override {
return gin::Wrappable<ReplyChannel>::GetObjectTemplateBuilder(isolate)
.SetMethod("sendReply", &ReplyChannel::SendReply);
}
const char* GetTypeName() override { return "ReplyChannel"; }
private:
explicit ReplyChannel(InvokeCallback callback)
: callback_(std::move(callback)) {}
~ReplyChannel() override {
if (callback_) {
v8::Isolate* isolate = electron::JavascriptEnvironment::GetIsolate();
// If there's no current context, it means we're shutting down, so we
// don't need to send an event.
if (!isolate->GetCurrentContext().IsEmpty()) {
v8::HandleScope scope(isolate);
auto message = gin::DataObjectBuilder(isolate)
.Set("error", "reply was never sent")
.Build();
SendReply(isolate, message);
}
}
}
bool SendReply(v8::Isolate* isolate, v8::Local<v8::Value> arg) {
if (!callback_)
return false;
blink::CloneableMessage message;
if (!gin::ConvertFromV8(isolate, arg, &message)) {
return false;
}
std::move(callback_).Run(std::move(message));
return true;
}
InvokeCallback callback_;
};
gin::WrapperInfo ReplyChannel::kWrapperInfo = {gin::kEmbedderNativeGin};
gin::Handle<gin_helper::internal::Event> WebContents::MakeEventWithSender(
v8::Isolate* isolate,
content::RenderFrameHost* frame,
electron::mojom::ElectronApiIPC::InvokeCallback callback) {
v8::Local<v8::Object> wrapper;
if (!GetWrapper(isolate).ToLocal(&wrapper))
return gin::Handle<gin_helper::internal::Event>();
gin::Handle<gin_helper::internal::Event> event =
gin_helper::internal::Event::New(isolate);
gin_helper::Dictionary dict(isolate, event.ToV8().As<v8::Object>());
if (callback)
dict.Set("_replyChannel",
ReplyChannel::Create(isolate, std::move(callback)));
if (frame) {
dict.Set("frameId", frame->GetRoutingID());
dict.Set("processId", frame->GetProcess()->GetID());
}
return event;
}
void WebContents::ReceivePostMessage(
const std::string& channel,
blink::TransferableMessage message,