summaryrefslogtreecommitdiffstats
path: root/src/core/renderer/web_channel_ipc_transport.cpp
diff options
context:
space:
mode:
authorPierre Rossi <pierre.rossi@digia.com>2014-08-14 02:21:56 +0800
committerPierre Rossi <pierre.rossi@theqtcompany.com>2015-02-12 08:07:29 +0000
commiteee482929a81ae9d685a0ee140733227ceac6543 (patch)
treea31842bbe485e6c32bb59538d4de11656c1cbbe8 /src/core/renderer/web_channel_ipc_transport.cpp
parentacce2537cf8781e7efbb17183a6b54c211e37b19 (diff)
Integrate with WebChannel
Provide a transport mechanism for WebChannel over chromium IPC and expose WebChannel in our experimental QML API. Co-authored by Milian Wolff. Change-Id: Ia24b1d4ebc8515de677d4849ec33cb55c963918e Reviewed-by: Andras Becsi <andras.becsi@theqtcompany.com>
Diffstat (limited to 'src/core/renderer/web_channel_ipc_transport.cpp')
-rw-r--r--src/core/renderer/web_channel_ipc_transport.cpp175
1 files changed, 175 insertions, 0 deletions
diff --git a/src/core/renderer/web_channel_ipc_transport.cpp b/src/core/renderer/web_channel_ipc_transport.cpp
new file mode 100644
index 000000000..0491a6103
--- /dev/null
+++ b/src/core/renderer/web_channel_ipc_transport.cpp
@@ -0,0 +1,175 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPLv3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "renderer/web_channel_ipc_transport.h"
+
+#include "common/qt_messages.h"
+
+#include "content/public/renderer/render_view.h"
+#include "third_party/WebKit/public/web/WebLocalFrame.h"
+#include "third_party/WebKit/public/web/WebView.h"
+#include "v8/include/v8.h"
+
+#include <QJsonDocument>
+
+static const char kWebChannelTransportExtensionName[] = "v8/WebChannelTransport";
+
+static const char kWebChannelTransportApi[] =
+ "if (typeof(navigator) === 'undefined')" \
+ " navigator = {};" \
+ "if (typeof(navigator.qtWebChannelTransport) === 'undefined')" \
+ " navigator.qtWebChannelTransport = {};" \
+ "navigator.qtWebChannelTransport.send = function(message) {" \
+ " native function NativeQtSendMessage();" \
+ " NativeQtSendMessage(message);" \
+ "};";
+
+class WebChannelTransportExtension : public v8::Extension {
+public:
+ static content::RenderView *GetRenderView();
+
+ WebChannelTransportExtension() : v8::Extension(kWebChannelTransportExtensionName, kWebChannelTransportApi)
+ {
+ }
+
+ virtual v8::Handle<v8::FunctionTemplate> GetNativeFunctionTemplate(v8::Isolate* isolate, v8::Handle<v8::String> name) Q_DECL_OVERRIDE;
+
+ static void NativeQtSendMessage(const v8::FunctionCallbackInfo<v8::Value>& args)
+ {
+ content::RenderView *renderView = GetRenderView();
+ if (!renderView || args.Length() != 1)
+ return;
+ v8::Handle<v8::Value> val = args[0];
+ 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);
+ renderView->Send(new WebChannelIPCTransportHost_SendMessage(renderView->GetRoutingID(), std::vector<char>(rawData, rawData + size)));
+ }
+};
+
+content::RenderView *WebChannelTransportExtension::GetRenderView()
+{
+ blink::WebLocalFrame *webframe = blink::WebLocalFrame::frameForCurrentContext();
+ DCHECK(webframe) << "There should be an active frame since we just got a native function called.";
+ if (!webframe)
+ return 0;
+
+ blink::WebView *webview = webframe->view();
+ if (!webview)
+ return 0; // can happen during closing
+
+ return content::RenderView::FromWebView(webview);
+}
+
+v8::Handle<v8::FunctionTemplate> WebChannelTransportExtension::GetNativeFunctionTemplate(v8::Isolate *isolate, v8::Handle<v8::String> name)
+{
+ if (name->Equals(v8::String::NewFromUtf8(isolate, "NativeQtSendMessage")))
+ return v8::FunctionTemplate::New(isolate, NativeQtSendMessage);
+
+ return v8::Handle<v8::FunctionTemplate>();
+}
+
+WebChannelIPCTransport::WebChannelIPCTransport(content::RenderView *renderView)
+ : content::RenderViewObserver(renderView)
+{
+}
+
+void WebChannelIPCTransport::dispatchWebChannelMessage(const std::vector<char> &binaryJSON)
+{
+ blink::WebView *webView = render_view()->GetWebView();
+ if (!webView)
+ return;
+
+ QJsonDocument doc = QJsonDocument::fromRawData(binaryJSON.data(), binaryJSON.size(), QJsonDocument::BypassValidation);
+ Q_ASSERT(doc.isObject());
+ QByteArray json = doc.toJson(QJsonDocument::Compact);
+
+ v8::Isolate *isolate = v8::Isolate::GetCurrent();
+ v8::HandleScope handleScope(isolate);
+ blink::WebFrame *frame = webView->mainFrame();
+ v8::Handle<v8::Context> context = frame->mainWorldScriptContext();
+ v8::Context::Scope contextScope(context);
+
+ v8::Handle<v8::Object> global(context->Global());
+ v8::Handle<v8::Value> navigatorValue(global->Get(v8::String::NewFromUtf8(isolate, "navigator")));
+ if (!navigatorValue->IsObject())
+ return;
+ v8::Handle<v8::Value> navigatorQtValue(navigatorValue->ToObject()->Get(v8::String::NewFromUtf8(isolate, "qtWebChannelTransport")));
+ if (!navigatorQtValue->IsObject())
+ return;
+ v8::Handle<v8::Value> onmessageCallbackValue(navigatorQtValue->ToObject()->Get(v8::String::NewFromUtf8(isolate, "onmessage")));
+ if (!onmessageCallbackValue->IsFunction()) {
+ qWarning("onmessage is not a callable property of navigator.qtWebChannelTransport. Some things might not work as expected.");
+ return;
+ }
+
+ v8::Handle<v8::Object> messageObject(v8::Object::New(isolate));
+ messageObject->ForceSet(v8::String::NewFromUtf8(isolate, "data")
+ , v8::String::NewFromUtf8(isolate, json.constData(), v8::String::kNormalString, json.size())
+ , v8::PropertyAttribute(v8::ReadOnly | v8::DontDelete));
+
+ 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->callFunctionEvenIfScriptDisabled(callback, navigatorQtValue->ToObject(), argc, argv);
+}
+
+v8::Extension *WebChannelIPCTransport::getV8Extension()
+{
+ return new WebChannelTransportExtension;
+}
+
+bool WebChannelIPCTransport::OnMessageReceived(const IPC::Message &message)
+{
+ bool handled = true;
+ IPC_BEGIN_MESSAGE_MAP(WebChannelIPCTransport, message)
+ IPC_MESSAGE_HANDLER(WebChannelIPCTransport_Message, dispatchWebChannelMessage)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+ return handled;
+}