Messages work both ways for web remote.

This commit is contained in:
John Maguire 2014-05-08 17:06:31 +02:00
parent 583c8bf419
commit d2c50c5298
10 changed files with 67 additions and 18 deletions

View File

@ -114,7 +114,6 @@ Application::Application(QObject* parent)
// Network Remote // Network Remote
ClementineWebPage* web_channel = new ClementineWebPage(this); ClementineWebPage* web_channel = new ClementineWebPage(this);
web_channel->mainFrame()->load(QUrl("http://localhost:8080/channel"));
network_remote_ = new NetworkRemote(web_channel, this); network_remote_ = new NetworkRemote(web_channel, this);
MoveToNewThread(network_remote_); MoveToNewThread(network_remote_);

View File

@ -4,6 +4,7 @@
#include <QNetworkCookie> #include <QNetworkCookie>
#include "config.h" #include "config.h"
#include "remotecontrolmessages.pb.h"
#include "covers/albumcoverfetcher.h" #include "covers/albumcoverfetcher.h"
#include "engines/enginebase.h" #include "engines/enginebase.h"
#include "engines/gstengine.h" #include "engines/gstengine.h"
@ -82,6 +83,8 @@ void RegisterMetaTypes() {
qRegisterMetaType<Subdirectory>("Subdirectory"); qRegisterMetaType<Subdirectory>("Subdirectory");
qRegisterMetaType<QList<QUrl> >("QList<QUrl>"); qRegisterMetaType<QList<QUrl> >("QList<QUrl>");
qRegisterMetaType<pb::remote::Message>("pb::remote::Message");
#ifdef HAVE_VK #ifdef HAVE_VK
qRegisterMetaType<MusicOwner>("MusicOwner"); qRegisterMetaType<MusicOwner>("MusicOwner");
qRegisterMetaTypeStreamOperators<MusicOwner>("MusicOwner"); qRegisterMetaTypeStreamOperators<MusicOwner>("MusicOwner");

View File

@ -1,12 +1,20 @@
#include "clementinewebpage.h" #include "clementinewebpage.h"
#include <QByteArray> #include <QByteArray>
#include <QMetaObject>
#include <QThread>
#include <QWebFrame> #include <QWebFrame>
#include "core/closure.h" #include "core/closure.h"
#include "core/logging.h" #include "core/logging.h"
#include "remotecontrolmessages.pb.h" #include "remotecontrolmessages.pb.h"
namespace {
const char* kRemoteEndpoint = "http://localhost:8080/channel/remote/%1";
} // namespace
ClementineWebPage::ClementineWebPage(QObject* parent) ClementineWebPage::ClementineWebPage(QObject* parent)
: QWebPage(parent) { : QWebPage(parent) {
qLog(Debug) << Q_FUNC_INFO; qLog(Debug) << Q_FUNC_INFO;
@ -17,8 +25,28 @@ ClementineWebPage::ClementineWebPage(QObject* parent)
}); });
} }
void ClementineWebPage::Init() {
QMetaObject::invokeMethod(this, "InitOnMainThread", Qt::QueuedConnection);
}
void ClementineWebPage::InitOnMainThread() {
Q_ASSERT(QThread::currentThread() == qApp->thread());
mainFrame()->load(QUrl("http://localhost:8080/channel/clementine"));
}
void ClementineWebPage::javaScriptConsoleMessage( void ClementineWebPage::javaScriptConsoleMessage(
const QString& message, int, const QString&) { const QString& message, int, const QString&) {
qLog(Error) << message;
}
bool ClementineWebPage::javaScriptConfirm(QWebFrame*, const QString& message) {
id_ = message;
qLog(Debug) << "id:" << message;
qLog(Debug) << QString(kRemoteEndpoint).arg(message);
return true;
}
void ClementineWebPage::javaScriptAlert(QWebFrame*, const QString& message) {
qLog(Debug) << message; qLog(Debug) << message;
QByteArray bytes = QByteArray::fromBase64(message.toAscii()); QByteArray bytes = QByteArray::fromBase64(message.toAscii());
@ -34,11 +62,8 @@ void ClementineWebPage::javaScriptConsoleMessage(
emit MessageReceived(msg); emit MessageReceived(msg);
} }
void ClementineWebPage::javaScriptAlert(QWebFrame*, const QString& message) {
qLog(Debug) << message;
}
bool ClementineWebPage::shouldInterruptJavaScript() { bool ClementineWebPage::shouldInterruptJavaScript() {
qLog(Debug) << Q_FUNC_INFO; qLog(Debug) << Q_FUNC_INFO;
// Make sure any long-running js does not get interrupted.
return false; return false;
} }

View File

@ -7,6 +7,8 @@ class ClementineWebPage : public QWebPage {
public: public:
explicit ClementineWebPage(QObject* parent = nullptr); explicit ClementineWebPage(QObject* parent = nullptr);
void Init();
const QString id() const { return id_; }
public slots: public slots:
bool shouldInterruptJavaScript(); bool shouldInterruptJavaScript();
@ -15,9 +17,18 @@ class ClementineWebPage : public QWebPage {
void Connected(); void Connected();
void MessageReceived(const pb::remote::Message& msg); void MessageReceived(const pb::remote::Message& msg);
private slots:
void InitOnMainThread();
protected: protected:
// For OOB communication for controlling the appengine channel.
virtual bool javaScriptConfirm(QWebFrame*, const QString& message);
// For generic error messages from the javascript.
virtual void javaScriptConsoleMessage( virtual void javaScriptConsoleMessage(
const QString& message, int line, const QString& source); const QString& message, int line, const QString& source);
// For receiving base64 proto messages; the actual remote control messages.
virtual void javaScriptAlert(QWebFrame*, const QString& message);
virtual void javaScriptAlert(QWebFrame*, const QString&); private:
QString id_;
}; };

View File

@ -79,6 +79,7 @@ IncomingDataParser::~IncomingDataParser() {}
bool IncomingDataParser::close_connection() { return close_connection_; } bool IncomingDataParser::close_connection() { return close_connection_; }
void IncomingDataParser::Parse(const pb::remote::Message& msg) { void IncomingDataParser::Parse(const pb::remote::Message& msg) {
qLog(Debug) << msg.DebugString().c_str();
close_connection_ = false; close_connection_ = false;
RemoteClient* client = qobject_cast<RemoteClient*>(sender()); RemoteClient* client = qobject_cast<RemoteClient*>(sender());

View File

@ -75,6 +75,7 @@ void NetworkRemote::SetupServer() {
connect(server_ipv6_.get(), SIGNAL(newConnection()), this, connect(server_ipv6_.get(), SIGNAL(newConnection()), this,
SLOT(AcceptConnection())); SLOT(AcceptConnection()));
connect(web_channel_.get(), SIGNAL(Connected()), SLOT(AcceptWebConnection())); connect(web_channel_.get(), SIGNAL(Connected()), SLOT(AcceptWebConnection()));
web_channel_->Init();
} }
void NetworkRemote::StartServer() { void NetworkRemote::StartServer() {
@ -136,6 +137,7 @@ void NetworkRemote::AcceptConnection() {
} }
void NetworkRemote::AcceptWebConnection() { void NetworkRemote::AcceptWebConnection() {
qLog(Debug) << Q_FUNC_INFO;
ConnectSignals(); ConnectSignals();
WebRemoteClient* client = new WebRemoteClient(web_channel_.get(), app_, this); WebRemoteClient* client = new WebRemoteClient(web_channel_.get(), app_, this);

View File

@ -22,7 +22,7 @@ class RemoteClient : public QObject {
bool downloader() const { return downloader_; } bool downloader() const { return downloader_; }
signals: signals:
void ParseMessage(const QByteArray& data); void Parse(const pb::remote::Message& msg);
private: private:
Application* app_; Application* app_;

View File

@ -25,9 +25,6 @@ class TcpRemoteClient : public RemoteClient {
private slots: private slots:
void IncomingData(); void IncomingData();
signals:
void Parse(const pb::remote::Message& msg);
private: private:
void ParseMessage(const QByteArray& data); void ParseMessage(const QByteArray& data);

View File

@ -5,10 +5,11 @@
#include "core/closure.h" #include "core/closure.h"
#include "core/logging.h" #include "core/logging.h"
#include "core/network.h" #include "core/network.h"
#include "networkremote/clementinewebpage.h"
namespace { namespace {
const char* kEndpoint = "http://localhost:8080/channel/push"; const char* kEndpoint = "http://localhost:8080/channel/clementine/push/%1";
} // namespace } // namespace
@ -17,6 +18,8 @@ WebRemoteClient::WebRemoteClient(
: RemoteClient(app, parent), : RemoteClient(app, parent),
web_channel_(web_channel), web_channel_(web_channel),
network_(new NetworkAccessManager) { network_(new NetworkAccessManager) {
connect(web_channel, SIGNAL(MessageReceived(const pb::remote::Message&)),
SIGNAL(Parse(const pb::remote::Message&)));
} }
WebRemoteClient::~WebRemoteClient() {} WebRemoteClient::~WebRemoteClient() {}
@ -25,14 +28,18 @@ void WebRemoteClient::SendData(pb::remote::Message* msg) {
qLog(Debug) << "Sending:" << msg->DebugString().c_str(); qLog(Debug) << "Sending:" << msg->DebugString().c_str();
std::string data = msg->SerializeAsString(); std::string data = msg->SerializeAsString();
QByteArray base64 = QByteArray(data.data(), data.size()).toBase64(); QByteArray base64 = QByteArray(data.data(), data.size()).toBase64();
QNetworkRequest request = QNetworkRequest(QUrl(kEndpoint)); QNetworkRequest request = QNetworkRequest(
QUrl(QString(kEndpoint).arg(web_channel_->id())));
QNetworkReply* reply = network_->post(request, base64); QNetworkReply* reply = network_->post(request, base64);
NewClosure(reply, SIGNAL(finished()), [&]() { NewClosure(reply, SIGNAL(finished()),
reply->deleteLater(); this, SLOT(SendDataFinished(QNetworkReply*)), reply);
qLog(Debug) << reply->error() }
<< reply->attribute(QNetworkRequest::HttpStatusCodeAttribute)
<< reply->readAll(); void WebRemoteClient::SendDataFinished(QNetworkReply* reply) {
}); reply->deleteLater();
qLog(Debug) << reply->error()
<< reply->attribute(QNetworkRequest::HttpStatusCodeAttribute)
<< reply->readAll();
} }
void WebRemoteClient::DisconnectClient(pb::remote::ReasonDisconnect reason) { void WebRemoteClient::DisconnectClient(pb::remote::ReasonDisconnect reason) {

View File

@ -7,6 +7,7 @@
class ClementineWebPage; class ClementineWebPage;
class NetworkAccessManager; class NetworkAccessManager;
class QNetworkReply;
class WebRemoteClient : public RemoteClient { class WebRemoteClient : public RemoteClient {
Q_OBJECT Q_OBJECT
@ -20,6 +21,9 @@ class WebRemoteClient : public RemoteClient {
void DisconnectClient(pb::remote::ReasonDisconnect reason); void DisconnectClient(pb::remote::ReasonDisconnect reason);
QAbstractSocket::SocketState state(); QAbstractSocket::SocketState state();
private slots:
void SendDataFinished(QNetworkReply*);
private: private:
ClementineWebPage* web_channel_; ClementineWebPage* web_channel_;
std::unique_ptr<NetworkAccessManager> network_; std::unique_ptr<NetworkAccessManager> network_;