Mozilla Firefox扩展(Extensions)开发——XPCOM&XUL(二)

来源:互联网 发布:seo软件 编辑:程序博客网 时间:2024/06/05 03:10

上节我们做了一个hello world,然而并没有什么卵用。这节我们实现一个具有实用功能的扩展吧!

创建我们的扩展开发目录,其结构如下:

sessionstore

                |——content

               |             |——overlay.js

               |               | ——overlay.xul

                |                 | ——prefs.xul

                |——defaults

                |                  |——preferences

                |                                    |——sessionstore-prefs.js

                |——chrome.manifest

                |——install.rdf

各文件的实现如下:

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">      <!-- Unique ID for extension. Can be in e-mail address format or GUID format -->      <em:id>sessionstore@xuldev.org</em:id>      <!-- Indicates that this add-on is an extension -->      <em:type>2</em:type>      <!-- Extension name displayed in Add-on Manager -->      <em:name>Hello, World!</em:name>      <!-- Extension version number. There is a version numbering scheme you must follow -->      <em:version>0.1</em:version>      <!-- Brief description displayed in Add-on Manager -->      <em:description>My sessionstore extension.</em:description>      <!-- Name of extension's primary developer. Change to your name -->      <em:creator>Gomita</em:creator>      <!-- Web page address through which extension is distributed -->      <em:homepageURL>http://www.xuldev.org/helloworld/</em:homepageURL>      <!-- This section gives details of the target application for the extension (in this case: Firefox 2) -->      <em:targetApplication>        <Description>          <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>          <em:minVersion>2.0</em:minVersion>          <em:maxVersion>4.0.0.*</em:maxVersion>        </Description>      </em:targetApplication>  <em:optionsURL>chrome://sessionstore/content/prefs.xul</em:optionsURL>  </Description>  </RDF> 
chrome.manifest

content sessionstore content/overlay chrome://browser/content/browser.xul chrome://sessionstore/content/overlay.xul
overlay.xul

<?xml version="1.0"?><overlay id="sessionstoreOverlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">  <script type="application/javascript"      src="chrome://sessionstore/content/overlay.js" />    <menupopup id="menu_ToolsPopup">      <menu label="Session Store" insertbefore="sanitizeSeparator">        <menupopup onpopupshowing="gSessionStore.createMenu(event);" oncommand="gSessionStore.restore(event);">  <menuitem label="Save Session" oncommand="gSessionStore.save(event);" />  <menuseparator />  <!-- Dynamically generated menu items go here -->  <menuseparator />  <menuitem label="Clear Sessions" oncommand="gSessionStore.clear(event);" /></menupopup>    </menu>  </menupopup></overlay>
overlay.js(这个代码看起来比较乱,实际上就是一个函数数组)

