aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Tkachev2016-07-13 12:52:04 +0600
committerAlexander Tkachev2016-08-24 16:07:55 +0600
commit85f1ce8ece7d4f4c6e54cfe29eaebe2c4ec13aec (patch)
tree1cdf0b580272b11870fb7144f32c42b328c94ce6
parent0a43dad629099505701b14723f1b22ba013a869e (diff)
downloadscummvm-rg350-85f1ce8ece7d4f4c6e54cfe29eaebe2c4ec13aec.tar.gz
scummvm-rg350-85f1ce8ece7d4f4c6e54cfe29eaebe2c4ec13aec.tar.bz2
scummvm-rg350-85f1ce8ece7d4f4c6e54cfe29eaebe2c4ec13aec.zip
CLOUD: Add BoxTokenRefresher and BoxStorage::info()
BoxTokenRefresher does refresh if HTTP 401 is returned by the server. To test refresher, BoxStorage::info() was added.
-rw-r--r--backends/cloud/box/boxstorage.cpp39
-rw-r--r--backends/cloud/box/boxtokenrefresher.cpp134
-rw-r--r--backends/cloud/box/boxtokenrefresher.h53
-rw-r--r--backends/module.mk1
4 files changed, 209 insertions, 18 deletions
diff --git a/backends/cloud/box/boxstorage.cpp b/backends/cloud/box/boxstorage.cpp
index 8a2e004e53..85bbf34221 100644
--- a/backends/cloud/box/boxstorage.cpp
+++ b/backends/cloud/box/boxstorage.cpp
@@ -22,6 +22,7 @@
#define FORBIDDEN_SYMBOL_ALLOW_ALL
#include "backends/cloud/box/boxstorage.h"
+#include "backends/cloud/box/boxtokenrefresher.h"
#include "backends/cloud/cloudmanager.h"
#include "backends/networking/curl/connectionmanager.h"
#include "backends/networking/curl/curljsonrequest.h"
@@ -141,20 +142,25 @@ void BoxStorage::infoInnerCallback(StorageInfoCallback outerCallback, Networking
Common::JSONObject info = json->asObject();
Common::String uid, name, email;
- uint64 quotaUsed = 0, quotaAllocated = 26843545600L; // 25 GB, because I actually don't know any way to find out the real one
-
- if (info.contains("createdBy") && info.getVal("createdBy")->isObject()) {
- Common::JSONObject createdBy = info.getVal("createdBy")->asObject();
- if (createdBy.contains("user") && createdBy.getVal("user")->isObject()) {
- Common::JSONObject user = createdBy.getVal("user")->asObject();
- uid = user.getVal("id")->asString();
- name = user.getVal("displayName")->asString();
- }
- }
+ uint64 quotaUsed = 0, quotaAllocated = 0;
- if (info.contains("size") && info.getVal("size")->isIntegerNumber()) {
- quotaUsed = info.getVal("size")->asIntegerNumber();
- }
+ // can check that "type": "user"
+ // there is also "max_upload_size", "phone" and "avatar_url"
+
+ if (info.contains("id") && info.getVal("id")->isString())
+ uid = info.getVal("id")->asString();
+
+ if (info.contains("name") && info.getVal("name")->isString())
+ name = info.getVal("name")->asString();
+
+ if (info.contains("login") && info.getVal("login")->isString())
+ email = info.getVal("login")->asString();
+
+ if (info.contains("space_amount") && info.getVal("space_amount")->isIntegerNumber())
+ quotaAllocated = info.getVal("space_amount")->asIntegerNumber();
+
+ if (info.contains("space_used") && info.getVal("space_used")->isIntegerNumber())
+ quotaUsed = info.getVal("space_used")->asIntegerNumber();
Common::String username = email;
if (username == "") username = name;
@@ -254,13 +260,10 @@ Networking::Request *BoxStorage::createDirectory(Common::String path, BoolCallba
}
Networking::Request *BoxStorage::info(StorageInfoCallback callback, Networking::ErrorCallback errorCallback) {
- /*
Networking::JsonCallback innerCallback = new Common::CallbackBridge<BoxStorage, StorageInfoResponse, Networking::JsonResponse>(this, &BoxStorage::infoInnerCallback, callback);
- Networking::CurlJsonRequest *request = new BoxTokenRefresher(this, innerCallback, errorCallback, "https://api.Box.com/v1.0/drive/special/approot");
- request->addHeader("Authorization: bearer " + _token);
+ Networking::CurlJsonRequest *request = new BoxTokenRefresher(this, innerCallback, errorCallback, "https://api.box.com/2.0/users/me");
+ request->addHeader("Authorization: Bearer " + _token);
return addRequest(request);
- */
- return nullptr; //TODO
}
Common::String BoxStorage::savesDirectoryPath() { return "saves/"; }
diff --git a/backends/cloud/box/boxtokenrefresher.cpp b/backends/cloud/box/boxtokenrefresher.cpp
new file mode 100644
index 0000000000..9dfbef537f
--- /dev/null
+++ b/backends/cloud/box/boxtokenrefresher.cpp
@@ -0,0 +1,134 @@
+/* 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/box/boxtokenrefresher.h"
+#include "backends/cloud/box/boxstorage.h"
+#include "backends/networking/curl/networkreadstream.h"
+#include "common/debug.h"
+#include "common/json.h"
+#include <curl/curl.h>
+
+namespace Cloud {
+namespace Box {
+
+BoxTokenRefresher::BoxTokenRefresher(BoxStorage *parent, Networking::JsonCallback callback, Networking::ErrorCallback ecb, const char *url):
+ CurlJsonRequest(callback, ecb, url), _parentStorage(parent) {}
+
+BoxTokenRefresher::~BoxTokenRefresher() {}
+
+void BoxTokenRefresher::tokenRefreshed(Storage::BoolResponse response) {
+ if (!response.value) {
+ //failed to refresh token, notify user with NULL in original callback
+ warning("BoxTokenRefresher: failed to refresh token");
+ finishError(Networking::ErrorResponse(this, false, true, "", -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 BoxTokenRefresher::finishJson(Common::JSONValue *json) {
+ if (!json) {
+ //that's probably not an error (200 OK)
+ CurlJsonRequest::finishJson(nullptr);
+ return;
+ }
+
+ Common::JSONObject result = json->asObject();
+ if (result.contains("type") && result.getVal("type")->isString() && result.getVal("type")->asString() == "error") {
+ //new token needed => request token & then retry original request
+ long httpCode = -1;
+ if (_stream) {
+ httpCode = _stream->httpResponseCode();
+ debug("code %ld", httpCode);
+ }
+
+ bool irrecoverable = true;
+
+ Common::String code, message;
+ if (result.contains("code")) {
+ code = result.getVal("code")->asString();
+ debug("code = %s", code.c_str());
+ }
+
+ if (result.contains("message")) {
+ message = result.getVal("message")->asString();
+ debug("message = %s", message.c_str());
+ }
+
+ //TODO: decide when token refreshment will help
+ //if (code == "unauthenticated") irrecoverable = false;
+
+ if (irrecoverable) {
+ finishError(Networking::ErrorResponse(this, false, true, json->stringify(true), httpCode));
+ delete json;
+ return;
+ }
+
+ pause();
+ delete json;
+ _parentStorage->getAccessToken(new Common::Callback<BoxTokenRefresher, Storage::BoolResponse>(this, &BoxTokenRefresher::tokenRefreshed));
+ return;
+ }
+
+ //notify user of success
+ CurlJsonRequest::finishJson(json);
+}
+
+void BoxTokenRefresher::finishError(Networking::ErrorResponse error) {
+ if (error.httpResponseCode == 401) { // invalid_token
+ pause();
+ _parentStorage->getAccessToken(new Common::Callback<BoxTokenRefresher, Storage::BoolResponse>(this, &BoxTokenRefresher::tokenRefreshed));
+ return;
+ }
+
+ // there are also 400 == invalid_request and 403 == insufficient_scope
+ // but TokenRefresher is there to refresh token when it's invalid only
+
+ Request::finishError(error);
+}
+
+void BoxTokenRefresher::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 BoxTokenRefresher::addHeader(Common::String header) {
+ _headers.push_back(header);
+ CurlJsonRequest::addHeader(header);
+}
+
+} // End of namespace Box
+} // End of namespace Cloud
diff --git a/backends/cloud/box/boxtokenrefresher.h b/backends/cloud/box/boxtokenrefresher.h
new file mode 100644
index 0000000000..7dedefdbe5
--- /dev/null
+++ b/backends/cloud/box/boxtokenrefresher.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_BOX_BOXTOKENREFRESHER_H
+#define BACKENDS_CLOUD_BOX_BOXTOKENREFRESHER_H
+
+#include "backends/cloud/storage.h"
+#include "backends/networking/curl/curljsonrequest.h"
+
+namespace Cloud {
+namespace Box {
+
+class BoxStorage;
+
+class BoxTokenRefresher: public Networking::CurlJsonRequest {
+ BoxStorage *_parentStorage;
+ Common::Array<Common::String> _headers;
+
+ void tokenRefreshed(Storage::BoolResponse response);
+
+ virtual void finishJson(Common::JSONValue *json);
+ virtual void finishError(Networking::ErrorResponse error);
+public:
+ BoxTokenRefresher(BoxStorage *parent, Networking::JsonCallback callback, Networking::ErrorCallback ecb, const char *url);
+ virtual ~BoxTokenRefresher();
+
+ virtual void setHeaders(Common::Array<Common::String> &headers);
+ virtual void addHeader(Common::String header);
+};
+
+} // End of namespace Box
+} // End of namespace Cloud
+
+#endif
diff --git a/backends/module.mk b/backends/module.mk
index d1737b19e5..2c2a4e2cfc 100644
--- a/backends/module.mk
+++ b/backends/module.mk
@@ -29,6 +29,7 @@ MODULE_OBJS += \
cloud/folderdownloadrequest.o \
cloud/savessyncrequest.o \
cloud/box/boxstorage.o \
+ cloud/box/boxtokenrefresher.o \
cloud/dropbox/dropboxstorage.o \
cloud/dropbox/dropboxcreatedirectoryrequest.o \
cloud/dropbox/dropboxlistdirectoryrequest.o \