Browse Source

QWebThreeConnector

cl-refactor
Marek Kotewicz 10 years ago
parent
commit
3b84093ab8
  1. 1
      alethzero/CMakeLists.txt
  2. 12
      alethzero/MainWin.cpp
  3. 3
      alethzero/MainWin.h
  4. 1
      libqethereum/CMakeLists.txt
  5. 64
      libqethereum/QEthereum.cpp
  6. 120
      libqethereum/QEthereum.h

1
alethzero/CMakeLists.txt

@ -54,6 +54,7 @@ endif ()
qt5_use_modules(${EXECUTEABLE} Core)# Gui Widgets Network WebKit WebKitWidgets)
target_link_libraries(${EXECUTEABLE} webthree qethereum ethereum evm ethcore devcrypto secp256k1 gmp ${CRYPTOPP_LS} serpent lll evmface devcore)
target_link_libraries(${EXECUTEABLE} ethrpc)
if (APPLE)
# First have qt5 install plugins and frameworks

12
alethzero/MainWin.cpp

@ -41,6 +41,7 @@
#include <libethereum/Client.h>
#include <libethereum/EthereumHost.h>
#include <libethereum/DownloadMan.h>
#include <libethrpc/WebThreeStubServer.h>
#include "DownloadView.h"
#include "MiningView.h"
#include "BuildInfo.h"
@ -143,11 +144,20 @@ Main::Main(QWidget *parent) :
QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
QWebFrame* f = ui->webView->page()->mainFrame();
f->disconnect(SIGNAL(javaScriptWindowObjectCleared()));
m_qweb = new QWebThree(this);
auto qdev = m_dev;
auto qeth = m_ethereum;
auto qshh = m_whisper;
auto qp2p = m_p2p;
connect(f, &QWebFrame::javaScriptWindowObjectCleared, QETH_INSTALL_JS_NAMESPACE(f, this, qdev, qeth, qshh, qp2p));
auto qweb = m_qweb;
auto list = owned().toStdList();
jsonrpcServer = auto_ptr<WebThreeStubServer>(new WebThreeStubServer(new QWebThreeConnector(qweb), *web3(), {std::begin(list), std::end(list)}));
jsonrpcServer->StartListening();
connect(f, &QWebFrame::javaScriptWindowObjectCleared, QETH_INSTALL_JS_NAMESPACE(f, this, qdev, qeth, qshh, qp2p, qweb));
});
connect(ui->webView, &QWebView::loadFinished, [=]()

3
alethzero/MainWin.h

@ -47,6 +47,7 @@ class MessageFilter;
}}
class QQuickView;
class WebThreeStubServer;
struct WorldState
{
@ -248,8 +249,10 @@ private:
QString m_logHistory;
bool m_logChanged = true;
std::auto_ptr<WebThreeStubServer> jsonrpcServer;
QDev* m_dev = nullptr;
QEthereum* m_ethereum = nullptr;
QWhisper* m_whisper = nullptr;
QPeer2Peer* m_p2p = nullptr;
QWebThree* m_qweb = nullptr;
};

1
libqethereum/CMakeLists.txt

@ -61,6 +61,7 @@ endif()
include_directories(/)
qt5_use_modules(${EXECUTABLE} Core Gui WebKit WebKitWidgets Widgets Network Quick Qml)
target_link_libraries(${EXECUTABLE} ethereum secp256k1 ${CRYPTOPP_LS})
target_link_libraries(${EXECUTABLE} ${JSONRPC_LS})
if (APPLE)
if (${ADDFRAMEWORKS})

64
libqethereum/QEthereum.cpp

