OxFF pan.do/ra Firefox Extension

This commit is contained in:
j 2010-08-03 22:49:30 +02:00
commit 22b9128e5f
15 changed files with 803 additions and 0 deletions

1
.bzrignore Normal file
View File

@ -0,0 +1 @@
OxFF/settings.sqlite

9
OxFF/chrome.manifest Normal file
View File

@ -0,0 +1,9 @@
content OxFF chrome/content/
overlay chrome://browser/content/browser.xul chrome://OxFF/content/browser.xul
resource ox modules/
interfaces components/nsIOxFF.xpt
component {32e2138b-2026-4cac-87c7-4f97ac4cf1c5} components/OxFF.js
contract @pan.do/ra_extension;1 {32e2138b-2026-4cac-87c7-4f97ac4cf1c5}
category JavaScript-global-constructor OxFF @pan.do/ra_extension;1

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet href="chrome://oxff/skin/overlay.css" type="text/css"?>
<!DOCTYPE overlay SYSTEM "chrome://oxff/locale/oxff.dtd">
<overlay id="oxff-overlay"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="chrome://OxFF/content/overlay.js"/>
</overlay>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@ -0,0 +1,193 @@
// -*- coding: utf-8 -*-
// vi:si:et:sw=2:sts=4:ts=2
Components.utils.import("resource://ox/utils.jsm");
function Site(site, access) {
this.site = site;
this.access = access;
this.status = access==1?"Allowed":"Denied";
}
Site.prototype = {
delete: function() {
var conn = ox.getDB();
var q = conn.createStatement("DELETE FROM site WHERE site = :site");
q.params.site = this.site;
q.executeStep();
},
toggle: function() {
var conn = ox.getDB();
if(this.access==1) this.access=0;
else this.access = 1;
var q = conn.createStatement("UPDATE site SET access = :access WHERE site = :site");
q.params.site = this.site;
q.params.access = this.access;
q.executeStep();
this.status = this.access==1?"Allowed":"Denied";
}
}
var OxFFManager = {
_sites : [],
_tree : null,
_view: {
_rowCount: 0,
get rowCount() {
return this._rowCount;
},
getCellText: function (aRow, aColumn) {
if (aColumn.id == "siteCol")
return OxFFManager._sites[aRow].site;
else if (aColumn.id == "statusCol")
return OxFFManager._sites[aRow].status;
return "";
},
isSeparator: function(aIndex) { return false; },
isSorted: function() { return false; },
isContainer: function(aIndex) { return false; },
setTree: function(aTree){},
getImageSrc: function(aRow, aColumn) {},
getProgressMode: function(aRow, aColumn) {},
getCellValue: function(aRow, aColumn) {},
cycleHeader: function(column) {},
getRowProperties: function(row,prop){},
getColumnProperties: function(column,prop){},
getCellProperties: function(row,column,prop){}
},
onLoad: function () {
this._tree = document.getElementById("sitesTree");
this._sites = [];
// load permissions into a table
var conn = ox.getDB();
var q = conn.createStatement("SELECT site, access FROM site");
while(q.executeStep()) {
var p = new Site(q.row.site, q.row.access);
this._sites.push(p);
}
this._view._rowCount = this._sites.length;
// sort and display the table
this._tree.treeBoxObject.view = this._view;
this.onSiteSort("site", false);
// disable "remove all" button if there are none
document.getElementById("removeAllSites").disabled = this._sites.length == 0;
},
onSiteDoubleclick: function (aEvent) {
var selection = this._tree.view.selection;
var rc = selection.getRangeCount();
for (var i = 0; i < rc; ++i) {
var min = { }; var max = { };
selection.getRangeAt(i, min, max);
for (var j = min.value; j <= max.value; ++j) {
this._sites[j].toggle();
}
}
},
onSiteSelected: function () {
var hasSelection = this._tree.view.selection.count > 0;
var hasRows = this._tree.view.rowCount > 0;
document.getElementById("removeSite").disabled = !hasRows || !hasSelection;
document.getElementById("removeAllSites").disabled = !hasRows;
},
onSiteDeleted: function () {
if (!this._view.rowCount)
return;
var removedSites = [];
gTreeUtils.deleteSelectedItems(this._tree, this._view, this._sites, removedSites);
for (var i = 0; i < removedSites.length; ++i) {
var p = removedSites[i];
p.delete();
}
document.getElementById("removeSite").disabled = !this._sites.length;
document.getElementById("removeAllSites").disabled = !this._sites.length;
},
onAllSitesDeleted: function () {
if (!this._view.rowCount)
return;
var removedSites = [];
gTreeUtils.deleteAll(this._tree, this._view, this._sites, removedSites);
for (var i = 0; i < removedSites.length; ++i) {
var p = removedSites[i];
p.delete();
}
document.getElementById("removeSite").disabled = true;
document.getElementById("removeAllSites").disabled = true;
},
_lastSiteSortColumn: "",
_lastSiteSortAscending: false,
onSiteSort: function (aColumn) {
this._lastSiteSortAscending = gTreeUtils.sort(this._tree,
this._view,
this._sites,
aColumn,
this._lastSiteSortColumn,
this._lastSiteSortAscending);
this._lastSiteSortColumn = aColumn;
},
};
var gTreeUtils = {
deleteAll: function (aTree, aView, aItems, aDeletedItems) {
for (var i = 0; i < aItems.length; ++i)
aDeletedItems.push(aItems[i]);
aItems.splice(0);
var oldCount = aView.rowCount;
aView._rowCount = 0;
aTree.treeBoxObject.rowCountChanged(0, -oldCount);
},
deleteSelectedItems: function (aTree, aView, aItems, aDeletedItems) {
var selection = aTree.view.selection;
selection.selectEventsSuppressed = true;
var rc = selection.getRangeCount();
for (var i = 0; i < rc; ++i) {
var min = { }; var max = { };
selection.getRangeAt(i, min, max);
for (var j = min.value; j <= max.value; ++j) {
aDeletedItems.push(aItems[j]);
aItems[j] = null;
}
}
var nextSelection = 0;
for (i = 0; i < aItems.length; ++i) {
if (!aItems[i]) {
var j = i;
while (j < aItems.length && !aItems[j])
++j;
aItems.splice(i, j - i);
nextSelection = j < aView.rowCount ? j - 1 : j - 2;
aView._rowCount -= j - i;
aTree.treeBoxObject.rowCountChanged(i, i - j);
}
}
if (aItems.length) {
selection.select(nextSelection);
aTree.treeBoxObject.ensureRowIsVisible(nextSelection);
aTree.focus();
}
selection.selectEventsSuppressed = false;
},
sort: function (aTree, aView, aDataSet, aColumn,
aLastSortColumn, aLastSortAscending) {
var ascending = (aColumn == aLastSortColumn) ? !aLastSortAscending : true;
aDataSet.sort(function (a, b) { return a[aColumn].toLowerCase().localeCompare(b[aColumn].toLowerCase()); });
if (!ascending)
aDataSet.reverse();
aTree.view.selection.select(-1);
aTree.view.selection.select(0);
aTree.treeBoxObject.invalidate();
aTree.treeBoxObject.ensureRowIsVisible(0);
return ascending;
}
};

