summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorPierre Rossi <pierre.rossi@digia.com>2013-09-09 17:49:18 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-11-04 12:15:19 +0100
commita99fdc02797ece15253ff863102d3257945abfab (patch)
treecead6337f019ab87afff0c0f0865a18d8a075556 /lib
parent1b3be641e660f9f87ec290e9adbb42558860ea37 (diff)
Implement QWebEnginePage::runJavaScript
We can't have QWebFrame::evaluateJavascript in its old form for several reasons, the first of which being that we don't have a QWebEngineFrame class anymore. This is worked around by adding an optional QString parameter with the frame's XPath. Another issue is that the WebKit1 API was synchronous, and this would not play nicely with the very asynchronous nature of chromium we're now sitting on top of. In order to make this obvious when porting, we rename it to runJavaScript which doesn't return any result. This also introduces a template member function overload that will accept function pointers, functors and lambdas,much like Qt5's new signal/slot syntax, in order to get the result of the javascript evaluation back. Change-Id: I64e15a6f5a168936c52a4da2cef6285dfd16e0d5 Reviewed-by: Zeno Albisser <zeno.albisser@digia.com> Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/type_conversion.h5
-rw-r--r--lib/web_contents_adapter.cpp101
-rw-r--r--lib/web_contents_adapter.h7
-rw-r--r--lib/widgets/Api/qwebenginepage.cpp22
-rw-r--r--lib/widgets/Api/qwebenginepage.h34
5 files changed, 165 insertions, 4 deletions
diff --git a/lib/type_conversion.h b/lib/type_conversion.h
index 6e2f55957..6a9a12428 100644
--- a/lib/type_conversion.h
+++ b/lib/type_conversion.h
@@ -56,6 +56,11 @@ inline QString toQt(const base::string16 &string)
return QString::fromUtf16(string.data());
}
+inline QString toQt(const std::string &string)
+{
+ return QString::fromStdString(string);
+}
+
inline base::string16 toString16(const QString &qString)
{
return base::string16(qString.utf16());
diff --git a/lib/web_contents_adapter.cpp b/lib/web_contents_adapter.cpp
index 9f895d2eb..a5eab5648 100644
--- a/lib/web_contents_adapter.cpp
+++ b/lib/web_contents_adapter.cpp
@@ -48,17 +48,103 @@
#include "web_contents_view_qt.h"
#include "web_engine_context.h"
-#include "content/public/browser/web_contents.h"
+#include "base/values.h"
#include "content/public/browser/navigation_entry.h"
+#include "content/public/browser/render_view_host.h"
+#include "content/public/browser/web_contents.h"
#include "content/public/common/page_zoom.h"
#include "content/public/common/renderer_preferences.h"
#include <QGuiApplication>
#include <QStyleHints>
+#include <QVariant>
static const int kTestWindowWidth = 800;
static const int kTestWindowHeight = 600;
+static QVariant fromJSValue(const base::Value *result)
+{
+ QVariant ret;
+ switch (result->GetType()) {
+ case base::Value::TYPE_NULL:
+ break;
+ case base::Value::TYPE_BOOLEAN:
+ {
+ bool out;
+ if (result->GetAsBoolean(&out))
+ ret.setValue(out);
+ break;
+ }
+ case base::Value::TYPE_INTEGER:
+ {
+ int out;
+ if (result->GetAsInteger(&out))
+ ret.setValue(out);
+ break;
+ }
+ case base::Value::TYPE_DOUBLE:
+ {
+ double out;
+ if (result->GetAsDouble(&out))
+ ret.setValue(out);
+ break;
+ }
+ case base::Value::TYPE_STRING:
+ {
+ base::string16 out;
+ if (result->GetAsString(&out))
+ ret.setValue(toQt(out));
+ break;
+ }
+ case base::Value::TYPE_LIST:
+ {
+ const base::ListValue *out;
+ if (result->GetAsList(&out)) {
+ QVariantList list;
+ list.reserve(out->GetSize());
+ for (size_t i = 0; i < out->GetSize(); ++i) {
+ const base::Value *outVal = 0;
+ if (out->Get(i, &outVal) && outVal)
+ list.insert(i, fromJSValue(outVal));
+ }
+ ret.setValue(list);
+ }
+ break;
+ }
+ case base::Value::TYPE_DICTIONARY:
+ {
+ const base::DictionaryValue *out;
+ if (result->GetAsDictionary(&out)) {
+ QVariantMap map;
+ base::DictionaryValue::Iterator it(*out);
+ while (!it.IsAtEnd()) {
+ map.insert(toQt(it.key()), fromJSValue(&it.value()));
+ it.Advance();
+ }
+ ret.setValue(map);
+ }
+ break;
+ }
+ case base::Value::TYPE_BINARY:
+ {
+ const base::BinaryValue *out = static_cast<const base::BinaryValue*>(result);
+ QByteArray data(out->GetBuffer(), out->GetSize());
+ ret.setValue(data);
+ break;
+ }
+ default:
+ Q_UNREACHABLE();
+ break;
+ }
+ return ret;
+}
+
+static void callbackOnEvaluateJS(JSCallbackBase *callback, const base::Value *result)
+{
+ callback->call(fromJSValue(result));
+ delete callback;
+}
+
class WebContentsAdapterPrivate {
public:
WebContentsAdapterPrivate();
@@ -245,3 +331,16 @@ void WebContentsAdapter::enableInspector(bool enable)
{
ContentBrowserClientQt::Get()->enableInspector(enable);
}
+
+void WebContentsAdapter::runJavaScript(const QString &javaScript, const QString &xPath, JSCallbackBase *func)
+{
+ Q_D(WebContentsAdapter);
+ content::RenderViewHost *rvh = d->webContents->GetRenderViewHost();
+ Q_ASSERT(rvh);
+ if (!func)
+ rvh->ExecuteJavascriptInWebFrame(toString16(xPath), toString16(javaScript));
+ else {
+ content::RenderViewHost::JavascriptResultCallback callback = base::Bind(&callbackOnEvaluateJS, func);
+ rvh->ExecuteJavascriptInWebFrameCallbackResult(toString16(xPath), toString16(javaScript), callback);
+ }
+}
diff --git a/lib/web_contents_adapter.h b/lib/web_contents_adapter.h
index 306e55e45..75db8207c 100644
--- a/lib/web_contents_adapter.h
+++ b/lib/web_contents_adapter.h
@@ -48,12 +48,18 @@
#include <QString>
#include <QUrl>
+QT_FORWARD_DECLARE_CLASS(QVariant)
namespace content {
class WebContents;
}
class WebContentsAdapterClient;
class WebContentsAdapterPrivate;
+struct JSCallbackBase {
+ virtual ~JSCallbackBase() {}
+ virtual void call(const QVariant&) = 0;
+};
+
class QWEBENGINE_EXPORT WebContentsAdapter : public QSharedData {
public:
@@ -82,6 +88,7 @@ public:
void setZoomFactor(qreal);
qreal currentZoomFactor() const;
void enableInspector(bool);
+ void runJavaScript(const QString &javaScript, const QString &xPath = QString(), JSCallbackBase * = 0);
private:
Q_DISABLE_COPY(WebContentsAdapter);
diff --git a/lib/widgets/Api/qwebenginepage.cpp b/lib/widgets/Api/qwebenginepage.cpp
index 223c67844..e37c6126d 100644
--- a/lib/widgets/Api/qwebenginepage.cpp
+++ b/lib/widgets/Api/qwebenginepage.cpp
@@ -406,6 +406,28 @@ void QWebEnginePage::setZoomFactor(qreal factor)
d->adapter->setZoomFactor(factor);
}
+void QWebEnginePage::runJavaScript(const QString &scriptSource, const QString &xPath)
+{
+ Q_D(QWebEnginePage);
+ d->adapter->runJavaScript(scriptSource, xPath);
+}
+
+namespace {
+struct JSCallbackFunctor : public JSCallbackBase {
+ JSCallbackFunctor(QtWebEnginePrivate::FunctorBase *functor) : m_func(functor) { }
+ ~JSCallbackFunctor() { delete m_func; }
+ void call(const QVariant &value) { (*m_func)(value); }
+private:
+ QtWebEnginePrivate::FunctorBase *m_func;
+};
+}
+
+void QWebEnginePage::runJavaScriptHelper(const QString &source, QtWebEnginePrivate::FunctorBase *functor, const QString &xPath)
+{
+ Q_D(QWebEnginePage);
+ d->adapter->runJavaScript(source, xPath, new JSCallbackFunctor(functor));
+}
+
QWebEnginePage *QWebEnginePage::createWindow(WebWindowType type)
{
Q_D(QWebEnginePage);
diff --git a/lib/widgets/Api/qwebenginepage.h b/lib/widgets/Api/qwebenginepage.h
index e426f8da6..8bb4176a6 100644
--- a/lib/widgets/Api/qwebenginepage.h
+++ b/lib/widgets/Api/qwebenginepage.h
@@ -50,6 +50,22 @@ class QWebEngineSecurityOrigin;
class QtViewportAttributesPrivate;
class QWebEngineHitTestResultPrivate;
+namespace QtWebEnginePrivate {
+
+struct FunctorBase {
+ virtual ~FunctorBase() {}
+ virtual void operator()(const QVariant &) = 0;
+};
+
+template <typename F>
+struct FunctorCallback : public FunctorBase {
+ FunctorCallback(F callback) : m_callback(callback) {}
+ virtual void operator()(const QVariant &value) { m_callback(value); }
+private:
+ F m_callback;
+};
+}
+
class QWEBENGINEWIDGETS_EXPORT QWebEngineHitTestResult {
public:
QWebEngineHitTestResult();
@@ -474,11 +490,15 @@ public:
QWebEngineSecurityOrigin securityOrigin() const;
+ void runJavaScript(const QString& scriptSource, const QString &xPath = QString());
+
+ template <typename F>
+ void runJavaScript(const QString& scriptSource, F func, const QString &xPath = QString());
+
public Q_SLOTS:
- // Ex-QWebFrame slots
- QVariant evaluateJavaScript(const QString& scriptSource) { Q_UNUSED(scriptSource); Q_UNREACHABLE(); return QVariant(); };
+ // Ex-QWebFrame slot
#ifndef QT_NO_PRINTER
- void print(QPrinter *printer) const { Q_UNUSED(printer); Q_UNREACHABLE(); };
+ void print(QPrinter *printer) const { Q_UNUSED(printer); Q_UNREACHABLE(); }
#endif
@@ -551,6 +571,7 @@ private:
#ifndef QT_NO_ACTION
Q_PRIVATE_SLOT(d_func(), void _q_webActionTriggered(bool checked))
#endif
+ void runJavaScriptHelper(const QString &source, QtWebEnginePrivate::FunctorBase *, const QString &xPath);
friend class QWebEngineView;
friend class QWebEngineViewPrivate;
@@ -559,6 +580,13 @@ private:
Q_DECLARE_OPERATORS_FOR_FLAGS(QWebEnginePage::FindFlags);
Q_DECLARE_OPERATORS_FOR_FLAGS(QWebEnginePage::RenderLayers);
+
+template <typename F>
+inline void QWebEnginePage::runJavaScript(const QString &scriptSource, F func, const QString &xPath)
+{
+ runJavaScriptHelper(scriptSource, new QtWebEnginePrivate::FunctorCallback<F>(func), xPath);
+}
+
QT_END_NAMESPACE
#endif // QWEBENGINEPAGE_H