Javascript 在Firefox加载项目录中选择一个文件

Javascript 在Firefox加载项目录中选择一个文件,javascript,firefox,firefox-addon,firefox-addon-sdk,Javascript,Firefox,Firefox Addon,Firefox Addon Sdk,为了简单起见,我正在将基于XUL的Firefox插件转换为基于SDK的版本。我在基于XUL的版本中使用的XPCOM模块似乎可以工作,但ci.nsIFile的行为有所不同 我不知道如何导航到smartProxy.py,它当前位于目录的最高级别 在XUL版本中,smartProxy.py位于chrome/bin/smartProxy.py上。我使用下面的命令来执行程序,它可以正常工作 getExeFile: function() { var file = cc["@mozilla.org/f

为了简单起见,我正在将基于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");
    return file;
},
下面是它的执行位置,它应该给出插件如何工作的完整图片

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以便执行它?

嘿,伙计,我刚刚在sdk上查找了一些东西。不要在install.rdf中解包,因为上面提到了这些性能问题。取而代之的是把它放在你的数据文件夹里。而不是像这样访问它:


目前仅NSIProcessAPI支持从Firefox运行外部命令。你已经为自己找到了这一点

打包python脚本。 SDK将仅打包某些文件/位置。将python脚本放在data/文件夹中是最容易的,因为这是SDK打包所有文件的位置之一

NSI过程 nsIProcess需要一个可执行文件,而该文件实际上需要是一个真实的文件,而不仅仅是XPI中包含的东西,默认情况下XPI是不解压缩的

因此,我们可能需要处理两种情况:

文件是一个真实的文件-只需执行它。 文件已打包-需要将数据提取/复制到临时真实文件中并执行该文件。 下面的代码处理这两个问题。我在OSX*nix上进行了测试,它对我有效,所以应该在Linux或BSD以及Windows上工作,无论是否使用em:unpack,您都应该避免使用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);
运行脚本 运行一个脚本而不是一个完整的二进制文件可能很棘手。对于Python,例如*nix操作系统需要被告知有解释器以及解释器是什么,解释器是由解释器完成的。
在Windows上,Python需要与.py文件类型注册一起安装,默认安装程序会这样做,但不是可移植版本。

到底什么不起作用?reutnred文件是否没有到smartProxy.py的正确路径?这就是您所说的“无法理解如何导航到smartyProxy.py”的意思吗?smartyProxy.py位于direcotry的最高级别?尝试:Cu.importresource://gre/modules/FileUtils.jsm; var py=FileUtils.getFile'ProfD',['extensions','smartProxy.py'];什么不起作用:它正在导航到一个不是我的扩展名的文件夹。它甚至似乎与firefox没有关联。我尝试了您的解决方案,但它没有按照我的预期工作,所以我检查了py.path并导航到它。我发现我的扩展被打包为.xpi。实际的文件夹和资源不在那里。我可以把它拆开,但这不是一个适合生产的解决方案。哦,哇,真奇怪。这个文件有你的扩展名吗?如果这是真的,那么您的扩展是xpi,而不是文件夹。如果你想导航到你的文件夹扩展名,我不知道如何使用sdk,但它肯定不是文件夹,而是xpi。除非你在install.rdf中将unpack设置为true?我知道了!非常感谢。在SDK中,他们使用package.json生成install.rdf。他们允许您将unpack设置为true,但由于性能问题,他们没有将其放在文档中。var file=FileUtils.getFile'ProfD',['extensions','jid1-xS8bcmiRpHSixA@jetpack“,”资源“,”我的插件“,”smartProxy.py];现在,我只需要找出如何阻止SDK在编译smartProxy.py时删除smartProxy.py,并进行测试,看看是什么影响jid1的名称-xS8bcmiRpHSixA@jetpack. 如果版本号经常改变,我可能需要编写一个自动处理连续性的脚本。这是防止编译器从包中删除smartProxy的一个好方法,但是如果不使用nsIProcess(我认为需要nsIProcess文件),我如何运行它?即使它是一个可执行文件或不需要命令行运行的东西,我也看不到任何通过self执行它的方法。它适用于HTML,因为它有面板API来显示itIt。它可以完美地防止SDK删除它。我建议使用NetUtils并将文件复制到ProfD文件夹,卸载插件时确保删除该文件。或者使用netutils通过文件输入流读取它,然后通过文件输出流将它发送到进程,这种方式实际上是一种有趣的方式,我会从中学到很多。发布一个主题我们可以在论坛上找到一些专家的答案,我很有兴趣看到这个答案。虽然这个答案本身并没有错,但它实际上并没有试图回答手头的实际问题,即如何运行XPI中包含的文件,还有一个子问题,为什么SDK不在XPI.depth中打包.py文件!我有一个想法。有没有可能再包装一份
source://在新的FileUtils.File中?就像这个例子一样,var py=new FileUtils.Fileself.data.url'module/script.py'然后在process.run中使用它?如何很好地表达它:不Dlolol:好的,谢谢你的好家伙:P给进程提供一个fileOutputStream,而不是制作文件的副本怎么样?与ostream.initfile、-1、-1、Ci.nsIFileOutputStream.DEFER_打开后类似;我们可以跳过asyncCopy并以某种方式提供流?这太棒了!谢谢我最终让它工作了,但这是一个更好的方法。
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);