View File

@ -0,0 +1,53 @@
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<?xml-stylesheet href="chrome://browser/skin/preferences/preferences.css" type="text/css"?>
<!DOCTYPE dialog SYSTEM "chrome://browser/locale/preferences/permissions.dtd" >
<window id="OxFFPreferences" class="windowDialog"
windowtype="Browser:Sites"
title="OxFF Sites"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
style="width: &window.width;;"
onload="OxFFManager.onLoad();"
persist="screenX screenY width height">
<script src="chrome://OxFF/content/options.js"/>
<keyset>
<key key="&windowClose.key;" modifiers="accel" oncommand="window.close();"/>
</keyset>
<vbox class="contentPane" flex="1">
<description id="permissionsText" control="url">The following sites have permission to use OxFF</description>
<separator class="thin"/>
<tree id="sitesTree" flex="1" style="height: 18em;"
hidecolumnpicker="true"
onselect="OxFFManager.onSiteSelected();">
<treecols>
<treecol id="siteCol" label="&treehead.sitename.label;" flex="3"
onclick="OxFFManager.onSiteSort('site');" persist="width"/>
<splitter class="tree-splitter"/>
<treecol id="statusCol" label="&treehead.status.label;" flex="1"
onclick="OxFFManager.onSiteSort('status');" persist="width"/>
</treecols>
<treechildren ondblclick="OxFFManager.onSiteDoubleclick(event)" />
</tree>
</vbox>
<hbox align="end">
<hbox class="actionButtons" flex="1">
<button id="removeSite" disabled="true"
accesskey="&removepermission.accesskey;"
icon="remove" label="&removepermission.label;"
oncommand="OxFFManager.onSiteDeleted();"/>
<button id="removeAllSites"
icon="clear" label="&removeallpermissions.label;"
accesskey="&removeallpermissions.accesskey;"
oncommand="OxFFManager.onAllSitesDeleted();"/>
<spacer flex="1"/>
</hbox>
<resizer type="window" dir="bottomend"/>
</hbox>
</window>

