使用Firefox扩展将文件写入到网页 [英] Expose file writing to a webpage with a Firefox extension

查看:146
本文介绍了使用Firefox扩展将文件写入到网页的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的客户端使用的是一个Web应用程序,用于存储注册表。
我需要做的是创建一个本地文件,因为收银软件需要从该文件读取以便打印。



到现在为止我是使用以下代码:

  netscape.security.PrivilegeManager.enablePrivilege(UniversalXPConnect); 
var file = Components.classes [@ mozilla.org/file/local;1\"].createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(filePath);

不幸的是,最新版本的Firefox已经不能工作了,所以我被告知,添加到创建文件。我试图开发一个附加组件(不知道如果成功),我有main.js看起来像这样:



<$ ($文件)
$ {
如果(!文件)返回;
const unicodeConverter = Components.classes [@ mozilla.org/intl/scriptableunicodeconverter]
.createInstance(Components.interfaces.nsIScriptableUnicodeConverter);

unicodeConverter.charset =UTF-8;

Text = unicodeConverter.ConvertFromUnicode(Text);
const os = Components.classes [@ mozilla.org/network/file-output-stream; 1]
.createInstance(Components.interfaces.nsIFileOutputStream);
os.init(File,0x02 | 0x08 | 0x20,0700,0);
os.write(Text,Text.length);
os.close();
},

阅读:
函数(File)
{
if(!File)return;
var res;

const is = Components.classes [@ mozilla.org/network/file-input-stream; 1]
.createInstance(Components.interfaces.nsIFileInputStream);
const sis = Components.classes [@ mozilla.org/scriptableinputstream;1]
.createInstance(Components.interfaces.nsIScriptableInputStream);
is.init(File,0x01,0400,null);
sis.init(is);

res = sis.read(sis.available());

is.close();

return res;
},
};

任何想法我应该如何使用main.js?在附件安装后找到它?
我需要使用像这样的东西:FileManager.Write(path,text)。

解决方案

如果我正确理解你的问题,你有一个在Firefox中运行的POS应用程序通过HTTP与某种本地网络服务器通信。您应用程序的客户端JavaScript需要能够读取&从浏览器PC的本地文件系统写入文件。

如果这是正确的,那么你可以这样做,如下所示。您需要创建一个Firefox插件,其中最简单的一种叫做bootstrapped(或restartless)插件。




