summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/common/qt_messages.h3
-rw-r--r--src/core/renderer/content_renderer_client_qt.cpp5
-rw-r--r--src/core/renderer/web_channel_ipc_transport.cpp237
-rw-r--r--src/core/renderer/web_channel_ipc_transport.h36
-rw-r--r--src/core/renderer_host/web_channel_ipc_transport_host.cpp89
-rw-r--r--src/core/renderer_host/web_channel_ipc_transport_host.h32
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