Stackedit/public/res/helpers/dropboxHelper.js

362 lines
12 KiB
JavaScript
Raw Normal View History

2013-11-05 23:03:38 +00:00
/*global Dropbox */
2013-05-27 19:45:33 +00:00
define([
"jquery",
"underscore",
2013-11-05 23:03:38 +00:00
"constants",
2013-05-27 19:45:33 +00:00
"core",
2014-01-13 18:57:59 +00:00
"utils",
2013-11-05 23:03:38 +00:00
"storage",
"logger",
"settings",
2013-07-30 08:46:36 +00:00
"eventMgr",
2013-10-06 14:34:40 +00:00
"classes/AsyncTask",
2014-01-13 18:57:59 +00:00
], function($, _, constants, core, utils, storage, logger, settings, eventMgr, AsyncTask) {
2013-04-07 15:22:13 +00:00
2013-11-05 23:03:38 +00:00
var client;
2013-05-29 19:55:23 +00:00
var authenticated = false;
2013-04-07 15:22:13 +00:00
2013-05-29 19:55:23 +00:00
var dropboxHelper = {};
2013-08-04 00:53:46 +00:00
// Listen to offline status changes
var isOffline = false;
eventMgr.addListener("onOfflineChanged", function(isOfflineParam) {
isOffline = isOfflineParam;
});
2013-04-07 15:22:13 +00:00
2013-05-29 19:55:23 +00:00
// Try to connect dropbox by downloading client.js
function connect(task) {
task.onRun(function() {
2013-08-04 00:53:46 +00:00
if(isOffline === true) {
2013-05-29 19:55:23 +00:00
client = undefined;
task.error(new Error("Operation not available in offline mode.|stopPublish"));
return;
}
if(client !== undefined) {
task.chain();
return;
}
$.ajax({
url: "libs/dropbox.min.js",
2013-05-29 19:55:23 +00:00
dataType: "script",
2013-11-05 23:03:38 +00:00
timeout: constants.AJAX_TIMEOUT
2013-05-29 19:55:23 +00:00
}).done(function() {
client = new Dropbox.Client({
key: settings.dropboxFullAccess === true ? constants.DROPBOX_APP_KEY : constants.DROPBOX_RESTRICTED_APP_KEY,
secret: settings.dropboxFullAccess === true ? constants.DROPBOX_APP_SECRET : constants.DROPBOX_RESTRICTED_APP_SECRET
2013-05-29 19:55:23 +00:00
});
2013-10-08 00:34:15 +00:00
client.authDriver(new Dropbox.AuthDriver.Popup({
2013-11-05 23:03:38 +00:00
receiverUrl: constants.BASE_URL + "html/dropbox-oauth-receiver.html",
2013-05-29 19:55:23 +00:00
rememberUser: true
}));
task.chain();
}).fail(function(jqXHR) {
var error = {
status: jqXHR.status,
responseText: jqXHR.statusText
};
handleError(error, task);
});
});
}
2013-04-07 15:22:13 +00:00
2013-05-29 19:55:23 +00:00
// Try to authenticate with Oauth
function authenticate(task) {
task.onRun(function() {
if(authenticated === true) {
task.chain();
return;
}
var immediate = true;
2013-10-06 14:34:40 +00:00
function oauthRedirect() {
2014-01-13 18:57:59 +00:00
utils.redirectConfirm('You are being redirected to <strong>Dropbox</strong> authorization page.', function() {
2013-10-06 14:34:40 +00:00
task.chain(localAuthenticate);
2013-10-13 21:13:27 +00:00
}, function() {
task.error(new Error('Operation canceled.'));
2013-10-06 14:34:40 +00:00
});
}
2013-05-29 19:55:23 +00:00
function localAuthenticate() {
if(immediate === false) {
// If not immediate we add time for user to enter his
// credentials
2013-11-05 23:03:38 +00:00
task.timeout = constants.ASYNC_TASK_LONG_TIMEOUT;
2013-05-29 19:55:23 +00:00
}
2013-10-08 00:34:15 +00:00
else {
client.reset();
}
2013-05-29 19:55:23 +00:00
client.authenticate({
interactive: !immediate
}, function(error, client) {
// Success
2013-10-08 00:34:15 +00:00
if(client.isAuthenticated() === true) {
2013-05-29 19:55:23 +00:00
authenticated = true;
task.chain();
return;
}
// If immediate did not work retry without immediate flag
if(immediate === true) {
immediate = false;
2013-10-06 14:34:40 +00:00
task.chain(oauthRedirect);
2013-05-29 19:55:23 +00:00
return;
}
// Error
task.error(new Error("Access to Dropbox account is not authorized."));
});
}
task.chain(localAuthenticate);
});
}
2013-04-07 15:22:13 +00:00
2013-05-29 19:55:23 +00:00
dropboxHelper.upload = function(path, content, callback) {
2013-11-05 23:03:38 +00:00
var result;
2013-06-16 10:47:35 +00:00
var task = new AsyncTask();
2013-05-29 19:55:23 +00:00
connect(task);
authenticate(task);
task.onRun(function() {
client.writeFile(path, content, function(error, stat) {
if(!error) {
result = stat;
task.chain();
return;
}
// Handle error
if(error.status === 400) {
error = 'Could not upload document into path "' + path + '".';
}
handleError(error, task);
});
});
task.onSuccess(function() {
callback(undefined, result);
});
task.onError(function(error) {
callback(error);
});
2013-06-16 10:47:35 +00:00
task.enqueue();
2013-05-29 19:55:23 +00:00
};
2013-04-07 15:22:13 +00:00
2013-05-29 19:55:23 +00:00
dropboxHelper.checkChanges = function(lastChangeId, callback) {
var changes = [];
var newChangeId = lastChangeId || 0;
2013-06-16 10:47:35 +00:00
var task = new AsyncTask();
2013-05-29 19:55:23 +00:00
connect(task);
authenticate(task);
task.onRun(function() {
function retrievePageOfChanges() {
client.pullChanges(newChangeId, function(error, pullChanges) {
if(error) {
handleError(error, task);
return;
}
// Retrieve success
newChangeId = pullChanges.cursor();
if(pullChanges.changes !== undefined) {
changes = changes.concat(pullChanges.changes);
}
if(pullChanges.shouldPullAgain) {
task.chain(retrievePageOfChanges);
}
else {
task.chain();
}
});
}
task.chain(retrievePageOfChanges);
});
task.onSuccess(function() {
callback(undefined, changes, newChangeId);
});
task.onError(function(error) {
callback(error);
});
2013-06-16 10:47:35 +00:00
task.enqueue();
2013-05-29 19:55:23 +00:00
};
2013-04-07 15:22:13 +00:00
2013-05-29 19:55:23 +00:00
dropboxHelper.downloadMetadata = function(paths, callback) {
var result = [];
2013-06-16 10:47:35 +00:00
var task = new AsyncTask();
2013-05-29 19:55:23 +00:00
connect(task);
authenticate(task);
task.onRun(function() {
function recursiveDownloadMetadata() {
if(paths.length === 0) {
task.chain();
return;
}
var path = paths[0];
client.stat(path, function(error, stat) {
if(stat) {
result.push(stat);
paths.shift();
task.chain(recursiveDownloadMetadata);
return;
}
handleError(error, task);
});
}
task.chain(recursiveDownloadMetadata);
});
task.onSuccess(function() {
callback(undefined, result);
});
task.onError(function(error) {
callback(error);
});
2013-06-16 10:47:35 +00:00
task.enqueue();
2013-05-29 19:55:23 +00:00
};
2013-04-07 15:22:13 +00:00
2013-05-29 19:55:23 +00:00
dropboxHelper.downloadContent = function(objects, callback) {
var result = [];
2013-06-16 10:47:35 +00:00
var task = new AsyncTask();
2013-05-29 19:55:23 +00:00
connect(task);
authenticate(task);
task.onRun(function() {
function recursiveDownloadContent() {
if(objects.length === 0) {
task.chain();
return;
}
var object = objects[0];
result.push(object);
2013-11-05 23:03:38 +00:00
var file;
2013-05-29 19:55:23 +00:00
// object may be a file
if(object.isFile === true) {
file = object;
}
// object may be a change
else if(object.wasRemoved !== undefined) {
file = object.stat;
}
if(!file) {
objects.shift();
task.chain(recursiveDownloadContent);
return;
}
client.readFile(file.path, function(error, data) {
if(_.isString(data)) {
2013-05-29 19:55:23 +00:00
file.content = data;
objects.shift();
task.chain(recursiveDownloadContent);
return;
}
handleError(error, task);
});
}
task.chain(recursiveDownloadContent);
});
task.onSuccess(function() {
callback(undefined, result);
});
task.onError(function(error) {
callback(error);
});
2013-06-16 10:47:35 +00:00
task.enqueue();
2013-05-29 19:55:23 +00:00
};
2013-04-27 23:16:38 +00:00
2013-05-29 19:55:23 +00:00
function handleError(error, task) {
var errorMsg = true;
if(error) {
logger.error(error);
// Try to analyze the error
if(typeof error === "string") {
errorMsg = error;
}
else {
errorMsg = "Dropbox error (" + error.status + ": " + error.responseText + ").";
2013-04-07 15:22:13 +00:00
2013-05-29 19:55:23 +00:00
if(error.status === 401 || error.status === 403) {
authenticated = false;
errorMsg = "Access to Dropbox account is not authorized.";
task.retry(new Error(errorMsg), 1);
return;
}
else if(error.status === 400 && error.responseText.indexOf("oauth_nonce") !== -1) {
// A bug I guess...
2013-11-05 23:03:38 +00:00
_.each(_.keys(storage), function(key) {
2013-05-29 19:55:23 +00:00
// We have to remove the Oauth cache from the
2013-11-05 23:03:38 +00:00
// storage
2013-05-29 19:55:23 +00:00
if(key.indexOf("dropbox-auth") === 0) {
2013-11-05 23:03:38 +00:00
storage.removeItem(key);
2013-05-29 19:55:23 +00:00
}
});
authenticated = false;
task.retry(new Error(errorMsg), 1);
return;
}
else if(error.status <= 0) {
client = undefined;
authenticated = false;
core.setOffline();
errorMsg = "|stopPublish";
}
}
}
task.error(new Error(errorMsg));
}
var pickerLoaded = false;
function loadPicker(task) {
task.onRun(function() {
if(pickerLoaded === true) {
task.chain();
return;
}
2013-10-13 21:13:27 +00:00
function chooserRedirect() {
2014-01-13 18:57:59 +00:00
utils.redirectConfirm('You are being redirected to <strong>Dropbox Chooser</strong> page.', function() {
2013-10-13 21:13:27 +00:00
task.chain();
}, function() {
task.error(new Error('Operation canceled.'));
});
}
2013-05-29 19:55:23 +00:00
$.ajax({
url: "https://www.dropbox.com/static/api/1/dropbox.js",
dataType: "script",
2013-11-05 23:03:38 +00:00
timeout: constants.AJAX_TIMEOUT
2013-05-29 19:55:23 +00:00
}).done(function() {
pickerLoaded = true;
2013-10-13 21:13:27 +00:00
task.chain(chooserRedirect);
2013-05-29 19:55:23 +00:00
}).fail(function(jqXHR) {
var error = {
status: jqXHR.status,
responseText: jqXHR.statusText
};
handleError(error, task);
});
});
}
dropboxHelper.picker = function(callback) {
var paths = [];
2013-06-16 10:47:35 +00:00
var task = new AsyncTask();
2013-05-29 19:55:23 +00:00
// Add some time for user to choose his files
2013-11-05 23:03:38 +00:00
task.timeout = constants.ASYNC_TASK_LONG_TIMEOUT;
2013-05-29 19:55:23 +00:00
connect(task);
loadPicker(task);
task.onRun(function() {
var options = {};
options.multiselect = true;
options.linkType = "direct";
options.success = function(files) {
for ( var i = 0; i < files.length; i++) {
var path = files[i].link;
path = path.replace(/.*\/view\/[^\/]*/, "");
paths.push(decodeURI(path));
}
task.chain();
2013-04-20 00:14:20 +00:00
};
options.cancel = function() {
2013-05-29 19:55:23 +00:00
task.chain();
2013-04-20 00:14:20 +00:00
};
2013-05-29 19:55:23 +00:00
Dropbox.choose(options);
});
task.onSuccess(function() {
callback(undefined, paths);
});
task.onError(function(error) {
callback(error);
});
2013-06-16 10:47:35 +00:00
task.enqueue();
2013-05-29 19:55:23 +00:00
};
2013-04-07 15:22:13 +00:00
2013-05-29 19:55:23 +00:00
return dropboxHelper;
2013-04-07 15:22:13 +00:00
});