@ -617,6 +617,70 @@ void QWhisper::poll()
{
}
QWebThree::QWebThree(QObject* _p): QObject(_p)
{
moveToThread(_p->thread());
}
QWebThree::~QWebThree()
{
}
static QString toJsonRpcMessage(QString _json)
{
QJsonObject f = QJsonDocument::fromJson(_json.toUtf8()).object();
QJsonObject res;
res["jsonrpc"] = "2.0";
if (f.contains("call"))
res["method"] = f["call"];
if (f.contains("args"))
res["params"] = f["args"];
if (f.contains("_id"))
res["id"] = f["_id"];
return QString::fromUtf8(QJsonDocument(res).toJson());
}
void QWebThree::postData(QString _json)
{
emit processData(toJsonRpcMessage(_json));
}
QWebThreeConnector::QWebThreeConnector(QWebThree* _q): m_qweb(_q)
{
}
QWebThreeConnector::~QWebThreeConnector()
{
StopListening();
}
bool QWebThreeConnector::StartListening()
{
connect(m_qweb, SIGNAL(processData(QString)), this, SLOT(onMessage(QString)));
return true;
}
bool QWebThreeConnector::StopListening()
{
this->disconnect();
return true;
}
bool QWebThreeConnector::SendResponse(std::string const& _response, void* _addInfo)
{
emit m_qweb->send(QString::fromStdString(_response));
return true;
}
void QWebThreeConnector::onMessage(QString const& _json)
{
OnRequest(_json.toStdString());
}
// extra bits needed to link on VS
#ifdef _MSC_VER

120
libqethereum/QEthereum.h

