aboutsummaryrefslogtreecommitdiff
path: root/backends/cloud/onedrive
diff options
context:
space:
mode:
authorAlexander Tkachev2016-05-24 23:08:48 +0600
committerAlexander Tkachev2016-08-24 16:07:55 +0600
commit5e346ea6fbcd4a028bc7dd63efd09ff42770f8ef (patch)
tree7cd7d12110bbc731c71a6a5eeebf55b30acddbc2 /backends/cloud/onedrive
parent5f4bbe6e9e08f5f76eada84497a7530ffb08fbf1 (diff)
downloadscummvm-rg350-5e346ea6fbcd4a028bc7dd63efd09ff42770f8ef.tar.gz
scummvm-rg350-5e346ea6fbcd4a028bc7dd63efd09ff42770f8ef.tar.bz2
scummvm-rg350-5e346ea6fbcd4a028bc7dd63efd09ff42770f8ef.zip
CLOUD: Add OneDrive refresh_token support
It might be not that easy to restart the request after new token received, though.
Diffstat (limited to 'backends/cloud/onedrive')
-rw-r--r--backends/cloud/onedrive/onedrivestorage.cpp139
-rw-r--r--backends/cloud/onedrive/onedrivestorage.h26
2 files changed, 115 insertions, 50 deletions
diff --git a/backends/cloud/onedrive/onedrivestorage.cpp b/backends/cloud/onedrive/onedrivestorage.cpp
index b632c74580..2f10841cc9 100644
--- a/backends/cloud/onedrive/onedrivestorage.cpp
+++ b/backends/cloud/onedrive/onedrivestorage.cpp
@@ -38,50 +38,111 @@ namespace OneDrive {
Common::String OneDriveStorage::KEY; //can't use ConfMan there yet, loading it on instance creation/auth
Common::String OneDriveStorage::SECRET; //TODO: hide these secrets somehow
-static void saveAccessTokenCallback(void *ptr) {
- Common::JSONValue *json = (Common::JSONValue *)ptr;
- if (json) {
- debug("saveAccessTokenCallback:");
- debug("%s", json->stringify(true).c_str());
-
- //TODO: do something about refresh token
- Common::JSONObject result = json->asObject();
- if (!result.contains("access_token") || !result.contains("user_id")) {
- warning("Bad response, no token/user_id passed");
- } else {
- OneDriveStorage::addStorage(result.getVal("access_token")->asString(), result.getVal("user_id")->asString());
- ConfMan.removeKey("onedrive_code", "cloud");
- debug("Done! You can use OneDrive now! Look:");
- g_system->getCloudManager()->syncSaves();
- }
+OneDriveStorage::OneDriveStorage(Common::String accessToken, Common::String userId, Common::String refreshToken):
+ _token(accessToken), _uid(userId), _refreshToken(refreshToken) {}
- delete json;
+OneDriveStorage::OneDriveStorage(Common::String code) {
+ getAccessToken(new Common::Callback<OneDriveStorage, bool>(this, &OneDriveStorage::codeFlowComplete), code);
+}
+
+OneDriveStorage::~OneDriveStorage() {}
+
+void OneDriveStorage::getAccessToken(BoolCallback callback, Common::String code) {
+ bool codeFlow = (code != "");
+
+ if (!codeFlow && _refreshToken == "") {
+ warning("OneDriveStorage: no refresh token available to get new access token.");
+ if (callback) (*callback)(false);
+ return;
+ }
+
+ Common::BaseCallback<> *innerCallback = new Common::CallbackBridge<OneDriveStorage, bool>(this, &OneDriveStorage::tokenRefreshed, callback);
+ Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://login.live.com/oauth20_token.srf");
+ if (codeFlow) {
+ request->addPostField("code=" + code);
+ request->addPostField("grant_type=authorization_code");
} else {
- debug("saveAccessTokenCallback: got NULL instead of JSON!");
+ request->addPostField("refresh_token=" + _refreshToken);
+ request->addPostField("grant_type=refresh_token");
}
+ request->addPostField("client_id=" + KEY);
+ request->addPostField("client_secret=" + SECRET);
+ request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F");
+ ConnMan.addRequest(request);
}
-OneDriveStorage::OneDriveStorage(Common::String accessToken, Common::String userId): _token(accessToken), _uid(userId) {
- curl_global_init(CURL_GLOBAL_ALL);
+void OneDriveStorage::tokenRefreshed(BoolCallback callback, void *jsonPointer) {
+ Common::JSONValue *json = (Common::JSONValue *)jsonPointer;
+ if (!json) {
+ warning("OneDriveStorage: got NULL instead of JSON");
+ if (callback) (*callback)(false);
+ return;
+ }
+
+ Common::JSONObject result = json->asObject();
+ if (!result.contains("access_token") || !result.contains("user_id") || !result.contains("refresh_token")) {
+ warning("Bad response, no token or user_id passed");
+ debug("%s", json->stringify().c_str());
+ if (callback) (*callback)(false);
+ } else {
+ _token = result.getVal("access_token")->asString();
+ _uid = result.getVal("user_id")->asString();
+ _refreshToken = result.getVal("refresh_token")->asString();
+ g_system->getCloudManager()->save(); //ask CloudManager to save our new refreshToken
+ if (callback) (*callback)(true);
+ }
+ delete json;
}
-OneDriveStorage::~OneDriveStorage() {
- curl_global_cleanup();
+void OneDriveStorage::codeFlowComplete(bool success) {
+ if (!success) {
+ warning("OneDriveStorage: failed to get access token through code flow");
+ return;
+ }
+
+ g_system->getCloudManager()->addStorage(this);
+ ConfMan.removeKey("onedrive_code", "cloud");
+ debug("Done! You can use OneDrive now! Look:");
+ g_system->getCloudManager()->syncSaves();
}
void OneDriveStorage::saveConfig(Common::String keyPrefix) {
ConfMan.set(keyPrefix + "type", "OneDrive", "cloud");
ConfMan.set(keyPrefix + "access_token", _token, "cloud");
ConfMan.set(keyPrefix + "user_id", _uid, "cloud");
+ ConfMan.set(keyPrefix + "refresh_token", _refreshToken, "cloud");
}
-void OneDriveStorage::syncSaves(BoolCallback callback) {
- //this is not the real syncSaves() implementation
+void OneDriveStorage::printJsonTokenReceived(bool success) {
+ if (success) syncSaves(0); //try again
+}
+
+void OneDriveStorage::printJson(void *jsonPointer) {
+ Common::JSONValue *json = (Common::JSONValue *)jsonPointer;
+ if (!json) {
+ warning("printJson: NULL");
+ return;
+ }
+
+ Common::JSONObject result = json->asObject();
+ if (result.contains("error")) {
+ //Common::JSONObject error = result.getVal("error")->asObject();
+ debug("bad token, trying again...");
+ getAccessToken(new Common::Callback<OneDriveStorage, bool>(this, &OneDriveStorage::printJsonTokenReceived));
+ delete json;
+ return;
+ }
+
+ debug("%s", json->stringify().c_str());
+ delete json;
}
-void OneDriveStorage::addStorage(Common::String token, Common::String uid) {
- Storage *storage = new OneDriveStorage(token, uid);
- g_system->getCloudManager()->addStorage(storage);
+void OneDriveStorage::syncSaves(BoolCallback callback) {
+ //this is not the real syncSaves() implementation
+ Common::BaseCallback<> *innerCallback = new Common::Callback<OneDriveStorage>(this, &OneDriveStorage::printJson);
+ Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(innerCallback, "https://api.onedrive.com/v1.0/drives/");
+ request->addHeader("Authorization: bearer " + _token);
+ ConnMan.addRequest(request);
}
OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) {
@@ -98,9 +159,15 @@ OneDriveStorage *OneDriveStorage::loadFromConfig(Common::String keyPrefix) {
return 0;
}
+ if (!ConfMan.hasKey(keyPrefix + "refresh_token", "cloud")) {
+ warning("No refresh_token found");
+ return 0;
+ }
+
Common::String accessToken = ConfMan.get(keyPrefix + "access_token", "cloud");
Common::String userId = ConfMan.get(keyPrefix + "user_id", "cloud");
- return new OneDriveStorage(accessToken, userId);
+ Common::String refreshToken = ConfMan.get(keyPrefix + "refresh_token", "cloud");
+ return new OneDriveStorage(accessToken, userId, refreshToken);
}
Common::String OneDriveStorage::getAuthLink() {
@@ -109,7 +176,7 @@ Common::String OneDriveStorage::getAuthLink() {
url += "&redirect_uri=http://localhost:12345/"; //that's for copy-pasting
//url += "&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F"; //that's "http://localhost:12345/" for automatic opening
url += "&client_id=" + KEY;
- url += "&scope=onedrive.appfolder"; //TODO
+ url += "&scope=onedrive.appfolder%20offline_access"; //TODO
return url;
}
@@ -124,7 +191,7 @@ void OneDriveStorage::authThroughConsole() {
if (ConfMan.hasKey("onedrive_code", "cloud")) {
//phase 2: get access_token using specified code
- getAccessToken(ConfMan.get("onedrive_code", "cloud"));
+ new OneDriveStorage(ConfMan.get("onedrive_code", "cloud"));
return;
}
@@ -135,17 +202,5 @@ void OneDriveStorage::authThroughConsole() {
debug("http://wiki.scummvm.org/index.php/User_Manual/Configuring_ScummVM#Using_the_configuration_file_to_configure_ScummVM\n");
}
-void OneDriveStorage::getAccessToken(Common::String code) {
- Common::BaseCallback<> *callback = new Common::GlobalFunctionCallback(saveAccessTokenCallback);
- Networking::CurlJsonRequest *request = new Networking::CurlJsonRequest(callback, "https://login.live.com/oauth20_token.srf");
- //Content-Type: application/x-www-form-urlencoded
- request->addPostField("code=" + code);
- request->addPostField("grant_type=authorization_code");
- request->addPostField("client_id=" + KEY);
- request->addPostField("client_secret=" + SECRET);
- request->addPostField("&redirect_uri=http%3A%2F%2Flocalhost%3A12345%2F");
- ConnMan.addRequest(request);
-}
-
} //end of namespace OneDrive
} //end of namespace Cloud
diff --git a/backends/cloud/onedrive/onedrivestorage.h b/backends/cloud/onedrive/onedrivestorage.h
index 99f8476bc1..28f37aee2c 100644
--- a/backends/cloud/onedrive/onedrivestorage.h
+++ b/backends/cloud/onedrive/onedrivestorage.h
@@ -32,13 +32,28 @@ namespace OneDrive {
class OneDriveStorage: public Cloud::Storage {
static Common::String KEY, SECRET;
- Common::String _token, _uid;
+ Common::String _token, _uid, _refreshToken;
/** This private constructor is called from loadFromConfig(). */
- OneDriveStorage(Common::String token, Common::String uid);
+ OneDriveStorage(Common::String token, Common::String uid, Common::String refreshToken);
- static void getAccessToken(Common::String code);
+ /**
+ * This private constructor is called from authThroughConsole() (phase 2).
+ * It uses OAuth code flow to get tokens.
+ */
+ OneDriveStorage(Common::String code);
+
+ /**
+ * Gets new access_token. If <code> passed is "", refresh_token is used.
+ * Use "" in order to refresh token and pass a callback, so you could
+ * continue your work when new token is available.
+ */
+ void getAccessToken(BoolCallback callback, Common::String code = "");
+ void tokenRefreshed(BoolCallback callback, void *jsonPointer);
+ void codeFlowComplete(bool success);
+ void printJson(void *jsonPointer);
+ void printJsonTokenReceived(bool success);
public:
virtual ~OneDriveStorage();
@@ -92,11 +107,6 @@ public:
virtual bool isWorking() { return false; } //TODO
/**
- * Add OneDriveStorage with given token and uid into Cloud::Manager.
- */
- static void addStorage(Common::String token, Common::String uid);
-
- /**
* Load token and user id from configs and return OneDriveStorage for those.
* @return pointer to the newly created OneDriveStorage or 0 if some problem occured.
*/