我正在尝试在我的扩展中获取 Firefox 命令行的参数:
'firefox.exe -viewapp url -another-command -blablala:somedata'
还有这里我找到了一个例子
但我不明白如何在浏览器首次启动时获取所有参数。 我需要在网络控制台中显示它,如下所示:
console.log(commandLine.arguments)
// -viewapp url -another-command -blablala:somedata
请帮忙
我发现你只是想看看它是用什么命令行参数启动的。我知道一个 js-ctypes 解决方案。这将需要您为不同的平台编写代码。这是一个开始,它为您提供了 Windows 和 Mac 上的参数。我还没做linux部分:
Cu.import('resource://gre/modules/osfile.jsm');
Cu.import('resource://gre/modules/ctypes.jsm');
var lib
var osname = OS.Constants.Sys.Name.toLowerCase();
if (osname.indexOf('win') === 0) {
// windows
lib = ctypes.open('kernel32');
var GetCommandLineW = lib.declare('GetCommandLineW', ctypes.winapi_abi, ctypes.jschar.ptr);
var rez = GetCommandLineW();
console.log('rez:', rez.readString());
} else if (osname == 'darwin') {
// mac
lib = ctypes.open(ctypes.libraryName('objc'));
// BASIC TYPES
var BOOL = ctypes.signed_char;
var NSUINTEGER = ctypes.unsigned_long;
// COMMON FUNCTIONS
var objc_getClass = lib.declare('objc_getClass', ctypes.default_abi, ctypes.voidptr_t, ctypes.char.ptr);
var objc_msgSend = lib.declare('objc_msgSend', ctypes.default_abi, ctypes.voidptr_t, ctypes.voidptr_t, ctypes.voidptr_t, '...');
var sel_registerName = lib.declare('sel_registerName', ctypes.default_abi, ctypes.voidptr_t, ctypes.char.ptr);
// current_application = [NSRunningApplication currentApplciation];
var NSProcessInfo = objc_getClass('NSProcessInfo');
var processInfo = sel_registerName('processInfo');
var process_info = objc_msgSend(NSProcessInfo, processInfo);
// bundle_identifier = [current_application bundleIdentifier]
var arguments = sel_registerName('arguments');
var args = objc_msgSend(process_info, arguments);
var count = sel_registerName('count');
var _count = objc_msgSend(args, count);
console.info('_count:', _count, _count.toString(), uneval(_count), parseInt(_count));
// make it into a js number
_count = parseInt(ctypes.cast(_count, NSUINTEGER).value);
console.log('_count:', _count);
var objectAtIndex = sel_registerName('objectAtIndex:'); // used in for loop
var UTF8String = sel_registerName('UTF8String'); // used in for loop
for (var i=0; i<_count; i++) {
var arg = objc_msgSend(args, objectAtIndex, NSUINTEGER(i)); // must wrap `i` in NSUINTEGER as its variadic, you have to specify the type. this is specific to js-ctypes
var argString = ctypes.cast(objc_msgSend(arg, UTF8String), ctypes.char.ptr);
console.log('arg "' + i + '":', argString.readStringReplaceMalformed(), 'arg:', arg, arg.toString(), uneval(arg));
}
} else {
// *nix
// todo
// per - http://stackoverflow.com/a/821889/1828637
var libcPaths = ['libc.so', 'libc.so.7', 'libc.so.61.0', 'libc.so.6', 'libc.so.0.1', 'libc.dylib'];
for (var i=0; i<libcPaths.length; i++) {
try {
lib = ctypes.open(libcPaths[i]);
break;
} catch(ignore) {}
}
if (!lib) {
throw new Error('failed to find libc on this system');
}
var popen = lib.declare('popen', ctypes.default_abi, ctypes.voidptr_t, ctypes.char.ptr, ctypes.char.ptr);
var fread = lib.declare('fread', ctypes.default_abi, ctypes.size_t, ctypes.voidptr_t, ctypes.size_t, ctypes.size_t, ctypes.voidptr_t);
var feof = lib.declare('feof', ctypes.default_abi, ctypes.int, ctypes.voidptr_t);
var pclose = lib.declare('pclose', ctypes.default_abi, ctypes.int, ctypes.voidptr_t);
var getpid = lib.declare('getpid', ctypes.default_abi, ctypes.int32_t);
// ps -fp 2540
var pid = getpid();
var file = popen('ps -ww -fp' + pid, 'r');
var buf = ctypes.char.array(100)();
var jsbuf = [];
var reachedEof = false;
while (!reachedEof) {
var cnt = fread(buf, 1, buf.length * buf.constructor.elementType.size, file);
cnt = parseInt(cnt);
if (cnt > 0) {
jsbuf.push(buf.readString().substring(0, cnt));
}
reachedEof = feof(file);
}
var closeit = pclose(file);
console.log('closeit:', closeit);
console.log('jsbuf:', jsbuf.join(''));
}
lib.close();
这是一个非常简单的插件,可以做到这一点:
https://github.com/Noitidart/Restore--remote/blob/master/bootstrap.js
这里的这个插件是一个引导程序(所以无需重新启动 - 这很好)插件。所以如果你使用 SDK,你就必须接触底层的东西。它也不需要像您链接到的 MDN 上的 chrome.manifest 文件。
这是市场上的插件 - https://addons.mozilla.org/en-US/firefox/addon/restore-remote/
这是代码:
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cm = Components.manager;
const Cu = Components.utils;
const Cr = Components.results;
Cm.QueryInterface(Ci.nsIComponentRegistrar);
Cu.import('resource://gre/modules/XPCOMUtils.jsm');
Cu.import('resource://gre/modules/Services.jsm');
Cu.import('resource://gre/modules/Preferences.jsm');
function RemoteCommandLine(target, url, cl) {
this._target = target;
this._url = url;
this._cl = cl;
}
RemoteCommandLine.prototype = {
get preventDefault() {
return this._cl.preventDefault;
},
set preventDefault(value) {
this._cl.preventDefault = value;
},
handleFlag: function(flag, caseSensitive) {
return false;
},
handleFlagWithParam: function(flag, caseSensitive) {
if (!(flag == 'new-tab' && this._target == Ci.nsIBrowserDOMWindow.OPEN_NEWTAB) &&
!(flag == 'new-window' && this._target == Ci.nsIBrowserDOMWindow.OPEN_NEWWINDOW))
return null;
var url = this._url;
this._url = null;
return url
},
resolveURI: function(url) {
return this._cl.resolveURI(url);
},
};
function Remote() {}
Remote.prototype = {
QueryInterface: XPCOMUtils.generateQI([Ci.nsICommandLineHandler]),
classDescription: 'remote',
classID: Components.ID('{1280e159-cac2-4188-af5a-e6089527b7b8}'),
contractID: '@mozilla.org/commandlinehandler/general-startup;1?type=remote',
handle: function(cmdLine)
{
try {
var remoteCommand = cmdLine.handleFlagWithParam("remote", true);
}
catch (e) {
throw Cr.NS_ERROR_ABORT;
}
if (remoteCommand != null) {
try {
var a = /^\s*(\w+)\(([^\)]*)\)\s*$/.exec(remoteCommand);
var remoteVerb;
if (a) {
remoteVerb = a[1].toLowerCase();
var remoteParams = [];
var sepIndex = a[2].lastIndexOf(",");
if (sepIndex == -1)
remoteParams[0] = a[2];
else {
remoteParams[0] = a[2].substring(0, sepIndex);
remoteParams[1] = a[2].substring(sepIndex + 1);
}
}
switch (remoteVerb) {
case "openurl":
case "openfile":
// openURL(<url>)
// openURL(<url>,new-window)
// openURL(<url>,new-tab)
// First param is the URL, second param (if present) is the "target"
// (tab, window)
var url = remoteParams[0];
var target = Ci.nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW;
if (remoteParams[1]) {
var targetParam = remoteParams[1].toLowerCase()
.replace(/^\s*|\s*$/g, "");
if (targetParam == "new-tab")
target = Ci.nsIBrowserDOMWindow.OPEN_NEWTAB;
else if (targetParam == "new-window")
target = Ci.nsIBrowserDOMWindow.OPEN_NEWWINDOW;
else {
// The "target" param isn't one of our supported values, so
// assume it's part of a URL that contains commas.
url += "," + remoteParams[1];
}
}
if (target == Ci.nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW) {
target = Preferences.get('browser.link.open_newwindow',
Ci.nsIBrowserDOMWindow.OPEN_NEWTAB);
}
var clh = Cc['@mozilla.org/browser/clh;1'].getService(Ci.nsICommandLineHandler);
clh.handle(new RemoteCommandLine(target, url, cmdLine));
break;
case "ping":
break;
default:
// Somebody sent us a remote command we don't know how to process:
// just abort.
throw "Unknown remote command.";
}
cmdLine.preventDefault = true;
}
catch (e) {
Components.utils.reportError(e);
// If we had a -remote flag but failed to process it, throw
// NS_ERROR_ABORT so that the xremote code knows to return a failure
// back to the handling code.
throw Cr.NS_ERROR_ABORT;
}
}
},
};
const RemoteFactory = XPCOMUtils.generateNSGetFactory([Remote])(Remote.prototype.classID);
function startup(aData, aReason) {
Cm.registerFactory(Remote.prototype.classID,
Remote.prototype.classDescription,
Remote.prototype.contractID,
RemoteFactory);
var catman = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
catman.addCategoryEntry('command-line-handler', 'l-remote', Remote.prototype.contractID, false, true);
}
function shutdown(aData, aReason) {
var catman = Cc["@mozilla.org/categorymanager;1"].getService(Ci.nsICategoryManager);
catman.deleteCategoryEntry('command-line-handler', 'l-remote', false);
Cm.unregisterFactory(Remote.prototype.classID, RemoteFactory);
}