Add webContents.sendToAll to send message to all frames

This commit is contained in:
Cheng Zhao 2016-05-27 16:58:49 +09:00
parent c1facec5a6
commit 9ab76fb884
7 changed files with 58 additions and 18 deletions

View file

@ -1090,7 +1090,12 @@ void WebContents::TabTraverse(bool reverse) {
bool WebContents::SendIPCMessage(const base::string16& channel, bool WebContents::SendIPCMessage(const base::string16& channel,
const base::ListValue& args) { const base::ListValue& args) {
return Send(new AtomViewMsg_Message(routing_id(), channel, args)); return Send(new AtomViewMsg_Message(routing_id(), false, channel, args));
}
bool WebContents::SendIPCMessageToAll(const base::string16& channel,
const base::ListValue& args) {
return Send(new AtomViewMsg_Message(routing_id(), true, channel, args));
} }
void WebContents::SendInputEvent(v8::Isolate* isolate, void WebContents::SendInputEvent(v8::Isolate* isolate,
@ -1258,6 +1263,7 @@ void WebContents::BuildPrototype(v8::Isolate* isolate,
.SetMethod("focus", &WebContents::Focus) .SetMethod("focus", &WebContents::Focus)
.SetMethod("tabTraverse", &WebContents::TabTraverse) .SetMethod("tabTraverse", &WebContents::TabTraverse)
.SetMethod("_send", &WebContents::SendIPCMessage) .SetMethod("_send", &WebContents::SendIPCMessage)
.SetMethod("_sendToAll", &WebContents::SendIPCMessageToAll)
.SetMethod("sendInputEvent", &WebContents::SendInputEvent) .SetMethod("sendInputEvent", &WebContents::SendInputEvent)
.SetMethod("beginFrameSubscription", .SetMethod("beginFrameSubscription",
&WebContents::BeginFrameSubscription) &WebContents::BeginFrameSubscription)

View file

@ -124,6 +124,8 @@ class WebContents : public mate::TrackableObject<WebContents>,
// Send messages to browser. // Send messages to browser.
bool SendIPCMessage(const base::string16& channel, bool SendIPCMessage(const base::string16& channel,
const base::ListValue& args); const base::ListValue& args);
bool SendIPCMessageToAll(const base::string16& channel,
const base::ListValue& args);
// Send WebInputEvent to the page. // Send WebInputEvent to the page.
void SendInputEvent(v8::Isolate* isolate, v8::Local<v8::Value> input_event); void SendInputEvent(v8::Isolate* isolate, v8::Local<v8::Value> input_event);

View file

@ -30,7 +30,8 @@ IPC_SYNC_MESSAGE_ROUTED2_1(AtomViewHostMsg_Message_Sync,
base::ListValue /* arguments */, base::ListValue /* arguments */,
base::string16 /* result (in JSON) */) base::string16 /* result (in JSON) */)
IPC_MESSAGE_ROUTED2(AtomViewMsg_Message, IPC_MESSAGE_ROUTED3(AtomViewMsg_Message,
bool /* send_to_all */,
base::string16 /* channel */, base::string16 /* channel */,
base::ListValue /* arguments */) base::ListValue /* arguments */)

View file

@ -35,7 +35,7 @@ void RemoteCallbackFreer::RunDestructor() {
base::ASCIIToUTF16("ELECTRON_RENDERER_RELEASE_CALLBACK"); base::ASCIIToUTF16("ELECTRON_RENDERER_RELEASE_CALLBACK");
base::ListValue args; base::ListValue args;
args.AppendInteger(object_id_); args.AppendInteger(object_id_);
Send(new AtomViewMsg_Message(routing_id(), channel, args)); Send(new AtomViewMsg_Message(routing_id(), false, channel, args));
Observe(nullptr); Observe(nullptr);
} }

View file

@ -59,6 +59,34 @@ std::vector<v8::Local<v8::Value>> ListValueToVector(
return result; return result;
} }
void EmitIPCEvent(blink::WebFrame* frame,
const base::string16& channel,
const base::ListValue& args) {
if (!frame || frame->isWebRemoteFrame())
return;
v8::Isolate* isolate = blink::mainThreadIsolate();
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = frame->mainWorldScriptContext();
v8::Context::Scope context_scope(context);
// Only emit IPC event for context with node integration.
node::Environment* env = node::Environment::GetCurrent(context);
if (!env)
return;
v8::Local<v8::Object> ipc;
if (GetIPCObject(isolate, context, &ipc)) {
auto args_vector = ListValueToVector(isolate, args);
// Insert the Event object, event.sender is ipc.
mate::Dictionary event = mate::Dictionary::CreateEmpty(isolate);
event.Set("sender", ipc);
args_vector.insert(args_vector.begin(), event.GetHandle());
mate::EmitEvent(isolate, ipc, channel, args_vector);
}
}
base::StringPiece NetResourceProvider(int key) { base::StringPiece NetResourceProvider(int key) {
if (key == IDR_DIR_HEADER_HTML) { if (key == IDR_DIR_HEADER_HTML) {
base::StringPiece html_data = base::StringPiece html_data =
@ -123,7 +151,8 @@ bool AtomRenderViewObserver::OnMessageReceived(const IPC::Message& message) {
return handled; return handled;
} }
void AtomRenderViewObserver::OnBrowserMessage(const base::string16& channel, void AtomRenderViewObserver::OnBrowserMessage(bool send_to_all,
const base::string16& channel,
const base::ListValue& args) { const base::ListValue& args) {
if (!document_created_) if (!document_created_)
return; return;
@ -135,20 +164,13 @@ void AtomRenderViewObserver::OnBrowserMessage(const base::string16& channel,
if (!frame || frame->isWebRemoteFrame()) if (!frame || frame->isWebRemoteFrame())
return; return;
v8::Isolate* isolate = blink::mainThreadIsolate(); EmitIPCEvent(frame, channel, args);
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Context> context = frame->mainWorldScriptContext(); // Also send the message to all sub-frames.
v8::Context::Scope context_scope(context); if (send_to_all) {
for (blink::WebFrame* child = frame->firstChild(); child;
v8::Local<v8::Object> ipc; child = child->nextSibling())
if (GetIPCObject(isolate, context, &ipc)) { EmitIPCEvent(child, channel, args);
auto args_vector = ListValueToVector(isolate, args);
// Insert the Event object, event.sender is ipc.
mate::Dictionary event = mate::Dictionary::CreateEmpty(isolate);
event.Set("sender", ipc);
args_vector.insert(args_vector.begin(), event.GetHandle());
mate::EmitEvent(isolate, ipc, channel, args_vector);
} }
} }

View file

@ -30,7 +30,8 @@ class AtomRenderViewObserver : public content::RenderViewObserver {
void DraggableRegionsChanged(blink::WebFrame* frame) override; void DraggableRegionsChanged(blink::WebFrame* frame) override;
bool OnMessageReceived(const IPC::Message& message) override; bool OnMessageReceived(const IPC::Message& message) override;
void OnBrowserMessage(const base::string16& channel, void OnBrowserMessage(bool send_to_all,
const base::string16& channel,
const base::ListValue& args); const base::ListValue& args);
// Weak reference to renderer client. // Weak reference to renderer client.

View file

@ -78,6 +78,14 @@ let wrapWebContents = function (webContents) {
return this._send(channel, args) return this._send(channel, args)
} }
// WebContents::sendToAll(channel, args..)
webContents.sendToAll = function (channel, ...args) {
if (channel == null) {
throw new Error('Missing required channel argument')
}
return this._sendToAll(channel, args)
}
// The navigation controller. // The navigation controller.
controller = new NavigationController(webContents) controller = new NavigationController(webContents)
ref1 = NavigationController.prototype ref1 = NavigationController.prototype