View File

359
OxFF/components/OxFF.js Normal file
View File

@ -0,0 +1,359 @@
// -*- 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");
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.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();
}
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 = "OxFF: ";
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/',
username: 'fix',
password: 'me',
_user: null,
//nsIOxFF
version: "bzr",
login: function(user) {
if(this._user==null) {
this._user = user;
return true;
}
return false;
},
logout: function(user) {
var _this = this;
this.api('shutdown', function() {
_this._user = null;
});
return true;
},
update: function() {
this.api('update', function() {});
return true;
},
access: function(request) {
if (typeof(request) == 'undefined') request = false;
var _this = this;
var conn = ox.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;
}
}
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;
},
volumes: function(callback) {
return this.api('volumes', callback);
return JSON.stringify(['Test', 'Another']);
},
api: function(action, data, callback) {
if (typeof(data) == 'function') {
callback = data;
data = {};
}
if(!this._access) {
this.debug('permission deinied', action, data);
return false;
}
if(!this._user) {
this.debug('login first', action, data);
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) {
//should check that it was infact not able to connect to server
_this.startDaemon();
//does this need a timeout?
ox.setTimeout(function() { _this.api(action, data, callback); }, 500);
}, 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;
var formData = Cc["@mozilla.org/files/formdata;1"]
.createInstance(Ci.nsIDOMFormData);
if (data) {
for(key in data) {
formData.append(key, data[key]);
}
}
req.open("POST", url, true, this.username, this.password);
req.send(formData);
return true;
},
files: function(callback) {
return this.api('files', callback.callback);
},
get: function(oshash, media, callback) {
return this.api('get', {'oshash': oshash, 'media': media}, callback.callback);
},
extract: function(oshash, media, callback) {
return this.api('extract', {'oshash': oshash, 'media': media}, callback);
},
addVolume: function(archive) {
if(!this._access) {
return false;
}
//var volumes = this.getVolumes(domain);
const nsIFilePicker = Ci.nsIFilePicker;
var fp = Cc["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
fp.init(this._window, "Choose location of " + archive, 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('add_volume', {'path': new_location}, function(result) {});
return true;
}
return false;
},
_internal_update: function() {
var new_files = [];
var volumes = this.getVolumes(this._site);
for (i in volumes) {
var volume = volumes[i];
var files = ox.glob(volume);
//filter files, only include folders and files with the right extensions,
//where to store or get the list of valid extensions? would be nice if set by domain...
for (f in files) {
var file = files[f];
//check if file is in known files
var info = this.getFormatInfo(file, false);
//strip volume path from info,
//+1 since volume paths are wihtout trailing folder seperator
info.path = file.substr(volume.length+1, file.length)
new_files.push(info);
//add to Files table
}
}
return JSON.stringify(new_files);
},
//private functions
permitAccess: function() {
this._access = true;
var conn = ox.getDB();
var q = conn.createStatement("INSERT OR REPLACE INTO site values (:site, 1)");
q.params.site = this._site;
q.executeStep();
},
denyAccess: function() {
this._access = false;
var conn = ox.getDB();
var q = conn.createStatement("INSERT OR REPLACE INTO site values (:site, 0)");
q.params.site = this._site;
q.executeStep();
},
startDaemon: function() {
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) {}
var process = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
process.init(file);
var args = [];
process.run(false, args, args.length);
}
Components.utils.import("resource://gre/modules/AddonManager.jsm");
AddonManager.getAddonByID(this.extensionID, function(addon) {
if (addon.hasResource(daemon)) {
var resource = addon.getResourceURI(daemon);
var file = resource.QueryInterface(Ci.nsIFileURL).file.QueryInterface(Ci.nsILocalFile);
runDaemon(file);
}
});
},
getVolumes: function(site) {
var conn = ox.getDB();
var q = conn.createStatement("SELECT path FROM volume WHERE domain = :domain");
q.params.domain = site;
var volumes = [];
try {
while (q.executeStep()) {
var path = q.row.path;
volumes.push(path);
}
}
finally {
q.reset();
}
return volumes;
},
getFormatInfo: function(filename, callback) {
var that = this;
var get_json = function(data) {
var json = {"format": "unknown"};
try {
json = JSON.parse(data);
} catch(e) {
json = {"format": "unknown"};
}
var source_file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
source_file.initWithPath(filename);
// Try to determine the MIME type of the file
//json.contentType = that.getMimeType(source_file);
return json;
}
var info_callback = function(data) {
callback(get_json(data));
}
var options = [filename, '--info'];
if (callback) {
ox.subprocess(this.bin('ffmpeg2theora'), options, callback);
return;
}
data = ox.subprocess(this.bin('ffmpeg2theora'), options, false);
return get_json(data);
},
bin: function(cmd) {
this._cmd_name = '/usr/local/bin/_cmd_';
return this._cmd_name.replace('_cmd_', cmd);
},
}
//4.0 only
var NSGetFactory = XPCOMUtils.generateNSGetFactory([OxFF]);

