/*
* Spreed WebRTC.
* Copyright (C) 2013-2015 struktur AG
*
* This file is part of Spreed WebRTC.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
*/
"use strict";
define(["jquery", "underscore", "webrtc.adapter"], function($, _) {
// fileUpload
return ["fileData", "fileTransfer", "safeApply", "alertify", "translation", function(fileData, fileTransfer, safeApply, alertify, translation) {
var Session = function(token, scope) {
this.token = token;
this.scope = scope;
this.running = true;
this.connections = {};
var cancel = scope.$on("cancelUpload", _.bind(function(event) {
cancel();
event.stopPropagation();
this.running = false;
_.each(this.connections, function(connection) {
connection.cancel();
});
this.connections = {};
this.scope = null;
}, this));
};
Session.prototype.handleRequest = function(scope, xfer, data) {
//console.log("handleRequest", [data], typeof data);
if (typeof data === "string") {
if (data.charCodeAt(0) === 2) {
// Ignore whatever shit is sent us by Firefox.
return;
}
// Control data request.
var msg;
try {
msg = JSON.parse(data);
} catch (e) {
// Invalid JSON.
console.warn("Invalid JSON received from file download request.", data);
xfer.cancel();
delete this.connections[xfer.id];
return;
}
this.processRequest(scope, xfer, msg);
} else {
console.warn("Unkown data type received -> ignored", typeof data, [data]);
xfer.cancel();
delete this.connections[xfer];
}
};
Session.prototype.processRequest = function(scope, xfer, msg) {
if (!this.running) {
xfer.cancel();
return;
}
if (!this.connections.hasOwnProperty(xfer.id)) {
console.log("New incoming download connection:", xfer);
this.connections[xfer.id] = xfer;
xfer.e.on("closed", _.bind(function() {
console.log("Incoming download connection closed:", xfer);
delete this.connections[xfer.id];
}, this));
}
var info = this.scope.info;
switch (msg.m) {
case "r":
// Request chunk.
//console.debug("Request a chunk", msg, xfer.id);
var chunk = parseInt(msg.i || 0, 10);
var file = fileData.getFile(info.id);
file.getChunk(chunk, _.bind(function(data) {
//console.log("Sending chunk", chunk, data.byteLength);
if (!this.running) {
return;
}
var filechunk = fileTransfer.makeChunk(chunk, data);
xfer.send(filechunk.raw());
safeApply(this.scope, function($scope) {
$scope.$emit("uploadedChunk", chunk, data.byteLength);
});
}, this));
break;
case "bye":
// Close this xfer.
xfer.cancel();
break;
default:
console.log("Unknown xfer control request", msg.m, msg);
break;
}
};
var FileUpload = function() {
this.supported = fileTransfer.supported;
};
FileUpload.prototype.bindClick = function(namespace, element, cb) {
// Helper to allow later modifications.
var binder = {
namespace: function() {
return namespace;
}
}
$(element).on("click", _.bind(function(event) {
event.preventDefault();
if (!this.supported) {
alertify.dialog.alert(translation._("Your browser does not support file transfer."));
return;
}
// Create new input.
var input = $('');
input.css({
visibility: "hidden",
position: "absolute",
left: "0px",
top: "0px",
height: "0px",
width: "0px"
});
input.change(function(ev) {
var dataTransfer = ev.target;
var files = [];
var i;
for (i = 0; i < dataTransfer.files.length; i++) {
files.push(fileData.createFile(binder.namespace(), dataTransfer.files[i]));
}
//console.log("click event", dataTransfer, files, files.length);
if (cb) {
cb(files);
}
});
input.click();
}, this));
// Return helper.
return binder;
};
FileUpload.prototype.bindDrop = function(namespace, element, cb) {
//console.log("Binding file upload drop to", namespace, element);
// Helper to allow later modifications.
var binder = {
namespace: function() {
return namespace;
}
}
$(element).on("dragover dragenter", function(event) {
event.preventDefault();
});
$(element).on("drop", _.bind(function(event) {
event.preventDefault();
if (!this.supported) {
alertify.dialog.alert(translation._("Your browser does not support file transfer."));
return;
}
var dataTransfer = event.originalEvent.dataTransfer;
var files = [];
var i;
for (i = 0; i < dataTransfer.files.length; i++) {
files.push(fileData.createFile(binder.namespace(), dataTransfer.files[i]));
}
//console.log("drop event", dataTransfer, files, files.length);
if (cb) {
cb(files);
}
}, this));
// Return helper.
return binder;
};
FileUpload.prototype.createSession = function(scope, token) {
var session = new Session(token, scope);
//console.log("Created new file download session", id, session);
return session;
};
FileUpload.prototype.startUpload = function(scope, token) {
var session = this.createSession(scope, token);
return session;
};
// Create singleton.
var fileUpload = new FileUpload();
return fileUpload;
}];
});