From fde45867731f12a1a1a82267ee739064cc76cbac Mon Sep 17 00:00:00 2001 From: John Maguire Date: Thu, 19 Dec 2013 14:56:46 +0100 Subject: [PATCH] Use Dropbox's long poll API to get real-time changes. --- src/internet/dropboxservice.cpp | 38 +++++++++++++++++++++++++++++++++ src/internet/dropboxservice.h | 2 ++ 2 files changed, 40 insertions(+) diff --git a/src/internet/dropboxservice.cpp b/src/internet/dropboxservice.cpp index f950c877d..75637616e 100644 --- a/src/internet/dropboxservice.cpp +++ b/src/internet/dropboxservice.cpp @@ -1,6 +1,7 @@ #include "dropboxservice.h" #include +#include #include @@ -27,6 +28,8 @@ static const char* kMediaEndpoint = "https://api.dropbox.com/1/media/dropbox/"; static const char* kDeltaEndpoint = "https://api.dropbox.com/1/delta"; +static const char* kLongPollEndpoint = + "https://api-notify.dropbox.com/1/longpoll_delta"; } // namespace @@ -152,6 +155,41 @@ void DropboxService::RequestFileListFinished(QNetworkReply* reply) { if (response.contains("has_more") && response["has_more"].toBool()) { RequestFileList(); + } else { + // Long-poll wait for changes. + LongPollDelta(); + } +} + +void DropboxService::LongPollDelta() { + QSettings s; + s.beginGroup(kSettingsGroup); + + QUrl request_url = QUrl(QString(kLongPollEndpoint)); + if (s.contains("cursor")) { + request_url.addQueryItem("cursor", s.value("cursor").toString()); + } + QNetworkRequest request(request_url); + request.setRawHeader("Authorization", GenerateAuthorisationHeader()); + QNetworkReply* reply = network_->get(request); + NewClosure(reply, SIGNAL(finished()), + this, SLOT(LongPollFinished(QNetworkReply*)), reply); +} + +void DropboxService::LongPollFinished(QNetworkReply* reply) { + reply->deleteLater(); + QJson::Parser parser; + QVariantMap response = parser.parse(reply).toMap(); + if (response["changes"].toBool()) { + // New changes, we should request deltas again. + qLog(Debug) << "Detected new dropbox changes; fetching..."; + RequestFileList(); + } else { + bool ok = false; + int backoff_secs = response["backoff"].toInt(&ok); + backoff_secs = ok ? backoff_secs : 0; + + QTimer::singleShot(backoff_secs * 1000, this, SLOT(LongPollDelta())); } } diff --git a/src/internet/dropboxservice.h b/src/internet/dropboxservice.h index cfc50440e..2e026ab10 100644 --- a/src/internet/dropboxservice.h +++ b/src/internet/dropboxservice.h @@ -31,6 +31,8 @@ class DropboxService : public CloudFileService { private slots: void RequestFileListFinished(QNetworkReply* reply); void FetchContentUrlFinished(QNetworkReply* reply, const QVariantMap& file); + void LongPollFinished(QNetworkReply* reply); + void LongPollDelta(); private: void RequestFileList();