summaryrefslogtreecommitdiff
path: root/rockworkd/libpebble/jskit
diff options
context:
space:
mode:
Diffstat (limited to 'rockworkd/libpebble/jskit')
-rw-r--r--rockworkd/libpebble/jskit/jskitconsole.cpp201
-rw-r--r--rockworkd/libpebble/jskit/jskitconsole.h56
-rw-r--r--rockworkd/libpebble/jskit/jskitmanager.cpp2
-rw-r--r--rockworkd/libpebble/jskit/jskitpebble.cpp9
-rw-r--r--rockworkd/libpebble/jskit/jskitpebble.h1
-rw-r--r--rockworkd/libpebble/jskit/jskitsetup.js104
-rw-r--r--rockworkd/libpebble/jskit/jskitwebsocket.cpp311
-rw-r--r--rockworkd/libpebble/jskit/jskitwebsocket.h79
8 files changed, 738 insertions, 25 deletions
diff --git a/rockworkd/libpebble/jskit/jskitconsole.cpp b/rockworkd/libpebble/jskit/jskitconsole.cpp
index 3d6c85c..384965b 100644
--- a/rockworkd/libpebble/jskit/jskitconsole.cpp
+++ b/rockworkd/libpebble/jskit/jskitconsole.cpp
@@ -4,26 +4,209 @@
JSKitConsole::JSKitConsole(QObject *parent) :
QObject(parent),
- l(metaObject()->className())
+ l("JSKit Log"),
+ w("JSKit Warning"),
+ e("JSKit Error"),
+ i("JSKit Info")
{
}
-void JSKitConsole::log(const QString &msg)
+void JSKitConsole::log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8, const QString &msg9)
{
- qCDebug(l) << msg;
+ qCDebug(l) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7 << msg8 << msg9;
}
-void JSKitConsole::warn(const QString &msg)
+void JSKitConsole::log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8)
{
- qCWarning(l) << msg;
+ qCDebug(l) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7 << msg8;
}
-void JSKitConsole::error(const QString &msg)
+void JSKitConsole::log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7)
{
- qCCritical(l) << msg;
+ qCDebug(l) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7;
}
-void JSKitConsole::info(const QString &msg)
+void JSKitConsole::log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6)
{
- qCDebug(l) << msg;
+ qCDebug(l) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6;
+}
+
+void JSKitConsole::log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5)
+{
+ qCDebug(l) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5;
+}
+
+void JSKitConsole::log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4)
+{
+ qCDebug(l) << msg0 << msg1 << msg2 << msg3 << msg4;
+}
+
+void JSKitConsole::log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3)
+{
+ qCDebug(l) << msg0 << msg1 << msg2 << msg3;
+}
+
+void JSKitConsole::log(const QString &msg0, const QString &msg1, const QString &msg2)
+{
+ qCDebug(l) << msg0 << msg1 << msg2;
+}
+
+void JSKitConsole::log(const QString &msg0, const QString &msg1)
+{
+ qCDebug(l) << msg0 << msg1;
+}
+
+void JSKitConsole::log(const QString &msg0)
+{
+ qCDebug(l) << msg0;
+}
+
+void JSKitConsole::warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8, const QString &msg9)
+{
+ qCWarning(w) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7 << msg8 << msg9;
+}
+
+void JSKitConsole::warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8)
+{
+ qCWarning(w) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7 << msg8;
+}
+
+void JSKitConsole::warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7)
+{
+ qCWarning(w) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7;
+}
+
+void JSKitConsole::warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6)
+{
+ qCWarning(w) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6;
+}
+
+void JSKitConsole::warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5)
+{
+ qCWarning(w) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5;
+}
+
+void JSKitConsole::warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4)
+{
+ qCWarning(w) << msg0 << msg1 << msg2 << msg3 << msg4;
+}
+
+void JSKitConsole::warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3)
+{
+ qCWarning(w) << msg0 << msg1 << msg2 << msg3;
+}
+
+void JSKitConsole::warn(const QString &msg0, const QString &msg1, const QString &msg2)
+{
+ qCWarning(w) << msg0 << msg1 << msg2;
+}
+
+void JSKitConsole::warn(const QString &msg0, const QString &msg1)
+{
+ qCWarning(w) << msg0 << msg1;
+}
+
+void JSKitConsole::warn(const QString &msg0)
+{
+ qCWarning(w) << msg0;
+}
+
+void JSKitConsole::error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8, const QString &msg9)
+{
+ qCCritical(e) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7 << msg8 << msg9;
+}
+
+void JSKitConsole::error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8)
+{
+ qCCritical(e) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7 << msg8;
+}
+
+void JSKitConsole::error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7)
+{
+ qCCritical(e) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7;
+}
+
+void JSKitConsole::error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6)
+{
+ qCCritical(e) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6;
+}
+
+void JSKitConsole::error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5)
+{
+ qCCritical(e) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5;
+}
+
+void JSKitConsole::error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4)
+{
+ qCCritical(e) << msg0 << msg1 << msg2 << msg3 << msg4;
+}
+
+void JSKitConsole::error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3)
+{
+ qCCritical(e) << msg0 << msg1 << msg2 << msg3;
+}
+
+void JSKitConsole::error(const QString &msg0, const QString &msg1, const QString &msg2)
+{
+ qCCritical(e) << msg0 << msg1 << msg2;
+}
+
+void JSKitConsole::error(const QString &msg0, const QString &msg1)
+{
+ qCCritical(e) << msg0 << msg1;
+}
+
+void JSKitConsole::error(const QString &msg0)
+{
+ qCCritical(e) << msg0;
+}
+
+void JSKitConsole::info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8, const QString &msg9)
+{
+ qCDebug(i) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7 << msg8 << msg9;
+}
+
+void JSKitConsole::info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8)
+{
+ qCDebug(i) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7 << msg8;
+}
+
+void JSKitConsole::info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7)
+{
+ qCDebug(i) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6 << msg7;
+}
+
+void JSKitConsole::info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6)
+{
+ qCDebug(i) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5 << msg6;
+}
+
+void JSKitConsole::info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5)
+{
+ qCDebug(i) << msg0 << msg1 << msg2 << msg3 << msg4 << msg5;
+}
+
+void JSKitConsole::info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4)
+{
+ qCDebug(i) << msg0 << msg1 << msg2 << msg3 << msg4;
+}
+
+void JSKitConsole::info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3)
+{
+ qCDebug(i) << msg0 << msg1 << msg2 << msg3;
+}
+
+void JSKitConsole::info(const QString &msg0, const QString &msg1, const QString &msg2)
+{
+ qCDebug(i) << msg0 << msg1 << msg2;
+}
+
+void JSKitConsole::info(const QString &msg0, const QString &msg1)
+{
+ qCDebug(i) << msg0 << msg1;
+}
+
+void JSKitConsole::info(const QString &msg0)
+{
+ qCDebug(i) << msg0;
}
diff --git a/rockworkd/libpebble/jskit/jskitconsole.h b/rockworkd/libpebble/jskit/jskitconsole.h
index 3896ae3..6f8970d 100644
--- a/rockworkd/libpebble/jskit/jskitconsole.h
+++ b/rockworkd/libpebble/jskit/jskitconsole.h
@@ -3,18 +3,66 @@
#include <QLoggingCategory>
+/*
+ We opted to do multiple overloaded functions rather than one with default
+ arguments as this method produces nicer log messages and wont omit (possibly)
+ important messages like empty string, undefined, or null.
+*/
+
class JSKitConsole : public QObject
{
Q_OBJECT
QLoggingCategory l;
+ QLoggingCategory w;
+ QLoggingCategory e;
+ QLoggingCategory i;
public:
explicit JSKitConsole(QObject *parent=0);
- Q_INVOKABLE void log(const QString &msg);
- Q_INVOKABLE void warn(const QString &msg);
- Q_INVOKABLE void error(const QString &msg);
- Q_INVOKABLE void info(const QString &msg);
+ Q_INVOKABLE void log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8, const QString &msg9);
+ Q_INVOKABLE void log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8);
+ Q_INVOKABLE void log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7);
+ Q_INVOKABLE void log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6);
+ Q_INVOKABLE void log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5);
+ Q_INVOKABLE void log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4);
+ Q_INVOKABLE void log(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3);
+ Q_INVOKABLE void log(const QString &msg0, const QString &msg1, const QString &msg2);
+ Q_INVOKABLE void log(const QString &msg0, const QString &msg1);
+ Q_INVOKABLE void log(const QString &msg0);
+
+ Q_INVOKABLE void warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8, const QString &msg9);
+ Q_INVOKABLE void warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8);
+ Q_INVOKABLE void warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7);
+ Q_INVOKABLE void warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6);
+ Q_INVOKABLE void warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5);
+ Q_INVOKABLE void warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4);
+ Q_INVOKABLE void warn(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3);
+ Q_INVOKABLE void warn(const QString &msg0, const QString &msg1, const QString &msg2);
+ Q_INVOKABLE void warn(const QString &msg0, const QString &msg1);
+ Q_INVOKABLE void warn(const QString &msg0);
+
+ Q_INVOKABLE void error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8, const QString &msg9);
+ Q_INVOKABLE void error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8);
+ Q_INVOKABLE void error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7);
+ Q_INVOKABLE void error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6);
+ Q_INVOKABLE void error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5);
+ Q_INVOKABLE void error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4);
+ Q_INVOKABLE void error(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3);
+ Q_INVOKABLE void error(const QString &msg0, const QString &msg1, const QString &msg2);
+ Q_INVOKABLE void error(const QString &msg0, const QString &msg1);
+ Q_INVOKABLE void error(const QString &msg0);
+
+ Q_INVOKABLE void info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8, const QString &msg9);
+ Q_INVOKABLE void info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7, const QString &msg8);
+ Q_INVOKABLE void info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6, const QString &msg7);
+ Q_INVOKABLE void info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5, const QString &msg6);
+ Q_INVOKABLE void info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4, const QString &msg5);
+ Q_INVOKABLE void info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3, const QString &msg4);
+ Q_INVOKABLE void info(const QString &msg0, const QString &msg1, const QString &msg2, const QString &msg3);
+ Q_INVOKABLE void info(const QString &msg0, const QString &msg1, const QString &msg2);
+ Q_INVOKABLE void info(const QString &msg0, const QString &msg1);
+ Q_INVOKABLE void info(const QString &msg0);
};
#endif // JSKITCONSOLE_H
diff --git a/rockworkd/libpebble/jskit/jskitmanager.cpp b/rockworkd/libpebble/jskit/jskitmanager.cpp
index 04bf674..8a03afd 100644
--- a/rockworkd/libpebble/jskit/jskitmanager.cpp
+++ b/rockworkd/libpebble/jskit/jskitmanager.cpp
@@ -82,7 +82,7 @@ AppInfo JSKitManager::currentApp()
void JSKitManager::handleAppStarted(const QUuid &uuid)
{
AppInfo info = m_apps->info(uuid);
- if (!info.uuid().isNull() && info.isJSKit()) {
+ if (!info.uuid().isNull() && info.isJSKit() && info.uuid() != m_curApp.uuid()) {
qCDebug(l) << "Preparing to start JSKit app" << info.uuid() << info.shortName();
m_curApp = info;
diff --git a/rockworkd/libpebble/jskit/jskitpebble.cpp b/rockworkd/libpebble/jskit/jskitpebble.cpp
index a300aef..e755d60 100644
--- a/rockworkd/libpebble/jskit/jskitpebble.cpp
+++ b/rockworkd/libpebble/jskit/jskitpebble.cpp
@@ -4,6 +4,7 @@
#include "jskitpebble.h"
#include "jskitxmlhttprequest.h"
+#include "jskitwebsocket.h"
static const char *token_salt = "0feeb7416d3c4546a19b04bccd8419b1";
@@ -315,10 +316,16 @@ void JSKitPebble::openURL(const QUrl &url)
QJSValue JSKitPebble::createXMLHttpRequest()
{
JSKitXMLHttpRequest *xhr = new JSKitXMLHttpRequest(m_mgr->engine());
- // Should be deleted by JS engine.
return m_mgr->engine()->newQObject(xhr);
}
+QJSValue JSKitPebble::createWebSocket(const QString &url, const QJSValue &protocols)
+{
+ JSKitWebSocket *ws = new JSKitWebSocket(m_mgr->engine(), url, protocols);
+ return m_mgr->engine()->newQObject(ws);
+}
+
+
QJSValue JSKitPebble::buildAckEventObject(uint transaction, const QString &message) const
{
QJSEngine *engine = m_mgr->engine();
diff --git a/rockworkd/libpebble/jskit/jskitpebble.h b/rockworkd/libpebble/jskit/jskitpebble.h
index d9cd670..c461adb 100644
--- a/rockworkd/libpebble/jskit/jskitpebble.h
+++ b/rockworkd/libpebble/jskit/jskitpebble.h
@@ -32,6 +32,7 @@ public:
Q_INVOKABLE void openURL(const QUrl &url);
Q_INVOKABLE QJSValue createXMLHttpRequest();
+ Q_INVOKABLE QJSValue createWebSocket(const QString &url, const QJSValue &protocols=QJSValue{});
void invokeCallbacks(const QString &type, const QJSValueList &args = QJSValueList());
diff --git a/rockworkd/libpebble/jskit/jskitsetup.js b/rockworkd/libpebble/jskit/jskitsetup.js
index 340c4f1..2f85c7d 100644
--- a/rockworkd/libpebble/jskit/jskitsetup.js
+++ b/rockworkd/libpebble/jskit/jskitsetup.js
@@ -81,16 +81,6 @@ console = new (function() {
);
})();
-/*localStorage = new (function() {
- _jskit.make_proxies(this, _jskit.localstorage,
- ['clear', 'getItem', 'setItem', 'removeItem', 'key']
- );
-
- _jskit.make_properties(this, _jskit.localstorage,
- ['length']
- );
-})();*/
-
//It appears that Proxy is not available since Qt is using Javascript v5
/*(function() {
var proxy = _jskit.make_proxies({}, _jskit.localstorage, ['set', 'has', 'deleteProperty', 'keys', 'enumerate']);
@@ -194,3 +184,97 @@ Object.defineProperty(window, "localStorage", new (function () {
localStorage.setItem(keys[index], value);
}
})();
+
+function WebSocket(url, protocols) {
+ var ws = _jskit.pebble.createWebSocket(url, protocols);
+ _jskit.make_proxies(this, ws, ['close', 'send']);
+ _jskit.make_properties(this, ws,
+ ['readyState', 'bufferedAmount', 'onopen', 'onerror', 'onclose', 'onmessage',
+ 'extensions', 'protocol', 'binaryType']);
+
+ this.CONNECTING = 0;
+ this.OPEN = 1;
+ this.CLOSING = 2;
+ this.CLOSED = 3;
+}
+
+//Borrowed from https://github.com/pebble/pypkjs/blob/master/pypkjs/javascript/events.py#L9
+Event = function(event_type, event_init_dict) {
+ var self = this;
+ this.stopPropagation = function() {};
+ this.stopImmediatePropagation = function() { self._aborted = true; }
+ this.preventDefault = function() { self.defaultPrevented = true; }
+ this.initEvent = function(event_type, bubbles, cancelable) {
+ self.type = event_type;
+ self.bubbles = bubbles;
+ self.cancelable = cancelable
+ };
+
+ if(!event_init_dict) event_init_dict = {};
+ this.type = event_type;
+ this.bubbles = event_init_dict.bubbles || false;
+ this.cancelable = event_init_dict.cancelable || false;
+ this.defaultPrevented = false;
+ this.target = null;
+ this.currentTarget = null;
+ this.eventPhase = 2;
+ this._aborted = false;
+};
+Event._init = function(event_type, event_init_dict) {
+ //Convenience function to call from the engine
+ return new Event(event_type, event_init_dict)
+};
+
+Event.NONE = 0;
+Event.CAPTURING_PHASE = 1;
+Event.AT_TARGET = 2;
+Event.BUBBLING_PHASE = 3;
+
+//Borrowed from https://github.com/pebble/pypkjs/blob/master/pypkjs/javascript/ws.py#L14
+CloseEvent = function(wasClean, code, reason, eventInitDict) {
+ Event.call(this, "close", eventInitDict);
+
+ Object.defineProperties(this, {
+ wasClean: {
+ get: function() { return wasClean; },
+ enumerable: true,
+ },
+ code: {
+ get: function() { return code; },
+ enumerable: true,
+ },
+ reason: {
+ get: function() { return reason; },
+ enumerable: true,
+ },
+ });
+};
+
+CloseEvent.prototype = Object.create(Event.prototype);
+CloseEvent.prototype.constructor = CloseEvent;
+CloseEvent._init = function(wasClean, code, reason) {
+ //Convenience function to call from the engine
+ return new CloseEvent(wasClean, code, reason)
+};
+
+MessageEvent = function(origin, data, eventInitDict) {
+ Event.call(this, "message", eventInitDict);
+
+ Object.defineProperties(this, {
+ origin: {
+ get: function() { return origin; },
+ enumerable: true,
+ },
+ data: {
+ get: function() { return data; },
+ enumerable: true,
+ }
+ });
+};
+
+MessageEvent.prototype = Object.create(Event.prototype);
+MessageEvent.prototype.constructor = MessageEvent;
+MessageEvent._init = function(origin, data) {
+ //Convenience function to call from the engine
+ return new MessageEvent(origin, data)
+}; \ No newline at end of file
diff --git a/rockworkd/libpebble/jskit/jskitwebsocket.cpp b/rockworkd/libpebble/jskit/jskitwebsocket.cpp
new file mode 100644
index 0000000..e66cdfb
--- /dev/null
+++ b/rockworkd/libpebble/jskit/jskitwebsocket.cpp
@@ -0,0 +1,311 @@
+#include "jskitwebsocket.h"
+#include "jskitmanager.h"
+
+JSKitWebSocket::JSKitWebSocket(QJSEngine *engine, const QString &url, const QJSValue &protocols) :
+ QObject(engine),
+ l(metaObject()->className()),
+ m_engine(engine),
+ m_webSocket(new QWebSocket("", QWebSocketProtocol::VersionLatest, this)),
+ m_url(url)
+{
+ //As of QT 5.5: "QWebSocket currently does not support extensions and subprotocols"
+ Q_UNUSED(protocols)
+
+ connect(m_webSocket, &QWebSocket::connected,
+ this, &JSKitWebSocket::handleConnected);
+ connect(m_webSocket, &QWebSocket::disconnected,
+ this, &JSKitWebSocket::handleDisconnected);
+ connect(m_webSocket, static_cast<void(QWebSocket::*)(QAbstractSocket::SocketError)>(&QWebSocket::error),
+ this, &JSKitWebSocket::handleError);
+ connect(m_webSocket, &QWebSocket::sslErrors,
+ this, &JSKitWebSocket::handleSslErrors);
+ connect(m_webSocket, &QWebSocket::textMessageReceived,
+ this, &JSKitWebSocket::handleTextMessageReceived);
+ connect(m_webSocket, &QWebSocket::binaryMessageReceived,
+ this, &JSKitWebSocket::handleBinaryMessageReceived);
+
+ qCDebug(l) << "WebSocket opened for" << url;
+ //m_webSocket->ignoreSslErrors();
+ m_webSocket->open(QUrl(url));
+}
+
+void JSKitWebSocket::send(const QJSValue &data)
+{
+ //TODO throw SYNTAX_ERR if "The data is a string that has unpaired surrogates" - https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Exceptions_thrown_2
+
+ if (m_readyState != OPEN) {
+ //TODO throw INVALID_STATE_ERR if not opened - https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Exceptions_thrown_2
+ qCDebug(l) << "trying to send when connection is not yet open";
+
+ return;
+ }
+
+ if (data.isUndefined() || data.isNull()) {
+ qCDebug(l) << "Refusing to send a null or undefined message";
+ } else if (data.isString()) {
+ qCDebug(l) << "Sending text message:" << data.toString();
+
+ QByteArray byteData = data.toString().toUtf8();
+ m_bufferedAmount += byteData.size();
+
+ m_webSocket->sendTextMessage(data.toString());
+ } else if (data.isObject()) {
+ if (data.hasProperty("byteLength")) {
+ // Looks like an ArrayView or an ArrayBufferView!
+ QJSValue buffer = data.property("buffer");
+ if (buffer.isUndefined()) {
+ // We must assume we've been passed an ArrayBuffer directly
+ buffer = data;
+ }
+
+ QJSValue array = buffer.property("_bytes");
+ int byteLength = buffer.property("byteLength").toInt();
+
+ if (array.isArray()) {
+ QByteArray byteData;
+ byteData.reserve(byteLength);
+
+ for (int i = 0; i < byteLength; i++) {
+ byteData.append(array.property(i).toInt());
+ }
+
+ qCDebug(l) << "sending binary message with" << byteData.length() << "bytes";
+
+ m_bufferedAmount += byteData.size();
+ m_webSocket->sendBinaryMessage(byteData);
+ } else {
+ qCWarning(l) << "Refusing to send an unknown/invalid ArrayBuffer" << data.toString();
+ }
+ } else {
+ qCWarning(l) << "Refusing to send an unknown object:" << data.toString();
+ }
+ }
+}
+
+void JSKitWebSocket::close(quint32 code, const QString &reason)
+{
+ //TODO throw SYNTAX_ERR if "The reason string contains unpaired surrogates" - https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Exceptions_thrown_2
+
+
+ QByteArray byteData = reason.toUtf8();
+ if (byteData.size() >= 123) {
+ //TODO throw SYNTAX_ERR for invalid reason - https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Exceptions_thrown
+ qCDebug(l) << "Invalid reason";
+
+ return;
+ }
+
+ QWebSocketProtocol::CloseCode closeCode = QWebSocketProtocol::CloseCodeNormal;
+ if ((code >= 1000 && code <= 1011) || code == 1015) {
+ closeCode = static_cast<QWebSocketProtocol::CloseCode>(code);;
+ }
+ else {
+ //TODO throw INVALID_ACCESS_ERR for invalide code - https://developer.mozilla.org/en-US/docs/Web/API/WebSocket#Exceptions_thrown
+ qCDebug(l) << "Invalid close code";
+
+ return;
+ }
+
+ m_webSocket->close(closeCode, reason);
+ m_readyState = CLOSING;
+}
+
+void JSKitWebSocket::setOnclose(const QJSValue &onclose)
+{
+ m_onclose = onclose;
+}
+
+void JSKitWebSocket::setOnerror(const QJSValue &onerror)
+{
+ m_onerror = onerror;
+}
+
+void JSKitWebSocket::setOnmessage(const QJSValue &onmessage)
+{
+ m_onmessage = onmessage;
+}
+
+void JSKitWebSocket::setOnopen(const QJSValue &onopen)
+{
+ m_onopen = onopen;
+}
+
+QJSValue JSKitWebSocket::onclose() const
+{
+ return m_onclose;
+}
+
+QJSValue JSKitWebSocket::onerror() const
+{
+ return m_onerror;
+}
+
+QJSValue JSKitWebSocket::onmessage() const
+{
+ return m_onmessage;
+}
+
+QJSValue JSKitWebSocket::onopen() const
+{
+ return m_onopen;
+}
+
+quint32 JSKitWebSocket::bufferedAmount()
+{
+ return m_bufferedAmount;
+}
+
+quint8 JSKitWebSocket::readyState()
+{
+ return m_readyState;
+}
+
+QString JSKitWebSocket::url()
+{
+ return m_url;
+}
+
+void JSKitWebSocket::handleConnected()
+{
+ m_readyState = OPEN;
+ qCDebug(l) << "Connection opened";
+
+ if (m_onopen.isCallable()) {
+ qCDebug(l) << "Going to call onopen";
+
+ QJSValueList eventArgs;
+ eventArgs.append("open");
+ QJSValue event = m_engine->globalObject().property("Event").property("_init").call(eventArgs);
+
+ QJSValueList args;
+ args.append(event);
+ QJSValue result = m_onopen.callWithInstance(m_engine->newQObject(this), args);
+ if (result.isError()) {
+ qCWarning(l) << "JS error in onopen handler:" << JSKitManager::describeError(result);
+ }
+ }
+}
+
+void JSKitWebSocket::handleDisconnected()
+{
+ m_readyState = CLOSED;
+ qCDebug(l) << "Connection closed";
+
+ if (m_onclose.isCallable()) {
+ qCDebug(l) << "Going to call onclose";
+
+ QJSValueList eventArgs;
+ eventArgs.append(QJSValue(true)); //wasClean
+ eventArgs.append(QJSValue(m_webSocket->closeCode()));
+ eventArgs.append(QJSValue(m_webSocket->closeReason()));
+
+ QJSValue event = m_engine->globalObject().property("CloseEvent").property("_init").call(eventArgs);
+
+ QJSValueList args;
+ args.append(event);
+
+ QJSValue result = m_onclose.callWithInstance(m_engine->newQObject(this));
+ if (result.isError()) {
+ qCWarning(l) << "JS error in onclose handler:" << JSKitManager::describeError(result);
+ }
+ }
+}
+
+void JSKitWebSocket::handleError(QAbstractSocket::SocketError error)
+{
+ qCDebug(l) << "Error:" << error;
+
+ if (m_onerror.isCallable()) {
+ qCDebug(l) << "Going to call onerror";
+
+ QJSValueList eventArgs;
+ eventArgs.append(QJSValue("error"));
+ QJSValue event = m_engine->globalObject().property("Event").property("_init").call(eventArgs);
+
+ QJSValueList args;
+ args.append(event);
+ QJSValue result = m_onerror.callWithInstance(m_engine->newQObject(this), args);
+ if (result.isError()) {
+ qCWarning(l) << "JS error in onclose handler:" << JSKitManager::describeError(result);
+ }
+ }
+}
+
+void JSKitWebSocket::handleSslErrors(const QList<QSslError> &errors)
+{
+ qCDebug(l) << "Ssl Errors:" << errors;
+
+ if (m_onerror.isCallable()) {
+ qCDebug(l) << "Going to call onerror";
+
+ QJSValueList eventArgs;
+ eventArgs.append(QJSValue("error"));
+ QJSValue event = m_engine->globalObject().property("Event").property("_init").call(eventArgs);
+
+ QJSValueList args;
+ args.append(event);
+ QJSValue result = m_onerror.callWithInstance(m_engine->newQObject(this), args);
+ if (result.isError()) {
+ qCWarning(l) << "JS error in onclose handler:" << JSKitManager::describeError(result);
+ }
+ }
+}
+
+void JSKitWebSocket::handleTextMessageReceived(const QString &message)
+{
+ qCDebug(l) << "Text message recieved: " << message;
+
+ callOnmessage(QJSValue(message));
+}
+
+void JSKitWebSocket::handleBinaryMessageReceived(const QByteArray &message)
+{
+ qCDebug(l) << "Binary message recieved";
+
+ if (m_onmessage.isCallable()) {
+ if (m_binaryType == "arraybuffer") {
+ QJSValue arrayBufferProto = m_engine->globalObject().property("ArrayBuffer").property("prototype");
+ QJSValue arrayBuf = m_engine->newObject();
+
+ if (arrayBufferProto.isUndefined()) {
+ qCWarning(l) << "Cannot find proto of ArrayBuffer";
+ } else {
+ arrayBuf.setPrototype(arrayBufferProto);
+ arrayBuf.setProperty("byteLength", m_engine->toScriptValue<uint>(message.size()));
+
+ QJSValue array = m_engine->newArray(message.size());
+ for (int i = 0; i < message.size(); i++) {
+ array.setProperty(i, m_engine->toScriptValue<int>(message[i]));
+ }
+
+ arrayBuf.setProperty("_bytes", array);
+ qCDebug(l) << "calling onmessage with ArrayBuffer of" << message.size() << "bytes";
+
+ callOnmessage(arrayBuf);
+ }
+ } else {
+ qCWarning(l) << "unsupported binaryType:" << m_binaryType;
+ }
+ }
+}
+
+void JSKitWebSocket::callOnmessage(QJSValue data)
+{
+ if (m_onmessage.isCallable()) {
+ qCDebug(l) << "Going to call onmessage";
+
+ QJSValueList eventArgs;
+ eventArgs.append(QJSValue(m_webSocket->origin()));
+ eventArgs.append(data);
+
+ QJSValue messageEvent = m_engine->globalObject().property("MessageEvent").property("_init").call(eventArgs);
+
+ QJSValueList args;
+ args.append(messageEvent);
+
+ QJSValue result = m_onmessage.callWithInstance(m_engine->newQObject(this), args);
+ if (result.isError()) {
+ qCWarning(l) << "JS error in onmessage handler:" << JSKitManager::describeError(result);
+ }
+ }
+}
diff --git a/rockworkd/libpebble/jskit/jskitwebsocket.h b/rockworkd/libpebble/jskit/jskitwebsocket.h
new file mode 100644
index 0000000..192e9a4
--- /dev/null
+++ b/rockworkd/libpebble/jskit/jskitwebsocket.h
@@ -0,0 +1,79 @@
+#ifndef JSKITWEBSOCKET_P_H
+#define JSKITWEBSOCKET_P_H
+
+#include <QLoggingCategory>
+#include <QWebSocket>
+#include <QJSEngine>
+
+class JSKitWebSocket : public QObject
+{
+ Q_OBJECT
+ QLoggingCategory l;
+
+ Q_PROPERTY(QString binaryType MEMBER m_binaryType)
+ Q_PROPERTY(quint32 bufferedAmount READ bufferedAmount)
+ Q_PROPERTY(QString extensions MEMBER m_extensions)
+ Q_PROPERTY(QJSValue onclose READ onclose WRITE setOnclose)
+ Q_PROPERTY(QJSValue onerror READ onerror WRITE setOnerror)
+ Q_PROPERTY(QJSValue onmessage READ onmessage WRITE setOnmessage)
+ Q_PROPERTY(QJSValue onopen READ onopen WRITE setOnopen)
+ Q_PROPERTY(QString protocol MEMBER m_protocol)
+ Q_PROPERTY(quint8 readyState READ readyState)
+ Q_PROPERTY(QString url READ url)
+
+public:
+ explicit JSKitWebSocket(QJSEngine *engine, const QString &url, const QJSValue &protocols=QJSValue());
+
+ enum ReadyStates {
+ CONNECTING = 0,
+ OPEN = 1,
+ CLOSING = 2,
+ CLOSED = 3
+ };
+ Q_ENUMS(ReadyStates)
+
+ Q_INVOKABLE void send(const QJSValue &data);
+ Q_INVOKABLE void close(quint32 code=1000, const QString &reason=QString());
+
+ void setOnclose(const QJSValue &onclose);
+ void setOnerror(const QJSValue &onerror);
+ void setOnmessage(const QJSValue &onmessage);
+ void setOnopen(const QJSValue &onopen);
+
+ QJSValue onclose() const;
+ QJSValue onerror() const;
+ QJSValue onmessage() const;
+ QJSValue onopen() const;
+
+ quint32 bufferedAmount();
+ quint8 readyState();
+ QString url();
+
+private slots:
+ void handleConnected();
+ void handleDisconnected();
+ void handleError(QAbstractSocket::SocketError error);
+ void handleSslErrors(const QList<QSslError> &errors);
+ void handleTextMessageReceived(const QString &message);
+ void handleBinaryMessageReceived(const QByteArray &message);
+
+private:
+ void callOnmessage(QJSValue data);
+
+private:
+ QJSEngine *m_engine;
+ QWebSocket *m_webSocket;
+
+ QString m_binaryType = "arraybuffer";
+ quint32 m_bufferedAmount = 0;
+ QString m_extensions;
+ QJSValue m_onclose;
+ QJSValue m_onerror;
+ QJSValue m_onmessage;
+ QJSValue m_onopen;
+ QString m_protocol;
+ quint8 m_readyState = CONNECTING;
+ QString m_url;
+};
+
+#endif // JSKITWEBSOCKET_P_H