[Scummvm-git-logs] scummvm master -> 8c1657503561aeac83c94bc7bccd2662e67a2074
sev-
sev at scummvm.org
Thu Feb 4 00:57:51 UTC 2021
This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
8c16575035 CLOUD: Update Dropbox to use refresh_token
Commit: 8c1657503561aeac83c94bc7bccd2662e67a2074
https://github.com/scummvm/scummvm/commit/8c1657503561aeac83c94bc7bccd2662e67a2074
Author: Alexander Tkachov (alexander at tkachov.ru)
Date: 2021-02-04T01:57:48+01:00
Commit Message:
CLOUD: Update Dropbox to use refresh_token
Dropbox is switching to short-lived access_token OAuth. This commit adapts Cloud::DropboxStorage to use refresh_token similarly to how other Storages do: by introducing a DropboxTokenRefresher.
It is used instead of plain CurlJsonRequest. It just checks if received JSON has access_token-related error and tries to refresh it, then repeats the original request transparently for the caller. If no such errors found, it just passes the info to the caller.
Changed paths:
A backends/cloud/dropbox/dropboxtokenrefresher.cpp
A backends/cloud/dropbox/dropboxtokenrefresher.h
backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp
backends/cloud/dropbox/dropboxcreatedirectoryrequest.h
backends/cloud/dropbox/dropboxinforequest.cpp
backends/cloud/dropbox/dropboxinforequest.h
backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp
backends/cloud/dropbox/dropboxlistdirectoryrequest.h
backends/cloud/dropbox/dropboxstorage.cpp
backends/cloud/dropbox/dropboxstorage.h
backends/cloud/dropbox/dropboxuploadrequest.cpp
backends/cloud/dropbox/dropboxuploadrequest.h
backends/module.mk
gui/options.cpp
diff --git a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp
index e410f0a5c4..632d4d3b48 100644
--- a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp
+++ b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp
@@ -21,6 +21,8 @@
*/
#include "backends/cloud/dropbox/dropboxcreatedirectoryrequest.h"
+#include "backends/cloud/dropbox/dropboxstorage.h"
+#include "backends/cloud/dropbox/dropboxtokenrefresher.h"
#include "backends/cloud/storage.h"
#include "backends/networking/curl/connectionmanager.h"
#include "backends/networking/curl/curljsonrequest.h"
@@ -32,8 +34,8 @@ namespace Dropbox {
#define DROPBOX_API_CREATE_FOLDER "https://api.dropboxapi.com/2/files/create_folder"
-DropboxCreateDirectoryRequest::DropboxCreateDirectoryRequest(Common::String token, Common::String path, Storage::BoolCallback cb, Networking::ErrorCallback ecb):
- Networking::Request(nullptr, ecb), _token(token), _path(path), _boolCallback(cb),
+DropboxCreateDirectoryRequest::DropboxCreateDirectoryRequest(DropboxStorage *storage, Common::String path, Storage::BoolCallback cb, Networking::ErrorCallback ecb):
+ Networking::Request(nullptr, ecb), _storage(storage), _path(path), _boolCallback(cb),
_workingRequest(nullptr), _ignoreCallback(false) {
start();
}
@@ -53,8 +55,8 @@ void DropboxCreateDirectoryRequest::start() {
Networking::JsonCallback innerCallback = new Common::Callback<DropboxCreateDirectoryRequest, Networking::JsonResponse>(this, &DropboxCreateDirectoryRequest::responseCallback);
Networking::ErrorCallback errorResponseCallback = new Common::Callback<DropboxCreateDirectoryRequest, Networking::ErrorResponse>(this, &DropboxCreateDirectoryRequest::errorCallback);
- Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorResponseCallback, DROPBOX_API_CREATE_FOLDER);
- request->addHeader("Authorization: Bearer " + _token);
+ Networking::CurlJsonRequest *request = new DropboxTokenRefresher(_storage, innerCallback, errorResponseCallback, DROPBOX_API_CREATE_FOLDER);
+ request->addHeader("Authorization: Bearer " + _storage->accessToken());
request->addHeader("Content-Type: application/json");
Common::JSONObject jsonRequestParameters;
diff --git a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.h b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.h
index 01faf4d8af..7ddd31fccd 100644
--- a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.h
+++ b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.h
@@ -30,8 +30,10 @@
namespace Cloud {
namespace Dropbox {
+class DropboxStorage;
+
class DropboxCreateDirectoryRequest: public Networking::Request {
- Common::String _token;
+ DropboxStorage *_storage;
Common::String _path;
Storage::BoolCallback _boolCallback;
Request *_workingRequest;
@@ -43,7 +45,7 @@ class DropboxCreateDirectoryRequest: public Networking::Request {
void errorCallback(Networking::ErrorResponse error);
void finishCreation(bool success);
public:
- DropboxCreateDirectoryRequest(Common::String token, Common::String path, Storage::BoolCallback cb, Networking::ErrorCallback ecb);
+ DropboxCreateDirectoryRequest(DropboxStorage *storage, Common::String path, Storage::BoolCallback cb, Networking::ErrorCallback ecb);
virtual ~DropboxCreateDirectoryRequest();
virtual void handle();
diff --git a/backends/cloud/dropbox/dropboxinforequest.cpp b/backends/cloud/dropbox/dropboxinforequest.cpp
index 08f5ca5223..6c16a11801 100644
--- a/backends/cloud/dropbox/dropboxinforequest.cpp
+++ b/backends/cloud/dropbox/dropboxinforequest.cpp
@@ -21,6 +21,8 @@
*/
#include "backends/cloud/dropbox/dropboxinforequest.h"
+#include "backends/cloud/dropbox/dropboxstorage.h"
+#include "backends/cloud/dropbox/dropboxtokenrefresher.h"
#include "backends/cloud/cloudmanager.h"
#include "backends/cloud/storage.h"
#include "backends/networking/curl/connectionmanager.h"
@@ -34,8 +36,8 @@ namespace Dropbox {
#define DROPBOX_API_GET_CURRENT_ACCOUNT "https://api.dropboxapi.com/2/users/get_current_account"
#define DROPBOX_API_GET_SPACE_USAGE "https://api.dropboxapi.com/2/users/get_space_usage"
-DropboxInfoRequest::DropboxInfoRequest(Common::String token, Storage::StorageInfoCallback cb, Networking::ErrorCallback ecb):
- Networking::Request(nullptr, ecb), _token(token), _infoCallback(cb),
+DropboxInfoRequest::DropboxInfoRequest(DropboxStorage *storage, Storage::StorageInfoCallback cb, Networking::ErrorCallback ecb):
+ Networking::Request(nullptr, ecb), _storage(storage), _infoCallback(cb),
_workingRequest(nullptr), _ignoreCallback(false) {
start();
}
@@ -55,8 +57,8 @@ void DropboxInfoRequest::start() {
Networking::JsonCallback innerCallback = new Common::Callback<DropboxInfoRequest, Networking::JsonResponse>(this, &DropboxInfoRequest::userResponseCallback);
Networking::ErrorCallback errorResponseCallback = new Common::Callback<DropboxInfoRequest, Networking::ErrorResponse>(this, &DropboxInfoRequest::errorCallback);
- Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorResponseCallback, DROPBOX_API_GET_CURRENT_ACCOUNT);
- request->addHeader("Authorization: Bearer " + _token);
+ Networking::CurlJsonRequest *request = new DropboxTokenRefresher(_storage, innerCallback, errorResponseCallback, DROPBOX_API_GET_CURRENT_ACCOUNT);
+ request->addHeader("Authorization: Bearer " + _storage->accessToken());
request->addHeader("Content-Type: application/json");
request->addPostField("null"); //use POST
@@ -109,8 +111,8 @@ void DropboxInfoRequest::userResponseCallback(Networking::JsonResponse response)
Networking::JsonCallback innerCallback = new Common::Callback<DropboxInfoRequest, Networking::JsonResponse>(this, &DropboxInfoRequest::quotaResponseCallback);
Networking::ErrorCallback errorResponseCallback = new Common::Callback<DropboxInfoRequest, Networking::ErrorResponse>(this, &DropboxInfoRequest::errorCallback);
- Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, errorResponseCallback, DROPBOX_API_GET_SPACE_USAGE);
- request->addHeader("Authorization: Bearer " + _token);
+ Networking::CurlJsonRequest *request = new DropboxTokenRefresher(_storage, innerCallback, errorResponseCallback, DROPBOX_API_GET_SPACE_USAGE);
+ request->addHeader("Authorization: Bearer " + _storage->accessToken());
request->addHeader("Content-Type: application/json");
request->addPostField("null"); //use POST
diff --git a/backends/cloud/dropbox/dropboxinforequest.h b/backends/cloud/dropbox/dropboxinforequest.h
index 0ed92cd68a..3035549a13 100644
--- a/backends/cloud/dropbox/dropboxinforequest.h
+++ b/backends/cloud/dropbox/dropboxinforequest.h
@@ -30,8 +30,10 @@
namespace Cloud {
namespace Dropbox {
+class DropboxStorage;
+
class DropboxInfoRequest: public Networking::Request {
- Common::String _token;
+ DropboxStorage *_storage;
Common::String _uid, _name, _email;
Storage::StorageInfoCallback _infoCallback;
Request *_workingRequest;
@@ -43,7 +45,7 @@ class DropboxInfoRequest: public Networking::Request {
void errorCallback(Networking::ErrorResponse error);
void finishInfo(StorageInfo info);
public:
- DropboxInfoRequest(Common::String token, Storage::StorageInfoCallback cb, Networking::ErrorCallback ecb);
+ DropboxInfoRequest(DropboxStorage *storage, Storage::StorageInfoCallback cb, Networking::ErrorCallback ecb);
virtual ~DropboxInfoRequest();
virtual void handle();
diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp
index 84a1918eff..0ffa0e3012 100644
--- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp
+++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.cpp
@@ -21,6 +21,8 @@
*/
#include "backends/cloud/dropbox/dropboxlistdirectoryrequest.h"
+#include "backends/cloud/dropbox/dropboxstorage.h"
+#include "backends/cloud/dropbox/dropboxtokenrefresher.h"
#include "backends/cloud/iso8601.h"
#include "backends/cloud/storage.h"
#include "backends/networking/curl/connectionmanager.h"
@@ -35,9 +37,9 @@ namespace Dropbox {
#define DROPBOX_API_LIST_FOLDER "https://api.dropboxapi.com/2/files/list_folder"
#define DROPBOX_API_LIST_FOLDER_CONTINUE "https://api.dropboxapi.com/2/files/list_folder/continue"
-DropboxListDirectoryRequest::DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive):
+DropboxListDirectoryRequest::DropboxListDirectoryRequest(DropboxStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive):
Networking::Request(nullptr, ecb), _requestedPath(path), _requestedRecursive(recursive), _listDirectoryCallback(cb),
- _token(token), _workingRequest(nullptr), _ignoreCallback(false) {
+ _storage(storage), _workingRequest(nullptr), _ignoreCallback(false) {
start();
}
@@ -57,8 +59,8 @@ void DropboxListDirectoryRequest::start() {
Networking::JsonCallback callback = new Common::Callback<DropboxListDirectoryRequest, Networking::JsonResponse>(this, &DropboxListDirectoryRequest::responseCallback);
Networking::ErrorCallback failureCallback = new Common::Callback<DropboxListDirectoryRequest, Networking::ErrorResponse>(this, &DropboxListDirectoryRequest::errorCallback);
- Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, failureCallback, DROPBOX_API_LIST_FOLDER);
- request->addHeader("Authorization: Bearer " + _token);
+ Networking::CurlJsonRequest *request = new DropboxTokenRefresher(_storage, callback, failureCallback, DROPBOX_API_LIST_FOLDER);
+ request->addHeader("Authorization: Bearer " + _storage->accessToken());
request->addHeader("Content-Type: application/json");
Common::JSONObject jsonRequestParameters;
@@ -180,8 +182,8 @@ void DropboxListDirectoryRequest::responseCallback(Networking::JsonResponse resp
Networking::JsonCallback callback = new Common::Callback<DropboxListDirectoryRequest, Networking::JsonResponse>(this, &DropboxListDirectoryRequest::responseCallback);
Networking::ErrorCallback failureCallback = new Common::Callback<DropboxListDirectoryRequest, Networking::ErrorResponse>(this, &DropboxListDirectoryRequest::errorCallback);
- Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, failureCallback, DROPBOX_API_LIST_FOLDER_CONTINUE);
- request->addHeader("Authorization: Bearer " + _token);
+ Networking::CurlJsonRequest *request = new DropboxTokenRefresher(_storage, callback, failureCallback, DROPBOX_API_LIST_FOLDER_CONTINUE);
+ request->addHeader("Authorization: Bearer " + _storage->accessToken());
request->addHeader("Content-Type: application/json");
Common::JSONObject jsonRequestParameters;
diff --git a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h
index f031d6198b..9bf7742818 100644
--- a/backends/cloud/dropbox/dropboxlistdirectoryrequest.h
+++ b/backends/cloud/dropbox/dropboxlistdirectoryrequest.h
@@ -31,12 +31,14 @@
namespace Cloud {
namespace Dropbox {
+class DropboxStorage;
+
class DropboxListDirectoryRequest: public Networking::Request {
Common::String _requestedPath;
bool _requestedRecursive;
Storage::ListDirectoryCallback _listDirectoryCallback;
- Common::String _token;
+ DropboxStorage *_storage;
Common::Array<StorageFile> _files;
Request *_workingRequest;
bool _ignoreCallback;
@@ -47,7 +49,7 @@ class DropboxListDirectoryRequest: public Networking::Request {
void errorCallback(Networking::ErrorResponse error);
void finishListing(Common::Array<StorageFile> &files);
public:
- DropboxListDirectoryRequest(Common::String token, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive = false);
+ DropboxListDirectoryRequest(DropboxStorage *storage, Common::String path, Storage::ListDirectoryCallback cb, Networking::ErrorCallback ecb, bool recursive = false);
virtual ~DropboxListDirectoryRequest();
virtual void handle();
diff --git a/backends/cloud/dropbox/dropboxstorage.cpp b/backends/cloud/dropbox/dropboxstorage.cpp
index 7edc609969..3669f839f7 100644
--- a/backends/cloud/dropbox/dropboxstorage.cpp
+++ b/backends/cloud/dropbox/dropboxstorage.cpp
@@ -40,7 +40,8 @@ namespace Dropbox {
#define DROPBOX_API_FILES_DOWNLOAD "https://content.dropboxapi.com/2/files/download"
-DropboxStorage::DropboxStorage(Common::String accessToken, bool enabled): BaseStorage(accessToken, "", enabled) {}
+DropboxStorage::DropboxStorage(Common::String accessToken, Common::String refreshToken, bool enabled):
+ BaseStorage(accessToken, refreshToken, enabled) {}
DropboxStorage::DropboxStorage(Common::String code, Networking::ErrorCallback cb): BaseStorage() {
getAccessToken(code, cb);
@@ -52,12 +53,13 @@ Common::String DropboxStorage::cloudProvider() { return "dropbox"; }
uint32 DropboxStorage::storageIndex() { return kStorageDropboxId; }
-bool DropboxStorage::needsRefreshToken() { return false; }
+bool DropboxStorage::needsRefreshToken() { return true; }
-bool DropboxStorage::canReuseRefreshToken() { return false; }
+bool DropboxStorage::canReuseRefreshToken() { return true; }
void DropboxStorage::saveConfig(Common::String keyPrefix) {
ConfMan.set(keyPrefix + "access_token", _token, ConfMan.kCloudDomain);
+ ConfMan.set(keyPrefix + "refresh_token", _refreshToken, ConfMan.kCloudDomain);
saveIsEnabledFlag(keyPrefix);
}
@@ -66,11 +68,11 @@ Common::String DropboxStorage::name() const {
}
Networking::Request *DropboxStorage::listDirectory(Common::String path, ListDirectoryCallback outerCallback, Networking::ErrorCallback errorCallback, bool recursive) {
- return addRequest(new DropboxListDirectoryRequest(_token, path, outerCallback, errorCallback, recursive));
+ return addRequest(new DropboxListDirectoryRequest(this, path, outerCallback, errorCallback, recursive));
}
Networking::Request *DropboxStorage::upload(Common::String path, Common::SeekableReadStream *contents, UploadCallback callback, Networking::ErrorCallback errorCallback) {
- return addRequest(new DropboxUploadRequest(_token, path, contents, callback, errorCallback));
+ return addRequest(new DropboxUploadRequest(this, path, contents, callback, errorCallback));
}
Networking::Request *DropboxStorage::streamFileById(Common::String path, Networking::NetworkReadStreamCallback callback, Networking::ErrorCallback errorCallback) {
@@ -92,13 +94,13 @@ Networking::Request *DropboxStorage::streamFileById(Common::String path, Network
Networking::Request *DropboxStorage::createDirectory(Common::String path, BoolCallback callback, Networking::ErrorCallback errorCallback) {
if (!errorCallback)
errorCallback = getErrorPrintingCallback();
- return addRequest(new DropboxCreateDirectoryRequest(_token, path, callback, errorCallback));
+ return addRequest(new DropboxCreateDirectoryRequest(this, path, callback, errorCallback));
}
Networking::Request *DropboxStorage::info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) {
if (!errorCallback)
errorCallback = getErrorPrintingCallback();
- return addRequest(new DropboxInfoRequest(_token, callback, errorCallback));
+ return addRequest(new DropboxInfoRequest(this, callback, errorCallback));
}
Common::String DropboxStorage::savesDirectoryPath() { return "/saves/"; }
@@ -109,12 +111,19 @@ DropboxStorage *DropboxStorage::loadFromConfig(Common::String keyPrefix) {
return nullptr;
}
- Common::String accessToken = ConfMan.get(keyPrefix + "access_token", ConfMan.kCloudDomain);
- return new DropboxStorage(accessToken, loadIsEnabledFlag(keyPrefix));
+ if (!ConfMan.hasKey(keyPrefix + "refresh_token", ConfMan.kCloudDomain)) {
+ warning("DropboxStorage: no refresh_token found");
+ return nullptr;
+ }
+
+ Common::String accessToken = ConfMan.get(keyPrefix + "access_token", ConfMan.kCloudDomain);
+ Common::String refreshToken = ConfMan.get(keyPrefix + "refresh_token", ConfMan.kCloudDomain);
+ return new DropboxStorage(accessToken, refreshToken, loadIsEnabledFlag(keyPrefix));
}
void DropboxStorage::removeFromConfig(Common::String keyPrefix) {
ConfMan.removeKey(keyPrefix + "access_token", ConfMan.kCloudDomain);
+ ConfMan.removeKey(keyPrefix + "refresh_token", ConfMan.kCloudDomain);
removeIsEnabledFlag(keyPrefix);
}
diff --git a/backends/cloud/dropbox/dropboxstorage.h b/backends/cloud/dropbox/dropboxstorage.h
index c6a1374357..bf007ebad6 100644
--- a/backends/cloud/dropbox/dropboxstorage.h
+++ b/backends/cloud/dropbox/dropboxstorage.h
@@ -32,7 +32,7 @@ namespace Dropbox {
class DropboxStorage: public Cloud::BaseStorage {
/** This private constructor is called from loadFromConfig(). */
- DropboxStorage(Common::String token, bool enabled);
+ DropboxStorage(Common::String token, Common::String refreshToken, bool enabled);
protected:
/**
@@ -103,6 +103,8 @@ public:
* Remove all DropboxStorage-related data from config.
*/
static void removeFromConfig(Common::String keyPrefix);
+
+ Common::String accessToken() const { return _token; }
};
} // End of namespace Dropbox
diff --git a/backends/cloud/dropbox/dropboxtokenrefresher.cpp b/backends/cloud/dropbox/dropboxtokenrefresher.cpp
new file mode 100644
index 0000000000..63995fa360
--- /dev/null
+++ b/backends/cloud/dropbox/dropboxtokenrefresher.cpp
@@ -0,0 +1,125 @@
+/* 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 <curl/curl.h>
+#include "backends/cloud/dropbox/dropboxtokenrefresher.h"
+#include "backends/cloud/dropbox/dropboxstorage.h"
+#include "backends/networking/curl/networkreadstream.h"
+#include "common/debug.h"
+#include "common/json.h"
+
+namespace Cloud {
+namespace Dropbox {
+
+DropboxTokenRefresher::DropboxTokenRefresher(DropboxStorage *parent, Networking::JsonCallback callback, Networking::ErrorCallback ecb, const char *url):
+ CurlJsonRequest(callback, ecb, url), _parentStorage(parent) {}
+
+DropboxTokenRefresher::~DropboxTokenRefresher() {}
+
+void DropboxTokenRefresher::tokenRefreshed(Storage::BoolResponse response) {
+ if (!response.value) {
+ //failed to refresh token, notify user with NULL in original callback
+ warning("DropboxTokenRefresher: failed to refresh token");
+ finishError(Networking::ErrorResponse(this, false, true, "DropboxTokenRefresher::tokenRefreshed: failed to refresh token", -1));
+ return;
+ }
+
+ //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")) {
+ _headers[i] = "Authorization: Bearer " + _parentStorage->accessToken();
+ }
+ }
+ setHeaders(_headers);
+
+ //successfully received refreshed token, can restart the original request now
+ retry(0);
+}
+
+void DropboxTokenRefresher::finishJson(Common::JSONValue *json) {
+ if (!json) {
+ //that's probably not an error (200 OK)
+ CurlJsonRequest::finishJson(nullptr);
+ return;
+ }
+
+ if (jsonIsObject(json, "DropboxTokenRefresher")) {
+ Common::JSONObject result = json->asObject();
+
+ if (result.contains("error") || result.contains("error_summary")) {
+ long httpCode = -1;
+ if (_stream) {
+ httpCode = _stream->httpResponseCode();
+ debug(9, "DropboxTokenRefresher: code %ld", httpCode);
+ }
+
+ bool irrecoverable = true;
+ if (jsonContainsString(result, "error_summary", "DropboxTokenRefresher")) {
+ if (result.getVal("error_summary")->asString().contains("expired_access_token")) {
+ irrecoverable = false;
+ }
+ }
+
+ if (irrecoverable) {
+ finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), httpCode));
+ delete json;
+ return;
+ }
+
+ pause();
+ delete json;
+ _parentStorage->refreshAccessToken(new Common::Callback<DropboxTokenRefresher, Storage::BoolResponse>(this, &DropboxTokenRefresher::tokenRefreshed));
+ return;
+ }
+ }
+
+ //notify user of success
+ CurlJsonRequest::finishJson(json);
+}
+
+void DropboxTokenRefresher::finishError(Networking::ErrorResponse error) {
+ if (error.httpResponseCode == 401) {
+ pause();
+ _parentStorage->refreshAccessToken(new Common::Callback<DropboxTokenRefresher, Storage::BoolResponse>(this, &DropboxTokenRefresher::tokenRefreshed));
+ return;
+ }
+
+ Request::finishError(error);
+}
+
+void DropboxTokenRefresher::setHeaders(Common::Array<Common::String> &headers) {
+ _headers = headers;
+ curl_slist_free_all(_headersList);
+ _headersList = 0;
+ for (uint32 i = 0; i < headers.size(); ++i)
+ CurlJsonRequest::addHeader(headers[i]);
+}
+
+void DropboxTokenRefresher::addHeader(Common::String header) {
+ _headers.push_back(header);
+ CurlJsonRequest::addHeader(header);
+}
+
+} // End of namespace Dropbox
+} // End of namespace Cloud
diff --git a/backends/cloud/dropbox/dropboxtokenrefresher.h b/backends/cloud/dropbox/dropboxtokenrefresher.h
new file mode 100644
index 0000000000..30ca3da398
--- /dev/null
+++ b/backends/cloud/dropbox/dropboxtokenrefresher.h
@@ -0,0 +1,53 @@
+/* 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_DROPBOX_DROPBOXTOKENREFRESHER_H
+#define BACKENDS_CLOUD_DROPBOX_DROPBOXTOKENREFRESHER_H
+
+#include "backends/cloud/storage.h"
+#include "backends/networking/curl/curljsonrequest.h"
+
+namespace Cloud {
+namespace Dropbox {
+
+class DropboxStorage;
+
+class DropboxTokenRefresher: public Networking::CurlJsonRequest {
+ DropboxStorage *_parentStorage;
+ Common::Array<Common::String> _headers;
+
+ void tokenRefreshed(Storage::BoolResponse response);
+
+ virtual void finishJson(Common::JSONValue *json);
+ virtual void finishError(Networking::ErrorResponse error);
+public:
+ DropboxTokenRefresher(DropboxStorage *parent, Networking::JsonCallback callback, Networking::ErrorCallback ecb, const char *url);
+ virtual ~DropboxTokenRefresher();
+
+ virtual void setHeaders(Common::Array<Common::String> &headers);
+ virtual void addHeader(Common::String header);
+};
+
+} // End of namespace Dropbox
+} // End of namespace Cloud
+
+#endif
diff --git a/backends/cloud/dropbox/dropboxuploadrequest.cpp b/backends/cloud/dropbox/dropboxuploadrequest.cpp
index 7330bae1fb..6c122e3258 100644
--- a/backends/cloud/dropbox/dropboxuploadrequest.cpp
+++ b/backends/cloud/dropbox/dropboxuploadrequest.cpp
@@ -21,6 +21,8 @@
*/
#include "backends/cloud/dropbox/dropboxuploadrequest.h"
+#include "backends/cloud/dropbox/dropboxstorage.h"
+#include "backends/cloud/dropbox/dropboxtokenrefresher.h"
#include "backends/cloud/iso8601.h"
#include "backends/cloud/storage.h"
#include "backends/networking/curl/connectionmanager.h"
@@ -34,8 +36,8 @@ namespace Dropbox {
#define DROPBOX_API_FILES_UPLOAD "https://content.dropboxapi.com/2/files/upload"
#define DROPBOX_API_FILES_UPLOAD_SESSION "https://content.dropboxapi.com/2/files/upload_session/"
-DropboxUploadRequest::DropboxUploadRequest(Common::String token, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback, Networking::ErrorCallback ecb):
- Networking::Request(nullptr, ecb), _token(token), _savePath(path), _contentsStream(contents), _uploadCallback(callback),
+DropboxUploadRequest::DropboxUploadRequest(DropboxStorage *storage, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback, Networking::ErrorCallback ecb):
+ Networking::Request(nullptr, ecb), _storage(storage), _savePath(path), _contentsStream(contents), _uploadCallback(callback),
_workingRequest(nullptr), _ignoreCallback(false) {
start();
}
@@ -109,8 +111,8 @@ void DropboxUploadRequest::uploadNextPart() {
Common::JSONValue value(jsonRequestParameters);
Networking::JsonCallback callback = new Common::Callback<DropboxUploadRequest, Networking::JsonResponse>(this, &DropboxUploadRequest::partUploadedCallback);
Networking::ErrorCallback failureCallback = new Common::Callback<DropboxUploadRequest, Networking::ErrorResponse>(this, &DropboxUploadRequest::partUploadedErrorCallback);
- Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, failureCallback, url);
- request->addHeader("Authorization: Bearer " + _token);
+ Networking::CurlJsonRequest *request = new DropboxTokenRefresher(_storage, callback, failureCallback, url.c_str());
+ request->addHeader("Authorization: Bearer " + _storage->accessToken());
request->addHeader("Content-Type: application/octet-stream");
request->addHeader("Dropbox-API-Arg: " + Common::JSON::stringify(&value));
diff --git a/backends/cloud/dropbox/dropboxuploadrequest.h b/backends/cloud/dropbox/dropboxuploadrequest.h
index c1c0047298..b4c8ab7916 100644
--- a/backends/cloud/dropbox/dropboxuploadrequest.h
+++ b/backends/cloud/dropbox/dropboxuploadrequest.h
@@ -31,8 +31,10 @@
namespace Cloud {
namespace Dropbox {
+class DropboxStorage;
+
class DropboxUploadRequest: public Networking::Request {
- Common::String _token;
+ DropboxStorage *_storage;
Common::String _savePath;
Common::SeekableReadStream *_contentsStream;
Storage::UploadCallback _uploadCallback;
@@ -47,7 +49,7 @@ class DropboxUploadRequest: public Networking::Request {
void finishUpload(StorageFile status);
public:
- DropboxUploadRequest(Common::String token, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback, Networking::ErrorCallback ecb);
+ DropboxUploadRequest(DropboxStorage *storage, Common::String path, Common::SeekableReadStream *contents, Storage::UploadCallback callback, Networking::ErrorCallback ecb);
virtual ~DropboxUploadRequest();
virtual void handle();
diff --git a/backends/module.mk b/backends/module.mk
index 9c34d4f4ea..e80a4f643b 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -48,6 +48,7 @@ MODULE_OBJS += \
cloud/dropbox/dropboxcreatedirectoryrequest.o \
cloud/dropbox/dropboxinforequest.o \
cloud/dropbox/dropboxlistdirectoryrequest.o \
+ cloud/dropbox/dropboxtokenrefresher.o \
cloud/dropbox/dropboxuploadrequest.o \
cloud/googledrive/googledrivelistdirectorybyidrequest.o \
cloud/googledrive/googledrivestorage.o \
diff --git a/gui/options.cpp b/gui/options.cpp
index 131f64340a..969cd3e882 100644
--- a/gui/options.cpp
+++ b/gui/options.cpp
@@ -2673,7 +2673,7 @@ void GlobalOptionsDialog::handleCommand(CommandSender *sender, uint32 cmd, uint3
Common::String url = "https://cloud.scummvm.org/";
switch (_selectedStorageIndex) {
case Cloud::kStorageDropboxId:
- url += "dropbox";
+ url += "dropbox?refresh_token=true";
break;
case Cloud::kStorageOneDriveId:
url += "onedrive";
More information about the Scummvm-git-logs
mailing list