From df3681dc6c401f3cebb6e767ef8b8ca4e1a8260b Mon Sep 17 00:00:00 2001 From: Michal Klocek Date: Tue, 26 Jun 2018 13:40:24 +0200 Subject: Migrate WebChannel IPC to mojo Mojoifies: * WebChannelIPCTransport_SetWorldId * WebChannelIPCTransport_Message * WebChannelIPCTransportHost_SendMessage This change is just the simple rewrite of IPC in web channel transport, however ultimate goal here is to use mojo directly in javascript land. Change-Id: Ifcf84659b1d48d99cc4e87849b8a258303e8fedc Reviewed-by: Kai Koehne --- src/core/common/qt_messages.h | 5 -- src/core/qtwebengine.gni | 1 + src/core/renderer/web_channel_ipc_transport.cpp | 62 +++++++++++++-------- src/core/renderer/web_channel_ipc_transport.h | 19 +++++-- .../web_channel_ipc_transport_host.cpp | 64 ++++++++++++++-------- .../renderer_host/web_channel_ipc_transport_host.h | 25 ++++++--- 6 files changed, 110 insertions(+), 66 deletions(-) (limited to 'src/core') diff --git a/src/core/common/qt_messages.h b/src/core/common/qt_messages.h index 4fc0819e3..71e1deef0 100644 --- a/src/core/common/qt_messages.h +++ b/src/core/common/qt_messages.h @@ -39,9 +39,6 @@ IPC_MESSAGE_ROUTED1(RenderViewObserverQt_FetchDocumentInnerText, IPC_MESSAGE_ROUTED1(RenderViewObserverQt_SetBackgroundColor, uint32_t /* color */) -IPC_MESSAGE_ROUTED1(WebChannelIPCTransport_SetWorldId, base::Optional /* worldId */) -IPC_MESSAGE_ROUTED2(WebChannelIPCTransport_Message, std::vector /*binaryJSON*/, uint /* worldId */) - // User scripts messages IPC_MESSAGE_ROUTED1(RenderFrameObserverHelper_AddScript, UserScriptData /* script */) @@ -73,8 +70,6 @@ IPC_MESSAGE_ROUTED2(RenderViewObserverHostQt_DidFetchDocumentInnerText, IPC_MESSAGE_ROUTED0(RenderViewObserverHostQt_DidFirstVisuallyNonEmptyLayout) -IPC_MESSAGE_ROUTED1(WebChannelIPCTransportHost_SendMessage, std::vector /*binaryJSON*/) - //----------------------------------------------------------------------------- // Misc messages // These are messages sent from the renderer to the browser process. diff --git a/src/core/qtwebengine.gni b/src/core/qtwebengine.gni index beb19a943..0fd8e4085 100644 --- a/src/core/qtwebengine.gni +++ b/src/core/qtwebengine.gni @@ -32,6 +32,7 @@ deps = [ "//third_party/blink/public:blink", "//third_party/mesa:mesa_headers", "//ui/accessibility", + "//qtwebengine/browser:interfaces", ":qtwebengine_sources", ":qtwebengine_resources" ] diff --git a/src/core/renderer/web_channel_ipc_transport.cpp b/src/core/renderer/web_channel_ipc_transport.cpp index 70aeabdcf..1f496e810 100644 --- a/src/core/renderer/web_channel_ipc_transport.cpp +++ b/src/core/renderer/web_channel_ipc_transport.cpp @@ -51,7 +51,11 @@ #include "gin/wrappable.h" #include "third_party/blink/public/web/blink.h" #include "third_party/blink/public/web/web_local_frame.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" #include "v8/include/v8.h" +#include "services/service_manager/public/cpp/interface_provider.h" +#include "qtwebengine/browser/qtwebchannel.mojom.h" #include @@ -154,9 +158,9 @@ void WebChannelTransport::NativeQtSendMessage(gin::Arguments *args) int size = 0; const char *rawData = doc.rawData(&size); - renderFrame->Send(new WebChannelIPCTransportHost_SendMessage( - renderFrame->GetRoutingID(), - std::vector(rawData, rawData + size))); + qtwebchannel::mojom::WebChannelTransportHostAssociatedPtr webChannelTransport; + renderFrame->GetRemoteAssociatedInterfaces()->GetInterface(&webChannelTransport); + webChannelTransport->DispatchWebChannelMessage(std::vector(rawData, rawData + size)); } gin::ObjectTemplateBuilder WebChannelTransport::GetObjectTemplateBuilder(v8::Isolate *isolate) @@ -167,29 +171,50 @@ gin::ObjectTemplateBuilder WebChannelTransport::GetObjectTemplateBuilder(v8::Iso WebChannelIPCTransport::WebChannelIPCTransport(content::RenderFrame *renderFrame) : content::RenderFrameObserver(renderFrame) + , m_worldId(0) + , m_worldInitialized(false) { + renderFrame->GetAssociatedInterfaceRegistry()->AddInterface( + base::Bind(&WebChannelIPCTransport::BindRequest, base::Unretained(this))); } -void WebChannelIPCTransport::setWorldId(base::Optional worldId) +void WebChannelIPCTransport::BindRequest( + qtwebchannel::mojom::WebChannelTransportRenderAssociatedRequest request) { + + m_binding.AddBinding(this, std::move(request)); +} + +void WebChannelIPCTransport::SetWorldId(uint32_t worldId) { - if (m_worldId == worldId) + if (m_worldInitialized && m_worldId == worldId) return; - if (m_worldId && m_canUseContext) - WebChannelTransport::Uninstall(render_frame()->GetWebFrame(), *m_worldId); + if (m_worldInitialized && m_canUseContext) + WebChannelTransport::Uninstall(render_frame()->GetWebFrame(), m_worldId); + m_worldInitialized = true; m_worldId = worldId; - if (m_worldId && m_canUseContext) - WebChannelTransport::Install(render_frame()->GetWebFrame(), *m_worldId); + if (m_canUseContext) + WebChannelTransport::Install(render_frame()->GetWebFrame(), m_worldId); +} + +void WebChannelIPCTransport::ResetWorldId() +{ + if (m_worldInitialized && m_canUseContext) + WebChannelTransport::Uninstall(render_frame()->GetWebFrame(), m_worldId); + + m_worldInitialized = false; + m_worldId = 0; } -void WebChannelIPCTransport::dispatchWebChannelMessage(const std::vector &binaryJson, uint worldId) +void WebChannelIPCTransport::DispatchWebChannelMessage(const std::vector &binaryJson, uint32_t worldId) { DCHECK(m_canUseContext); DCHECK(m_worldId == worldId); - QJsonDocument doc = QJsonDocument::fromRawData(binaryJson.data(), binaryJson.size(), QJsonDocument::BypassValidation); + QJsonDocument doc = QJsonDocument::fromRawData(reinterpret_cast(binaryJson.data()), + binaryJson.size(), QJsonDocument::BypassValidation); DCHECK(doc.isObject()); QByteArray json = doc.toJson(QJsonDocument::Compact); @@ -241,22 +266,11 @@ void WebChannelIPCTransport::DidClearWindowObject() { if (!m_canUseContext) { m_canUseContext = true; - if (m_worldId) - WebChannelTransport::Install(render_frame()->GetWebFrame(), *m_worldId); + if (m_worldInitialized) + WebChannelTransport::Install(render_frame()->GetWebFrame(), m_worldId); } } -bool WebChannelIPCTransport::OnMessageReceived(const IPC::Message &message) -{ - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(WebChannelIPCTransport, message) - IPC_MESSAGE_HANDLER(WebChannelIPCTransport_SetWorldId, setWorldId) - IPC_MESSAGE_HANDLER(WebChannelIPCTransport_Message, dispatchWebChannelMessage) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} - void WebChannelIPCTransport::OnDestruct() { delete this; diff --git a/src/core/renderer/web_channel_ipc_transport.h b/src/core/renderer/web_channel_ipc_transport.h index 19494360a..178c20ed1 100644 --- a/src/core/renderer/web_channel_ipc_transport.h +++ b/src/core/renderer/web_channel_ipc_transport.h @@ -41,30 +41,39 @@ #define WEB_CHANNEL_IPC_TRANSPORT_H #include "content/public/renderer/render_frame_observer.h" +#include "services/service_manager/public/cpp/binder_registry.h" +#include "mojo/public/cpp/bindings/associated_binding_set.h" +#include "qtwebengine/browser/qtwebchannel.mojom.h" #include namespace QtWebEngineCore { -class WebChannelIPCTransport : private content::RenderFrameObserver { +class WebChannelIPCTransport: private content::RenderFrameObserver, + public qtwebchannel::mojom::WebChannelTransportRender { public: WebChannelIPCTransport(content::RenderFrame *); private: - void setWorldId(base::Optional worldId); - void dispatchWebChannelMessage(const std::vector &binaryJson, uint worldId); + // qtwebchannel::mojom::WebChannelTransportRender + void SetWorldId(uint32_t worldId) override; + void ResetWorldId() override; + void DispatchWebChannelMessage(const std::vector& binaryJson, uint32_t worldId) override; // RenderFrameObserver void WillReleaseScriptContext(v8::Local context, int worldId) override; void DidClearWindowObject() override; - bool OnMessageReceived(const IPC::Message &message) override; void OnDestruct() override; + void BindRequest(qtwebchannel::mojom::WebChannelTransportRenderAssociatedRequest request); +private: // The worldId from our WebChannelIPCTransportHost or empty when there is no // WebChannelIPCTransportHost. - base::Optional m_worldId; + uint32_t m_worldId; + bool m_worldInitialized; // True means it's currently OK to manipulate the frame's script context. bool m_canUseContext = false; + mojo::AssociatedBindingSet m_binding; }; } // namespace 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 d99dfde97..e1929e4cd 100644 --- a/src/core/renderer_host/web_channel_ipc_transport_host.cpp +++ b/src/core/renderer_host/web_channel_ipc_transport_host.cpp @@ -42,7 +42,10 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" - +#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h" +#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h" +#include "services/service_manager/public/cpp/interface_provider.h" +#include "qtwebengine/browser/qtwebchannel.mojom.h" #include "common/qt_messages.h" #include @@ -72,13 +75,21 @@ inline QDebug operator<<(QDebug stream, const base::Optional &opt) WebChannelIPCTransportHost::WebChannelIPCTransportHost(content::WebContents *contents, uint worldId, QObject *parent) : QWebChannelAbstractTransport(parent) , content::WebContentsObserver(contents) + , m_worldId(worldId) + , m_binding(contents, this) { - setWorldId(worldId); + for (content::RenderFrameHost *frame : contents->GetAllFrames()) + setWorldId(frame, worldId); } WebChannelIPCTransportHost::~WebChannelIPCTransportHost() { - setWorldId(base::nullopt); + resetWorldId(); +} + +uint WebChannelIPCTransportHost::worldId() const +{ + return m_worldId; } void WebChannelIPCTransportHost::sendMessage(const QJsonObject &message) @@ -87,11 +98,13 @@ void WebChannelIPCTransportHost::sendMessage(const QJsonObject &message) int size = 0; const char *rawData = doc.rawData(&size); content::RenderFrameHost *frame = web_contents()->GetMainFrame(); + qtwebchannel::mojom::WebChannelTransportRenderAssociatedPtr webChannelTransport; + frame->GetRemoteAssociatedInterfaces()->GetInterface(&webChannelTransport); qCDebug(log).nospace() << "sending webchannel message to " << frame << ": " << doc; - frame->Send(new WebChannelIPCTransport_Message(frame->GetRoutingID(), std::vector(rawData, rawData + size), *m_worldId)); + webChannelTransport->DispatchWebChannelMessage(std::vector(rawData, rawData + size), m_worldId); } -void WebChannelIPCTransportHost::setWorldId(base::Optional worldId) +void WebChannelIPCTransportHost::setWorldId(uint32_t worldId) { if (m_worldId == worldId) return; @@ -100,23 +113,41 @@ void WebChannelIPCTransportHost::setWorldId(base::Optional worldId) m_worldId = worldId; } -void WebChannelIPCTransportHost::setWorldId(content::RenderFrameHost *frame, base::Optional worldId) +void WebChannelIPCTransportHost::setWorldId(content::RenderFrameHost *frame, uint32_t worldId) { if (!frame->IsRenderFrameLive()) return; qCDebug(log).nospace() << "sending setWorldId(" << worldId << ") message to " << frame; - frame->Send(new WebChannelIPCTransport_SetWorldId(frame->GetRoutingID(), worldId)); + qtwebchannel::mojom::WebChannelTransportRenderAssociatedPtr webChannelTransport; + frame->GetRemoteAssociatedInterfaces()->GetInterface(&webChannelTransport); + webChannelTransport->SetWorldId(worldId); } -void WebChannelIPCTransportHost::onWebChannelMessage(const std::vector &message) +void WebChannelIPCTransportHost::resetWorldId() +{ + for (content::RenderFrameHost *frame : web_contents()->GetAllFrames()) { + if (!frame->IsRenderFrameLive()) + return; + qtwebchannel::mojom::WebChannelTransportRenderAssociatedPtr webChannelTransport; + frame->GetRemoteAssociatedInterfaces()->GetInterface(&webChannelTransport); + webChannelTransport->ResetWorldId(); + } +} + +void WebChannelIPCTransportHost::DispatchWebChannelMessage(const std::vector &binaryJson) { content::RenderFrameHost *frame = web_contents()->GetMainFrame(); + if (m_binding.GetCurrentTargetFrame() != frame) { + return; + } + QJsonDocument doc; // QJsonDocument::fromRawData does not check the length before it starts // parsing the QJsonPrivate::Header and QJsonPrivate::Base structures. - if (message.size() >= sizeof(QJsonPrivate::Header) + sizeof(QJsonPrivate::Base)) - doc = QJsonDocument::fromRawData(message.data(), message.size()); + if (binaryJson.size() >= sizeof(QJsonPrivate::Header) + sizeof(QJsonPrivate::Base)) + doc = QJsonDocument::fromRawData(reinterpret_cast(binaryJson.data()), + binaryJson.size()); if (!doc.isObject()) { qCCritical(log).nospace() << "received invalid webchannel message from " << frame; @@ -132,17 +163,4 @@ void WebChannelIPCTransportHost::RenderFrameCreated(content::RenderFrameHost *fr setWorldId(frame, m_worldId); } -bool WebChannelIPCTransportHost::OnMessageReceived(const IPC::Message& message, content::RenderFrameHost *receiver) -{ - if (receiver != web_contents()->GetMainFrame()) - return false; - - bool handled = true; - IPC_BEGIN_MESSAGE_MAP(WebChannelIPCTransportHost, message) - IPC_MESSAGE_HANDLER(WebChannelIPCTransportHost_SendMessage, onWebChannelMessage) - IPC_MESSAGE_UNHANDLED(handled = false) - IPC_END_MESSAGE_MAP() - return handled; -} - } // namespace QtWebEngineCore 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 3a814a794..94891f25f 100644 --- a/src/core/renderer_host/web_channel_ipc_transport_host.h +++ b/src/core/renderer_host/web_channel_ipc_transport_host.h @@ -43,6 +43,9 @@ #include "qtwebenginecoreglobal.h" #include "content/public/browser/web_contents_observer.h" +#include "services/service_manager/public/cpp/binder_registry.h" +#include "content/public/browser/web_contents_binding_set.h" +#include "qtwebengine/browser/qtwebchannel.mojom.h" #include @@ -51,29 +54,33 @@ QT_FORWARD_DECLARE_CLASS(QString) namespace QtWebEngineCore { class WebChannelIPCTransportHost : public QWebChannelAbstractTransport - , private content::WebContentsObserver { + , private content::WebContentsObserver + , qtwebchannel::mojom::WebChannelTransportHost { public: - WebChannelIPCTransportHost(content::WebContents *webContents, uint worldId = 0, QObject *parent = nullptr); - virtual ~WebChannelIPCTransportHost(); + WebChannelIPCTransportHost(content::WebContents *webContents, uint32_t worldId = 0, QObject *parent = nullptr); + ~WebChannelIPCTransportHost() override; - void setWorldId(uint worldId) { setWorldId(base::Optional(worldId)); } - uint worldId() const { return *m_worldId; } + void setWorldId(uint32_t worldId); + uint32_t worldId() const; // QWebChannelAbstractTransport void sendMessage(const QJsonObject &message) override; private: - void setWorldId(base::Optional worldId); - void setWorldId(content::RenderFrameHost *frame, base::Optional worldId); + void setWorldId(content::RenderFrameHost *frame, uint32_t worldId); + void resetWorldId(); void onWebChannelMessage(const std::vector &message); // WebContentsObserver void RenderFrameCreated(content::RenderFrameHost *frame) override; - bool OnMessageReceived(const IPC::Message& message, content::RenderFrameHost *receiver) override; + + // qtwebchannel::mojom::WebChannelTransportHost + void DispatchWebChannelMessage(const std::vector &binaryJson) override; // Empty only during construction/destruction. Synchronized to all the // WebChannelIPCTransports/RenderFrames in the observed WebContents. - base::Optional m_worldId; + uint32_t m_worldId; + content::WebContentsFrameBindingSet m_binding; }; } // namespace -- cgit v1.2.3