@ -5,6 +5,7 @@
#include <QtCore/QList>
#include <libdevcore/CommonIO.h>
#include <libethcore/CommonEth.h>
#include <jsonrpc/rpc.h>
namespace dev
{
@ -269,65 +270,72 @@ private:
std::vector<unsigned> m_watches;
};
class QWebThree: public QObject
{
Q_OBJECT
public:
QWebThree(QObject* _p);
virtual ~QWebThree();
void installJSNamespace(QWebFrame* _f);
Q_INVOKABLE void postData(QString _json);
signals:
void processData(QString _json);
void send(QString _json);
private:
QObject* m_main = nullptr;
QWebFrame* m_frame = nullptr;
QDev* m_dev = nullptr;
QEthereum* m_ethereum = nullptr;
QWhisper* m_whisper = nullptr;
QPeer2Peer* m_p2p = nullptr;
};
class QWebThreeConnector: public QObject, public jsonrpc::AbstractServerConnector
{
Q_OBJECT
public:
QWebThreeConnector(QWebThree* _q);
virtual ~QWebThreeConnector();
virtual bool StartListening();
virtual bool StopListening();
bool virtual SendResponse(std::string const& _response,
void* _addInfo = NULL);
public slots:
void onMessage(QString const& _json);
private:
QWebThree* m_qweb;
};
// TODO: p2p object condition
#define QETH_INSTALL_JS_NAMESPACE(_frame, _env, _dev, _eth, _shh, _p2p) [_frame, _env, _dev, _eth, _shh, _p2p]() \
#define QETH_INSTALL_JS_NAMESPACE(_frame, _env, _dev, _eth, _shh, _p2p, qweb) [_frame, _env, _dev, _eth, _shh, _p2p, qweb]() \
{ \
_frame->disconnect(); \
_frame->addToJavaScriptWindowObject("env", _env, QWebFrame::QtOwnership); \
_frame->addToJavaScriptWindowObject("dev", _dev, QWebFrame::ScriptOwnership); \
if (_eth) \
{ \
_frame->addToJavaScriptWindowObject("eth", _eth, QWebFrame::ScriptOwnership); \
_frame->addToJavaScriptWindowObject("p2p", _p2p, QWebFrame::ScriptOwnership); \
_frame->evaluateJavaScript("eth.setCoinbase = function(a, f) { window.setTimeout(function () { eth.coinbase = a; if (f) {f(true);}}, 0); }"); \
_frame->evaluateJavaScript("eth.getCoinbase = function(f) { window.setTimeout(function () { if (f) {f(eth.coinbase);}}, 0); }"); \
_frame->evaluateJavaScript("eth.listening = {get listening() {return p2p.listening}, set listening(l) {p2p.listening = l}}"); \
_frame->evaluateJavaScript("eth.setListening = function(a, f) { window.setTimeout(function () { eth.listening = a; if (f) {f(true);}}, 0); }"); \
_frame->evaluateJavaScript("eth.getListening = function(f) { window.setTimeout(function () { if (f) {f(eth.listening);}}, 0); }"); \
_frame->evaluateJavaScript("eth.setMining = function(a, f) { window.setTimeout(function () { eth.mining = a; if (f) {f(true);}}, 0); }"); \
_frame->evaluateJavaScript("eth.getMining = function(f) { window.setTimeout(function () { if (f) { f(eth.mining);}}, 0); }"); \
_frame->evaluateJavaScript("eth.getGasPrice = function(f) { window.setTimeout(function () { if (f) {f(eth.gasPrice);}}, 0); }"); \
_frame->evaluateJavaScript("eth.getAccounts = function(f) { window.setTimeout(function () { if (f) {f(eth.accounts);}}, 0); }"); \
_frame->evaluateJavaScript("eth.peerCount = {get peerCount() {return p2p.peerCount}}"); \
_frame->evaluateJavaScript("eth.getPeerCount = function(f) { window.setTimeout(function () { if (f) {f(eth.peerCount);}}, 0); }"); \
_frame->evaluateJavaScript("eth.getDefaultBlock = function(f) { window.setTimeout(function () { if (f) {f(eth.defaultBlock);}}, 0); }"); \
_frame->evaluateJavaScript("eth.getNumber = function(f) { window.setTimeout(function () { if (f) {f(eth.number);}}, 0); }"); \
_frame->evaluateJavaScript("eth.messages = function(a) { return JSON.parse(eth.getMessagesImpl(JSON.stringify(a))); }"); \
_frame->evaluateJavaScript("eth.getMessages = function(a, f) { window.setTimeout(function () { if (f) { f(JSON.parse(eth.getMessagesImpl(JSON.stringify(a)))); }}, 0);}"); \
_frame->evaluateJavaScript("eth.getBalanceAt = function() { var args = Array.prototype.slice.call(arguments, 0, -1); f = arguments[arguments.length - 1]; window.setTimeout(function () { if (f) { f(eth.balanceAt.apply(null, args)); }},0);}"); \
_frame->evaluateJavaScript("eth.getStateAt = function() { var args = Array.prototype.slice.call(arguments, 0, -1); f = arguments[arguments.length - 1]; window.setTimeout(function () { if (f) { f(eth.stateAt.apply(null, args)); }},0);}"); \
_frame->evaluateJavaScript("eth.getCountAt = function() { var args = Array.prototype.slice.call(arguments, 0, -1); f = arguments[arguments.length - 1]; window.setTimeout(function () { if (f) { f(eth.countAt.apply(null, args)); }},0);}"); \
_frame->evaluateJavaScript("eth.getCodeAt = function() { var args = Array.prototype.slice.call(arguments, 0, -1); f = arguments[arguments.length - 1]; window.setTimeout(function () { if (f) { f(eth.codeAt.apply(null, args)); }},0);}"); \
_frame->evaluateJavaScript("eth.transact = function(a) { var ret = eth.doTransactImpl(JSON.stringify(a)); return ret; }"); \
_frame->evaluateJavaScript("eth.doTransact = function() { var args = Array.prototype.slice.call(arguments, 0, -1); f = arguments[arguments.length - 1]; window.setTimeout(function () { if (f) { f(eth.transact.apply(null, args)); }},0);}"); \
_frame->evaluateJavaScript("eth.call = function(a) { var ret = eth.doCallImpl(JSON.stringify(a)); return ret; }"); \
_frame->evaluateJavaScript("eth.doCall = function() { var args = Array.prototype.slice.call(arguments, 0, -1); f = arguments[arguments.length - 1]; window.setTimeout(function () { if (f) { f(eth.call.apply(null, args)); }},0);}"); \
_frame->evaluateJavaScript("eth.block = function(a) { return JSON.parse(eth.getBlockImpl(JSON.stringify(a))); }"); \
_frame->evaluateJavaScript("eth.getBlock = function() { var args = Array.prototype.slice.call(arguments, 0, -1); f = arguments[arguments.length - 1]; window.setTimeout(function () { if (f) { f(eth.block.apply(null, args)); }},0);}"); \
_frame->evaluateJavaScript("eth.transaction = function(a, i) { return JSON.parse(eth.getTransactionImpl(JSON.stringify(a), i)); }"); \
_frame->evaluateJavaScript("eth.getTransaction = function() { var args = Array.prototype.slice.call(arguments, 0, -1); f = arguments[arguments.length - 1]; window.setTimeout(function () { if (f) { f(eth.transaction.apply(null, args)); }},0);}"); \
_frame->evaluateJavaScript("eth.uncle = function(a, i) { return JSON.parse(eth.getUncleImpl(JSON.stringify(a), i)); }"); \
_frame->evaluateJavaScript("eth.getUncle = function() { var args = Array.prototype.slice.call(arguments, 0, -1); f = arguments[arguments.length - 1]; window.setTimeout(function () { if (f) { f(eth.uncle.apply(null, args)); }},0);}"); \
_frame->evaluateJavaScript("eth.makeWatch = function(a) { var ww = eth.newWatch(a); var ret = { w: ww }; ret.uninstall = function() { eth.killWatch(w); }; ret.changed = function(f) { eth.watchChanged.connect(function(nw) { if (nw == ww) f() }); }; ret.messages = function() { return JSON.parse(eth.watchMessages(this.w)) }; return ret; }"); \
_frame->evaluateJavaScript("eth.watch = function(a) { return eth.makeWatch(JSON.stringify(a)) }"); \
} \
if (_shh) \
{ \
_frame->addToJavaScriptWindowObject("shh", _shh, QWebFrame::ScriptOwnership); \
_frame->evaluateJavaScript("shh.makeWatch = function(a) { var ww = shh.newWatch(a); var ret = { w: ww }; ret.uninstall = function() { shh.killWatch(w); }; ret.changed = function(f) { shh.watchChanged.connect(function(nw) { if (nw == ww) f() }); }; ret.messages = function() { return JSON.parse(shh.watchMessages(this.w)) }; return ret; }"); \
_frame->evaluateJavaScript("shh.watch = function(a) { return shh.makeWatch(JSON.stringify(a)) }"); \
} \
_frame->addToJavaScriptWindowObject("_web3", qweb, QWebFrame::ScriptOwnership); \
_frame->evaluateJavaScript("navigator.qt = _web3;"); \
_frame->evaluateJavaScript("(function () {" \
"navigator.qt.handlers = [];" \
"Object.defineProperty(navigator.qt, 'onmessage', {" \
" set: function(handler) {" \
" navigator.qt.handlers.push(handler);" \
" }" \
"})" \
"})()"); \
_frame->evaluateJavaScript("navigator.qt.send.connect(function (res) {" \
"navigator.qt.handlers.forEach(function (handler) {" \
" handler(res);" \
"})" \
"})"); \
}
template <unsigned N> inline boost::multiprecision::number<boost::multiprecision::cpp_int_backend<N * 8, N * 8, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>> toInt(QString const& _s)
{
if (_s.startsWith("0x"))
return dev::fromBigEndian<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<N * 8, N * 8, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>>(dev::fromHex(_s.toStdString().substr(2)));
else if (!_s.contains(QRegExp("[^0-9]")))
// Hex or Decimal
return boost::multiprecision::number<boost::multiprecision::cpp_int_backend<N * 8, N * 8, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>(_s.toStdString());
else
// Binary
return dev::fromBigEndian<boost::multiprecision::number<boost::multiprecision::cpp_int_backend<N * 8, N * 8, boost::multiprecision::unsigned_magnitude, boost::multiprecision::unchecked, void>>>(asBytes(padded(_s, N)));
}

Loading…
Cancel
Save