summaryrefslogtreecommitdiffstats
path: root/src/shared/envjsnatives.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared/envjsnatives.cpp')
-rw-r--r--src/shared/envjsnatives.cpp275
1 files changed, 275 insertions, 0 deletions
diff --git a/src/shared/envjsnatives.cpp b/src/shared/envjsnatives.cpp
new file mode 100644
index 0000000..6508f20
--- /dev/null
+++ b/src/shared/envjsnatives.cpp
@@ -0,0 +1,275 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file may be used under the terms of the GNU General Public
+** License version 2.0 or 3.0 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 GNU
+** General Public Licensing requirements will be met:
+** http://www.fsf.org/licensing/licenses/info/GPLv2.html and
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+
+#include <QtCore>
+#include <QtScript>
+#include <QtNetwork>
+
+// Exported API.
+void initializeEnvjsNatives(QScriptEngine *);
+
+#define ENVJS_FUNCTIONS(V) \
+ V(lineSource) \
+ V(eval) \
+ V(loadInlineScript) \
+ V(loadLocalScript) \
+ V(sync) \
+ V(spawn) \
+ V(sleep) \
+ V(loadFrame) \
+ V(unloadFrame) \
+ V(proxy) \
+ V(getcwd) \
+ V(runAsync) \
+ V(writeToFile) \
+ V(writeToTempFile) \
+ V(readFromFile) \
+ V(deleteFile) \
+ V(connection)
+
+static QScriptValue Envjs_lineSource(QScriptContext *, QScriptEngine *)
+{
+ // Supposed to return the source text of the line causing the error.
+ //QScriptValue e = ctx->argument(0);
+ return "(line ?)";
+}
+
+static QScriptValue Envjs_eval(QScriptContext *ctx, QScriptEngine *eng)
+{
+ // Don't know what this is. this-object? Variable scope?
+ // QScriptValue scope = ctx->argument(0);
+
+ QScriptValue source = ctx->argument(1);
+ QScriptValue sourceName = ctx->argument(0);
+ return eng->evaluate(source.toString(), sourceName.toString());
+}
+
+static QScriptValue Envjs_loadInlineScript(QScriptContext *ctx, QScriptEngine *)
+{
+ return ctx->throwError("loadInlineScript() not implemented");
+}
+
+static QScriptValue Envjs_loadLocalScript(QScriptContext *ctx, QScriptEngine *)
+{
+ return ctx->throwError("loadLocalScript() not implemented");
+}
+
+static QScriptValue Envjs_sync(QScriptContext *ctx, QScriptEngine *)
+{
+ return ctx->argument(0);
+}
+
+static QScriptValue Envjs_spawn(QScriptContext *ctx, QScriptEngine *)
+{
+ QScriptValue fun = ctx->argument(0);
+ return fun.call();
+}
+
+class SleepyThread : public QThread
+{
+public:
+ static void msleep(unsigned long msecs)
+ { QThread::msleep(msecs); }
+};
+
+static QScriptValue Envjs_sleep(QScriptContext *ctx, QScriptEngine *eng)
+{
+ uint msecs = ctx->argument(0).toUInt32();
+ static_cast<SleepyThread*>(QThread::currentThread())->msleep(msecs);
+ return eng->undefinedValue();
+}
+
+static QScriptValue Envjs_loadFrame(QScriptContext *ctx, QScriptEngine *)
+{
+ return ctx->throwError("loadFrame() not implemented");
+}
+
+static QScriptValue Envjs_unloadFrame(QScriptContext *ctx, QScriptEngine *)
+{
+ return ctx->throwError("unloadFrame() not implemented");
+}
+
+static QScriptValue Envjs_proxy(QScriptContext *ctx, QScriptEngine *)
+{
+ return ctx->throwError("proxy() not implemented");
+}
+
+static QScriptValue Envjs_getcwd(QScriptContext *, QScriptEngine *)
+{
+ return QDir::currentPath();
+}
+
+class QtScriptFunctionInvoker : public QObject
+{
+ Q_OBJECT
+public:
+ QtScriptFunctionInvoker(const QScriptValue &fn, QObject *parent = 0)
+ : QObject(parent), fun(fn)
+ {}
+
+ void invokeLater()
+ {
+ QMetaObject::invokeMethod(this, "invoke", Qt::QueuedConnection);
+ }
+
+private slots:
+ void invoke()
+ {
+ fun.call();
+ deleteLater();
+ }
+
+private:
+ QScriptValue fun;
+};
+
+static QScriptValue Envjs_runAsync(QScriptContext *ctx, QScriptEngine *eng)
+{
+ QScriptValue fun = ctx->argument(0);
+ QtScriptFunctionInvoker *invoker = new QtScriptFunctionInvoker(fun, eng);
+ invoker->invokeLater();
+ return eng->undefinedValue();
+}
+
+static QScriptValue Envjs_writeToFile(QScriptContext *ctx, QScriptEngine *eng)
+{
+ QScriptValue text = ctx->argument(0);
+ QScriptValue url = ctx->argument(1);
+ QString path = QUrl(url.toString()).toLocalFile();
+ QFile file(path);
+ file.open(QIODevice::WriteOnly);
+ QTextStream stream(&file);
+ stream.setCodec(QTextCodec::codecForName("UTF-8"));
+ stream << text.toString();
+ return eng->undefinedValue();
+}
+
+static QScriptValue Envjs_writeToTempFile(QScriptContext *ctx, QScriptEngine *)
+{
+// QScriptValue text = ctx->argument(0);
+// QScriptValue suffix = ctx->argument(1);
+// QString fileName = QString::fromLatin1("envjs-tmp%0").arg(suffix.toString()));
+// ### Create file and write text. File should be deleted when engine is.
+ return ctx->throwError("writeToTempFile() not implemented");
+}
+
+static QScriptValue Envjs_readFromFile(QScriptContext *ctx, QScriptEngine *)
+{
+ QScriptValue url = ctx->argument(0);
+ QString path = QUrl(url.toString()).toLocalFile();
+ QFile file(path);
+ file.open(QIODevice::ReadOnly);
+ QTextStream stream(&file);
+ stream.setCodec(QTextCodec::codecForName("UTF-8"));
+ return stream.readAll();
+}
+
+static QScriptValue Envjs_deleteFile(QScriptContext *ctx, QScriptEngine *eng)
+{
+ QScriptValue url = ctx->argument(0);
+ QString path = QUrl(url.toString()).toLocalFile();
+ QFile file(path);
+ file.remove();
+ return eng->undefinedValue();
+}
+
+static QScriptValue Envjs_connection(QScriptContext *ctx, QScriptEngine *eng)
+{
+ // TODO: if xhr.async is true, all this stuff should be done in a
+ // delayed call or different thread, then the response handler can
+ // be called (in this thread).
+
+ QScriptValue xhr = ctx->argument(0);
+ QScriptValue responseHandler = ctx->argument(1);
+ QScriptValue data = ctx->argument(2);
+ QUrl url = QUrl(xhr.property("url").toString());
+ QNetworkAccessManager nam; // TODO: get a manager from somewhere...
+ QNetworkRequest req(url);
+
+ QScriptValueIterator it(xhr.property("headers"));
+ while (it.hasNext()) {
+ it.next();
+ req.setRawHeader(it.name().toUtf8(), it.value().toString().toUtf8());
+ }
+
+ QString method = xhr.property("method").toString();
+ QNetworkReply *rep = 0;
+ if (method == QLatin1String("GET"))
+ rep = nam.get(req);
+ else if (method == QLatin1String("PUT"))
+ rep = nam.put(req, data.toString().toUtf8());
+ else if (method == QLatin1String("POST"))
+ rep = nam.put(req, data.toString().toUtf8());
+ else if (method == QLatin1String("HEAD"))
+ rep = nam.head(req);
+ else if (method == QLatin1String("DELETE"))
+ rep = nam.deleteResource(req);
+ else
+ return ctx->throwError(QString::fromLatin1("request method %0 not implemented").arg(method));
+ // TODO: connect to reply's download/uploadProgress(),
+ // implement HEADERS_RECEIVED and LOADING states
+
+ QEventLoop loop;
+ QObject::connect(rep, SIGNAL(finished()), &loop, SLOT(quit()));
+ loop.exec();
+
+ QScriptValue responseHeaders = xhr.property("responseHeaders");
+ QList<QNetworkReply::RawHeaderPair> rawHeaderPairs = rep->rawHeaderPairs();
+ for (int i = 0; i < rawHeaderPairs.size(); ++i) {
+ const QNetworkReply::RawHeaderPair &rhp = rawHeaderPairs.at(i);
+ responseHeaders.setProperty(QString::fromUtf8(rhp.first), QString::fromUtf8(rhp.second));
+ }
+
+ xhr.setProperty("readyState", 4);
+ QVariant statusCode = rep->attribute(QNetworkRequest::HttpStatusCodeAttribute);
+ if (statusCode.isValid())
+ xhr.setProperty("status", statusCode.toInt());
+ QVariant reasonPhrase = rep->attribute(QNetworkRequest::HttpReasonPhraseAttribute);
+ if (reasonPhrase.isValid())
+ xhr.setProperty("statusText", reasonPhrase.toString());
+
+ QByteArray responseData = rep->readAll();
+ xhr.setProperty("responseText", QString::fromUtf8(responseData));
+
+ if (responseHandler.isFunction())
+ responseHandler.call();
+
+ return eng->undefinedValue();
+}
+
+void initializeEnvjsNatives(QScriptEngine *eng)
+{
+ QScriptValue envjs = eng->globalObject().property("Envjs");
+ if (!envjs.isObject()) {
+ eng->currentContext()->throwError("env.js must be evaluated before natives can be initialized");
+ return;
+ }
+
+ envjs.setProperty("platform", "QtScript");
+
+ envjs.setProperty("log", eng->globalObject().property("print"));
+
+#define SET_ENVJS_FUNCTION(f) envjs.setProperty(#f, eng->newFunction(Envjs_##f));
+ ENVJS_FUNCTIONS(SET_ENVJS_FUNCTION)
+#undef SET_ENVJS_FUNCTION
+}
+
+#include "envjsnatives.moc"