2012-12-12 95 views
3

我有一個Web應用程序,我的客戶用於現金註冊表。 我需要做的是創建一個本地文件,因爲收銀機的軟件需要從該文件讀取才能打印。使用Firefox擴展公開文件寫入網頁

到現在爲止我用這個代碼:

netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); 
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile); 
file.initWithPath(filePath); 
與此不工作了Firefox的最新版本

可惜,所以我被告知,我需要和附加創建file.I」已經盡力開發一個附加(不知道是否成功地)和我main.js看起來像這樣:

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; 
    }, 
}; 

任何想法,我應該如何使用main.js哪裏找到它添加後? - 安裝? 我需要使用這樣的東西:FileManager.Write(路徑,文本)。

回答

1

對不起,超晚回覆。

如果我正確理解你的問題,你有一個在Firefox中運行的P.O.S應用程序通過HTTP與某種本地網絡服務器通信。您應用程序的客戶端JavaScript需要能夠從瀏覽器PC的本地文件系統讀取&寫入文件。

如果這是正確的,那麼你可以這樣做,如下所示。您需要創建一個Firefox插件,其中最簡單的一種稱爲「引導式」(或「無重啓」)插件。


一個無需重啓插件包含兩個文件:

  • bootstrap.js(包含你的 '特權' 代碼的JavaScript文件)
  • 的install.rdf(XML文件描述你的插件來Firefrox )

要構建插件,只需將兩個文件放在ZIP文件的頂層(無文件夾!)中,文件擴展名爲.xpi。要安裝插件,導航到about:addons,然後從工具菜單中點擊Install from file,找到您的XPI,打開它,然後在短暫延遲後選擇Install


install.rdf把這樣的事情:

<?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>[email protected]</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> 

你需要實現兩個強制性JavaScript函數在bootstrap.js

  • startup() - 叫當您安裝插件,以及您的瀏覽器啓動時。
  • shutdown() - 在卸載插件時以及瀏覽器關閉時調用。

您應該在startup()中調用您的「特權」代碼的其餘部分。爲了衛生,您可以(也可能應該)執行install()uninstall()函數。

開始在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); 
    } 
} 

基本上,爲您的Web瀏覽器的每個電流&未來的窗口調用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; 
     var windowType = domDocument.getAttribute("windowtype"); 
     if (windowType == "navigator:browser") 
     WindowListener.setupBrowserUI(chromeWindow); 
    }, false); 
    }, 
    onCloseWindow: function(chromeWindow) { }, 
    onWindowTitleChange: function(chromeWindow, newTitle) { } 
}; 

即設置了一個事件偵聽器OpenWindow事件,並依次安裝在每個ChromeWindow的TabBrowserload事件的事件偵聽器。該load事件處理程序被定義爲:

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); 
    } 
} 

爲目標的正確頁面(通過檢查window.location.href及其window對象,它被定義爲來電install_my_privileged_methods

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); 
     } 
    } 
); 
} 

我沒有測試此代碼。這是你上面寫的什麼straigh向前翻譯...我假設的作品!

這增加兩個特殊的方法,WriteFile & ReadFile,到所選的window對象。在Web應用程序的(授權)的JavaScript代碼中使用它們像這樣:

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! 
}); 

最後,install_privileged_method被定義爲:

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); 
    } 
    }; 
})();