diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index de5794315a87..fdc1be59ea59 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -1019,6 +1019,7 @@ bool WebContents::OnMessageReceived(const IPC::Message& message, IPC_MESSAGE_HANDLER(AtomFrameHostMsg_Message, OnRendererMessage) IPC_MESSAGE_FORWARD_DELAY_REPLY(AtomFrameHostMsg_Message_Sync, &helper, FrameDispatchHelper::OnRendererMessageSync) + IPC_MESSAGE_HANDLER(AtomFrameHostMsg_Message_To, OnRendererMessageTo) IPC_MESSAGE_FORWARD_DELAY_REPLY( AtomFrameHostMsg_SetTemporaryZoomLevel, &helper, FrameDispatchHelper::OnSetTemporaryZoomLevel) @@ -2077,6 +2078,19 @@ void WebContents::OnRendererMessageSync(content::RenderFrameHost* frame_host, EmitWithSender(channel, frame_host, message, args); } +void WebContents::OnRendererMessageTo(content::RenderFrameHost* frame_host, + bool send_to_all, + int32_t web_contents_id, + const base::string16& channel, + const base::ListValue& args) { + auto* web_contents = mate::TrackableObject::FromWeakMapID( + isolate(), web_contents_id); + + if (web_contents) { + web_contents->SendIPCMessage(send_to_all, channel, args); + } +} + // static mate::Handle WebContents::CreateFrom( v8::Isolate* isolate, diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index b71df399da94..420d99237513 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -419,6 +419,13 @@ class WebContents : public mate::TrackableObject, const base::ListValue& args, IPC::Message* message); + // Called when received a message from renderer to be forwarded. + void OnRendererMessageTo(content::RenderFrameHost* frame_host, + bool send_to_all, + int32_t web_contents_id, + const base::string16& channel, + const base::ListValue& args); + // Called when received a synchronous message from renderer to // set temporary zoom level. void OnSetTemporaryZoomLevel(content::RenderFrameHost* frame_host, diff --git a/atom/common/api/api_messages.h b/atom/common/api/api_messages.h index e77a82fa0067..8a4127780462 100644 --- a/atom/common/api/api_messages.h +++ b/atom/common/api/api_messages.h @@ -33,6 +33,12 @@ IPC_SYNC_MESSAGE_ROUTED2_1(AtomFrameHostMsg_Message_Sync, base::ListValue /* arguments */, base::ListValue /* result */) +IPC_MESSAGE_ROUTED4(AtomFrameHostMsg_Message_To, + bool /* send_to_all */, + int32_t /* web_contents_id */, + base::string16 /* channel */, + base::ListValue /* arguments */) + IPC_MESSAGE_ROUTED3(AtomFrameMsg_Message, bool /* send_to_all */, std::string /* channel */, diff --git a/atom/renderer/api/atom_api_renderer_ipc.cc b/atom/renderer/api/atom_api_renderer_ipc.cc index 2e860e9368cb..17c5b904d634 100644 --- a/atom/renderer/api/atom_api_renderer_ipc.cc +++ b/atom/renderer/api/atom_api_renderer_ipc.cc @@ -60,6 +60,23 @@ base::ListValue SendSync(mate::Arguments* args, return result; } +void SendTo(mate::Arguments* args, + bool send_to_all, + int32_t web_contents_id, + const base::string16& channel, + const base::ListValue& arguments) { + RenderFrame* render_frame = GetCurrentRenderFrame(); + if (render_frame == nullptr) + return; + + bool success = render_frame->Send( + new AtomFrameHostMsg_Message_To(render_frame->GetRoutingID(), send_to_all, + web_contents_id, channel, arguments)); + + if (!success) + args->ThrowError("Unable to send AtomFrameHostMsg_Message_To"); +} + void Initialize(v8::Local exports, v8::Local unused, v8::Local context, @@ -67,6 +84,7 @@ void Initialize(v8::Local exports, mate::Dictionary dict(context->GetIsolate(), exports); dict.SetMethod("send", &Send); dict.SetMethod("sendSync", &SendSync); + dict.SetMethod("sendTo", &SendTo); } } // namespace api diff --git a/atom/renderer/api/atom_api_renderer_ipc.h b/atom/renderer/api/atom_api_renderer_ipc.h index 7d26016fc0df..5cc43beddc51 100644 --- a/atom/renderer/api/atom_api_renderer_ipc.h +++ b/atom/renderer/api/atom_api_renderer_ipc.h @@ -22,6 +22,12 @@ base::ListValue SendSync(mate::Arguments* args, const std::string& channel, const base::ListValue& arguments); +void SendTo(mate::Arguments* args, + bool send_to_all, + int32_t web_contents_id, + const base::string16& channel, + const base::ListValue& arguments); + void Initialize(v8::Local exports, v8::Local unused, v8::Local context, diff --git a/lib/browser/rpc-server.js b/lib/browser/rpc-server.js index ff9f77321de3..aa284864a1bf 100644 --- a/lib/browser/rpc-server.js +++ b/lib/browser/rpc-server.js @@ -5,7 +5,7 @@ const {EventEmitter} = require('events') const fs = require('fs') const v8Util = process.atomBinding('v8_util') -const {ipcMain, isPromise, webContents} = electron +const {ipcMain, isPromise} = electron const objectsRegistry = require('./objects-registry') const bufferUtils = require('../common/buffer-utils') @@ -417,20 +417,6 @@ ipcMain.on('ELECTRON_BROWSER_ASYNC_CALL_TO_GUEST_VIEW', function (event, context } }) -ipcMain.on('ELECTRON_BROWSER_SEND_TO', function (event, sendToAll, webContentsId, channel, ...args) { - let contents = webContents.fromId(webContentsId) - if (!contents) { - console.error(`Sending message to WebContents with unknown ID ${webContentsId}`) - return - } - - if (sendToAll) { - contents.sendToAll(channel, ...args) - } else { - contents.send(channel, ...args) - } -}) - // Implements window.close() ipcMain.on('ELECTRON_BROWSER_WINDOW_CLOSE', function (event) { const window = event.sender.getOwnerBrowserWindow() diff --git a/lib/renderer/api/ipc-renderer.js b/lib/renderer/api/ipc-renderer.js index 3e138c1e5b00..3c083216c126 100644 --- a/lib/renderer/api/ipc-renderer.js +++ b/lib/renderer/api/ipc-renderer.js @@ -19,19 +19,11 @@ ipcRenderer.sendToHost = function (...args) { } ipcRenderer.sendTo = function (webContentsId, channel, ...args) { - if (typeof webContentsId !== 'number') { - throw new TypeError('First argument has to be webContentsId') - } - - ipcRenderer.send('ELECTRON_BROWSER_SEND_TO', false, webContentsId, channel, ...args) + return binding.sendTo(false, webContentsId, channel, args) } ipcRenderer.sendToAll = function (webContentsId, channel, ...args) { - if (typeof webContentsId !== 'number') { - throw new TypeError('First argument has to be webContentsId') - } - - ipcRenderer.send('ELECTRON_BROWSER_SEND_TO', true, webContentsId, channel, ...args) + return binding.sendTo(true, webContentsId, channel, args) } const removeAllListeners = ipcRenderer.removeAllListeners.bind(ipcRenderer)