上节我们做了一个hello world,然而并没有什么卵用。这节我们实现一个具有实用功能的扩展吧!
创建我们的扩展开发目录,其结构如下:
sessionstore
|——content
| |——overlay.js
| | ——overlay.xul
| | ——prefs.xul
|——defaults
| |——preferences
| |——sessionstore-prefs.js
|——chrome.manifest
|——install.rdf
各文件的实现如下:
install.rdf
[email protected]
2
Hello, World!
0.1
My sessionstore extension.
Gomita
http://www.xuldev.org/helloworld/
{ec8030f7-c20a-464f-9b0e-13a3a9e97384}
2.0
4.0.0.*
chrome://sessionstore/content/prefs.xul
chrome.manifest
content sessionstore content/
overlay chrome://browser/content/browser.xul chrome://sessionstore/content/overlay.xul
overlay.xul
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
sessionstore-prefs.js
pref("extensions.sessionstore.warnOnClear", true);
pref("extensions.sessionstore.replaceTabs", 2);