BIN
OxFF/components/nsIOxFF.xpt Normal file

Binary file not shown.

28
OxFF/install.rdf Normal file
View File

@ -0,0 +1,28 @@
<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>OxFF@pan.do</em:id>
<em:version>bzr</em:version>
<em:type>2</em:type>
<!-- Firefox -->
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>3.5</em:minVersion>
<em:maxVersion>4.0b9</em:maxVersion>
</Description>
</em:targetApplication>
<!-- Front End MetaData -->
<em:name>pan.do/ra Firefox extension</em:name>
<em:description>integrate local files with pan.do/ra databases</em:description>
<em:creator>pan.do/ra</em:creator>
<em:homepageURL>https://pan.do/ra_extension</em:homepageURL>
<em:iconURL>chrome://OxFF/content/icon.png</em:iconURL>
<em:updateURL>https://pan.do/ra_extension/update.rdf</em:updateURL>
<em:optionsURL>chrome://OxFF/content/options.xul</em:optionsURL>
</Description>
</RDF>

80
OxFF/modules/utils.jsm Normal file
View File

@ -0,0 +1,80 @@
// -*- coding: utf-8 -*-
// vi:si:et:sw=4:sts=4:ts=4
let EXPORTED_SYMBOLS = [ "ox" ];
const Cc = Components.classes;
const Ci = Components.interfaces;
let ox = {
getDB: function() {
var file = Cc["@mozilla.org/file/directory_service;1"].getService(Ci.nsIProperties)
.get("ProfD", Ci.nsIFile);
file.append("OxFF.sqlite");
var storageService = Cc["@mozilla.org/storage/service;1"].getService(Ci.mozIStorageService);
var conn = storageService.openDatabase(file);
conn.executeSimpleSQL("CREATE TABLE IF NOT EXISTS site (site varchar(1024) unique, access INT)");
return conn;
},
setTimeout: function(callback, timeout) {
var timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
timer.initWithCallback(callback, timeout, Ci.nsITimer.TYPE_ONE_SHOT);
},
glob: function (path) {
/*
return array of all files(in all subdirectories) for given directory
*/
var directory = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
directory.initWithPath(path);
var entries = directory.directoryEntries;
var array = [];
while(entries.hasMoreElements()) {
var entry = entries.getNext();
entry.QueryInterface(Components.interfaces.nsIFile);
if(entry.isDirectory()) {
var sub = this.glob(entry.path);
for(i in sub) {
array.push(sub[i]);
}
} else {
array.push(entry.path);
}
}
return array;
},
subprocess: function(command, options, callback) {
if(!this.ipcService) {
this.ipcService = Cc["@mozilla.org/process/ipc-service;1"]
.getService().QueryInterface(Ci.nsIIPCService);
}
var cmd = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsILocalFile);
cmd.initWithPath(command);
if(command.indexOf(".exe")==-1 &&
command.substr(0, 15) != "/usr/local/bin/" &&
command.substr(0, 9) != "/usr/bin/") {
cmd.permissions = 0755;
}
if (typeof(callback) == 'function') {
var thread = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager)
.newThread(0);
var backgroundTask = {
run: function() {
var result = that.ipcService.run(cmd, options, options.length);
callback(result);
}
}
thread.dispatch(backgroundTask, thread.DISPATCH_NORMAL);
} else { //no callback, call subprocess blocking, will only return once done
/*
dump('\ncmd: ');
dump(cmd.path)
dump('\n');
dump(options)
*/
return this.ipcService.run(cmd, options, options.length);
}
},
};

