chore: make rpc-server reply to sender frame instead of the main frame (#15973)
* chore: make rpc-server reply to frame * fix: check IsRenderFrameLive
This commit is contained in:
parent
eb8fcf833c
commit
db2fda1b6f
5 changed files with 51 additions and 10 deletions
|
@ -1674,6 +1674,23 @@ bool WebContents::SendIPCMessageWithSender(bool internal,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool WebContents::SendIPCMessageToFrame(bool internal,
|
||||
bool send_to_all,
|
||||
int32_t frame_id,
|
||||
const std::string& channel,
|
||||
const base::ListValue& args) {
|
||||
auto frames = web_contents()->GetAllFrames();
|
||||
auto iter = std::find_if(frames.begin(), frames.end(), [frame_id](auto* f) {
|
||||
return f->GetRoutingID() == frame_id;
|
||||
});
|
||||
if (iter == frames.end())
|
||||
return false;
|
||||
if (!(*iter)->IsRenderFrameLive())
|
||||
return false;
|
||||
return (*iter)->Send(new AtomFrameMsg_Message(
|
||||
frame_id, internal, send_to_all, channel, args, 0 /* sender_id */));
|
||||
}
|
||||
|
||||
void WebContents::SendInputEvent(v8::Isolate* isolate,
|
||||
v8::Local<v8::Value> input_event) {
|
||||
content::RenderWidgetHostView* view =
|
||||
|
@ -2119,6 +2136,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
|
|||
.SetMethod("isFocused", &WebContents::IsFocused)
|
||||
.SetMethod("tabTraverse", &WebContents::TabTraverse)
|
||||
.SetMethod("_send", &WebContents::SendIPCMessage)
|
||||
.SetMethod("_sendToFrame", &WebContents::SendIPCMessageToFrame)
|
||||
.SetMethod("sendInputEvent", &WebContents::SendInputEvent)
|
||||
.SetMethod("beginFrameSubscription", &WebContents::BeginFrameSubscription)
|
||||
.SetMethod("endFrameSubscription", &WebContents::EndFrameSubscription)
|
||||
|
@ -2183,7 +2201,7 @@ void WebContents::OnRendererMessage(content::RenderFrameHost* frame_host,
|
|||
const std::string& channel,
|
||||
const base::ListValue& args) {
|
||||
// webContents.emit(channel, new Event(), args...);
|
||||
Emit(channel, args);
|
||||
EmitWithSender(channel, frame_host, nullptr, args);
|
||||
}
|
||||
|
||||
void WebContents::OnRendererMessageSync(content::RenderFrameHost* frame_host,
|
||||
|
|
|
@ -218,6 +218,12 @@ class WebContents : public mate::TrackableObject<WebContents>,
|
|||
const base::ListValue& args,
|
||||
int32_t sender_id = 0);
|
||||
|
||||
bool SendIPCMessageToFrame(bool internal,
|
||||
bool send_to_all,
|
||||
int32_t frame_id,
|
||||
const std::string& channel,
|
||||
const base::ListValue& args);
|
||||
|
||||
// Send WebInputEvent to the page.
|
||||
void SendInputEvent(v8::Isolate* isolate, v8::Local<v8::Value> input_event);
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include "atom/browser/api/event_emitter.h"
|
||||
|
||||
#include "atom/browser/api/event.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "native_mate/arguments.h"
|
||||
#include "native_mate/dictionary.h"
|
||||
#include "native_mate/object_template_builder.h"
|
||||
|
@ -56,6 +57,8 @@ v8::Local<v8::Object> CreateJSEvent(v8::Isolate* isolate,
|
|||
event = CreateEventObject(isolate);
|
||||
}
|
||||
mate::Dictionary(isolate, event).Set("sender", object);
|
||||
if (sender)
|
||||
mate::Dictionary(isolate, event).Set("frameId", sender->GetRoutingID());
|
||||
return event;
|
||||
}
|
||||
|
||||
|
|
|
@ -142,6 +142,18 @@ WebContents.prototype._sendInternalToAll = function (channel, ...args) {
|
|||
|
||||
return this._send(internal, sendToAll, channel, args)
|
||||
}
|
||||
WebContents.prototype._sendToFrameInternal = function (frameId, channel, ...args) {
|
||||
if (typeof channel !== 'string') {
|
||||
throw new Error('Missing required channel argument')
|
||||
} else if (typeof frameId !== 'number') {
|
||||
throw new Error('Missing required frameId argument')
|
||||
}
|
||||
|
||||
const internal = true
|
||||
const sendToAll = false
|
||||
|
||||
return this._sendToFrame(internal, sendToAll, frameId, channel, args)
|
||||
}
|
||||
|
||||
// Following methods are mapped to webFrame.
|
||||
const webFrameMethods = [
|
||||
|
|
|
@ -174,7 +174,7 @@ const removeRemoteListenersAndLogWarning = (sender, callIntoRenderer) => {
|
|||
}
|
||||
|
||||
// Convert array of meta data from renderer into array of real values.
|
||||
const unwrapArgs = function (sender, contextId, args) {
|
||||
const unwrapArgs = function (sender, frameId, contextId, args) {
|
||||
const metaToValue = function (meta) {
|
||||
switch (meta.type) {
|
||||
case 'value':
|
||||
|
@ -182,7 +182,7 @@ const unwrapArgs = function (sender, contextId, args) {
|
|||
case 'remote-object':
|
||||
return objectsRegistry.get(meta.id)
|
||||
case 'array':
|
||||
return unwrapArgs(sender, contextId, meta.value)
|
||||
return unwrapArgs(sender, frameId, contextId, meta.value)
|
||||
case 'buffer':
|
||||
return bufferUtils.metaToBuffer(meta.value)
|
||||
case 'date':
|
||||
|
@ -216,9 +216,11 @@ const unwrapArgs = function (sender, contextId, args) {
|
|||
}
|
||||
|
||||
const callIntoRenderer = function (...args) {
|
||||
let succeed = false
|
||||
if (!sender.isDestroyed()) {
|
||||
sender._sendInternal('ELECTRON_RENDERER_CALLBACK', contextId, meta.id, valueToMeta(sender, contextId, args))
|
||||
} else {
|
||||
succeed = sender._sendToFrameInternal(frameId, 'ELECTRON_RENDERER_CALLBACK', contextId, meta.id, valueToMeta(sender, contextId, args))
|
||||
}
|
||||
if (!succeed) {
|
||||
removeRemoteListenersAndLogWarning(this, callIntoRenderer)
|
||||
}
|
||||
}
|
||||
|
@ -334,7 +336,7 @@ handleRemoteCommand('ELECTRON_BROWSER_CURRENT_WEB_CONTENTS', function (event, co
|
|||
})
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_CONSTRUCTOR', function (event, contextId, id, args) {
|
||||
args = unwrapArgs(event.sender, contextId, args)
|
||||
args = unwrapArgs(event.sender, event.frameId, contextId, args)
|
||||
const constructor = objectsRegistry.get(id)
|
||||
|
||||
if (constructor == null) {
|
||||
|
@ -345,7 +347,7 @@ handleRemoteCommand('ELECTRON_BROWSER_CONSTRUCTOR', function (event, contextId,
|
|||
})
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_FUNCTION_CALL', function (event, contextId, id, args) {
|
||||
args = unwrapArgs(event.sender, contextId, args)
|
||||
args = unwrapArgs(event.sender, event.frameId, contextId, args)
|
||||
const func = objectsRegistry.get(id)
|
||||
|
||||
if (func == null) {
|
||||
|
@ -356,7 +358,7 @@ handleRemoteCommand('ELECTRON_BROWSER_FUNCTION_CALL', function (event, contextId
|
|||
})
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_MEMBER_CONSTRUCTOR', function (event, contextId, id, method, args) {
|
||||
args = unwrapArgs(event.sender, contextId, args)
|
||||
args = unwrapArgs(event.sender, event.frameId, contextId, args)
|
||||
const object = objectsRegistry.get(id)
|
||||
|
||||
if (object == null) {
|
||||
|
@ -367,7 +369,7 @@ handleRemoteCommand('ELECTRON_BROWSER_MEMBER_CONSTRUCTOR', function (event, cont
|
|||
})
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_MEMBER_CALL', function (event, contextId, id, method, args) {
|
||||
args = unwrapArgs(event.sender, contextId, args)
|
||||
args = unwrapArgs(event.sender, event.frameId, contextId, args)
|
||||
const obj = objectsRegistry.get(id)
|
||||
|
||||
if (obj == null) {
|
||||
|
@ -378,7 +380,7 @@ handleRemoteCommand('ELECTRON_BROWSER_MEMBER_CALL', function (event, contextId,
|
|||
})
|
||||
|
||||
handleRemoteCommand('ELECTRON_BROWSER_MEMBER_SET', function (event, contextId, id, name, args) {
|
||||
args = unwrapArgs(event.sender, contextId, args)
|
||||
args = unwrapArgs(event.sender, event.frameId, contextId, args)
|
||||
const obj = objectsRegistry.get(id)
|
||||
|
||||
if (obj == null) {
|
||||
|
|
Loading…
Reference in a new issue