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

上节我们做了一个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>[email protected]</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进行保存和再次打开,这个是不是有些实用了呢~

Mozilla Firefox扩展(Extensions)开发——XPCOM&XUL(二)_第1张图片

你可能感兴趣的:(Mozilla Firefox扩展(Extensions)开发——XPCOM&XUL(二))