diff --git a/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp b/backends/cloud/dropbox/dropboxcreatedirectoryrequest.cpp index e410f0a5c4c..632d4d3b48e 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(this, &DropboxCreateDirectoryRequest::responseCallback); Networking::ErrorCallback errorResponseCallback = new Common::Callback(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 01faf4d8afa..7ddd31fccda 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 08f5ca52231..6c16a118013 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(this, &DropboxInfoRequest::userResponseCallback); Networking::ErrorCallback errorResponseCallback = new Common::Callback(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(this, &DropboxInfoRequest::quotaResponseCallback); Networking::ErrorCallback errorResponseCallback = new Common::Callback(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 0ed92cd68aa..3035549a133 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 84a1918eff0..0ffa0e30121 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(this, &DropboxListDirectoryRequest::responseCallback); Networking::ErrorCallback failureCallback = new Common::Callback(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(this, &DropboxListDirectoryRequest::responseCallback); Networking::ErrorCallback failureCallback = new Common::Callback(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 f031d6198bc..9bf77428184 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 _files; Request *_workingRequest; bool _ignoreCallback; @@ -47,7 +49,7 @@ class DropboxListDirectoryRequest: public Networking::Request { void errorCallback(Networking::ErrorResponse error); void finishListing(Common::Array &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 7edc609969c..3669f839f79 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 c6a13743570..bf007ebad66 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 00000000000..63995fa3601 --- /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 +#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(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(this, &DropboxTokenRefresher::tokenRefreshed)); + return; + } + + Request::finishError(error); +} + +void DropboxTokenRefresher::setHeaders(Common::Array &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 00000000000..30ca3da398a --- /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 _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 &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 7330bae1fb2..6c122e32585 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(this, &DropboxUploadRequest::partUploadedCallback); Networking::ErrorCallback failureCallback = new Common::Callback(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 c1c00472980..b4c8ab79168 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 9c34d4f4ea5..e80a4f643b2 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 131f64340a2..969cd3e8822 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";