OxFF/OxFF/components/OxFF.js

419 lines
13 KiB
JavaScript

// -*- coding: utf-8 -*-
// vi:si:et:sw=2:sts=4:ts=2
/*
OxFF - local extension for pan.do/ra
http://pan.do/ra
2009-2010 - GPL 3.0
*/
const Cc = Components.classes;
const Ci = Components.interfaces;
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://ox/utils.jsm");
Components.utils.import("resource://ox/oxff.jsm");
Components.utils.import("resource://ox/firefogg.jsm");
var OxFFFactory =
{
createInstance: function (outer, iid)
{
if (outer != null)
throw NS_ERROR_NO_AGGREGATION;
return (new OxFF()).QueryInterface(iid);
}
};
function OxFF() {
var _this = this;
var windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
var nsWindow = windowMediator.getMostRecentWindow("navigator:browser");
this._window = nsWindow.content;
this._window.addEventListener("unload", function() { _this.logout() }, false);
this.app = Cc["@mozilla.org/fuel/application;1"].getService(Ci.fuelIApplication);
this._site = this._window.document.location.hostname;
if(!this._site) {
this._site = 'localhost';
}
this.access();
if(!oxff.get('username')) {
oxff.set('username', ox.makeRandomString(8));
oxff.set('password', ox.makeRandomString(8));
}
this.username = oxff.get('username');
this.password = oxff.get('password');
try {
var em = Cc["@mozilla.org/extensions/manager;1"]
.getService(Ci.nsIExtensionManager);
var f = em.getInstallLocation('firefogg@firefogg.org').getItemFile('firefogg@firefogg.org', 'ffmpeg2theora');
_this._ffmpeg2theora = f.path;
} catch(e) {
Components.utils.import("resource://gre/modules/AddonManager.jsm");
AddonManager.getAddonByID('firefogg@firefogg.org', function(addon) {
if (addon.hasResource('bin')) {
var resource = addon.getResourceURI('bin');
var file = resource.QueryInterface(Ci.nsIFileURL).file.QueryInterface(Ci.nsILocalFile);
file.append('ffmpeg2theora');
_this._ffmpeg2theora = file.path;
}
});
}
}
OxFF.prototype = {
classDescription: "OxFF pan.do/ra Firefox extension",
classID: Components.ID("{32e2138b-2026-4cac-87c7-4f97ac4cf1c5}"),
contractID: "@pan.do/ra_extension;1",
extensionID: "OxFF@pan.do",
_xpcom_factory : OxFFFactory,
_xpcom_categories : [{
category: "JavaScript global constructor",
entry: "OxFF"
}],
_prefs : Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch),
_window : null,
_icon : null,
_protocolCallbacks : {},
QueryInterface: XPCOMUtils.generateQI(
[Ci.nsIOxFF,
Ci.nsISecurityCheckedComponent,
Ci.nsISupportsWeakReference,
Ci.nsIClassInfo]),
// nsIClassInfo
implementationLanguage: Ci.nsIProgrammingLanguage.JAVASCRIPT,
flags: Ci.nsIClassInfo.DOM_OBJECT,
getInterfaces: function getInterfaces(aCount) {
var interfaces = [Ci.nsIOxFF,
Ci.nsISecurityCheckedComponent,
Ci.nsISupportsWeakReference,
Ci.nsIClassInfo];
aCount.value = interfaces.length;
return interfaces;
},
getHelperForLanguage: function getHelperForLanguage(aLanguage) {
return null;
},
//nsISecurityCheckedComponent
canCallMethod: function canCallMethod(iid, methodName) {
Components.utils.reportError(methodName);
return "AllAccess";
},
canCreateWrapper: function canCreateWrapper(iid) {
return "AllAccess";
},
canGetProperty: function canGetProperty(iid, propertyName) {
Components.utils.reportError(propertyName);
return "AllAccess";
},
canSetProperty: function canSetProperty(iid, propertyName) {
Components.utils.reportError(propertyName);
return "NoAccess";
},
debug: function() {
var msg = this.extensionID + ": ";
for(var i=0;i<arguments.length;i++) {
msg += arguments[i];
if(i+1<arguments.length)
msg += ', ';
}
this.app.console.log(msg);
},
base: 'http://127.0.0.1:2620/',
_user: null,
//nsIOxFF
version: "bzr",
access: function(request) {
if (typeof(request) == 'undefined') request = false;
var _this = this;
var conn = oxff.getDB();
var q = conn.createStatement("SELECT access FROM site WHERE site = :site");
q.params.site = this._site;
this._access = false;
while(q.executeStep()) {
if(q.row.access == 1) {
this._access = true;
}
}
q.finalize();
if(request && !this._access) {
var windowMediator = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
var nsWindow = windowMediator.getMostRecentWindow("navigator:browser");
var box = nsWindow.gBrowser.getNotificationBox();
var buttons = [{
label : "Allow",
accessKey : "A",
callback : function() { _this.permitAccess(); }
},
{
label : "Deny",
accessKey : "D",
callback : function() { _this.denyAccess(); }
}];
box.appendNotification("Do you wnat to allow "+_this._site+" to manage archvies on your computer",
'oxff_permission' , null , box.PRIORITY_INFO_MEDIUM , buttons);
}
return this._access;
},
api: function(action, data, callback) {
var _this = this;
if (typeof(data) == 'function') {
callback = data;
data = {};
}
if(!this.canAccess())
return false;
data["site"] = this._site;
data["user"] = this._user;
var req = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
.createInstance(Ci.nsIXMLHttpRequest);
req.addEventListener("error", function(e) {
_this.startDaemon();
ox.setTimeout(function() { _this.api(action, data, callback); }, 1000);
}, false);
req.addEventListener("load", function(e) {
//links should have base prefixed or whatever proxy is used to access them, i.e. some api call
//var data = JSON.parse(e.target.responseText);
//callback(data);
callback(e.target.responseText);
}, false);
var base = this.base; //later base can not be a public property
var url = base + action;
//req.open("POST", url, true, this.username, this.password);
req.open("POST", url, true);
try {
var formData = Cc["@mozilla.org/files/formdata;1"].createInstance(Ci.nsIDOMFormData);
if (data) {
for(key in data) {
formData.append(key, data[key]);
}
}
} catch(e) {
var converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].createInstance(Ci.nsIScriptableUnicodeConverter);
converter.charset = "UTF-8";
var boundary = "--------XX" + Math.random();
var formData='';
if (data) {
for(key in data) {
if (data[key]) {
formData +="--" + boundary + "\r\n" +
"Content-Disposition: form-data; name=\""+key+"\"\r\n\r\n" +
data[key] + "\r\n";
}
}
}
formData += "--" + boundary + "--\r\n";
req.setRequestHeader("Content-type", "multipart/form-data; boundary=" + boundary);
req.setRequestHeader("Content-length", formData.length);
var formData = converter.convertToInputStream(formData);
}
req.send(formData);
return true;
},
extract: function(oshash, media, callback) {
return this.api('extract', {'oshash': oshash, 'media': media}, callback);
},
upload: function(url, file, callback, progress) {
if(!this.chunk_upload) {
var _this = this;
this.chunk_upload = new FirefoggUploader(this, file, url, {});
this.chunk_upload.onProgress(function(upload_progress) {
var info = {'status': 'uploading', 'progress': upload_progress};
progress(JSON.stringify(info));
});
this.chunk_upload.ready = true;
this.chunk_upload.start();
this.chunk_upload.done(function() {
_this.chunk_upload = null;
var info = {'status': 'done', 'progress': 1};
callback(JSON.stringify(info));
});
return true;
}
return false;
},
uploadVideo: function(oshash, url, profile, callback, progress) {
var _this = this;
if(!this.canAccess())
return false;
if(progress)
progress = progress.callback;
var timer = ox.setInterval(function() {
_this.api('extract', {'oshash': oshash, 'media': profile}, function(result) {
var data = JSON.parse(result);
if (data.status == 'extracting') {
if(progress) {
var info = {'status': data.status, 'progress': data.progress};
progress(JSON.stringify(info));
}
} else {
timer.cancel();
if(data.status == 'available') {
_this.upload(url, data.video, callback.callback, progress);
} else if(data.status == 'failed') {
_this.debug('failed');
}
}
});
}, 2000);
return true;
},
files: function(volume, callback) {
return this.api('files', {'volume': volume}, callback.callback);
},
get: function(oshash, media, callback) {
return this.api('get', {'oshash': oshash, 'media': media}, callback.callback);
},
login: function(user) {
if(this._user==null) {
this._user = user;
return true;
}
return false;
},
logout: function(user) {
var _this = this;
this.api('stop', function() {
_this._user = null;
_this._daemon = null;
});
if (this.chunk_upload) {
this.chunk_upload.cancel();
this.chunk_upload = null;
}
return true;
},
update: function(callback) {
this.api('update', callback.callback);
return true;
},
setLocation: function(name) {
if(!this._access) {
return false;
}
const nsIFilePicker = Ci.nsIFilePicker;
var fp = Cc["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
fp.init(this._window, "Set Locatin of "+name+" for " + this._site, nsIFilePicker.modeGetFolder);
fp.appendFilters(nsIFilePicker.filterAll);
var rv = fp.show();
if (rv == nsIFilePicker.returnOK || rv == nsIFilePicker.returnReplace) {
var new_location = fp.file.path;
this.api('set_location', {'name': name, 'path': new_location}, function(result) {});
return true;
}
return false;
},
removeVolume: function(name) {
return this.api('remove_volume', {'name': name});
},
renameVolume: function(name, new_name) {
return this.api('rename_volume', {'name': name, 'new_name': new_name});
},
volumes: function(callback) {
return this.api('volumes', callback.callback);
},
//private functions
permitAccess: function() {
this._access = true;
oxff.access(this._site, this._access);
},
denyAccess: function() {
this._access = false;
oxff.access(this._site, this._access);
},
canAccess: function() {
if(!this._access) {
this.debug('permission deinied', action, data);
return false;
}
if(!this._user) {
this.debug('login first', action, data);
return false;
}
return true;
},
startDaemon: function() {
var _this = this;
//if daemon is already running to not start it again
if(this._daemon && this._daemon.isRunning) {
this.debug('daemon is still starting up, not starting again');
return false;
}
var osString = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
var daemon = "";
if (osString == "WINNT")
daemon = 'oxd.exe';
else
daemon = 'oxd.py';
function runDaemon(file) {
try {
file.permissions = 0755;
} catch (e) {}
_this._daemon = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
_this._daemon.init(file);
var args = [oxff.getDBFile().path, _this._ffmpeg2theora];
_this._daemon.runw(false, args, args.length);
}
try {
var em = Cc["@mozilla.org/extensions/manager;1"]
.getService(Ci.nsIExtensionManager);
var file = em.getInstallLocation(this.extensionID).getItemFile(this.extensionID, daemon);
runDaemon(file);
} catch(e) {
Components.utils.import("resource://gre/modules/AddonManager.jsm");
AddonManager.getAddonByID(this.extensionID, function(addon) {
if (addon.hasResource('bin')) {
var resource = addon.getResourceURI('bin');
var file = resource.QueryInterface(Ci.nsIFileURL).file.QueryInterface(Ci.nsILocalFile);
file.append(daemon);
runDaemon(file);
}
});
}
},
}
/**
* XPCOMUtils.generateNSGetFactory was introduced in Mozilla 2 (Firefox 4).
* XPCOMUtils.generateNSGetModule is for Mozilla 1.9.2 (Firefox 3.6).
*/
if (XPCOMUtils.generateNSGetFactory)
var NSGetFactory = XPCOMUtils.generateNSGetFactory([OxFF]);
else
var NSGetModule = XPCOMUtils.generateNSGetModule([OxFF]);