var gSessionStore = {  // Directory to save sessions (nsILocalFile)  _dir: null,  // Initialization  init: function() {  var dirSvc = Components.classes["@mozilla.org/file/directory_service;1"]               .getService(Components.interfaces.nsIProperties);  this._dir = dirSvc.get("ProfD", Components.interfaces.nsILocalFile);  this._dir.append("sessionstore");  if (!this._dir.exists())    this._dir.create(this._dir.DIRECTORY_TYPE, 0700);},  // uninitialization  uninit: function() {  this._dir = null;},  // Save session (event handler)  save: function(event) {  event.stopPropagation();  var ss = Components.classes["@mozilla.org/browser/sessionstore;1"]           .getService(Components.interfaces.nsISessionStore);  var state = ss.getBrowserState();  var fileName = "session_" + Date.now() + ".js";  var file = this._dir.clone();  file.append(fileName);  this._writeFile(file, state);},  // Restore session (event handler)  restore: function(event) {  var fileName = event.target.getAttribute("fileName");  var file = this._dir.clone();  file.append(fileName);  var state = this._readFile(file);  var ss = Components.classes["@mozilla.org/browser/sessionstore;1"]           .getService(Components.interfaces.nsISessionStore);  ss.setWindowState(window, state, false);},  // Delete session (event handler)  clear: function(event)  {    event.preventBubble();    var fileEnum = this._dir.directoryEntries;    while (fileEnum.hasMoreElements()) {      var file = fileEnum.getNext().QueryInterface(Components.interfaces.nsIFile);      file.remove(false);      // debug      dump("SessionStore> clear: " + file.leafName + "\n");    }  },  // Dynamically generate menu items (event handler)  createMenu: function(event)  {    var menupopup = event.target;    for (var i = menupopup.childNodes.length - 1; i >= 0; i--) {      var node = menupopup.childNodes[i];      if (node.hasAttribute("fileName"))        menupopup.removeChild(node);    }    var fileEnum = this._dir.directoryEntries;    while (fileEnum.hasMoreElements()) {      var file = fileEnum.getNext().QueryInterface(Components.interfaces.nsIFile);      var re = new RegExp("^session_(\\d+)\.js$");      if (!re.test(file.leafName))        continue;      var dateTime = new Date(parseInt(RegExp.$1, 10)).toLocaleString();      var menuitem = document.createElement("menuitem");      menuitem.setAttribute("label", dateTime);      menuitem.setAttribute("fileName", file.leafName);      menupopup.insertBefore(menuitem, menupopup.firstChild.nextSibling.nextSibling);    }  },   // Read file  _readFile: function(aFile)  {    try {      var stream = Components.classes["@mozilla.org/network/file-input-stream;1"].                   createInstance(Components.interfaces.nsIFileInputStream);      stream.init(aFile, 0x01, 0, 0);      var cvstream = Components.classes["@mozilla.org/intl/converter-input-stream;1"].                     createInstance(Components.interfaces.nsIConverterInputStream);      cvstream.init(stream, "UTF-8", 1024, Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);      var content = "";      var data = {};      while (cvstream.readString(4096, data)) {        content += data.value;      }      cvstream.close();      return content.replace(/\r\n?/g, "\n");    }    catch (ex) { }    return null;  },   // Write file  _writeFile: function(aFile, aData)  {    // init stream    var stream = Components.classes["@mozilla.org/network/safe-file-output-stream;1"].                 createInstance(Components.interfaces.nsIFileOutputStream);    stream.init(aFile, 0x02 | 0x08 | 0x20, 0600, 0);    // convert to UTF-8    var converter = Components.classes["@mozilla.org/intl/scriptableunicodeconverter"].                    createInstance(Components.interfaces.nsIScriptableUnicodeConverter);    converter.charset = "UTF-8";    var convertedData = converter.ConvertFromUnicode(aData);    convertedData += converter.Finish();    // write and close stream    stream.write(convertedData, convertedData.length);    if (stream instanceof Components.interfaces.nsISafeOutputStream) {      stream.finish();    } else {      stream.close();    }  },};window.addEventListener("load", function(){gSessionStore.init(); }, false);window.addEventListener("unload", function(){gSessionStore.uninit(); }, false);
prefs.xul

<?xml version="1.0"?><?xml-stylesheet href="chrome://global/skin/" type="text/css"?><prefwindow id="sessionstorePrefs" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"     title="Session Store Preferences">  <prefpane>    <preferences>      <preference id="extensions.sessionstore.warnOnClear"           name="extensions.sessionstore.warnOnClear"           type="bool" />      <preference id="extensions.sessionstore.replaceTabs"           name="extensions.sessionstore.replaceTabs"           type="int" />    </preferences>    <checkbox label="Confirm before clearing sessions"         preference="extensions.sessionstore.warnOnClear" />    <groupbox>      <caption label="When restoring session:" />      <radiogroup preference="extensions.sessionstore.replaceTabs">        <radio value="0" label="Keep current tabs" />        <radio value="1" label="Replace current tabs"/>        <radio value="2" label="Ask me every time" />      </radiogroup>    </groupbox>  </prefpane></prefwindow>
sessionstore-prefs.js

pref("extensions.sessionstore.warnOnClear", true);pref("extensions.sessionstore.replaceTabs", 2);

参看上节的方法进行打包安装后,就可以看到效果啦,可以对自己访问的页面session进行保存和再次打开,这个是不是有些实用了呢~

1 0
原创粉丝点击