You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
richdocuments/js/editor/server/pullbox/Server.js

300 lines
11 KiB
JavaScript

/**
* @license
* Copyright (C) 2013 KO GmbH <copyright@kogmbh.com>
*
* @licstart
* The JavaScript code in this page is free software: you can redistribute it
* and/or modify it under the terms of the GNU Affero General Public License
* (GNU AGPL) as published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version. The code is distributed
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU AGPL for more details.
*
* As additional permission under GNU AGPL version 3 section 7, you
* may distribute non-source (e.g., minimized or compacted) forms of
* that code without the copy of the GNU GPL normally required by
* section 4, provided you include this license notice and a URL
* through which recipients can access the Corresponding Source.
*
* As a special exception to the AGPL, any HTML file which merely makes function
* calls to this code, and for that purpose includes it by reference shall be
* deemed a separate work for copyright law purposes. In addition, the copyright
* holders of this code give you permission to combine this code with free
* software libraries that are released under the GNU LGPL. You may copy and
* distribute such a system following the terms of the GNU AGPL for this code
* and the LGPL for the libraries. If you modify this code, you may extend this
* exception to your version of the code, but you are not obligated to do so.
* If you do not wish to do so, delete this exception statement from your
* version.
*
* This license applies to this entire compilation.
* @licend
* @source: http://www.webodf.org/
* @source: http://gitorious.org/webodf/webodf/
*/
/*global XMLHttpRequest, runtime, core, ops*/
define("webodf/editor/server/pullbox/Server", [], function () {
"use strict";
runtime.loadClass("core.Base64");
runtime.loadClass("core.ByteArrayWriter");
/**
* @constructor
* @implements ops.Server
* @param {{url:string}} args
*/
return function PullBoxServer(args) {
var self = this,
token,
base64 = new core.Base64();
args = args || {};
args.url = args.url || "/WSER";
args.sessionStateToFileUrl = args.sessionStateToFileUrl || "/SS2F"
this.getGenesisUrl = function (sessionId) {
return "/session/" + sessionId + "/genesis";
};
/**
* @param {!Object} message
* @param {!function(!string)} cb
* @return {undefined}
*/
function call(message, cb) {
var xhr = new XMLHttpRequest(),
byteArrayWriter = new core.ByteArrayWriter("utf8"),
messageString = JSON.stringify(message),
data;
function handleResult() {
if (xhr.readyState === 4) {
if ((xhr.status < 200 || xhr.status >= 300) && xhr.status === 0) {
// report error
runtime.log("Status " + String(xhr.status) + ": " +
xhr.responseText || xhr.statusText);
}
cb(xhr.responseText);
}
}
runtime.log("Sending message to server: "+messageString);
// create body data for request from metadata and payload
byteArrayWriter.appendString(messageString);
// byteArrayWriter.appendByteArray(zipData);
data = byteArrayWriter.getByteArray();
// do the request
xhr.open('POST', args.url, true);
if (token) {
xhr.setRequestHeader("requesttoken", token);
}
xhr.onreadystatechange = handleResult;
// ArrayBufferView will have an ArrayBuffer property, in WebKit, XHR can send()
// an ArrayBuffer, In Firefox, one must use sendAsBinary with a string
if (data.buffer && !xhr.sendAsBinary) {
data = data.buffer; // webkit supports sending an ArrayBuffer
} else {
// encode into a string, this works in FireFox >= 3
data = runtime.byteArrayToString(data, "binary");
}
try {
if (xhr.sendAsBinary) {
xhr.sendAsBinary(data);
} else {
xhr.send(data);
}
} catch (e) {
runtime.log("Problem with calling server: " + e + " " + data);
cb(e.message);
}
}
this.call = call;
this.getToken = function () {
return token;
};
/**
* for pre-authenticated use
*/
this.setToken = function (a_token) {
token = a_token;
};
/*jslint unparam: true*/
/**
* @param {!number} timeout in milliseconds
* @param {!function(!string)} callback
* @return {undefined}
*/
this.connect = function (timeout, callback) {
/*
var accumulatedWaitingTime = 0;
// already tried connecting?
if (self.networkStatus() === "ready") {
return;
}
*/
callback("ready");
};
/*jslint unparam: false*/
/**
* @return {!string}
*/
this.networkStatus = function () {
return "ready";
};
/**
* @param {!string} login
* @param {!string} password
* @param {function(!Object)} successCb
* @param {function(!string)} failCb
* @return {undefined}
*/
this.login = function (login, password, successCb, failCb) {
call({
command: "login",
args: {
login: base64.toBase64(login),
password: base64.toBase64(password)
}
}, function(responseData) {
var response = /**@type {{token:string}}*/(runtime.fromJson(responseData));
runtime.log("Login reply: " + responseData);
if (response.hasOwnProperty("token")) {
token = response.token;
runtime.log("Caching token: " + self.getToken());
successCb(response);
} else {
failCb(responseData);
}
});
};
/**
* @param {!string} userId
* @param {!string} sessionId
* @param {!function(!string)} successCb
* @param {function()=} failCb
* @return {undefined}
*/
this.joinSession = function (userId, sessionId, successCb, failCb) {
call({
command: "join_session",
args: {
user_id: userId,
es_id: sessionId
}
}, function(responseData) {
var response = /**@type {{success:string, member_id:string}}*/(runtime.fromJson(responseData));
runtime.log("join_session reply: " + responseData);
if (response.hasOwnProperty("success") && response.success) {
successCb(response.member_id);
} else {
if (failCb) {
failCb();
}
}
});
};
/**
* @param {!string} sessionId
* @param {!string} memberId
* @param {!function()} successCb
* @param {function()=} failCb
* @return {undefined}
*/
this.leaveSession = function (sessionId, memberId, successCb, failCb) {
call({
command: "leave_session",
args: {
es_id: sessionId,
member_id: memberId
}
}, function(responseData) {
var response = /**@type {{success:string, member_id:string}}*/(runtime.fromJson(responseData));
runtime.log("leave_session reply: " + responseData);
if (response.hasOwnProperty("success") && response.success) {
successCb();
} else {
if (failCb) {
failCb();
}
}
});
};
/**
* @param {!string} sessionId
* @param {!string} memberId
* @param {!string} seqHead
* @param {function()=} callback
* @return {undefined}
*/
this.writeSessionStateToFile = function(sessionId, memberId, seqHead, fileData, callback) {
// code copied from BrowserRuntime.writeFile and adapted
var xhr = new XMLHttpRequest();
function handleResult() {
if (xhr.readyState === 4) {
if (xhr.status === 0 && !xhr.responseText) {// TODO: check makes sense here as well?
// for local files there is no difference between missing
// and empty files, so empty files are considered as errors
runtime.log("File " + args.sessionStateToFileUrl + " is empty.");
} else if ((xhr.status >= 200 && xhr.status < 300) ||
xhr.status === 0) {
// report success
runtime.log(null);
} else {
// report error
runtime.log("Status " + String(xhr.status) + ": " +
xhr.responseText || xhr.statusText);
}
callback();
}
}
// do the request
xhr.open('POST', args.sessionStateToFileUrl, true);
if (token) {
xhr.setRequestHeader("requesttoken", token);
}
xhr.setRequestHeader("webodf-session-id", sessionId);
xhr.setRequestHeader("webodf-member-id", memberId);
xhr.setRequestHeader("webodf-session-revision", seqHead);
xhr.onreadystatechange = handleResult;
// ArrayBufferView will have an ArrayBuffer property, in WebKit, XHR can send()
// an ArrayBuffer, In Firefox, one must use sendAsBinary with a string
if (fileData.buffer && !xhr.sendAsBinary) {
fileData = fileData.buffer; // webkit supports sending an ArrayBuffer
} else {
// encode into a string, this works in FireFox >= 3
fileData = runtime.byteArrayToString(fileData, "binary");
}
try {
if (xhr.sendAsBinary) {
xhr.sendAsBinary(fileData);
} else {
xhr.send(fileData);
}
} catch (e) {
runtime.log("Problem with calling \"writeSessionStateToFile\" on server");
callback(e.message);
}
};
};
});