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.
This commit is contained in:
Alexander Tkachov 2021-01-04 15:28:29 +07:00 committed by Eugene Sandulenko
parent a7776e9ef2
commit 8c16575035
14 changed files with 245 additions and 39 deletions

View file

@ -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;

View file

@ -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();

View file

@ -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

View file

@ -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();

View file

@ -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;

View file

@ -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();

View file

@ -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;
}
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);
return new DropboxStorage(accessToken, loadIsEnabledFlag(keyPrefix));
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);
}

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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));

View file

@ -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();

View file

@ -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 \

View file

@ -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";