23
build.sh Executable file
View File

@ -0,0 +1,23 @@
#!/bin/bash
cd `dirname $0`
release=`bzr tags | grep ".0 " | tail -1 | awk '{print $1}' | cut -d- -f2| tr "." " " |awk '{print $1"."$2}'`
release_rev=`bzr tags | grep ".0 " | tail -1 | awk '{print $2}'`
current_rev=`bzr revno`
version=$release.`printf %02d $(( $current_rev-$release_rev ))`
#update idl file
./src/make.sh
mkdir -p dist
sed -i "s/version: \".*\"/version: \"$version\"/g" OxFF/components/OxFF.js
sed -i "s/em:version>.*<\/em:version/em:version>$version<\/em:version/g" OxFF/install.rdf
rm -f dist/OxFF-$version.xpi
zip -9 -r dist/OxFF-$version.xpi * \
-x \*.~1~ -x \*.orig
#cleanup
sed -i "s/version: \".*\"/version: \"bzr\"/g" OxFF/components/OxFF.js
sed -i "s/em:version>.*<\/em:version/em:version>bzr<\/em:version/g" OxFF/install.rdf

8
src/make.sh Executable file
View File

@ -0,0 +1,8 @@
#!/bin/sh
cd `dirname $0`
XULRUNNER=xulrunner-1.9.2.8
IDL_PREFIX=/usr/share/idl/$XULRUNNER
XPIDL=/usr/lib/$XULRUNNER/xpidl
XPT=../OxFF/components/nsIOxFF.xpt
IDL=nsIOxFF.idl
$XPIDL -m typelib -w -v -I $IDL_PREFIX -e $XPT $IDL

30
src/nsIOxFF.idl Normal file
View File

@ -0,0 +1,30 @@
#include "nsISupports.idl"
[function, scriptable, uuid(70015be1-2620-4682-ba3c-8023e7cb42ac)]
interface oxICallback : nsISupports
{
/**
* @param result string
*/
void callback(in AString result);
};
[scriptable, uuid(333280ed-2620-46ed-916d-b9c29e84d9ba)]
interface nsIOxFF : nsISupports
{
readonly attribute string version;
boolean login(in AString user);
boolean addVolume();
string import();
float progress(in AString oshash);
boolean access([optional] in boolean request);
boolean update();
string volumes();
boolean files(in oxICallback callback);
boolean get(in AString oshash, in AString media, in oxICallback callback);
boolean extract(in AString oshash, in AString media, in oxICallback callback);
boolean logout();
};

10
test/import.html Normal file
View File

@ -0,0 +1,10 @@
<script>
var ox = new OxFF();
ox.access(true);
ox.get('b2c8f0aa3a447d09', 'stills', function(result) { console.log(result);});
ox.login('j');
//ox.files(function(result) { console.log(result);});
</script>