aboutsummaryrefslogtreecommitdiff
path: root/backends/cloud
diff options
context:
space:
mode:
authorAlexander Tkachev2016-05-26 21:40:01 +0600
committerAlexander Tkachev2016-08-24 16:07:55 +0600
commit8f6bcdf55da97db98384c2a8cb9dcdf34232ac35 (patch)
treea1ec4f773c2891cf432f05af2461ca161959a017 /backends/cloud
parentb246c17850687e7b15b644b761fbfe835ffc1c32 (diff)
downloadscummvm-rg350-8f6bcdf55da97db98384c2a8cb9dcdf34232ac35.tar.gz
scummvm-rg350-8f6bcdf55da97db98384c2a8cb9dcdf34232ac35.tar.bz2
scummvm-rg350-8f6bcdf55da97db98384c2a8cb9dcdf34232ac35.zip
CLOUD: Add OneDriveTokenRefresher
OneDriveTokenRefresher is a CurlJsonRequest replacement for OneDriveStorage methods. It behaves very similarly, but checks received JSON before passing it to user. If it contains "error" key, it attempts to refresh the token through OneDriveStorage, and then restarts the original request, so user won't notice that there ever was an error.
Diffstat (limited to 'backends/cloud')
-rw-r--r--backends/cloud/onedrive/onedrivestorage.cpp16
-rw-r--r--backends/cloud/onedrive/onedrivestorage.h15
-rw-r--r--backends/cloud/onedrive/onedrivetokenrefresher.cpp124
-rw-r--r--backends/cloud/onedrive/onedrivetokenrefresher.h61
4 files changed, 196 insertions, 20 deletions
diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp
index 833ba8e558..6f91cadd37 100644
--- a/backends/cloud/onedrive/onedrivestorage.cpp
+++ b/backends/cloud/onedrive/onedrivestorage.cpp
@@ -31,6 +31,7 @@
#include <common/file.h>
#include "common/system.h"
#include "common/cloudmanager.h"
+#include "onedrivetokenrefresher.h"
namespace Cloud {
namespace OneDrive {
@@ -113,10 +114,6 @@ void OneDriveStorage::saveConfig(Common::String keyPrefix) {
ConfMan.set(keyPrefix + "refresh_token", _refreshToken, "cloud");
}
-void OneDriveStorage::printJsonTokenReceived(RequestBoolPair pair) {
- if (pair.value) syncSaves(0); //try again
-}
-
void OneDriveStorage::printJson(Networking::RequestJsonPair pair) {
Common::JSONValue *json = pair.value;
if (!json) {
@@ -124,15 +121,6 @@ void OneDriveStorage::printJson(Networking::RequestJsonPair pair) {
return;
}
- Common::JSONObject result = json->asObject();
- if (result.contains("error")) {
- //Common::JSONObject error = result.getVal("error")->asObject();
- debug("bad token, trying again...");
- getAccessToken(new Common::Callback<OneDriveStorage, RequestBoolPair>(this, &OneDriveStorage::printJsonTokenReceived));
- delete json;
- return;
- }
-
debug("%s", json->stringify().c_str());
delete json;
}
@@ -140,7 +128,7 @@ void OneDriveStorage::printJson(Networking::RequestJsonPair pair) {
int32 OneDriveStorage::syncSaves(BoolCallback callback) {
//this is not the real syncSaves() implementation
Networking::JsonCallback innerCallback = new Common::Callback<OneDriveStorage, Networking::RequestJsonPair>(this, &OneDriveStorage::printJson);
- Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.onedrive.com/v1.0/drives/");
+ Networking::CurlJsonRequest *request = new OneDriveTokenRefresher(this, innerCallback, "https://api.onedrive.com/v1.0/drives/");
request->addHeader("Authorization: bearer " + _token);
return ConnMan.addRequest(request);
}
diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h
index 1cb7017d64..e120691a08 100644
--- a/backends/cloud/onedrive/onedrivestorage.h
+++ b/backends/cloud/onedrive/onedrivestorage.h
@@ -44,12 +44,6 @@ class OneDriveStorage: public Cloud::Storage {
*/
OneDriveStorage(Common::String code);
- /**
- * Gets new access_token. If <code> passed is "", refresh_token is used.
- * Use "" in order to refresh token and pass a callback, so you could
- * continue your work when new token is available.
- */
- void getAccessToken(BoolCallback callback, Common::String code = "");
void tokenRefreshed(BoolCallback callback, Networking::RequestJsonPair pair);
void codeFlowComplete(RequestBoolPair pair);
@@ -122,6 +116,15 @@ public:
* Show message with OneDrive auth instructions. (Temporary)
*/
static void authThroughConsole();
+
+ /**
+ * Gets new access_token. If <code> passed is "", refresh_token is used.
+ * Use "" in order to refresh token and pass a callback, so you could
+ * continue your work when new token is available.
+ */
+ void getAccessToken(BoolCallback callback, Common::String code = "");
+
+ Common::String accessToken() { return _token; }
};
} //end of namespace OneDrive
diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.cpp b/backends/cloud/onedrive/onedrivetokenrefresher.cpp
new file mode 100644
index 0000000000..5e72717740
--- /dev/null
+++ b/backends/cloud/onedrive/onedrivetokenrefresher.cpp
@@ -0,0 +1,124 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program 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 2
+* of the License, or (at your option) any later version.
+*
+* This program 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 this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+#define FORBIDDEN_SYMBOL_ALLOW_ALL
+
+#include "backends/cloud/onedrive/onedrivetokenrefresher.h"
+#include "backends/cloud/onedrive/onedrivestorage.h"
+#include "backends/networking/curl/connectionmanager.h"
+#include "backends/networking/curl/curljsonrequest.h"
+#include "common/config-manager.h"
+#include "common/debug.h"
+#include "common/json.h"
+#include <curl/curl.h>
+
+namespace Cloud {
+namespace OneDrive {
+
+OneDriveTokenRefresher::OneDriveTokenRefresher(OneDriveStorage *parent, Networking::JsonCallback callback, const char *url):
+ CurlJsonRequest(0, url),
+ _parentStorage(parent),
+ _innerRequest(
+ new CurlJsonRequest(
+ new Common::Callback<OneDriveTokenRefresher, Networking::RequestJsonPair>(this, &OneDriveTokenRefresher::innerRequestCallback),
+ url
+ )
+ ), _jsonCallback(callback), _retryId(-1), _started(false) {}
+
+OneDriveTokenRefresher::~OneDriveTokenRefresher() {}
+
+void OneDriveTokenRefresher::innerRequestCallback(Networking::RequestJsonPair pair) {
+ if (!pair.value) {
+ //notify user of failure
+ warning("OneDriveTokenRefresher: got NULL instead of JSON");
+ ConnMan.getRequestInfo(_id).state = Networking::FINISHED;
+ if (_jsonCallback) (*_jsonCallback)(Networking::RequestJsonPair(_id, 0));
+ return;
+ }
+
+ Common::JSONObject result = pair.value->asObject();
+ if (result.contains("error")) {
+ //new token needed => request token & then retry original request
+ ConnMan.getRequestInfo(pair.id).state = Networking::PAUSED;
+ _retryId = pair.id;
+ delete pair.value;
+ _parentStorage->getAccessToken(new Common::Callback<OneDriveTokenRefresher, Storage::RequestBoolPair>(this, &OneDriveTokenRefresher::tokenRefreshed));
+ return;
+ }
+
+ //notify user of success
+ ConnMan.getRequestInfo(_id).state = Networking::FINISHED;
+ if (_jsonCallback) (*_jsonCallback)(Networking::RequestJsonPair(_id, pair.value));
+}
+
+void OneDriveTokenRefresher::tokenRefreshed(Storage::RequestBoolPair pair) {
+ if (!pair.value) {
+ //failed to refresh token, notify user with NULL in original callback
+ warning("OneDriveTokenRefresher: failed to refresh token");
+ ConnMan.getRequestInfo(_id).state = Networking::FINISHED;
+ if (_jsonCallback) (*_jsonCallback)(Networking::RequestJsonPair(_id, 0));
+ return;
+ }
+
+ //successfully received refreshed token, can restart the original request now
+ Networking::RequestInfo &info = ConnMan.getRequestInfo(_retryId);
+ info.state = Networking::RETRY;
+ info.retryInSeconds = 1;
+
+ //update headers: first change header with token, then pass those to request
+ for (uint32 i = 0; i < _headers.size(); ++i) {
+ if (_headers[i].contains("Authorization: bearer ")) {
+ _headers[i] = "Authorization: bearer " + _parentStorage->accessToken();
+ }
+ }
+ CurlJsonRequest *retryRequest = (CurlJsonRequest *)info.request;
+ if (retryRequest) retryRequest->setHeaders(_headers);
+}
+
+void OneDriveTokenRefresher::handle() {
+ if (!_started) {
+ for (uint32 i = 0; i < _headers.size(); ++i)
+ _innerRequest->addHeader(_headers[i]);
+ _started = true;
+ ConnMan.addRequest(_innerRequest);
+ }
+}
+
+void OneDriveTokenRefresher::restart() {
+ //can't restart as all headers were passed to _innerRequest which is probably dead now
+ warning("OneDriveTokenRefresher: cannot be restarted");
+ ConnMan.getRequestInfo(_id).state = Networking::FINISHED;
+ if (_jsonCallback) (*_jsonCallback)(Networking::RequestJsonPair(_id, 0));
+}
+
+Networking::NetworkReadStream *OneDriveTokenRefresher::execute() {
+ if (!_started) {
+ for (uint32 i = 0; i < _headers.size(); ++i)
+ _innerRequest->addHeader(_headers[i]);
+ _started = true;
+ } else {
+ warning("OneDriveTokenRefresher: inner Request is already started");
+ }
+ return _innerRequest->execute();
+}
+
+} //end of namespace OneDrive
+} //end of namespace Cloud
diff --git a/backends/cloud/onedrive/onedrivetokenrefresher.h b/backends/cloud/onedrive/onedrivetokenrefresher.h
new file mode 100644
index 0000000000..976851282e
--- /dev/null
+++ b/backends/cloud/onedrive/onedrivetokenrefresher.h
@@ -0,0 +1,61 @@
+/* ScummVM - Graphic Adventure Engine
+*
+* ScummVM is the legal property of its developers, whose names
+* are too numerous to list here. Please refer to the COPYRIGHT
+* file distributed with this source distribution.
+*
+* This program 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 2
+* of the License, or (at your option) any later version.
+*
+* This program 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 this program; if not, write to the Free Software
+* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+*
+*/
+
+#ifndef BACKENDS_CLOUD_ONEDRIVE_ONEDRIVETOKENREFRESHER_H
+#define BACKENDS_CLOUD_ONEDRIVE_ONEDRIVETOKENREFRESHER_H
+
+#include "backends/cloud/storage.h"
+#include "common/callback.h"
+#include "backends/networking/curl/curljsonrequest.h"
+
+namespace Cloud {
+namespace OneDrive {
+
+class OneDriveStorage;
+
+class OneDriveTokenRefresher: public Networking::CurlJsonRequest {
+ OneDriveStorage *_parentStorage;
+ Common::Array<Common::String> _headers;
+ Networking::CurlJsonRequest *_innerRequest;
+ Networking::JsonCallback _jsonCallback;
+ int32 _retryId;
+ bool _started;
+
+ void innerRequestCallback(Networking::RequestJsonPair pair);
+ void tokenRefreshed(Storage::RequestBoolPair pair);
+public:
+ OneDriveTokenRefresher(OneDriveStorage *parent, Networking::JsonCallback callback, const char *url);
+ virtual ~OneDriveTokenRefresher();
+
+ virtual void handle();
+ virtual void restart();
+
+ virtual void setHeaders(Common::Array<Common::String> &headers) { _headers = headers; }
+ virtual void addHeader(Common::String header) { _headers.push_back(header); }
+ virtual void addPostField(Common::String field) { _innerRequest->addPostField(field); }
+ virtual Networking::NetworkReadStream *execute();
+};
+
+} //end of namespace OneDrive
+} //end of namespace Cloud
+
+#endif