无重启的插件由两个文件组成:


  • bootstrap.js(包含您的特权代码的JavaScript文件)
  • install.rdf(描述您的插件到Firefrox的XML文件)


  • 要构建插件,只需将两个文件放在ZIP文件的顶层(无文件夹!)中,文件扩展名为的.xpi 。要安装插件,请导航至 about:addons ,然后从工具菜单中,单击从文件安装,找到您的XPI ,打开它,然后短暂的延迟选择安装






    install.rdf 中加入如下内容:

     < xml version =1.0?> 
    xmlns:em =http://www.mozilla。组织/ 2004 / EM-RDF#>
    <描述about =urn:mozilla:install-manifest>
    < em:id> youraddonname @ yourdomain< / em:id>
    < em:type> 2< / em:type>
    < em:name>插件名称< / em:name>
    < em:version> 1.0< / em:version>
    < em:bootstrap> true< / em:bootstrap>
    < em:description>描述您的插件。< / em:description>
    < em:creator>您的名字< / em:creator>

    <! - Firefox桌面 - >
    < em:targetApplication>
    <说明>
    < em:id> {ec8030f7-c20a-464f-9b0e-13a3a9e97384}< / em:id>
    < em:minVersion> 4.0。*< / em:minVersion>
    < em:maxVersion> 29.0。*< / em:maxVersion>
    < /说明>
    < / em:targetApplication>
    < /说明>
    < / RDF>






    您需要在 bootstrap.js


    • code> - 当你安装插件时,以及你的浏览器启动时调用。
    • shutdown()你卸载插件,当你的浏览器关闭。



    您应该在<$ c中调用剩下的特权 $ C>启动()。为了卫生,你可以(也可能应该)执行 install() uninstall()函数。 >

    首先在 bootstrap.js 中执行以下代码:

      const Cc = Components.classes; 
    const Ci = Components.interfaces;
    让consoleService = Cc [@ mozilla.org/consoleservice;1]
    .getService(Ci.nsIConsoleService);
    let wm = Cc [@ mozilla.org/appshell/window-mediator;1]
    .getService(Ci.nsIWindowMediator);

    函数LOG(msg){
    consoleService.logStringMessage(EXTENSION:+ msg);


    函数启动(){
    尝试{
    LOG(正在启动...);
    let windows = wm.getEnumerator(navigator:browser);
    while(windows.hasMoreElements()){
    let chromeWindow = windows.getNext()。QueryInterface(Ci.nsIDOMWindow);
    WindowListener.setupBrowserUI(chromeWindow);
    }
    wm.addListener(WindowListener);
    LOG(完成启动);
    } catch(e){
    LOG(error starting:+ e);



    函数shutdown(){
    try {
    LOG(shutting down ...);
    let windows = wm.getEnumerator(navigator:browser);
    while(windows.hasMoreElements()){
    let chromeWindow = windows.getNext()。QueryInterface(Ci.nsIDOMWindow);
    WindowListener.tearDownBrowserUI(chromeWindow);
    }
    wm.addListener(WindowListener);
    LOG(done shutdown。);
    } catch(e){
    LOG(error shutting down:+ e);




    $ b $ p
    $ b基本上,调用 WindowListener .setupBrowserUI()为每个当前&你的网页浏览器的未来窗口。 WindowListener 定义如下:

      var WindowListener = {
    setupBrowserUI:function(chromeWindow){
    chromeWindow.gBrowser.addEventListener('load',my_load_handler,true);

    tearDownBrowserUI:function(chromeWindow){
    chromeWindow.gBrowser.removeEventListener('load',my_load_handler,true);
    },
    onOpenWindow:function(xulWindow){
    let chromeWindow = xulWindow.QueryInterface(Ci.nsIInterfaceRequestor)
    .getInterface(Ci.nsIDOMWindow);
    chromeWindow.addEventListener(load,function listener(){
    chromeWindow.removeEventListener(load,listener,false);
    var domDocument = chromeWindow.document.documentElement; $ b $ (windowType ==navigator:browser)
    WindowListener.setupBrowserUI(chromeWindow);
    },false);
    },
    onWindowTitleChange:function(chromeWindow,newTitle){}
    };

    OpenWindow 事件,然后为每个ChromeWindow的 TabBrowser 中的 load 事件安装一个事件侦听器。 load 事件处理程序的定义如下:
    $ b

      var my_load_handler = function evt){
    try {
    var browserEnumerator = wm.getEnumerator(navigator:browser);
    while(browserEnumerator.hasMoreElements()){
    var browserWin = browserEnumerator.getNext();
    var tabbrowser = browserWin.gBrowser;
    var numTabs = tabbrowser.browsers.length; (var index = 0; index< numTabs; index ++){
    var currentBrowser = tabbrowser.getBrowserAtIndex(index);
    var domWindow = currentBrowser.contentWindow.wrappedJSObject;
    //识别你的目标页面($)
    if(domWindow.location.href =='http:// yourserver / yourpage'){
    //安装特权方法(如果还没有)
    if(!domWindow.hasOwnProperty('__ my_priv_members__'){
    install_my_privileged_methods(browserWin,domWindow);
    }
    }
    }














    $

    通过检查 window.location.href 并调用 install_my_privileged_methods
    pre $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ >函数install_my_privileged_methods(chromeWindow,domWindow){
    install_privileged_method(chromeWindow,domWindow,'WriteFile',
    函数(priv){
    返回函数(File,Text,cb){
    priv.call([File,Text],函数(rstatus,rdata,rerror){
    如果(cb)cb(rstatus,rerror);
    });
    };
    },
    函数(chromeWindow,args,cb){
    var [File,Text] = args;
    if(!File)return cb(0,null,需要文件名);
    try {
    const unicodeConverter =
    Cc [@ mozilla.org/intl/scriptableunicodeconverter]
    .createInstance(Ci.nsIScriptableUnicodeConverter);
    unicodeConverter.charset =UTF-8;
    Text = unicodeConverter.ConvertFromUnicode(Text);
    const os = Cc [@ mozilla.org/network/file-output-stream;1]
    .createInstance(Ci.nsIFileOutputStream);
    os.init(File,0x02 | 0x08 | 0x20,0700,0);
    os.write(Text,Text.length);
    os.close();
    cb(1,null,null);
    } catch(e){
    cb(0,null,error writing file:+ e);
    }
    }
    );
    $ b install_privileged_method(chromeWindow,domWindow,'ReadFile',
    函数(priv){
    返回函数(File,cb){
    priv.call([File] ,函数(rstatus,rdata,rerror){
    if(cb)cb(rstatus,rdata,rerror);
    });
    };
    },
    函数(chromeWindow,args,cb){
    var [File] = args;
    if(!File)return cb(0,null,need a filename);
    try {
    const is = Cc [@ mozilla.org/network/file-input-stream; 1]
    .createInstance(Ci.nsIFileInputStream);
    const sis = Cc [@ mozilla。 org / scriptableinputstream; 1]
    .createInstance(Ci.nsIScriptableInputStream);
    is.init(File,0x01,0400,null);
    sis.init(is);
    $ var text = sis.read(sis.available());
    is.close();
    cb(1,Text,null);
    } catch(e){
    cb(0,null,读取文件错误:+ e);
    }
    }
    );
    }

    我没有测试这段代码。这是一个直接转换你上面写的东西...我会假设的工作!

    这增加了两个特殊的方法, WriteFile & ReadFile ,到选定的窗口对象。在您的Web应用程序的(非特权)JavaScript代码中,使用它们如下所示:

      var buffer ='...'; //要写入的文本
    window.WriteFile('C:\\\\\\\\\\\\\\\\\''',',buffer,function(ok,errmsg){
    如果(!ok)alert(errmsg);
    });
    $ b $ window.ReadFile('C:\\\\\\\\\\\\\\\\\\\'''),function(ok,buffer,errmsg){
    if(! OK)return alert(errmsg);
    //在这里使用缓冲区!
    });

    最后, install_privileged_method 定义为: / p>

      var install_privileged_method =(function(){
    var gensym =(function(){
    var __sym = 0;
    return function(){return'__sym _'+(__ sym ++);}
    ))();
    返回函数(chromeWindow,target,slot,handler,methodFactory){
    try {
    target .__ pmcache__ = target.hasOwnProperty('__ pmcache__')
    ?target .__ pmcache__
    :{ticket_no:0,callbacks:{},namespace:gensym()};
    target [slot] = methodFactory({call:function(fargs,fcb){
    try {
    var ticket_no = target .__ pmcache __。ticket_no ++;
    target .__ pmcache __。callbacks [ ticket_no] = fcb;
    var cevent = target.document.createEvent(CustomEvent);
    cevent.initCustomEvent(
    target .__ pmcache __。namespace +'。'+ slot,
    真的,真的,{fargs:farg s,ticket_no:ticket_no}
    );
    target.dispatchEvent(cevent);
    } catch(ue){
    fcb(0,null,'untrusted dispatcher error:'+ ue);
    }
    }});
    LOG(安装不受信任的调度程序的方法+ slot +'。);
    target.addEventListener(
    target .__ pmcache __。namespace +'。'+ slot,
    function(cevent){
    var ticket_no = cevent.detail.ticket_no;
    var (#)fargs = cevent.detail.fargs;
    var fcb = target .__ pmcache __。callbacks [ticket_no];
    try {
    handler(chromeWindow,fargs,fcb);
    } catch pe)​​{
    fcb(0,null,'特权处理程序错误:'+ pe);
    }
    },
    false,
    true
    ) ;
    LOG(方法安装的特权处理程序+ slot +'。);
    } catch(ie){
    LOG(错误安装处理程序/特权工厂+
    method+ slot +':+ ie);
    }
    };
    })();


    I have a web application that my client uses for the cash registry. What I need to do is to create a local file as the cash register's software needs to read from that file in order to print.

    Until now i was using this code:

    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
    var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
    file.initWithPath(filePath);
    

    Unfortunately with the latest version of firefox this isn't working anymore so I was told that i need and add-on to create the file.I've tried to develop an add-on(don't know if succesfully) and i have main.js looking like this :

    var FileManager =
    {
    Write:
        function (File, Text)
        {
            if (!File) return;
            const unicodeConverter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"]
                .createInstance(Components.interfaces.nsIScriptableUnicodeConverter);
    
            unicodeConverter.charset = "UTF-8";
    
            Text = unicodeConverter.ConvertFromUnicode(Text);
            const os = Components.classes["@mozilla.org/network/file-output-stream;1"]
              .createInstance(Components.interfaces.nsIFileOutputStream);
            os.init(File, 0x02 | 0x08 | 0x20, 0700, 0);
            os.write(Text, Text.length);
            os.close();
        },
    
    Read:
        function (File)
        {
            if (!File) return;
            var res;
    
            const is = Components.classes["@mozilla.org/network/file-input-stream;1"]
                .createInstance(Components.interfaces.nsIFileInputStream);
            const sis = Components.classes["@mozilla.org/scriptableinputstream;1"]
                .createInstance(Components.interfaces.nsIScriptableInputStream);
            is.init(File, 0x01, 0400, null);
            sis.init(is);
    
            res = sis.read(sis.available());
    
            is.close();
    
            return res;
        },
    }; 
    

    Any ideas how should I use main.js?Where I find it after the add-on is installed? I need to use something like this : FileManager.Write(path,text).

    解决方案

    Sorry about the super-late reply.

    If I understand your question correctly, you have a P.O.S application that runs in Firefox talking to some sort of local webserver via HTTP. The client-side JavaScript of your application needs to be able to read & write files from the local filesystem of the browser's PC.

    If that's correct, then you can do so as follows. You'll need to create a Firefox addon, the simpliest kind of which is called a "bootstrapped" (or "restartless") addon.


    A restartless addon consists of two files:

    • bootstrap.js (The JavaScript file containing your 'privileged' code)
    • install.rdf (an XML file describing your addon to Firefrox)

    To build the addon, simply place both files inside the top-level (no folders!) of a ZIP file with the file extension .xpi. To install the addon, navigate to about:addons then from the tools menu, click Install from file, find your XPI, open it, then after a short delay choose Install.


    In install.rdf put something like this:

    <?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>youraddonname@yourdomain</em:id>
            <em:type>2</em:type>
            <em:name>Name of your addon</em:name>
            <em:version>1.0</em:version>
            <em:bootstrap>true</em:bootstrap>
            <em:description>Describe your addon.</em:description>
            <em:creator>Your name</em:creator>
    
            <!-- Firefox Desktop -->
            <em:targetApplication>
                <Description>
                    <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
                    <em:minVersion>4.0.*</em:minVersion>
                    <em:maxVersion>29.0.*</em:maxVersion>
                </Description>
            </em:targetApplication>
        </Description>
    </RDF>
    


    You need to implement two mandatory JavaScript functions in the bootstrap.js:

    • startup() - called when you install the addon, and when your browser starts up.
    • shutdown() - called when you uninstall the addon, and when your browser shuts down.

    You should call the rest of your 'privileged' code in startup(). For hygiene, you can (and probably should) also implement install() and uninstall() functions.

    Start by implementing the following code in bootstrap.js:

    const Cc = Components.classes;
    const Ci = Components.interfaces;
    let consoleService = Cc["@mozilla.org/consoleservice;1"]
                            .getService(Ci.nsIConsoleService);
    let wm             = Cc["@mozilla.org/appshell/window-mediator;1"]
                            .getService(Ci.nsIWindowMediator);
    
    function LOG(msg) {
      consoleService.logStringMessage("EXTENSION: "+msg);    
    }
    
    function startup() {
      try {
        LOG("starting up...");
        let windows = wm.getEnumerator("navigator:browser");
        while (windows.hasMoreElements()) {
          let chromeWindow = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
          WindowListener.setupBrowserUI(chromeWindow);
        }
        wm.addListener(WindowListener);
        LOG("done startup.");
      } catch (e) {
        LOG("error starting up: "+e);
      }
    }
    
    function shutdown() {
      try {
        LOG("shutting down...");
        let windows = wm.getEnumerator("navigator:browser");
        while (windows.hasMoreElements()) {
          let chromeWindow = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
          WindowListener.tearDownBrowserUI(chromeWindow);
        }
        wm.addListener(WindowListener);
        LOG("done shutdown.");
      } catch (e) {
        LOG("error shutting down: "+e);
      }
    }
    

    Basically, that calls WindowListener.setupBrowserUI() for each current & future window of your web-browser. WindowListener is defined as follows:

    var WindowListener = {
      setupBrowserUI: function(chromeWindow) {
        chromeWindow.gBrowser.addEventListener('load', my_load_handler, true);
      },
      tearDownBrowserUI: function(chromeWindow) {
        chromeWindow.gBrowser.removeEventListener('load', my_load_handler, true);
      },
      onOpenWindow: function(xulWindow) {
        let chromeWindow = xulWindow.QueryInterface(Ci.nsIInterfaceRequestor)
                             .getInterface(Ci.nsIDOMWindow);
        chromeWindow.addEventListener("load", function listener() {
          chromeWindow.removeEventListener("load", listener, false);
          var domDocument = chromeWindow.document.documentElement;
          var windowType = domDocument.getAttribute("windowtype");
          if (windowType == "navigator:browser")
            WindowListener.setupBrowserUI(chromeWindow);
        }, false);
      },
      onCloseWindow: function(chromeWindow) { },
      onWindowTitleChange: function(chromeWindow, newTitle) { }
    };
    

    That sets up an event listener for the OpenWindow event, and in turn installs an event listener for load events in the TabBrowser of each ChromeWindow. The load event handler is defined as:

    var my_load_handler = function (evt) {
      try {
        var browserEnumerator = wm.getEnumerator("navigator:browser");
        while (browserEnumerator.hasMoreElements()) {
          var browserWin = browserEnumerator.getNext();
          var tabbrowser = browserWin.gBrowser;
          var numTabs = tabbrowser.browsers.length;
          for (var index = 0; index < numTabs; index++) {
            var currentBrowser = tabbrowser.getBrowserAtIndex(index);
            var domWindow = currentBrowser.contentWindow.wrappedJSObject;
            // identify your target page(s)...
            if (domWindow.location.href == 'http://yourserver/yourpage') {
              // install the privileged methods (if not already there)
              if (!domWindow.hasOwnProperty('__my_priv_members__') {
                install_my_privileged_methods(browserWin, domWindow);
              }
            }
          }
        }
      } catch (e) {
        LOG(e);
      }
    }
    

    That targets the correct pages (by checking the window.location.href and calls install_my_privileged_methods on their window object, which is defined as:

    function install_my_privileged_methods(chromeWindow, domWindow) {
      install_privileged_method(chromeWindow, domWindow, 'WriteFile', 
        function(priv) {
          return function(File, Text, cb) {
            priv.call([File, Text], function(rstatus, rdata, rerror){
              if (cb) cb(rstatus, rerror);
            });
          };
        },
        function (chromeWindow, args, cb) {
          var [File, Text] = args;
          if (!File) return cb(0, null, "need a filename");
          try {
            const unicodeConverter = 
               Cc["@mozilla.org/intl/scriptableunicodeconverter"]
                 .createInstance(Ci.nsIScriptableUnicodeConverter);
            unicodeConverter.charset = "UTF-8";
            Text = unicodeConverter.ConvertFromUnicode(Text);
            const os = Cc["@mozilla.org/network/file-output-stream;1"]
                         .createInstance(Ci.nsIFileOutputStream);
            os.init(File, 0x02 | 0x08 | 0x20, 0700, 0);
            os.write(Text, Text.length);
            os.close();
            cb(1, null, null);
          } catch (e) {
            cb(0, null, "error writing file: "+e);
          }
        }
      );
    
      install_privileged_method(chromeWindow, domWindow, 'ReadFile', 
        function(priv) {
          return function(File, cb) {
            priv.call([File], function(rstatus, rdata, rerror){
              if (cb) cb(rstatus, rdata, rerror);
            });
          };
        },
        function (chromeWindow, args, cb) {
          var [File] = args;
          if (!File) return cb(0, null, "need a filename");
          try {
            const is = Cc["@mozilla.org/network/file-input-stream;1"]
                         .createInstance(Ci.nsIFileInputStream);
            const sis = Cc["@mozilla.org/scriptableinputstream;1"]
                          .createInstance(Ci.nsIScriptableInputStream);
            is.init(File, 0x01, 0400, null);
            sis.init(is);
            var Text = sis.read(sis.available());    
            is.close();
            cb(1, Text, null);
          } catch (e) {
            cb(0, null, "error reading file: "+e);
          }
        }
      );
    }
    

    I didn't test this code. It's a straigh-forward translation of what you wrote above... I'll assume that works!

    That add two special methods, WriteFile & ReadFile, to the chosen window objects. In your web application's (unprivileged) JavaScript code use them like this:

    var buffer = '...'; // the text to be written
    window.WriteFile('C:\\path\\to\\file.txt', buffer, function(ok, errmsg) {
      if (!ok) alert(errmsg);
    });
    
    window.ReadFile('C:\\path\\to\\file.txt', function(ok, buffer, errmsg) { 
      if (!ok) return alert(errmsg);
      // use buffer here!
    });
    

    Finally, install_privileged_method is defined as:

    var install_privileged_method = (function(){
      var gensym = (function (){
        var __sym = 0;
        return function () { return '__sym_'+(__sym++); }
      })();
      return function (chromeWindow, target, slot, handler, methodFactory) {
        try {
          target.__pmcache__ = target.hasOwnProperty('__pmcache__')
            ? target.__pmcache__
            : { ticket_no: 0, callbacks: {}, namespace: gensym() };
          target[slot] = methodFactory({ call: function(fargs, fcb) {
            try {
              var ticket_no = target.__pmcache__.ticket_no++;
              target.__pmcache__.callbacks[ticket_no] = fcb;
              var cevent = target.document.createEvent("CustomEvent");
              cevent.initCustomEvent(
                target.__pmcache__.namespace+'.'+slot,
                true, true, { fargs: fargs, ticket_no: ticket_no }
              );
              target.dispatchEvent(cevent);
            } catch (ue) {
              fcb(0, null, 'untrusted dispatcher error: '+ue);
            }
          }});
          LOG("installed untrusted dispatcher for method '"+slot+"'.");
          target.addEventListener(
            target.__pmcache__.namespace+'.'+slot,
            function(cevent){
              var ticket_no = cevent.detail.ticket_no;
              var fargs = cevent.detail.fargs;
              var fcb = target.__pmcache__.callbacks[ticket_no];
              try {
                handler(chromeWindow, fargs, fcb);
              } catch (pe) {
                fcb(0, null, 'privileged handler error: '+pe);
              }
            },
            false,
            true
          );
          LOG("installed privileged handler for method '"+slot+"'.");
        } catch (ie) {
          LOG("ERROR installing handler/factory for privileged "+
              "method '"+slot+"': "+ie);
        }
      };
    })();
    

    这篇关于使用Firefox扩展将文件写入到网页的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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