diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/core/common/qt_messages.h | 3 | ||||
-rw-r--r-- | src/core/renderer/content_renderer_client_qt.cpp | 5 | ||||
-rw-r--r-- | src/core/renderer/web_channel_ipc_transport.cpp | 237 | ||||
-rw-r--r-- | src/core/renderer/web_channel_ipc_transport.h | 36 | ||||
-rw-r--r-- | src/core/renderer_host/web_channel_ipc_transport_host.cpp | 89 | ||||
-rw-r--r-- | src/core/renderer_host/web_channel_ipc_transport_host.h | 32 |
6 files changed, 199 insertions, 203 deletions
diff --git a/src/core/common/qt_messages.h b/src/core/common/qt_messages.h index 62d88521c..411d06bc8 100644 --- a/src/core/common/qt_messages.h +++ b/src/core/common/qt_messages.h @@ -40,8 +40,7 @@ IPC_MESSAGE_ROUTED1(RenderViewObserverQt_FetchDocumentInnerText, IPC_MESSAGE_ROUTED1(RenderViewObserverQt_SetBackgroundColor, uint32_t /* color */) -IPC_MESSAGE_ROUTED1(WebChannelIPCTransport_Install, uint /* worldId */) -IPC_MESSAGE_ROUTED1(WebChannelIPCTransport_Uninstall, uint /* worldId */) +IPC_MESSAGE_ROUTED1(WebChannelIPCTransport_SetWorldId, base::Optional<uint> /* worldId */) IPC_MESSAGE_ROUTED2(WebChannelIPCTransport_Message, std::vector<char> /*binaryJSON*/, uint /* worldId */) // User scripts messages diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp index 56ebfec30..74edc4369 100644 --- a/src/core/renderer/content_renderer_client_qt.cpp +++ b/src/core/renderer/content_renderer_client_qt.cpp @@ -123,13 +123,14 @@ void ContentRendererClientQt::RenderViewCreated(content::RenderView* render_view { // RenderViewObservers destroy themselves with their RenderView. new RenderViewObserverQt(render_view, m_webCacheImpl.data()); - new WebChannelIPCTransport(render_view); UserResourceController::instance()->renderViewCreated(render_view); } void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame* render_frame) { new QtWebEngineCore::RenderFrameObserverQt(render_frame); + if (render_frame->IsMainFrame()) + new WebChannelIPCTransport(render_frame); UserResourceController::instance()->renderFrameCreated(render_frame); #if BUILDFLAG(ENABLE_SPELLCHECK) @@ -150,8 +151,6 @@ void ContentRendererClientQt::RunScriptsAtDocumentStart(content::RenderFrame* re if (!render_frame_observer || render_frame_observer->isFrameDetached()) return; // The frame is invisible to scripts. - if (WebChannelIPCTransport *transport = WebChannelIPCTransport::Get(render_frame->GetRenderView())) - transport->RunScriptsAtDocumentStart(render_frame); UserResourceController::instance()->RunScriptsAtDocumentStart(render_frame); } diff --git a/src/core/renderer/web_channel_ipc_transport.cpp b/src/core/renderer/web_channel_ipc_transport.cpp index 534ee302d..bb544168f 100644 --- a/src/core/renderer/web_channel_ipc_transport.cpp +++ b/src/core/renderer/web_channel_ipc_transport.cpp @@ -45,13 +45,12 @@ #include "common/qt_messages.h" #include "content/public/renderer/render_frame.h" -#include "content/public/renderer/render_view.h" #include "gin/arguments.h" #include "gin/handle.h" #include "gin/object_template_builder.h" #include "gin/wrappable.h" +#include "third_party/WebKit/public/web/WebKit.h" #include "third_party/WebKit/public/web/WebLocalFrame.h" -#include "third_party/WebKit/public/web/WebView.h" #include "v8/include/v8.h" #include <QJsonDocument> @@ -61,193 +60,189 @@ namespace QtWebEngineCore { class WebChannelTransport : public gin::Wrappable<WebChannelTransport> { public: static gin::WrapperInfo kWrapperInfo; - static void Install(blink::WebFrame *frame, uint worldId); - static void Uninstall(blink::WebFrame *frame, uint worldId); + static void Install(blink::WebLocalFrame *frame, uint worldId); + static void Uninstall(blink::WebLocalFrame *frame, uint worldId); private: - content::RenderView *GetRenderView(v8::Isolate *isolate); - WebChannelTransport() { } - gin::ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate *isolate) override; + WebChannelTransport() {} + bool NativeQtSendMessage(gin::Arguments *args); - bool NativeQtSendMessage(gin::Arguments *args) - { - content::RenderView *renderView = GetRenderView(args->isolate()); - if (!renderView || args->Length() != 1) - return false; - v8::Handle<v8::Value> val; - args->GetNext(&val); - if (!val->IsString() && !val->IsStringObject()) - return false; - 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())); - return false; - } - int size = 0; - const char *rawData = doc.rawData(&size); - if (size == 0) - return false; - renderView->Send(new WebChannelIPCTransportHost_SendMessage(renderView->GetRoutingID(), std::vector<char>(rawData, rawData + size))); - return true; - } + // gin::WrappableBase + gin::ObjectTemplateBuilder GetObjectTemplateBuilder(v8::Isolate *isolate) override; DISALLOW_COPY_AND_ASSIGN(WebChannelTransport); }; gin::WrapperInfo WebChannelTransport::kWrapperInfo = { gin::kEmbedderNativeGin }; -void WebChannelTransport::Install(blink::WebFrame *frame, uint worldId) +void WebChannelTransport::Install(blink::WebLocalFrame *frame, uint worldId) { - v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::Isolate *isolate = blink::MainThreadIsolate(); v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context; + v8::Local<v8::Context> context; if (worldId == 0) - context = frame->ToWebLocalFrame()->MainWorldScriptContext(); + context = frame->MainWorldScriptContext(); else - context = frame->ToWebLocalFrame()->IsolatedWorldScriptContext(worldId); + context = frame->IsolatedWorldScriptContext(worldId); v8::Context::Scope contextScope(context); gin::Handle<WebChannelTransport> transport = gin::CreateHandle(isolate, new WebChannelTransport); - v8::Handle<v8::Object> global = context->Global(); - v8::Handle<v8::Object> qt = global->Get(gin::StringToV8(isolate, "qt"))->ToObject(); - if (qt.IsEmpty()) { - qt = v8::Object::New(isolate); - global->Set(gin::StringToV8(isolate, "qt"), qt); + + v8::Local<v8::Object> global = context->Global(); + v8::Local<v8::Value> qtObjectValue = global->Get(gin::StringToV8(isolate, "qt")); + v8::Local<v8::Object> qtObject; + if (qtObjectValue.IsEmpty() || !qtObjectValue->IsObject()) { + qtObject = v8::Object::New(isolate); + global->Set(gin::StringToV8(isolate, "qt"), qtObject); + } else { + qtObject = v8::Local<v8::Object>::Cast(qtObjectValue); } - qt->Set(gin::StringToV8(isolate, "webChannelTransport"), transport.ToV8()); + qtObject->Set(gin::StringToV8(isolate, "webChannelTransport"), transport.ToV8()); } -void WebChannelTransport::Uninstall(blink::WebFrame *frame, uint worldId) +void WebChannelTransport::Uninstall(blink::WebLocalFrame *frame, uint worldId) { - v8::Isolate *isolate = v8::Isolate::GetCurrent(); + v8::Isolate *isolate = blink::MainThreadIsolate(); v8::HandleScope handleScope(isolate); - v8::Handle<v8::Context> context; + v8::Local<v8::Context> context; if (worldId == 0) - context = frame->ToWebLocalFrame()->MainWorldScriptContext(); + context = frame->MainWorldScriptContext(); else - context = frame->ToWebLocalFrame()->IsolatedWorldScriptContext(worldId); + context = frame->IsolatedWorldScriptContext(worldId); v8::Context::Scope contextScope(context); - v8::Handle<v8::Object> global(context->Global()); - v8::Handle<v8::Object> qt = global->Get(gin::StringToV8(isolate, "qt"))->ToObject(); - if (qt.IsEmpty()) + v8::Local<v8::Object> global(context->Global()); + v8::Local<v8::Value> qtObjectValue = global->Get(gin::StringToV8(isolate, "qt")); + if (qtObjectValue.IsEmpty() || !qtObjectValue->IsObject()) return; - qt->Delete(gin::StringToV8(isolate, "webChannelTransport")); -} - -gin::ObjectTemplateBuilder WebChannelTransport::GetObjectTemplateBuilder(v8::Isolate *isolate) -{ - return gin::Wrappable<WebChannelTransport>::GetObjectTemplateBuilder(isolate).SetMethod("send", &WebChannelTransport::NativeQtSendMessage); + v8::Local<v8::Object> qtObject = v8::Local<v8::Object>::Cast(qtObjectValue); + qtObject->Delete(gin::StringToV8(isolate, "webChannelTransport")); } -content::RenderView *WebChannelTransport::GetRenderView(v8::Isolate *isolate) +bool WebChannelTransport::NativeQtSendMessage(gin::Arguments *args) { - blink::WebLocalFrame *webframe = blink::WebLocalFrame::FrameForContext(isolate->GetCurrentContext()); - DCHECK(webframe) << "There should be an active frame since we just got a native function called."; - if (!webframe) - return 0; + blink::WebLocalFrame *frame = blink::WebLocalFrame::FrameForCurrentContext(); + if (!frame || !frame->View()) + return false; + + content::RenderFrame *renderFrame = content::RenderFrame::FromWebFrame(frame); + if (!renderFrame) + return false; + + std::string message; + if (!args->GetNext(&message)) + return false; + + QByteArray valueData(message.data(), message.size()); + QJsonParseError error; + QJsonDocument doc = QJsonDocument::fromJson(valueData, &error); + if (error.error != QJsonParseError::NoError) { + LOG(WARNING) << "Parsing error: " << qPrintable(error.errorString()); + return false; + } - blink::WebView *webview = webframe->View(); - if (!webview) - return 0; // can happen during closing + int size = 0; + const char *rawData = doc.rawData(&size); + if (size == 0) + return false; - return content::RenderView::FromWebView(webview); + renderFrame->Send(new WebChannelIPCTransportHost_SendMessage( + renderFrame->GetRoutingID(), + std::vector<char>(rawData, rawData + size))); + return true; } -WebChannelIPCTransport::WebChannelIPCTransport(content::RenderView *renderView) - : content::RenderViewObserver(renderView) - , content::RenderViewObserverTracker<WebChannelIPCTransport>(renderView) - , m_installed(false) - , m_installedWorldId(0) +gin::ObjectTemplateBuilder WebChannelTransport::GetObjectTemplateBuilder(v8::Isolate *isolate) { + return gin::Wrappable<WebChannelTransport>::GetObjectTemplateBuilder(isolate) + .SetMethod("send", &WebChannelTransport::NativeQtSendMessage); } -void WebChannelIPCTransport::RunScriptsAtDocumentStart(content::RenderFrame *render_frame) +WebChannelIPCTransport::WebChannelIPCTransport(content::RenderFrame *renderFrame) + : content::RenderFrameObserver(renderFrame) { - // JavaScript run before this point doesn't stick, and needs to be redone. - // ### FIXME: we should try no even installing before - if (m_installed && render_frame->IsMainFrame()) - WebChannelTransport::Install(render_frame->GetWebFrame(), m_installedWorldId); } - -void WebChannelIPCTransport::installWebChannel(uint worldId) +void WebChannelIPCTransport::setWorldId(base::Optional<uint> worldId) { - blink::WebView *webView = render_view()->GetWebView(); - if (!webView) + if (m_worldId == worldId) return; - WebChannelTransport::Install(webView->MainFrame(), worldId); - m_installed = true; - m_installedWorldId = worldId; -} -void WebChannelIPCTransport::uninstallWebChannel(uint worldId) -{ - Q_ASSERT(worldId == m_installedWorldId); - blink::WebView *webView = render_view()->GetWebView(); - if (!webView) - return; - WebChannelTransport::Uninstall(webView->MainFrame(), worldId); - m_installed = false; + if (m_worldId && m_canUseContext) + WebChannelTransport::Uninstall(render_frame()->GetWebFrame(), *m_worldId); + + m_worldId = worldId; + + if (m_worldId && m_canUseContext) + WebChannelTransport::Install(render_frame()->GetWebFrame(), *m_worldId); } -void WebChannelIPCTransport::dispatchWebChannelMessage(const std::vector<char> &binaryJSON, uint worldId) +void WebChannelIPCTransport::dispatchWebChannelMessage(const std::vector<char> &binaryJson, uint worldId) { - blink::WebView *webView = render_view()->GetWebView(); - if (!webView) - return; + DCHECK(m_canUseContext); + DCHECK(m_worldId == worldId); - QJsonDocument doc = QJsonDocument::fromRawData(binaryJSON.data(), binaryJSON.size(), QJsonDocument::BypassValidation); - Q_ASSERT(doc.isObject()); + QJsonDocument doc = QJsonDocument::fromRawData(binaryJson.data(), binaryJson.size(), QJsonDocument::BypassValidation); + DCHECK(doc.isObject()); QByteArray json = doc.toJson(QJsonDocument::Compact); - v8::Isolate *isolate = v8::Isolate::GetCurrent(); + blink::WebLocalFrame *frame = render_frame()->GetWebFrame(); + v8::Isolate *isolate = blink::MainThreadIsolate(); v8::HandleScope handleScope(isolate); - blink::WebFrame *frame = webView->MainFrame(); - v8::Handle<v8::Context> context; + v8::Local<v8::Context> context; if (worldId == 0) - context = frame->ToWebLocalFrame()->MainWorldScriptContext(); + context = frame->MainWorldScriptContext(); else - context = frame->ToWebLocalFrame()->IsolatedWorldScriptContext(worldId); + context = frame->IsolatedWorldScriptContext(worldId); v8::Context::Scope contextScope(context); - v8::Handle<v8::Object> global(context->Global()); - v8::Handle<v8::Value> qtObjectValue(global->Get(gin::StringToV8(isolate, "qt"))); - if (!qtObjectValue->IsObject()) + v8::Local<v8::Object> global(context->Global()); + v8::Local<v8::Value> qtObjectValue(global->Get(gin::StringToV8(isolate, "qt"))); + if (qtObjectValue.IsEmpty() || !qtObjectValue->IsObject()) return; - v8::Handle<v8::Value> webChannelObjectValue(qtObjectValue->ToObject()->Get(gin::StringToV8(isolate, "webChannelTransport"))); - if (!webChannelObjectValue->IsObject()) + v8::Local<v8::Object> qtObject = v8::Local<v8::Object>::Cast(qtObjectValue); + v8::Local<v8::Value> webChannelObjectValue(qtObject->Get(gin::StringToV8(isolate, "webChannelTransport"))); + if (webChannelObjectValue.IsEmpty() || !webChannelObjectValue->IsObject()) return; - v8::Handle<v8::Value> onmessageCallbackValue(webChannelObjectValue->ToObject()->Get(gin::StringToV8(isolate, "onmessage"))); - if (!onmessageCallbackValue->IsFunction()) { - qWarning("onmessage is not a callable property of qt.webChannelTransport. Some things might not work as expected."); + v8::Local<v8::Object> webChannelObject = v8::Local<v8::Object>::Cast(webChannelObjectValue); + v8::Local<v8::Value> callbackValue(webChannelObject->Get(gin::StringToV8(isolate, "onmessage"))); + if (callbackValue.IsEmpty() || !callbackValue->IsFunction()) { + LOG(WARNING) << "onmessage is not a callable property of qt.webChannelTransport. Some things might not work as expected."; return; } - v8::Handle<v8::Object> messageObject(v8::Object::New(isolate)); + v8::Local<v8::Object> messageObject(v8::Object::New(isolate)); v8::Maybe<bool> wasSet = messageObject->DefineOwnProperty( context, v8::String::NewFromUtf8(isolate, "data"), v8::String::NewFromUtf8(isolate, json.constData(), v8::String::kNormalString, json.size()), v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete)); - Q_ASSERT(!wasSet.IsNothing() && wasSet.FromJust()); + DCHECK(!wasSet.IsNothing() && wasSet.FromJust()); + + v8::Local<v8::Function> callback = v8::Local<v8::Function>::Cast(callbackValue); + v8::Local<v8::Value> argv[] = { messageObject }; + frame->CallFunctionEvenIfScriptDisabled(callback, webChannelObject, 1, argv); +} + +void WebChannelIPCTransport::WillReleaseScriptContext(v8::Local<v8::Context> context, int worldId) +{ + if (static_cast<uint>(worldId) == m_worldId) + m_canUseContext = false; +} - v8::Handle<v8::Function> callback = v8::Handle<v8::Function>::Cast(onmessageCallbackValue); - const int argc = 1; - v8::Handle<v8::Value> argv[argc]; - argv[0] = messageObject; - frame->ToWebLocalFrame()->CallFunctionEvenIfScriptDisabled(callback, webChannelObjectValue->ToObject(), argc, argv); +void WebChannelIPCTransport::DidClearWindowObject() +{ + if (!m_canUseContext) { + m_canUseContext = true; + if (m_worldId) + 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_Install, installWebChannel) - IPC_MESSAGE_HANDLER(WebChannelIPCTransport_Uninstall, uninstallWebChannel) + IPC_MESSAGE_HANDLER(WebChannelIPCTransport_SetWorldId, setWorldId) IPC_MESSAGE_HANDLER(WebChannelIPCTransport_Message, dispatchWebChannelMessage) IPC_MESSAGE_UNHANDLED(handled = false) IPC_END_MESSAGE_MAP() @@ -259,4 +254,4 @@ void WebChannelIPCTransport::OnDestruct() delete this; } -} // namespace +} // namespace QtWebEngineCore diff --git a/src/core/renderer/web_channel_ipc_transport.h b/src/core/renderer/web_channel_ipc_transport.h index 04041c6c7..19494360a 100644 --- a/src/core/renderer/web_channel_ipc_transport.h +++ b/src/core/renderer/web_channel_ipc_transport.h @@ -40,41 +40,31 @@ #ifndef WEB_CHANNEL_IPC_TRANSPORT_H #define WEB_CHANNEL_IPC_TRANSPORT_H -#include "base/values.h" -#include "content/public/renderer/render_view_observer.h" -#include "content/public/renderer/render_view_observer_tracker.h" +#include "content/public/renderer/render_frame_observer.h" #include <QtCore/qglobal.h> -namespace content { -class RenderFrame; -} - -namespace v8 { -class Extension; -} - namespace QtWebEngineCore { -class WebChannelIPCTransport : public content::RenderViewObserver - , public content::RenderViewObserverTracker<WebChannelIPCTransport> -{ +class WebChannelIPCTransport : private content::RenderFrameObserver { public: - WebChannelIPCTransport(content::RenderView *); - - void RunScriptsAtDocumentStart(content::RenderFrame *render_frame); + WebChannelIPCTransport(content::RenderFrame *); private: - void dispatchWebChannelMessage(const std::vector<char> &binaryJSON, uint worldId); - void installWebChannel(uint worldId); - void uninstallWebChannel(uint worldId); + void setWorldId(base::Optional<uint> worldId); + void dispatchWebChannelMessage(const std::vector<char> &binaryJson, uint worldId); - // content::RenderViewObserver overrides: + // RenderFrameObserver + void WillReleaseScriptContext(v8::Local<v8::Context> context, int worldId) override; + void DidClearWindowObject() override; bool OnMessageReceived(const IPC::Message &message) override; void OnDestruct() override; - bool m_installed; - uint m_installedWorldId; + // The worldId from our WebChannelIPCTransportHost or empty when there is no + // WebChannelIPCTransportHost. + base::Optional<uint> m_worldId; + // True means it's currently OK to manipulate the frame's script context. + bool m_canUseContext = false; }; } // 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 b624d7e45..6b32093a6 100644 --- a/src/core/renderer_host/web_channel_ipc_transport_host.cpp +++ b/src/core/renderer_host/web_channel_ipc_transport_host.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebEngine module of the Qt Toolkit. @@ -39,70 +39,71 @@ #include "web_channel_ipc_transport_host.h" -#include "base/strings/string16.h" -#include "content/public/browser/render_view_host.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" #include "content/public/browser/web_contents.h" #include "common/qt_messages.h" -#include "type_conversion.h" #include <QJsonDocument> #include <QJsonObject> +#include <QLoggingCategory> namespace QtWebEngineCore { +Q_LOGGING_CATEGORY(log, "qt.webengine.webchanneltransport"); + +inline QDebug operator<<(QDebug stream, content::RenderFrameHost *frame) +{ + return stream << "frame " << frame->GetRoutingID() << " in process " << frame->GetProcess()->GetID(); +} + +template <class T> +inline QDebug operator<<(QDebug stream, const base::Optional<T> &opt) +{ + if (opt) + return stream << *opt; + else + return stream << "nullopt"; +} + WebChannelIPCTransportHost::WebChannelIPCTransportHost(content::WebContents *contents, uint worldId, QObject *parent) : QWebChannelAbstractTransport(parent) , content::WebContentsObserver(contents) - , m_worldId(worldId) { - contents->GetRenderViewHost()->Send( - new WebChannelIPCTransport_Install( - contents->GetRenderViewHost()->GetRoutingID(), - m_worldId)); + setWorldId(worldId); } WebChannelIPCTransportHost::~WebChannelIPCTransportHost() { + setWorldId(base::nullopt); } -void WebChannelIPCTransportHost::RenderViewHostChanged(content::RenderViewHost *oldHost, content::RenderViewHost *) -{ - if (oldHost) - oldHost->Send(new WebChannelIPCTransport_Uninstall(oldHost->GetRoutingID(), m_worldId)); -} - -void WebChannelIPCTransportHost::RenderViewCreated(content::RenderViewHost *view_host) +void WebChannelIPCTransportHost::sendMessage(const QJsonObject &message) { - // Make sure the new view knows a webchannel is installed and in which world. - view_host->Send(new WebChannelIPCTransport_Install(view_host->GetRoutingID(), m_worldId)); + QJsonDocument doc(message); + int size = 0; + const char *rawData = doc.rawData(&size); + content::RenderFrameHost *frame = web_contents()->GetMainFrame(); + qCDebug(log).nospace() << "sending webchannel message to " << frame << ": " << doc; + frame->Send(new WebChannelIPCTransport_Message(frame->GetRoutingID(), std::vector<char>(rawData, rawData + size), *m_worldId)); } -void WebChannelIPCTransportHost::setWorldId(uint worldId) +void WebChannelIPCTransportHost::setWorldId(base::Optional<uint> worldId) { - if (worldId == m_worldId) + if (m_worldId == worldId) return; - web_contents()->GetRenderViewHost()->Send( - new WebChannelIPCTransport_Uninstall( - web_contents()->GetRenderViewHost()->GetRoutingID(), - m_worldId)); + for (content::RenderFrameHost *frame : web_contents()->GetAllFrames()) + setWorldId(frame, worldId); m_worldId = worldId; - web_contents()->GetRenderViewHost()->Send( - new WebChannelIPCTransport_Install( - web_contents()->GetRenderViewHost()->GetRoutingID(), - m_worldId)); } -void WebChannelIPCTransportHost::sendMessage(const QJsonObject &message) +void WebChannelIPCTransportHost::setWorldId(content::RenderFrameHost *frame, base::Optional<uint> worldId) { - QJsonDocument doc(message); - int size = 0; - const char *rawData = doc.rawData(&size); - web_contents()->GetRenderViewHost()->Send( - new WebChannelIPCTransport_Message( - web_contents()->GetRenderViewHost()->GetRoutingID(), - std::vector<char>(rawData, rawData + size), - m_worldId)); + if (!frame->IsRenderFrameLive()) + return; + qCDebug(log).nospace() << "sending setWorldId(" << worldId << ") message to " << frame; + frame->Send(new WebChannelIPCTransport_SetWorldId(frame->GetRoutingID(), worldId)); } void WebChannelIPCTransportHost::onWebChannelMessage(const std::vector<char> &message) @@ -110,11 +111,21 @@ void WebChannelIPCTransportHost::onWebChannelMessage(const std::vector<char> &me Q_ASSERT(!message.empty()); QJsonDocument doc = QJsonDocument::fromRawData(message.data(), message.size(), QJsonDocument::BypassValidation); Q_ASSERT(doc.isObject()); + content::RenderFrameHost *frame = web_contents()->GetMainFrame(); + qCDebug(log).nospace() << "received webchannel message from " << frame << ": " << doc; Q_EMIT messageReceived(doc.object(), this); } -bool WebChannelIPCTransportHost::OnMessageReceived(const IPC::Message &message) +void WebChannelIPCTransportHost::RenderFrameCreated(content::RenderFrameHost *frame) { + 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) @@ -123,4 +134,4 @@ bool WebChannelIPCTransportHost::OnMessageReceived(const IPC::Message &message) return handled; } -} // namespace +} // 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 a1e697a91..3a814a794 100644 --- a/src/core/renderer_host/web_channel_ipc_transport_host.h +++ b/src/core/renderer_host/web_channel_ipc_transport_host.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebEngine module of the Qt Toolkit. @@ -40,38 +40,40 @@ #ifndef WEB_CHANNEL_IPC_TRANSPORT_H #define WEB_CHANNEL_IPC_TRANSPORT_H +#include "qtwebenginecoreglobal.h" -#include <QtWebChannel/QWebChannelAbstractTransport> #include "content/public/browser/web_contents_observer.h" -#include "qtwebenginecoreglobal.h" -#include <QtCore/QObject> +#include <QWebChannelAbstractTransport> QT_FORWARD_DECLARE_CLASS(QString) namespace QtWebEngineCore { class WebChannelIPCTransportHost : public QWebChannelAbstractTransport - , public content::WebContentsObserver -{ + , private content::WebContentsObserver { public: - WebChannelIPCTransportHost(content::WebContents *, uint worldId = 0, QObject *parent = 0); + WebChannelIPCTransportHost(content::WebContents *webContents, uint worldId = 0, QObject *parent = nullptr); virtual ~WebChannelIPCTransportHost(); - // WebContentsObserver - void RenderViewHostChanged(content::RenderViewHost* old_host, content::RenderViewHost* new_host) override; - void RenderViewCreated(content::RenderViewHost* render_view_host) override; + void setWorldId(uint worldId) { setWorldId(base::Optional<uint>(worldId)); } + uint worldId() const { return *m_worldId; } // QWebChannelAbstractTransport void sendMessage(const QJsonObject &message) override; - void setWorldId(uint worldId); - uint worldId() const { return m_worldId; } - private: - bool OnMessageReceived(const IPC::Message& message) override; + void setWorldId(base::Optional<uint> worldId); + void setWorldId(content::RenderFrameHost *frame, base::Optional<uint> worldId); void onWebChannelMessage(const std::vector<char> &message); - uint m_worldId; + + // WebContentsObserver + void RenderFrameCreated(content::RenderFrameHost *frame) override; + bool OnMessageReceived(const IPC::Message& message, content::RenderFrameHost *receiver) override; + + // Empty only during construction/destruction. Synchronized to all the + // WebChannelIPCTransports/RenderFrames in the observed WebContents. + base::Optional<uint> m_worldId; }; } // namespace |