在Firefox附件目录中选择一个文件 [英] Select A File Within Firefox Add-On Directory

查看:196
本文介绍了在Firefox附件目录中选择一个文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为了简单起见,我将基于XUL的Firefox插件转换为基于SDK的版本。我在基于XUL的版本中使用的XPCOM模块似乎工作,但ci.nsIFile行为有所不同。



我无法弄清楚如何导航到smartProxy.py目前位于目录的最高级别。



在XUL版本中,smartProxy.py位于chrome / bin / smartproxy.py中。

  getExeFile:function(){
var file = cc [@ mozilla.org/file/directory_service;1\"].getService(ci.nsIProperties).get(\"ProfD,ci.nsIFile);
file.append(smartProxy.py);
返回文件;



$ b $ p
$ b

下面是执行的地方,它应该给出附加工作。

  start:function(){
if(this.process&& this。 process.isRunning)
return;
this.process = cc [@ mozilla.org/process/util;1\"].createInstance(ci.nsIProcess);
this.process.init(this.getExeFile());
this.process.runAsync([],0,this.processObserver);
this.setProxy();
this.executeObservers();
},

如何查找smartProxy.py以便执行?

解决方案

现在只能从 nsIProcess API。你已经知道了这一点。



打包python脚本。



SDK将只打包文件/位置。将python脚本放在 data / 文件夹中是最简单的,因为这是SDK打包所有文件的位置之一。



$ h $ $ ns

$ ns
$ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $'是一个真正的文件(不只是包含在XPI中的东西,默认情况下是不解压的)。



所以有两种情况我们可能要处理:


  1. 文件是一个真正的文件 - 只需执行它。

  2. 文件打包 - 需要提取/数据转换为(临时)实际文件并执行。

以下代码处理两者。我测试过,它适用于我OSX(* nix,所以应该在Linux或BSD上)以及Windows,有和没有EM:解压(你应该避免EM:解压缩)。

  const self = require(sdk / self); 

const {Cc,Ci,Cu} = require(chrome);

Cu.import(resource://gre/modules/Services.jsm);
Cu.import(resource://gre/modules/NetUtil.jsm);

const ChromeRegistry = Cc [@ mozilla.org/chrome/chrome-registry; 1]。
getService(Ci.nsIChromeRegistry);
const ResProtoHandler = Services.io.getProtocolHandler(resource)。
QueryInterface(Ci.nsIResProtocolHandler);

函数copyToTemp(uri,callback){
//基于https://stackoverflow.com/a/24850643/484441
let file = Services.dirsvc.get TmpD,Ci.nsIFile);
file.append(self.name +_+ uri.spec.replace(/^.+ \ //,));
file.createUnique(Ci.nsIFile,0o0700);
NetUtil.asyncFetch(uri,function(istream){
let ostream = Cc [@ mozilla.org/network/file-output-stream; 1]。
createInstance(Ci。 nsifileOutputStream);
ostream.init(file,-1,-1,Ci.nsIFileOutputStream.DEFER_OPEN);
NetUtil.asyncCopy(istream,ostream,function(result){
callback& & callback(file,result);
});
});


function runProcessAndThen(file,callback){
console.log(running,file.path);

let proc = Cc [@ mozilla.org/process/util;1\"].createInstance(Ci.nsIProcess);
尝试{
//在unix上设置可执行位
file.permissions = file.permissions | 0o0500;
}
catch(ex){
//可能会丢?
}
proc.init(file);
proc.runAsync([],0,callback);


函数runFromURIWithPotentialCopy(uri,callback){
if(!uri.spec){
uri = Services.io.newURI(uri,null,null );

if(uri.scheme ===resource){
//需要进一步解析。剥去间接的一层,递归
//自己调用。
uri = Services.io.newURI(ResProtoHandler.resolveURI(uri),null,null);
return runFromURIWithPotentialCopy(uri,callback);
}

if(uri.scheme ===chrome){
//需要进一步解析。剥去间接的一层,递归
//自己调用。
return runFromURIWithPotentialCopy(ChromeRegistry.convertChromeURL(uri),callback);


if(ui instanceof Ci.nsIFileURL){
//我们可以直接执行一个纯文件。
return runProcessAndThen(uri.file,callback);


if(ui instanceof Ci.nsIJARURI){
//打包文件(最有可能是XPI)。
//需要将数据复制到一些纯文件并运行结果。
return copyToTemp(uri,function(f){
runProcessAndThen(f,function(){
try {
//自行清理
f.remove (false);
}
catch(ex){
console.error(无法再次删除tmp文件,例如);
}
callback.apply (null,arguments);
});
});
}

抛出错误(无法处理URI);


函数afterRun(主题,主题,数据){
console.log(subject,topic,data);


函数runFileFromDataDirectory(name,callback){
try {
runFromURIWithPotentialCopy(self.data.url(name),callback);
}
catch(ex){
console.error(ex);



runFileFromDataDirectory(test.py,afterRun);



运行脚本



运行脚本(而不是一个完整的二进制)可能会非常棘手。在Python的情况下,例如* nix操作系统需要被告知有一个解释器和这是什么,这是由 shebang 完成的。
在Windows上,Python需要安装 .py 文件类型注册,这是默认的安装程序所能做的,但不是可移植的版本。 >

I'm converting an XUL-based Firefox add-on to an SDK based version for simplicity. The XPCOM modules I use in the XUL-based version seem to work but ci.nsIFile is behaving differently.

I can't figure out how to navigate to smartProxy.py which currently sits on the highest level of the directory.

In the XUL version smartProxy.py sits on chrome/bin/smartproxy.py. I use the commands below to execute the program and it works without error.

getExeFile: function() {
    var file = cc["@mozilla.org/file/directory_service;1"].getService(ci.nsIProperties).get("ProfD", ci.nsIFile);
    file.append("smartProxy.py");
    return file;
},

This below is where it's executed which should give a full picture of how the add-on works.

start: function() {
    if (this.process && this.process.isRunning)
        return;
    this.process = cc["@mozilla.org/process/util;1"].createInstance(ci.nsIProcess);
    this.process.init(this.getExeFile());
    this.process.runAsync([], 0, this.processObserver);
    this.setProxy();
    this.executeObservers();
},

How do I go about finding smartProxy.py so that it can be executed?

解决方案

Running an external command from Firefox right now is only supported with the nsIProcess API. You figured out this bit for yourself already.

Packaging a python script.

The SDK will only package certain files/locations. It would be easiest to just place the python script in the data/ folder, because that is one of the locations the SDK will package all files from.

nsIProcess

nsIProcess needs an executable file, and that file actually needs to be a real file (not just something contained within the XPI, which by default is not unpacked).

So there are two cases we might want to handle:

  1. File is a real file - Just execute it.
  2. File is packaged - Need to extract/copy the data into a (temporary) real file and execute that.

The following code deals with both. I tested and it works for me on OSX (*nix, so should work on Linux or BSDs as well) and Windows, with and without em:unpack (and you should avoid em:unpack).

const self = require("sdk/self");

const {Cc, Ci, Cu} = require("chrome");

Cu.import("resource://gre/modules/Services.jsm");
Cu.import("resource://gre/modules/NetUtil.jsm");

const ChromeRegistry = Cc["@mozilla.org/chrome/chrome-registry;1"].
                       getService(Ci.nsIChromeRegistry);
const ResProtoHandler = Services.io.getProtocolHandler("resource").
                        QueryInterface(Ci.nsIResProtocolHandler);

function copyToTemp(uri, callback) {
  // Based on https://stackoverflow.com/a/24850643/484441
  let file = Services.dirsvc.get("TmpD", Ci.nsIFile);
  file.append(self.name + "_" + uri.spec.replace(/^.+\//, ""));
  file.createUnique(Ci.nsIFile, 0o0700);
  NetUtil.asyncFetch(uri, function(istream) {
    let ostream = Cc["@mozilla.org/network/file-output-stream;1"].
                  createInstance(Ci.nsIFileOutputStream);
    ostream.init(file, -1, -1, Ci.nsIFileOutputStream.DEFER_OPEN);
    NetUtil.asyncCopy(istream, ostream, function(result) {
      callback && callback(file, result);
    });
  });
}

function runProcessAndThen(file, callback) {
  console.log("running", file.path);

  let proc = Cc["@mozilla.org/process/util;1"].createInstance(Ci.nsIProcess);
  try {
    // Set executable bit on unix
    file.permissions = file.permissions | 0o0500;
  }
  catch (ex) {
    // Might throw?!
  }
  proc.init(file);
  proc.runAsync([], 0, callback);
}

function runFromURIWithPotentialCopy(uri, callback) {
  if (!uri.spec) {
    uri = Services.io.newURI(uri, null, null);
  }
  if (uri.scheme === "resource") {
    // Need to resolve futher. Strip one layer of indirection and recursively
    // call ourselves.
    uri = Services.io.newURI(ResProtoHandler.resolveURI(uri), null, null);
    return runFromURIWithPotentialCopy(uri, callback);
  }

  if (uri.scheme === "chrome") {
    // Need to resolve futher. Strip one layer of indirection and recursively
    // call ourselves.
    return runFromURIWithPotentialCopy(ChromeRegistry.convertChromeURL(uri), callback);
  }

  if (uri instanceof Ci.nsIFileURL) {
    // A plain file we can execute directly.
    return runProcessAndThen(uri.file, callback);
  }

  if (uri instanceof Ci.nsIJARURI) {
    // A packaged file (in an XPI most likely).
    // Need to copy the data into some plain file and run the result.
    return copyToTemp(uri, function(f) {
      runProcessAndThen(f, function() {
        try {
          // Clean up after ourselves.
          f.remove(false);
        }
        catch (ex) {
          console.error("Failed to remove tmp file again", ex);
        }
        callback.apply(null, arguments);
      });
    });
  }

  throw new Error("Cannot handle URI");
}

function afterRun(subject, topic, data) {
  console.log(subject, topic, data);
}

function runFileFromDataDirectory(name, callback) {
  try {
    runFromURIWithPotentialCopy(self.data.url(name), callback);
  }
  catch (ex) {
    console.error(ex);
  }
}

runFileFromDataDirectory("test.py", afterRun);

Running a script

Running a script (as opposed to a full-blown binary) can be tricky. In case of Python e.g. the *nix OSes needs to be told that there is an interpreter and what this is, which is done by a shebang. On Windows, Python needs to be installed with .py file type registration, which the default installer will do, but not "portable" versions".

这篇关于在Firefox附件目录中选择一个文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