From 8a722631f3b59bee898e73aad299d9950bb70844 Mon Sep 17 00:00:00 2001 From: Christophe Chapuis Date: Wed, 30 Sep 2015 19:48:02 +0200 Subject: [PATCH 04/18] Implement Sync IPC messaging through qt.webChannelTransport.sendSync Signed-off-by: Christophe Chapuis --- src/core/common/qt_messages.h | 2 ++ src/core/renderer/web_channel_ipc_transport.cpp | 42 +++++++++++++++++++++- .../web_channel_ipc_transport_host.cpp | 17 ++++++++- .../renderer_host/web_channel_ipc_transport_host.h | 3 ++ 4 files changed, 62 insertions(+), 2 deletions(-) diff --git a/src/core/common/qt_messages.h b/src/core/common/qt_messages.h index d998db2..62642cd 100644 --- a/src/core/common/qt_messages.h +++ b/src/core/common/qt_messages.h @@ -69,6 +69,8 @@ IPC_MESSAGE_ROUTED0(RenderViewObserverHostQt_DidFirstVisuallyNonEmptyLayout) IPC_MESSAGE_ROUTED1(WebChannelIPCTransportHost_SendMessage, std::vector /*binaryJSON*/) +IPC_SYNC_MESSAGE_ROUTED1_1(WebChannelIPCTransportHost_SendMessageSync, std::vector /*binaryJSON*/, std::vector /*binaryJSON*/) + //----------------------------------------------------------------------------- // Misc messages // These are messages sent from the renderer to the browser process. diff --git a/src/core/renderer/web_channel_ipc_transport.cpp b/src/core/renderer/web_channel_ipc_transport.cpp index 161d6f4..18f6b31 100644 --- a/src/core/renderer/web_channel_ipc_transport.cpp +++ b/src/core/renderer/web_channel_ipc_transport.cpp @@ -89,6 +89,44 @@ private: renderView->Send(new WebChannelIPCTransportHost_SendMessage(renderView->GetRoutingID(), std::vector(rawData, rawData + size))); } + void NativeQtSendMessageSync(gin::Arguments *args) + { + content::RenderView *renderView = GetRenderView(args->isolate()); + if (!renderView || args->Length() != 1) + return; + v8::Handle val; + args->GetNext(&val); + if (!val->IsString() && !val->IsStringObject()) + return; + v8::String::Utf8Value utf8(val->ToString()); + + QByteArray valueData(*utf8, utf8.length()); + QJsonParseError error; + QJsonDocument doc = QJsonDocument::fromJson(valueData, &error); + if (error.error != QJsonParseError::NoError) + qWarning("%s %d: Parsing error: %s",__FILE__, __LINE__, qPrintable(error.errorString())); + int size = 0; + const char *rawData = doc.rawData(&size); + + std::vector replyData; + WebChannelIPCTransportHost_SendMessageSync *message = new WebChannelIPCTransportHost_SendMessageSync(renderView->GetRoutingID(), std::vector(rawData, rawData + size), &replyData); + // Enable the UI thread in browser to receive messages. + message->EnableMessagePumping(); + renderView->Send(message); + + QJsonDocument docReply = QJsonDocument::fromRawData(replyData.data(), replyData.size(), QJsonDocument::BypassValidation); + Q_ASSERT(docReply.isObject()); + QByteArray jsonReply = docReply.toJson(QJsonDocument::Compact); + + v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::Handle replyObject(v8::Object::New(isolate)); + replyObject->ForceSet(v8::String::NewFromUtf8(isolate, "data") + , v8::String::NewFromUtf8(isolate, jsonReply.constData(), v8::String::kNormalString, jsonReply.size()) + , v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); + + args->Return(replyObject); + } + DISALLOW_COPY_AND_ASSIGN(WebChannelTransport); }; @@ -135,7 +173,9 @@ void WebChannelTransport::Uninstall(blink::WebFrame *frame, uint worldId) gin::ObjectTemplateBuilder WebChannelTransport::GetObjectTemplateBuilder(v8::Isolate *isolate) { - return gin::Wrappable::GetObjectTemplateBuilder(isolate).SetMethod("send", &WebChannelTransport::NativeQtSendMessage); + return gin::Wrappable::GetObjectTemplateBuilder(isolate) + .SetMethod("send", &WebChannelTransport::NativeQtSendMessage) + .SetMethod("sendSync", &WebChannelTransport::NativeQtSendMessageSync); } content::RenderView *WebChannelTransport::GetRenderView(v8::Isolate *isolate) diff --git a/src/core/renderer_host/web_channel_ipc_transport_host.cpp b/src/core/renderer_host/web_channel_ipc_transport_host.cpp index aef16f0..7d0cfb0 100644 --- a/src/core/renderer_host/web_channel_ipc_transport_host.cpp +++ b/src/core/renderer_host/web_channel_ipc_transport_host.cpp @@ -53,6 +53,7 @@ WebChannelIPCTransportHost::WebChannelIPCTransportHost(content::WebContents *con : QWebChannelAbstractTransport(parent) , content::WebContentsObserver(contents) , m_worldId(worldId) + ,_mWaitingReply(0) { Send(new WebChannelIPCTransport_Install(routing_id(), m_worldId)); } @@ -82,7 +83,14 @@ void WebChannelIPCTransportHost::sendMessage(const QJsonObject &message) QJsonDocument doc(message); int size = 0; const char *rawData = doc.rawData(&size); - Send(new WebChannelIPCTransport_Message(routing_id(), std::vector(rawData, rawData + size), m_worldId)); + if (_mWaitingReply) { + WebChannelIPCTransportHost_SendMessageSync::WriteReplyParams(_mWaitingReply, std::vector(rawData, rawData + size)); + Send(_mWaitingReply); + _mWaitingReply = 0; + } + else { + Send(new WebChannelIPCTransport_Message(routing_id(), std::vector(rawData, rawData + size), m_worldId)); + } } void WebChannelIPCTransportHost::onWebChannelMessage(const std::vector &message) @@ -92,11 +100,18 @@ void WebChannelIPCTransportHost::onWebChannelMessage(const std::vector &me Q_EMIT messageReceived(doc.object(), this); } +void WebChannelIPCTransportHost::onWebChannelMessageSync(const std::vector &message, IPC::Message *reply) +{ + _mWaitingReply = reply; + onWebChannelMessage(message); +} + bool WebChannelIPCTransportHost::OnMessageReceived(const IPC::Message &message) { bool handled = true; IPC_BEGIN_MESSAGE_MAP(WebChannelIPCTransportHost, message) IPC_MESSAGE_HANDLER(WebChannelIPCTransportHost_SendMessage, onWebChannelMessage) + IPC_MESSAGE_HANDLER_DELAY_REPLY(WebChannelIPCTransportHost_SendMessageSync, onWebChannelMessageSync) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() return handled; diff --git a/src/core/renderer_host/web_channel_ipc_transport_host.h b/src/core/renderer_host/web_channel_ipc_transport_host.h index aa40647..bfb0523 100644 --- a/src/core/renderer_host/web_channel_ipc_transport_host.h +++ b/src/core/renderer_host/web_channel_ipc_transport_host.h @@ -70,7 +70,10 @@ public: private: bool OnMessageReceived(const IPC::Message& message) override; void onWebChannelMessage(const std::vector &message); + void onWebChannelMessageSync(const std::vector &message, IPC::Message *reply); + uint m_worldId; + IPC::Message *_mWaitingReply; }; } // namespace -- 2.7.4