Add back old integration pipe modes for use on Linux
This commit is contained in:
parent
4a90c8acda
commit
7fd299bd64
2 changed files with 199 additions and 11 deletions
|
@ -41,7 +41,7 @@ Zotero.Integration = new function() {
|
||||||
var _osascriptFile;
|
var _osascriptFile;
|
||||||
var _inProgress = false;
|
var _inProgress = false;
|
||||||
var _integrationVersionsOK = null;
|
var _integrationVersionsOK = null;
|
||||||
var _useDeferredOpenForIntegrationPipe = false;
|
var _pipeMode = false;
|
||||||
var _winUser32;
|
var _winUser32;
|
||||||
|
|
||||||
this.sessions = {};
|
this.sessions = {};
|
||||||
|
@ -213,9 +213,9 @@ Zotero.Integration = new function() {
|
||||||
/**
|
/**
|
||||||
* Listens asynchronously for data on the integration pipe and reads it when available
|
* Listens asynchronously for data on the integration pipe and reads it when available
|
||||||
*
|
*
|
||||||
* Used to read from the integration pipe on Fx 4
|
* Used to read from the integration pipe on Fx 4.2
|
||||||
*/
|
*/
|
||||||
var _integrationPipeListenerFx4 = {
|
var _integrationPipeListenerFx42 = {
|
||||||
"onStartRequest":function() {},
|
"onStartRequest":function() {},
|
||||||
"onStopRequest":function() {},
|
"onStopRequest":function() {},
|
||||||
|
|
||||||
|
@ -256,8 +256,8 @@ Zotero.Integration = new function() {
|
||||||
* Initializes the nsIInputStream and nsIInputStreamPump to read from _fifoFile
|
* Initializes the nsIInputStream and nsIInputStreamPump to read from _fifoFile
|
||||||
*/
|
*/
|
||||||
function _initializePipeStreamPump() {
|
function _initializePipeStreamPump() {
|
||||||
if(_useDeferredOpenForIntegrationPipe) {
|
if(_pipeMode === "deferredOpen") {
|
||||||
// Fx 4 supports deferred open; no need to use sh
|
// Fx >4 supports deferred open; no need to use sh
|
||||||
var fifoStream = Components.classes["@mozilla.org/network/file-input-stream;1"].
|
var fifoStream = Components.classes["@mozilla.org/network/file-input-stream;1"].
|
||||||
createInstance(Components.interfaces.nsIFileInputStream);
|
createInstance(Components.interfaces.nsIFileInputStream);
|
||||||
fifoStream.QueryInterface(Components.interfaces.nsIFileInputStream);
|
fifoStream.QueryInterface(Components.interfaces.nsIFileInputStream);
|
||||||
|
@ -267,7 +267,7 @@ Zotero.Integration = new function() {
|
||||||
var pump = Components.classes["@mozilla.org/network/input-stream-pump;1"].
|
var pump = Components.classes["@mozilla.org/network/input-stream-pump;1"].
|
||||||
createInstance(Components.interfaces.nsIInputStreamPump);
|
createInstance(Components.interfaces.nsIInputStreamPump);
|
||||||
pump.init(fifoStream, -1, -1, 4096, 1, true);
|
pump.init(fifoStream, -1, -1, 4096, 1, true);
|
||||||
pump.asyncRead(_integrationPipeListenerFx4, null);
|
pump.asyncRead(_integrationPipeListenerFx42, null);
|
||||||
} else {
|
} else {
|
||||||
// Fx 3.6 doesn't support deferred open
|
// Fx 3.6 doesn't support deferred open
|
||||||
_shProc.runAsync(_shCmd, _shCmd.length, _integrationPipeObserverFx36);
|
_shProc.runAsync(_shCmd, _shCmd.length, _integrationPipeObserverFx36);
|
||||||
|
@ -278,7 +278,29 @@ Zotero.Integration = new function() {
|
||||||
* Initializes the Zotero Integration Pipe
|
* Initializes the Zotero Integration Pipe
|
||||||
*/
|
*/
|
||||||
function _initializeIntegrationPipe() {
|
function _initializeIntegrationPipe() {
|
||||||
_useDeferredOpenForIntegrationPipe = false; // this will only work with Gecko 2.0.1
|
var verComp = Components.classes["@mozilla.org/xpcom/version-comparator;1"]
|
||||||
|
.getService(Components.interfaces.nsIVersionComparator);
|
||||||
|
var appInfo = Components.classes["@mozilla.org/xre/app-info;1"].
|
||||||
|
getService(Components.interfaces.nsIXULAppInfo);
|
||||||
|
if(Zotero.isFx4) {
|
||||||
|
if(verComp.compare("2.0b9pre", appInfo.platformVersion) > 0) {
|
||||||
|
Components.utils.reportError("Zotero word processor integration requires "+
|
||||||
|
"Firefox 4.0b9 or later. Please update to the latest Firefox 4.0 beta.");
|
||||||
|
return;
|
||||||
|
} else if(verComp.compare("2.2a1pre", appInfo.platformVersion) <= 0) {
|
||||||
|
_pipeMode = "deferredOpen";
|
||||||
|
} else {
|
||||||
|
_pipeMode = "fx4thread";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(Zotero.isMac) {
|
||||||
|
_pipeMode = "subprocess";
|
||||||
|
} else {
|
||||||
|
_pipeMode = "fx36thread";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Zotero.debug("Using integration pipe mode "+_pipeMode);
|
||||||
|
|
||||||
// make a new pipe
|
// make a new pipe
|
||||||
var mkfifo = Components.classes["@mozilla.org/file/local;1"].
|
var mkfifo = Components.classes["@mozilla.org/file/local;1"].
|
||||||
|
@ -300,7 +322,7 @@ Zotero.Integration = new function() {
|
||||||
proc.run(true, [_fifoFile.path], 1);
|
proc.run(true, [_fifoFile.path], 1);
|
||||||
|
|
||||||
if(_fifoFile.exists()) {
|
if(_fifoFile.exists()) {
|
||||||
if(!_useDeferredOpenForIntegrationPipe) {
|
if(_pipeMode === "subprocess") {
|
||||||
// no deferred open capability, so we need to use the sh/tmpfile hack
|
// no deferred open capability, so we need to use the sh/tmpfile hack
|
||||||
|
|
||||||
// make a tmp file
|
// make a tmp file
|
||||||
|
@ -318,10 +340,104 @@ Zotero.Integration = new function() {
|
||||||
_shProc = Components.classes["@mozilla.org/process/util;1"].
|
_shProc = Components.classes["@mozilla.org/process/util;1"].
|
||||||
createInstance(Components.interfaces.nsIProcess);
|
createInstance(Components.interfaces.nsIProcess);
|
||||||
_shProc.init(sh);
|
_shProc.init(sh);
|
||||||
|
|
||||||
|
_initializePipeStreamPump();
|
||||||
|
} else if(_pipeMode === "deferredOpen") {
|
||||||
|
_initializePipeStreamPump();
|
||||||
|
} else if(_pipeMode === "fx36thread") {
|
||||||
|
var main = Components.classes["@mozilla.org/thread-manager;1"].getService().mainThread;
|
||||||
|
var background = Components.classes["@mozilla.org/thread-manager;1"].getService().newThread(0);
|
||||||
|
|
||||||
|
function mainThread(agent, cmd, doc) {
|
||||||
|
this.agent = agent;
|
||||||
|
this.cmd = cmd;
|
||||||
|
this.document = doc;
|
||||||
|
}
|
||||||
|
mainThread.prototype.run = function() {
|
||||||
|
Zotero.Integration.execCommand(this.agent, this.cmd, this.document);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fifoThread() {}
|
||||||
|
fifoThread.prototype.run = function() {
|
||||||
|
var fifoStream = Components.classes["@mozilla.org/network/file-input-stream;1"].
|
||||||
|
createInstance(Components.interfaces.nsIFileInputStream);
|
||||||
|
var line = {};
|
||||||
|
while(true) {
|
||||||
|
fifoStream.QueryInterface(Components.interfaces.nsIFileInputStream);
|
||||||
|
fifoStream.init(_fifoFile, -1, 0, 0);
|
||||||
|
fifoStream.QueryInterface(Components.interfaces.nsILineInputStream);
|
||||||
|
fifoStream.readLine(line);
|
||||||
|
fifoStream.close();
|
||||||
|
|
||||||
|
var parts = line.value.split(" ");
|
||||||
|
var agent = parts[0];
|
||||||
|
var cmd = parts[1];
|
||||||
|
var document = parts.length >= 3 ? line.value.substr(agent.length+cmd.length+2) : null;
|
||||||
|
if(agent == "Zotero" && cmd == "shutdown") return;
|
||||||
|
main.dispatch(new mainThread(agent, cmd, document), background.DISPATCH_NORMAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fifoThread.prototype.QueryInterface = mainThread.prototype.QueryInterface = function(iid) {
|
||||||
|
if (iid.equals(Components.interfaces.nsIRunnable) ||
|
||||||
|
iid.equals(Components.interfaces.nsISupports)) return this;
|
||||||
|
throw Components.results.NS_ERROR_NO_INTERFACE;
|
||||||
|
}
|
||||||
|
|
||||||
|
background.dispatch(new fifoThread(), background.DISPATCH_NORMAL);
|
||||||
|
} else if(_pipeMode === "fx4thread") {
|
||||||
|
Components.utils.import("resource://gre/modules/ctypes.jsm");
|
||||||
|
|
||||||
|
// get possible names for libc
|
||||||
|
if(Zotero.isMac) {
|
||||||
|
var possibleLibcs = ["/usr/lib/libc.dylib"];
|
||||||
|
} else {
|
||||||
|
var possibleLibcs = [
|
||||||
|
"libc.so.6",
|
||||||
|
"libc.so.6.1",
|
||||||
|
"libc.so"
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// try all possibilities
|
||||||
|
while(possibleLibcs.length) {
|
||||||
|
var libc = possibleLibcs.shift();
|
||||||
|
try {
|
||||||
|
var lib = ctypes.open(libc);
|
||||||
|
break;
|
||||||
|
} catch(e) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// throw appropriate error on failure
|
||||||
|
if(!lib) {
|
||||||
|
throw "libc could not be loaded. Please post on the Zotero Forums so we can add "+
|
||||||
|
"support for your operating system.";
|
||||||
|
}
|
||||||
|
|
||||||
|
// int mkfifo(const char *path, mode_t mode);
|
||||||
|
var mkfifo = lib.declare("mkfifo", ctypes.default_abi, ctypes.int, ctypes.char.ptr, ctypes.unsigned_int);
|
||||||
|
|
||||||
|
// make pipe
|
||||||
|
var ret = mkfifo(_fifoFile.path, 0600);
|
||||||
|
if(!_fifoFile.exists()) return false;
|
||||||
|
lib.close();
|
||||||
|
|
||||||
|
// set up worker
|
||||||
|
var worker = Components.classes["@mozilla.org/threads/workerfactory;1"]
|
||||||
|
.createInstance(Components.interfaces.nsIWorkerFactory)
|
||||||
|
.newChromeWorker("chrome://zotero/content/xpcom/integration_worker.js");
|
||||||
|
worker.onmessage = function(event) {
|
||||||
|
if(event.data[0] == "Exception") {
|
||||||
|
throw event.data[1];
|
||||||
|
} else if(event.data[0] == "Debug") {
|
||||||
|
Zotero.debug(event.data[1]);
|
||||||
|
} else {
|
||||||
|
Zotero.Integration.execCommand(event.data[0], event.data[1], event.data[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
worker.postMessage({"path":_fifoFile.path, "libc":libc});
|
||||||
}
|
}
|
||||||
|
|
||||||
_initializePipeStreamPump();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,7 +557,7 @@ Zotero.Integration = new function() {
|
||||||
oStream.write(cmd, cmd.length);
|
oStream.write(cmd, cmd.length);
|
||||||
oStream.close();
|
oStream.close();
|
||||||
_fifoFile.remove(false);
|
_fifoFile.remove(false);
|
||||||
if(!__useDeferredOpenForIntegrationPipe) _tmpFile.remove(false);
|
if(_pipeMode === "subprocess") _tmpFile.remove(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
72
chrome/content/zotero/xpcom/integration_worker.js
Normal file
72
chrome/content/zotero/xpcom/integration_worker.js
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
***** BEGIN LICENSE BLOCK *****
|
||||||
|
|
||||||
|
Copyright © 2009 Center for History and New Media
|
||||||
|
George Mason University, Fairfax, Virginia, USA
|
||||||
|
http://zotero.org
|
||||||
|
|
||||||
|
This file is part of Zotero.
|
||||||
|
|
||||||
|
Zotero is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Zotero 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Zotero. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
***** END LICENSE BLOCK *****
|
||||||
|
*/
|
||||||
|
|
||||||
|
onmessage = function(event) {
|
||||||
|
var path = event.data.path;
|
||||||
|
|
||||||
|
// ctypes declarations follow
|
||||||
|
var lib = ctypes.open(event.data.libc);
|
||||||
|
|
||||||
|
// int open(const char *path, int oflag, ...);
|
||||||
|
var open = lib.declare("open", ctypes.default_abi, ctypes.int, ctypes.char.ptr, ctypes.int);
|
||||||
|
|
||||||
|
// ssize_t read(int fildes, void *buf, size_t nbyte);
|
||||||
|
var read = lib.declare("read", ctypes.default_abi, ctypes.ssize_t, ctypes.int,
|
||||||
|
ctypes.char.ptr, ctypes.size_t);
|
||||||
|
|
||||||
|
// int close(int fildes);
|
||||||
|
var close = lib.declare("close", ctypes.default_abi, ctypes.int, ctypes.int);
|
||||||
|
|
||||||
|
// define buffer for reading from fifo
|
||||||
|
const BUFFER_SIZE = 4096;
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
var buf = ctypes.char.array(BUFFER_SIZE)("");
|
||||||
|
|
||||||
|
// open fifo (this will block until something writes to it)
|
||||||
|
var fd = open(path, 0);
|
||||||
|
|
||||||
|
// read from fifo and close it
|
||||||
|
read(fd, buf, BUFFER_SIZE-1);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
// extract message
|
||||||
|
var string = buf.readString();
|
||||||
|
var parts = string.match(/^([^ \n]*) ([^ \n]*)(?: ([^\n]*))?\n?$/);
|
||||||
|
if(!parts) {
|
||||||
|
postMessage(["Exception", "Integration Worker: Invalid input received: "+string]);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var agent = parts[1].toString();
|
||||||
|
var cmd = parts[2].toString();
|
||||||
|
var document = parts[3] ? parts[3] : null;
|
||||||
|
if(agent == "Zotero" && cmd == "shutdown") {
|
||||||
|
postMessage(["Debug", "Integration Worker: Shutting down"]);
|
||||||
|
lib.close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
postMessage([agent, cmd, document]);
|
||||||
|
}
|
||||||
|
};
|
Loading…
Add table
Add a link
Reference in a new issue