arkpar
10 years ago
committed by
arkpar
12 changed files with 636 additions and 38 deletions
@ -0,0 +1,141 @@ |
|||||
|
/*
|
||||
|
This file is part of cpp-ethereum. |
||||
|
|
||||
|
cpp-ethereum is free software: you can redistribute it and/or modify |
||||
|
it under the terms of the GNU General Public License as published by |
||||
|
the Free Software Foundation, either version 3 of the License, or |
||||
|
(at your option) any later version. |
||||
|
|
||||
|
cpp-ethereum is distributed in the hope that it will be useful, |
||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
GNU General Public License for more details. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file DappHost.cpp
|
||||
|
* @author Arkadiy Paronyan <arkadiy@ethdev.org> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
|
||||
|
#include <microhttpd.h> |
||||
|
#include <boost/algorithm/string.hpp> |
||||
|
#include <libdevcore/Common.h> |
||||
|
#include <QUrl> |
||||
|
#include "DappHost.h" |
||||
|
|
||||
|
using namespace dev; |
||||
|
|
||||
|
DappHost::DappHost(int _port, int _threads): |
||||
|
m_port(_port), m_threads(_threads), m_running(false), m_daemon(nullptr) |
||||
|
{ |
||||
|
startListening(); |
||||
|
} |
||||
|
|
||||
|
DappHost::~DappHost() |
||||
|
{ |
||||
|
stopListening(); |
||||
|
} |
||||
|
|
||||
|
void DappHost::startListening() |
||||
|
{ |
||||
|
if(!this->m_running) |
||||
|
{ |
||||
|
this->m_daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, this->m_port, nullptr, nullptr, &DappHost::callback, this, MHD_OPTION_THREAD_POOL_SIZE, this->m_threads, MHD_OPTION_END); |
||||
|
if (this->m_daemon != nullptr) |
||||
|
this->m_running = true; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void DappHost::stopListening() |
||||
|
{ |
||||
|
if(this->m_running) |
||||
|
{ |
||||
|
MHD_stop_daemon(this->m_daemon); |
||||
|
this->m_running = false; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
void DappHost::sendOptionsResponse(MHD_Connection* _connection) |
||||
|
{ |
||||
|
MHD_Response *result = MHD_create_response_from_data(0, NULL, 0, 1); |
||||
|
MHD_add_response_header(result, "Allow", "GET, OPTIONS"); |
||||
|
//MHD_add_response_header(result, "Access-Control-Allow-Origin", "*");
|
||||
|
MHD_add_response_header(result, "Access-Control-Allow-Headers", "origin, content-type, accept"); |
||||
|
MHD_add_response_header(result, "DAV", "1"); |
||||
|
MHD_queue_response(_connection, MHD_HTTP_OK, result); |
||||
|
MHD_destroy_response(result); |
||||
|
} |
||||
|
|
||||
|
void DappHost::sendNotAllowedResponse(MHD_Connection* _connection) |
||||
|
{ |
||||
|
MHD_Response *result = MHD_create_response_from_data(0, NULL, 0, 1); |
||||
|
MHD_add_response_header(result, "Allow", "GET, OPTIONS"); |
||||
|
MHD_queue_response(_connection, MHD_HTTP_METHOD_NOT_ALLOWED, result); |
||||
|
MHD_destroy_response(result); |
||||
|
} |
||||
|
|
||||
|
void DappHost::sendResponse(std::string const& _url, MHD_Connection* _connection) |
||||
|
{ |
||||
|
QUrl requestUrl(QString::fromStdString(_url)); |
||||
|
QString path = requestUrl.path().toLower(); |
||||
|
if (path.isEmpty()) |
||||
|
path = "/"; |
||||
|
|
||||
|
bytesConstRef response; |
||||
|
unsigned code = MHD_HTTP_NOT_FOUND; |
||||
|
std::string contentType; |
||||
|
|
||||
|
while (!path.isEmpty()) |
||||
|
{ |
||||
|
auto iter = m_entriesByPath.find(path); |
||||
|
if (iter != m_entriesByPath.end()) |
||||
|
{ |
||||
|
ManifestEntry const* entry = iter->second; |
||||
|
auto contentIter = m_dapp.content.find(entry->hash); |
||||
|
if (contentIter == m_dapp.content.end()) |
||||
|
break; |
||||
|
|
||||
|
response = bytesConstRef(contentIter->second.data(), contentIter->second.size()); |
||||
|
code = entry->httpStatus != 0 ? entry->httpStatus : MHD_HTTP_OK; |
||||
|
contentType = entry->contentType; |
||||
|
break; |
||||
|
} |
||||
|
path.truncate(path.length() - 1); |
||||
|
path = path.mid(0, path.lastIndexOf('/')); |
||||
|
} |
||||
|
|
||||
|
MHD_Response *result = MHD_create_response_from_data(response.size(), const_cast<byte*>(response.data()), 0, 1); |
||||
|
if (!contentType.empty()) |
||||
|
MHD_add_response_header(result, "Content-Type", contentType.c_str()); |
||||
|
//MHD_add_response_header(result, "Access-Control-Allow-Origin", "*");
|
||||
|
MHD_queue_response(_connection, code, result); |
||||
|
MHD_destroy_response(result); |
||||
|
} |
||||
|
|
||||
|
int DappHost::callback(void* _cls, MHD_Connection* _connection, char const* _url, char const* _method, char const* _version, char const* _uploadData, size_t* _uploadDataSize, void** _conCls) |
||||
|
{ |
||||
|
(void)_version; |
||||
|
(void)_uploadData; |
||||
|
(void)_uploadDataSize; |
||||
|
(void)_conCls; |
||||
|
DappHost* host = static_cast<DappHost*>(_cls); |
||||
|
if (std::string("GET") == _method) |
||||
|
host->sendResponse(std::string(_url), _connection); |
||||
|
else if (std::string("OPTIONS") == _method) |
||||
|
host->sendOptionsResponse(_connection); |
||||
|
else |
||||
|
host->sendNotAllowedResponse(_connection); |
||||
|
return MHD_YES; |
||||
|
} |
||||
|
|
||||
|
QUrl DappHost::hostDapp(Dapp&& _dapp) |
||||
|
{ |
||||
|
m_dapp = std::move(_dapp); |
||||
|
m_entriesByPath.clear(); |
||||
|
for (ManifestEntry const& entry: m_dapp.manifest.entries) |
||||
|
m_entriesByPath[QString::fromStdString(entry.path)] = &entry; |
||||
|
|
||||
|
return QUrl(QString("http://localhost:%1/").arg(m_port)); |
||||
|
} |
@ -0,0 +1,58 @@ |
|||||
|
/*
|
||||
|
This file is part of cpp-ethereum. |
||||
|
|
||||
|
cpp-ethereum is free software: you can redistribute it and/or modify |
||||
|
it under the terms of the GNU General Public License as published by |
||||
|
the Free Software Foundation, either version 3 of the License, or |
||||
|
(at your option) any later version. |
||||
|
|
||||
|
cpp-ethereum is distributed in the hope that it will be useful, |
||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
GNU General Public License for more details. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file DappHost.h
|
||||
|
* @author Arkadiy Paronyan <arkadiy@ethdev.org> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <map> |
||||
|
#include <QUrl> |
||||
|
#include <QString> |
||||
|
#include "DappLoader.h" |
||||
|
|
||||
|
struct MHD_Daemon; |
||||
|
struct MHD_Connection; |
||||
|
|
||||
|
/// DApp web server. Servers web content, resolves paths by hashes
|
||||
|
class DappHost |
||||
|
{ |
||||
|
public: |
||||
|
/// @param _port Network pork to listen for incoming connections
|
||||
|
/// @param _threads Max number of threads to process requests
|
||||
|
DappHost(int _port, int _threads = 10); |
||||
|
virtual ~DappHost(); |
||||
|
/// Load and host a dapp. Previsous dapp in discarded. Synchronous
|
||||
|
QUrl hostDapp(Dapp&& _dapp); |
||||
|
|
||||
|
private: |
||||
|
void startListening(); |
||||
|
void stopListening(); |
||||
|
void sendOptionsResponse(MHD_Connection* _connection); |
||||
|
void sendNotAllowedResponse(MHD_Connection* _connection); |
||||
|
void sendResponse(std::string const& _url, MHD_Connection* _connection); |
||||
|
static int callback(void* _cls, MHD_Connection* _connection, char const* _url, char const* _method, char const* _version, char const* _uploadData, size_t* _uploadDataSize, void** _conCls); |
||||
|
|
||||
|
int m_port; |
||||
|
int m_threads; |
||||
|
bool m_running; |
||||
|
MHD_Daemon* m_daemon; |
||||
|
Dapp m_dapp; |
||||
|
std::map<QString, ManifestEntry const*> m_entriesByPath; |
||||
|
}; |
||||
|
|
@ -0,0 +1,203 @@ |
|||||
|
/*
|
||||
|
This file is part of cpp-ethereum. |
||||
|
|
||||
|
cpp-ethereum is free software: you can redistribute it and/or modify |
||||
|
it under the terms of the GNU General Public License as published by |
||||
|
the Free Software Foundation, either version 3 of the License, or |
||||
|
(at your option) any later version. |
||||
|
|
||||
|
cpp-ethereum is distributed in the hope that it will be useful, |
||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
GNU General Public License for more details. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file DappLoader.cpp
|
||||
|
* @author Arkadiy Paronyan <arkadiy@ethdev.org> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
|
||||
|
#include <algorithm> |
||||
|
#include <json/json.h> |
||||
|
#include <QUrl> |
||||
|
#include <QStringList> |
||||
|
#include <QNetworkAccessManager> |
||||
|
#include <QNetworkReply> |
||||
|
#include <libdevcore/Common.h> |
||||
|
#include <libdevcore/RLP.h> |
||||
|
#include <libdevcrypto/CryptoPP.h> |
||||
|
#include <libdevcrypto/SHA3.h> |
||||
|
#include <libethcore/CommonJS.h> |
||||
|
#include <libethereum/Client.h> |
||||
|
#include <libwebthree/WebThree.h> |
||||
|
#include "DappLoader.h" |
||||
|
|
||||
|
using namespace dev; |
||||
|
using namespace dev::eth; |
||||
|
using namespace dev::crypto; |
||||
|
|
||||
|
Address c_registrar = Address("0000000000000000000000000000000000000a28"); |
||||
|
Address c_urlHint = Address("0000000000000000000000000000000000000a29"); |
||||
|
|
||||
|
QString contentsOfQResource(std::string const& res); |
||||
|
|
||||
|
DappLoader::DappLoader(QObject* _parent, WebThreeDirect* _web3): |
||||
|
QObject(_parent), m_web3(_web3) |
||||
|
{ |
||||
|
connect(&m_net, &QNetworkAccessManager::finished, this, &DappLoader::downloadComplete); |
||||
|
} |
||||
|
|
||||
|
DappLocation DappLoader::resolveAppUri(QString const& _uri) |
||||
|
{ |
||||
|
QUrl url(_uri); |
||||
|
if (!url.scheme().isEmpty() && url.scheme() != "eth") |
||||
|
throw dev::Exception(); //TODO:
|
||||
|
|
||||
|
QStringList parts = url.host().split('.', QString::SkipEmptyParts); |
||||
|
QStringList domainParts; |
||||
|
std::reverse(parts.begin(), parts.end()); |
||||
|
parts.append(url.path().split('/', QString::SkipEmptyParts)); |
||||
|
|
||||
|
Address address = c_registrar; |
||||
|
Address lastAddress; |
||||
|
int partIndex = 0; |
||||
|
|
||||
|
h256 contentHash; |
||||
|
|
||||
|
while (address && partIndex < parts.length()) |
||||
|
{ |
||||
|
lastAddress = address; |
||||
|
string32 name = { 0 }; |
||||
|
QByteArray utf8 = parts[partIndex].toUtf8(); |
||||
|
std::copy(utf8.data(), utf8.data() + utf8.size(), name.data()); |
||||
|
address = abiOut<Address>(web3()->ethereum()->call(address, abiIn("addr(string32)", name))); |
||||
|
domainParts.append(parts[partIndex]); |
||||
|
if (!address) |
||||
|
{ |
||||
|
//we have the address of the last part, try to get content hash
|
||||
|
contentHash = abiOut<h256>(web3()->ethereum()->call(lastAddress, abiIn("content(string32)", name))); |
||||
|
if (!contentHash) |
||||
|
throw dev::Exception() << errinfo_comment("Can't resolve address"); |
||||
|
} |
||||
|
++partIndex; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
string32 contentUrl = abiOut<string32>(web3()->ethereum()->call(c_urlHint, abiIn("url(hash256)", contentHash))); |
||||
|
QString domain = domainParts.join('/'); |
||||
|
parts.erase(parts.begin(), parts.begin() + partIndex); |
||||
|
QString path = parts.join('/'); |
||||
|
QString contentUrlString = QString::fromUtf8(std::string(contentUrl.data(), contentUrl.size()).c_str()); |
||||
|
if (!contentUrlString.startsWith("http://") || !contentUrlString.startsWith("https://")) |
||||
|
contentUrlString = "http://" + contentUrlString; |
||||
|
return DappLocation { domain, path, contentUrlString, contentHash }; |
||||
|
} |
||||
|
|
||||
|
void DappLoader::downloadComplete(QNetworkReply* _reply) |
||||
|
{ |
||||
|
try |
||||
|
{ |
||||
|
//try to interpret as rlp
|
||||
|
QByteArray data = _reply->readAll(); |
||||
|
_reply->deleteLater(); |
||||
|
|
||||
|
h256 expected = m_uriHashes[_reply->request().url()]; |
||||
|
bytes package(reinterpret_cast<unsigned char const*>(data.constData()), reinterpret_cast<unsigned char const*>(data.constData() + data.size())); |
||||
|
Secp256k1 dec; |
||||
|
dec.decrypt(expected, package); |
||||
|
h256 got = sha3(package); |
||||
|
if (got != expected) |
||||
|
{ |
||||
|
//try base64
|
||||
|
data = QByteArray::fromBase64(data); |
||||
|
package = bytes(reinterpret_cast<unsigned char const*>(data.constData()), reinterpret_cast<unsigned char const*>(data.constData() + data.size())); |
||||
|
dec.decrypt(expected, package); |
||||
|
got = sha3(package); |
||||
|
if (got != expected) |
||||
|
throw dev::Exception() << errinfo_comment("Dapp content hash does not match"); |
||||
|
} |
||||
|
|
||||
|
RLP rlp(package); |
||||
|
loadDapp(rlp); |
||||
|
} |
||||
|
catch (...) |
||||
|
{ |
||||
|
qWarning() << tr("Error downloading DApp: ") << boost::current_exception_diagnostic_information().c_str(); |
||||
|
emit dappError(); |
||||
|
} |
||||
|
|
||||
|
} |
||||
|
|
||||
|
void DappLoader::loadDapp(RLP const& _rlp) |
||||
|
{ |
||||
|
Dapp dapp; |
||||
|
unsigned len = _rlp.itemCountStrict(); |
||||
|
dapp.manifest = loadManifest(_rlp[0].toString()); |
||||
|
for (unsigned c = 1; c < len; ++c) |
||||
|
{ |
||||
|
bytesConstRef content = _rlp[c].toBytesConstRef(); |
||||
|
h256 hash = sha3(content); |
||||
|
auto entry = std::find_if(dapp.manifest.entries.cbegin(), dapp.manifest.entries.cend(), [=](ManifestEntry const& _e) { return _e.hash == hash; }); |
||||
|
if (entry != dapp.manifest.entries.cend()) |
||||
|
{ |
||||
|
if (entry->path == "/deployment.js") |
||||
|
{ |
||||
|
//inject web3 code
|
||||
|
QString code; |
||||
|
code += contentsOfQResource(":/js/bignumber.min.js"); |
||||
|
code += "\n"; |
||||
|
code += contentsOfQResource(":/js/webthree.js"); |
||||
|
code += "\n"; |
||||
|
code += contentsOfQResource(":/js/setup.js"); |
||||
|
code += "\n"; |
||||
|
QByteArray res = code.toLatin1(); |
||||
|
bytes b(res.data(), res.data() + res.size()); |
||||
|
b.insert(b.end(), content.begin(), content.end()); |
||||
|
dapp.content[hash] = b; |
||||
|
} |
||||
|
else |
||||
|
dapp.content[hash] = content.toBytes(); |
||||
|
} |
||||
|
else |
||||
|
throw dev::Exception() << errinfo_comment("Dapp content hash does not match"); |
||||
|
} |
||||
|
emit dappReady(dapp); |
||||
|
} |
||||
|
|
||||
|
Manifest DappLoader::loadManifest(std::string const& _manifest) |
||||
|
{ |
||||
|
/// https://github.com/ethereum/go-ethereum/wiki/URL-Scheme
|
||||
|
Manifest manifest; |
||||
|
Json::Reader jsonReader; |
||||
|
Json::Value root; |
||||
|
jsonReader.parse(_manifest, root, false); |
||||
|
|
||||
|
Json::Value entries = root["entries"]; |
||||
|
for (Json::ValueIterator it = entries.begin(); it != entries.end(); ++it) |
||||
|
{ |
||||
|
Json::Value const& entryValue = *it; |
||||
|
std::string path = entryValue["path"].asString(); |
||||
|
if (path.size() == 0 || path[0] != '/') |
||||
|
path = "/" + path; |
||||
|
std::string contentType = entryValue["contentType"].asString(); |
||||
|
std::string strHash = entryValue["hash"].asString(); |
||||
|
if (strHash.length() == 64) |
||||
|
strHash = "0x" + strHash; |
||||
|
h256 hash = jsToFixed<32>(strHash); |
||||
|
unsigned httpStatus = entryValue["status"].asInt(); |
||||
|
manifest.entries.push_back(ManifestEntry{ path, hash, contentType, httpStatus }); |
||||
|
} |
||||
|
return manifest; |
||||
|
} |
||||
|
|
||||
|
void DappLoader::loadDapp(QString const& _uri) |
||||
|
{ |
||||
|
DappLocation location = resolveAppUri(_uri); |
||||
|
QUrl uri(location.contentUri); |
||||
|
QNetworkRequest request(uri); |
||||
|
m_uriHashes[uri] = location.contentHash; |
||||
|
m_net.get(request); |
||||
|
} |
||||
|
|
@ -0,0 +1,94 @@ |
|||||
|
/*
|
||||
|
This file is part of cpp-ethereum. |
||||
|
|
||||
|
cpp-ethereum is free software: you can redistribute it and/or modify |
||||
|
it under the terms of the GNU General Public License as published by |
||||
|
the Free Software Foundation, either version 3 of the License, or |
||||
|
(at your option) any later version. |
||||
|
|
||||
|
cpp-ethereum is distributed in the hope that it will be useful, |
||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
GNU General Public License for more details. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file DappLoader.h
|
||||
|
* @author Arkadiy Paronyan <arkadiy@ethdev.org> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <map> |
||||
|
#include <string> |
||||
|
#include <vector> |
||||
|
#include <QObject> |
||||
|
#include <QString> |
||||
|
#include <QUrl> |
||||
|
#include <QNetworkAccessManager> |
||||
|
#include <libdevcore/FixedHash.h> |
||||
|
|
||||
|
namespace dev |
||||
|
{ |
||||
|
class WebThreeDirect; |
||||
|
class RLP; |
||||
|
} |
||||
|
|
||||
|
struct ManifestEntry |
||||
|
{ |
||||
|
std::string path; |
||||
|
dev::h256 hash; |
||||
|
std::string contentType; |
||||
|
unsigned httpStatus; |
||||
|
}; |
||||
|
|
||||
|
struct Manifest |
||||
|
{ |
||||
|
std::vector<ManifestEntry> entries; |
||||
|
}; |
||||
|
|
||||
|
struct Dapp |
||||
|
{ |
||||
|
Manifest manifest; |
||||
|
std::map<dev::h256, dev::bytes> content; |
||||
|
}; |
||||
|
|
||||
|
|
||||
|
struct DappLocation |
||||
|
{ |
||||
|
QString canonDomain; |
||||
|
QString path; |
||||
|
QString contentUri; |
||||
|
dev::h256 contentHash; |
||||
|
}; |
||||
|
|
||||
|
///Downloads, unpacks and prepares DApps for hosting
|
||||
|
class DappLoader: public QObject |
||||
|
{ |
||||
|
Q_OBJECT |
||||
|
public: |
||||
|
DappLoader(QObject* _parent, dev::WebThreeDirect* _web3); |
||||
|
///Load a new DApp. Resolves a name with a name reg contract. Asynchronous. dappReady is emitted once everything is read, dappError othervise
|
||||
|
///@param _uri Eth name path
|
||||
|
void loadDapp(QString const& _uri); |
||||
|
|
||||
|
signals: |
||||
|
void dappReady(Dapp& _dapp); |
||||
|
void dappError(); |
||||
|
|
||||
|
private slots: |
||||
|
void downloadComplete(QNetworkReply* _reply); |
||||
|
|
||||
|
private: |
||||
|
dev::WebThreeDirect* web3() const { return m_web3; } |
||||
|
DappLocation resolveAppUri(QString const& _uri); |
||||
|
void loadDapp(dev::RLP const& _rlp); |
||||
|
Manifest loadManifest(std::string const& _manifest); |
||||
|
|
||||
|
dev::WebThreeDirect* m_web3; |
||||
|
QNetworkAccessManager m_net; |
||||
|
std::map<QUrl, dev::h256> m_uriHashes; |
||||
|
}; |
||||
|
|
@ -0,0 +1,29 @@ |
|||||
|
/*
|
||||
|
This file is part of cpp-ethereum. |
||||
|
|
||||
|
cpp-ethereum is free software: you can redistribute it and/or modify |
||||
|
it under the terms of the GNU General Public License as published by |
||||
|
the Free Software Foundation, either version 3 of the License, or |
||||
|
(at your option) any later version. |
||||
|
|
||||
|
cpp-ethereum is distributed in the hope that it will be useful, |
||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
GNU General Public License for more details. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file WebPage.cpp
|
||||
|
* @author Arkadiy Paronyan arkadiy@ethdev.com> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
|
||||
|
#pragma GCC diagnostic ignored "-Wpedantic" //QtWebEngineWidgets/qwebenginecertificateerror.h:78:348: error: extra ';'
|
||||
|
#include "WebPage.h" |
||||
|
|
||||
|
void WebPage::javaScriptConsoleMessage(QWebEnginePage::JavaScriptConsoleMessageLevel _level, const QString& _message, int _lineNumber, const QString& _sourceID) |
||||
|
{ |
||||
|
QString prefix = _level == QWebEnginePage::ErrorMessageLevel ? "error" : _level == QWebEnginePage::WarningMessageLevel ? "warning" : ""; |
||||
|
emit consoleMessage(QString("%1(%2:%3):%4").arg(prefix).arg(_sourceID).arg(_lineNumber).arg(_message)); |
||||
|
} |
@ -0,0 +1,37 @@ |
|||||
|
/*
|
||||
|
This file is part of cpp-ethereum. |
||||
|
|
||||
|
cpp-ethereum is free software: you can redistribute it and/or modify |
||||
|
it under the terms of the GNU General Public License as published by |
||||
|
the Free Software Foundation, either version 3 of the License, or |
||||
|
(at your option) any later version. |
||||
|
|
||||
|
cpp-ethereum is distributed in the hope that it will be useful, |
||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
|
GNU General Public License for more details. |
||||
|
|
||||
|
You should have received a copy of the GNU General Public License |
||||
|
along with cpp-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
*/ |
||||
|
/** @file WebPage.h
|
||||
|
* @author Arkadiy Paronyan arkadiy@ethdev.com> |
||||
|
* @date 2015 |
||||
|
*/ |
||||
|
|
||||
|
#pragma once |
||||
|
|
||||
|
#include <QString> |
||||
|
#include <QtWebEngineWidgets/QWebEnginePage> |
||||
|
|
||||
|
class WebPage: public QWebEnginePage |
||||
|
{ |
||||
|
Q_OBJECT |
||||
|
public: |
||||
|
WebPage(QObject* _parent): QWebEnginePage(_parent) { } |
||||
|
signals: |
||||
|
void consoleMessage(QString const& _msg); |
||||
|
|
||||
|
protected: |
||||
|
void javaScriptConsoleMessage(QWebEnginePage::JavaScriptConsoleMessageLevel _level, const QString& _message, int _lineNumber, const QString& _sourceID) override; |
||||
|
}; |
Loading…
Reference in new issue