+ Lots of cleanup after the sessionstore transplant

+ Now saving pageBounds.
+ Removed some unnecessary save calls and added some necessary ones
+ Added a reset command to the dev menu; wipes storage and refreshes
+ Fixed the save command on the dev menu so it now works again
+ Reconnected storage sanity checks
+ Removed a bunch of now unused storage code
+ Fixed a problem with cold start
+ Removed a bunch of logging code
+ Pulled BrowserWatcher out of tabs.js
+ Added a direct link to the code documentation to the dev menu
This commit is contained in:
Ian Gilman 2010-05-24 14:49:03 -07:00
parent e92aca399e
commit 987baafa7c
8 changed files with 356 additions and 350 deletions

View File

@ -0,0 +1,117 @@
// Title: browserwatcher.js
(function(){
Utils.log('warning! browserwatcher.js has not been tested since the code was taken from tabs.js!');
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
// ##########
// Class: WindowWatcher
function WindowWatcher() {
var self = this;
var observer = {
observe: function(window, event) {
if (event == "domwindowopened") {
if (self.onWindowOpened)
self.onWindowOpened(window);
} else
if (self.onWindowClosed)
self.onWindowClosed(window);
}
};
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]
.getService(Ci.nsIWindowWatcher);
ww.registerNotification(observer);
Extension.addUnloadMethod(
this,
function() {
ww.unregisterNotification(observer);
});
}
// ##########
// Class: BrowserWatcher
// When this object is instantiated, the given onLoad() is called for
// all browser windows, and subsequently for all newly-opened browser
// windows. When a browser window closes, onUnload() is called.
// onUnload() is also called once for each browser window when the
// extension is unloaded.
function BrowserWatcher(options) {
var pendingHandlers = [];
function makeSafeFunc(func) {
function safeFunc(window) {
try {
func(window);
} catch (e) {
Utils.log(e);
}
};
return safeFunc;
}
function addUnloader(chromeWindow, func) {
function onUnload() {
chromeWindow.removeEventListener("unload", onUnload, false);
pendingHandlers.splice(pendingHandlers.indexOf(onUnload), 1);
func(chromeWindow);
}
pendingHandlers.push(onUnload);
chromeWindow.addEventListener("unload", onUnload, false);
}
function loadAndBind(chromeWindow) {
if (options.onLoad)
(makeSafeFunc(options.onLoad))(chromeWindow);
if (options.onUnload)
addUnloader(chromeWindow, makeSafeFunc(options.onUnload));
}
var wm = Cc["@mozilla.org/appshell/window-mediator;1"]
.getService(Ci.nsIWindowMediator);
var enumerator = wm.getEnumerator(XULApp.appWindowType);
while (enumerator.hasMoreElements()) {
var chromeWindow = enumerator.getNext();
if (chromeWindow.gIsDoneLoading)
loadAndBind(chromeWindow);
else
onWindowOpened(chromeWindow);
}
function onWindowOpened(chromeWindow) {
function removeListener() {
chromeWindow.removeEventListener("load", onLoad, false);
pendingHandlers.splice(pendingHandlers.indexOf(removeListener), 1);
}
function onLoad() {
removeListener();
var type = chromeWindow.document.documentElement
.getAttribute("windowtype");
if (type == XULApp.appWindowType)
loadAndBind(chromeWindow);
}
chromeWindow.addEventListener("load", onLoad, false);
pendingHandlers.push(removeListener);
}
var ww = new WindowWatcher();
ww.onWindowOpened = onWindowOpened;
Extension.addUnloadMethod(
this,
function() {
ww.unload();
var handlers = pendingHandlers.slice();
handlers.forEach(function(handler) { handler(); });
});
}
})();

View File

@ -162,6 +162,8 @@ window.Group = function(listOfEls, options) {
});
} else
self.adjustTitleSize();
self.save();
}
this.$title
@ -276,9 +278,10 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
save: function() {
if (!this._inited) // too soon to save now
return;
var data = this.getStorageData();
/* Utils.log("data to save: " + data.toSource()); */
Storage.saveGroup(Utils.getCurrentWindow(), data);
if(Groups.groupStorageSanity(data))
Storage.saveGroup(Utils.getCurrentWindow(), data);
},
// ----------
@ -300,7 +303,6 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
var css = {width: w};
this.$title.css(css);
this.$titleShield.css(css);
this.save();
},
// ----------
@ -554,15 +556,13 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
self.remove($el);
});
item.parent = this;
item.setParent(this);
if(typeof(item.setResizable) == 'function')
item.setResizable(false);
if(item.tab == Utils.activeTab)
Groups.setActiveGroup(this);
item.save();
}
if(!options.dontArrange)
@ -601,7 +601,7 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
if(index != -1)
this._children.splice(index, 1);
item.parent = null;
item.setParent(null);
item.removeClass("tabInGroup");
item.removeClass("stacked");
item.removeClass("stack-trayed");
@ -627,7 +627,6 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
var toRemove = $.merge([], this._children);
$.each(toRemove, function(index, child) {
self.remove(child, {dontArrange: true});
child.save();
});
},
@ -861,8 +860,6 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
this.arrange({z: z + 2});
}
this.save();
},
// ----------
@ -931,8 +928,6 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
this.$resizer.fadeOut();
$(this.container).resizable('disable');
}
this.save();
},
// ----------
@ -994,8 +989,6 @@ window.Group.prototype = $.extend(new Item(), new Subscribable(), {
// actions is necessary for a good user experience.
self.onNextNewTab(doNextTab);
this.save();
},
// ----------
@ -1283,13 +1276,14 @@ window.Groups = {
init: function() {
this.groups = [];
this.nextID = 1;
this._inited = false;
},
// ----------
getNextID: function() {
var result = this.nextID;
this.nextID++;
Storage.saveGroupsData(Utils.getCurrentWindow(), {nextID:this.nextID});
this.save();
return result;
},
@ -1303,73 +1297,77 @@ window.Groups = {
return data;
},
// ----------
saveAll: function() {
this.save();
$.each(this.groups, function(index, group) {
group.save();
});
},
// ----------
save: function() {
if (!this._inited) // too soon to save now
return;
Storage.saveGroupsData(Utils.getCurrentWindow(), {nextID:this.nextID});
},
// ----------
reconstitute: function(groupsData, groupData) {
try {
/* Utils.log("in reconst"); */
if(groupsData && groupsData.nextID)
this.nextID = groupsData.nextID;
else {
// Decrement and increment. Increment will trigger a save, and that is
// actually what we want here.
--this.nextID;
this.getNextID();
}
if(groupsData && groupsData.nextID)
this.nextID = groupsData.nextID;
if(groupData) {
for (var id in groupData) {
/*
Utils.log("id: " + id);
Utils.log("groupData[id]: "+ groupData[id].toSource());
*/
var group = groupData[id];
/* Utils.log("src: " +group.toSource()); */
var isNewTabsGroup = (group.title == 'New Tabs');
if(groupData) {
for (var id in groupData) {
var group = groupData[id];
if(this.groupStorageSanity(group)) {
var isNewTabsGroup = (group.title == 'New Tabs');
var options = {
locked: {
close: isNewTabsGroup,
title: isNewTabsGroup
},
dontPush: true
};
new Group([], $.extend({}, group, options));
}
}
}
var group = this.getNewTabGroup();
if(!group) {
var box = this.getBoundsForNewTabGroup();
var options = {
locked: {
close: isNewTabsGroup,
title: isNewTabsGroup
close: true,
title: true
},
dontPush: true
dontPush: true,
bounds: box,
title: 'New Tabs'
};
new Group([], $.extend({}, group, options));
new Group([], options);
}
}
var group = this.getNewTabGroup();
if(!group) {
var box = this.getBoundsForNewTabGroup();
var options = {
locked: {
close: true,
title: true
},
dontPush: true,
bounds: box,
title: 'New Tabs'
};
new Group([], options);
}
this._inited = true;
this.save(); // for nextID
}catch(e){
Utils.log("error in recons: "+e);
}
},
// ----------
storageSanity: function(data) {
groupStorageSanity: function(groupData) {
// TODO: check everything
if(!data.groups)
return false;
var sane = true;
$.each(data.groups, function(index, group) {
if(!isRect(group.bounds)) {
Utils.log('Groups.storageSanity: bad bounds', group.bounds);
sane = false;
}
});
if(!isRect(groupData.bounds)) {
Utils.log('Groups.groupStorageSanity: bad bounds', groupData.bounds);
sane = false;
}
return sane;
},

View File

@ -11,6 +11,7 @@
// close - function()
// addOnClose - function(referenceObject, callback)
// removeOnClose - function(referenceObject)
// save - function()
//
// ... and this property:
// defaultSize - a Point
@ -73,6 +74,7 @@ window.Item.prototype = {
Utils.assert('Subclass must provide close', typeof(this.close) == 'function');
Utils.assert('Subclass must provide addOnClose', typeof(this.addOnClose) == 'function');
Utils.assert('Subclass must provide removeOnClose', typeof(this.removeOnClose) == 'function');
Utils.assert('Subclass must provide save', typeof(this.save) == 'function');
Utils.assert('Subclass must provide defaultSize', isPoint(this.defaultSize));
Utils.assert('Subclass must provide locked', this.locked);
@ -136,6 +138,7 @@ window.Item.prototype = {
setUserSize: function() {
Utils.assert('this.bounds', isRect(this.bounds));
this.userSize = new Point(this.bounds.width, this.bounds.height);
this.save();
},
// ----------
@ -153,6 +156,14 @@ window.Item.prototype = {
$(this.container).css({"-moz-transform": value});
},
// ----------
// Function: setParent
//
setParent: function(parent) {
this.parent = parent;
this.save();
},
// ----------
// Function: pushAway
// Pushes all other items away so none overlap this Item.

View File

@ -5,6 +5,7 @@ Storage = {
GROUP_DATA_IDENTIFIER: "tabcandy-group",
GROUPS_DATA_IDENTIFIER: "tabcandy-groups",
TAB_DATA_IDENTIFIER: "tabcandy-tab",
UI_DATA_IDENTIFIER: "tabcandy-ui",
// ----------
init: function() {
@ -12,9 +13,31 @@ Storage = {
.getService(Components.interfaces.nsISessionStore);
},
// ----------
wipe: function() {
try {
var win = Utils.getCurrentWindow();
var self = this;
// ___ Tabs
Tabs.forEach(function(tab) {
self.saveTab(tab.raw, null);
});
// ___ Other
this.saveGroupsData(win, {});
this.saveUIData(win, {});
this._sessionStore.setWindowValue(win, this.GROUP_DATA_IDENTIFIER,
JSON.stringify({}));
} catch (e) {
Utils.log("Error in wipe: "+e);
}
},
// ----------
saveTab: function(tab, data) {
/* Utils.log("AAAAAAAAAAAAAAAAAAAAAAAAAAA saving tab data, tab: " + tab.toSource() + ", data: "+data.toSource()); */
/* Utils.log("AAAAAAAAAAAAAAAAAAAAAAAAAAA saving tab data"); */
this._sessionStore.setTabValue(tab, this.TAB_DATA_IDENTIFIER,
JSON.stringify(data));
},
@ -32,6 +55,8 @@ Storage = {
// getWindowValue will fail if the property doesn't exist
Utils.log("Error in readTabData: "+e);
}
/* Utils.log('tab', existingData); */
return existingData;
},
@ -69,71 +94,48 @@ Storage = {
// ----------
saveGroupsData: function(win, data) {
/* Utils.log("GGGGGGGGGGGGGGGGGGGGGGGGGGGGGG " + data.toSource()); */
this._sessionStore.setWindowValue(win, this.GROUPS_DATA_IDENTIFIER,
JSON.stringify(data));
this.saveData(win, this.GROUPS_DATA_IDENTIFIER, data);
},
// ----------
readGroupsData: function(win) {
return this.readData(win, this.GROUPS_DATA_IDENTIFIER);
},
// ----------
saveUIData: function(win, data) {
this.saveData(win, this.UI_DATA_IDENTIFIER, data);
},
// ----------
readUIData: function(win) {
return this.readData(win, this.UI_DATA_IDENTIFIER);
},
// ----------
saveData: function(win, id, data) {
try {
this._sessionStore.setWindowValue(win, id, JSON.stringify(data));
} catch (e) {
Utils.log("Error in saveData: "+e);
}
/* Utils.log('save data', id, data); */
},
// ----------
readData: function(win, id) {
var existingData = {};
try {
/* Utils.log("readGroupsData: "+this._sessionStore.getWindowValue(win, this.GROUPS_DATA_IDENTIFIER)); */
existingData = JSON.parse(
this._sessionStore.getWindowValue(win, this.GROUPS_DATA_IDENTIFIER)
);
var data = this._sessionStore.getWindowValue(win, id);
if(data)
existingData = JSON.parse(data);
} catch (e) {
// getWindowValue will fail if the property doesn't exist
Utils.log("Error in readData: "+e);
}
/* Utils.log('read data', id, existingData); */
return existingData;
},
// ----------
read: function() {
var data = {};
var file = this.getFile();
if(file.exists()) {
var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"].
createInstance(Components.interfaces.nsIFileInputStream);
var cstream = Components.classes["@mozilla.org/intl/converter-input-stream;1"].
createInstance(Components.interfaces.nsIConverterInputStream);
fstream.init(file, -1, 0, 0);
cstream.init(fstream, "UTF-8", 0, 0); // you can use another encoding here if you wish
let (str = {}) {
cstream.readString(-1, str); // read the whole file and put it in str.value
if(str.value)
data = JSON.parse(str.value);
}
cstream.close(); // this closes fstream
}
return data;
},
// ----------
write: function(data) {
var file = this.getFile();
var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"].
createInstance(Components.interfaces.nsIFileOutputStream);
foStream.init(file, 0x02 | 0x08 | 0x20, 0666, 0);
var str = JSON.stringify(data);
foStream.write(str, str.length);
foStream.close();
},
// ----------
getFile: function() {
var file = Components.classes["@mozilla.org/file/directory_service;1"].
getService(Components.interfaces.nsIProperties).
get("ProfD", Components.interfaces.nsIFile);
file.append('tabcandy');
if(!file.exists())
file.create(Components.interfaces.nsIFile.DIRECTORY_TYPE, 0777);
file.append(Switch.name + '.json');
return file;
}
};

View File

@ -13,6 +13,7 @@ window.TabItem = function(container, tab) {
this._init(container);
this.reconnected = false;
this._hasBeenDrawn = false;
this.tab = tab;
this.setResizable(true);
@ -22,6 +23,13 @@ window.TabItem = function(container, tab) {
this.tab.mirror.addOnClose(this, function(who, info) {
TabItems.unregister(self);
});
this.tab.mirror.addSubscriber(this, 'urlChanged', function(who, info) {
if(!self.reconnected && (info.oldURL == 'about:blank' || !info.oldURL))
TabItems.reconnect(self);
self.save();
});
};
window.TabItem.prototype = $.extend(new Item(), {
@ -37,13 +45,13 @@ window.TabItem.prototype = $.extend(new Item(), {
// ----------
save: function() {
/* Utils.log((this.tab ? this.tab.url : ''), this.reconnected); */
try{
if (!("tab" in this) || !("raw" in this.tab) || !this.reconnected) // too soon to save
return;
var data = this.getStorageData();
/* Utils.log("data to save", data); */
Storage.saveTab(this.tab.raw, data);
if(TabItems.storageSanity(data))
Storage.saveTab(this.tab.raw, data);
}catch(e){
Utils.log("Error in saving tab value: "+e);
}
@ -320,20 +328,19 @@ window.TabItems = {
if(TabItems.reconnect(item))
reconnected = true;
else if(!tab.url || tab.url == 'about:blank') {
tab.mirror.addSubscriber(item, 'urlChanged', function(who, info) {
Utils.assert('changing away from blank', info.oldURL == 'about:blank' || !info.oldURL);
TabItems.reconnect(item);
who.removeSubscriber(item);
});
}
else
Groups.newTab(item);
}
});
/* Utils.log("reconnected: "+reconnected); */
/*
Utils.log(reconnected, $div.length, !!Groups);
if(!reconnected && $div.length == 1 && Groups){
Utils.log('new tab');
Groups.newTab($div.data('tabItem'));
}
*/
// TODO: Figure out this really weird bug?
@ -448,6 +455,14 @@ window.TabItems = {
return $(tab).data("tabItem");
},
// ----------
saveAll: function() {
var items = this.getItems();
$.each(items, function(index, item) {
item.save();
});
},
// ----------
reconstitute: function() {
var items = this.getItems();
@ -461,34 +476,26 @@ window.TabItems = {
// ----------
storageSanity: function(data) {
// TODO: check everything
if(!data.tabs)
return false;
var sane = true;
$.each(data.tabs, function(index, tab) {
if(!isRect(tab.bounds)) {
Utils.log('TabItems.storageSanity: bad bounds', tab.bounds);
sane = false;
}
});
if(!isRect(data.bounds)) {
Utils.log('TabItems.storageSanity: bad bounds', data.bounds);
sane = false;
}
return sane;
},
// ----------
reconnect: function(item) {
var found = false;
try{
/* Utils.log("trying to reconnect"); */
if(item.reconnected) {
/* Utils.log("already done"); */
return true;
}
var found = false;
var tab = Storage.getTabData(item.tab.raw);
/* Utils.log("this is our tab", tab, item.tab.url); */
if (tab) {
if (tab && this.storageSanity(tab)) {
if(item.parent)
item.parent.remove(item);
@ -499,11 +506,12 @@ window.TabItems = {
if(tab.groupID) {
var group = Groups.group(tab.groupID);
/* Utils.log("group found: " + group); */
group.add(item);
if(group) {
group.add(item);
if(item.tab == Utils.activeTab)
Groups.setActiveGroup(item.parent);
if(item.tab == Utils.activeTab)
Groups.setActiveGroup(item.parent);
}
}
Groups.updateTabBarForActiveGroup();

View File

@ -8,7 +8,7 @@ window.Keys = {meta: false};
Navbar = {
// ----------
get el(){
var win = Utils.activeWindow;
var win = Utils.getCurrentWindow();
if(win) {
var navbar = win.gBrowser.ownerDocument.getElementById("navigator-toolbox");
return navbar;
@ -18,7 +18,7 @@ Navbar = {
},
get urlBar(){
var win = Utils.activeWindow;
var win = Utils.getCurrentWindow();
if(win) {
var navbar = win.gBrowser.ownerDocument.getElementById("urlbar");
return navbar;
@ -535,7 +535,7 @@ UIClass.prototype = {
var me = this;
setTimeout(function() { // Marshal event from chrome thread to DOM thread
try{
if(me.contentWindow.location.host == "tabcandy") {
if(me.contentWindow == window) {
self.focused = true;
Page.hideChrome();
} else {
@ -554,47 +554,30 @@ UIClass.prototype = {
}, 1);
});
// ___ Page
Page.init();
// ___ Storage
var data = Storage.read();
var sane = this.storageSanity(data);
if(!sane || data.dataVersion < 2) {
data.groups = null;
data.tabs = null;
data.pageBounds = null;
if(!sane)
alert('storage data is bad; starting fresh');
}
var groupsData = Storage.readGroupsData(Utils.activeWindow);
var groupData = Storage.readGroupData(Utils.activeWindow);
/*
Utils.log("in UI init");
Utils.log(data.toSource());
Utils.log(groupsData.toSource());
Utils.log(groupData.toSource());
*/
Groups.reconstitute(groupsData, groupData);
TabItems.init();
TabItems.reconstitute();
$(window).bind('beforeunload', function() {
if(self.initialized)
self.save();
self.showChrome();
self.tabBar.showAllTabs();
});
// ___ Page
Page.init();
// ___ Storage
var currentWindow = Utils.getCurrentWindow();
var data = Storage.readUIData(currentWindow);
this.storageSanity(data);
var groupsData = Storage.readGroupsData(currentWindow);
var groupData = Storage.readGroupData(currentWindow);
Groups.reconstitute(groupsData, groupData);
TabItems.init();
TabItems.reconstitute();
// ___ resizing
data.pageBounds = null;
if(data.pageBounds) {
this.pageBounds = data.pageBounds;
this.resize();
this.resize(true);
} else
this.pageBounds = Items.getPageBounds();
@ -607,6 +590,7 @@ UIClass.prototype = {
// ___ Done
this.initialized = true;
this.save(); // for this.pageBounds
}catch(e) {
Utils.log("Error in UIClass(): " + e);
Utils.log(e.fileName);
@ -692,6 +676,7 @@ UIClass.prototype = {
});
this.pageBounds = Items.getPageBounds();
this.save();
},
// ----------
@ -716,10 +701,21 @@ UIClass.prototype = {
code: function() {
location.href = '../../index.html';
}
}, {
name: 'code docs',
code: function() {
location.href = '../../doc/index.html';
}
}, {
name: 'save',
code: function() {
self.save();
self.saveAll();
}
}, {
name: 'reset',
code: function() {
Storage.wipe();
location.href = '';
}
}];
@ -736,21 +732,24 @@ UIClass.prototype = {
}
},
// ----------
saveAll: function() {
this.save();
Groups.saveAll();
TabItems.saveAll();
},
// ----------
save: function() {
return;
if(!this.initialized)
return;
var data = {
dataVersion: 2,
groups: Groups.getStorageData(),
tabs: TabItems.getStorageData(),
pageBounds: Items.getPageBounds()
pageBounds: this.pageBounds
};
/* Utils.error(this.pageBounds, data.pageBounds); */
if(this.storageSanity(data))
Storage.write(data);
else
alert('storage data is bad; reverting to previous version');
Storage.saveUIData(Utils.getCurrentWindow(), data);
},
// ----------
@ -758,17 +757,13 @@ UIClass.prototype = {
if($.isEmptyObject(data))
return true;
var sane = true;
sane = sane && typeof(data.dataVersion) == 'number';
sane = sane && isRect(data.pageBounds);
if(!isRect(data.pageBounds)) {
Utils.log('UI.storageSanity: bad pageBounds', data.pageBounds);
data.pageBounds = null;
return false;
}
if(data.tabs)
sane = sane && TabItems.storageSanity(data.tabs);
if(data.groups)
sane = sane && Groups.storageSanity(data.groups);
return sane;
return true;
},
// ----------

View File

@ -1,13 +1,14 @@
// Title: tabs.js
(function(){
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cu = Components.utils;
const Cr = Components.results;
// ##########
// Class: XULApp
// Singelton
var XULApp = {
appWindowType: "navigator:browser",
tabStripForWindow: function(aWindow) {
@ -30,7 +31,8 @@ var XULApp = {
}
};
// ##########
// Class: Dictionary
function Dictionary() {
var keys = [];
var values = [];
@ -69,6 +71,8 @@ function Dictionary() {
this.__defineGetter__("length", function() { return keys.length; });
}
// ##########
// Class: ImmutableArray
function ImmutableArray(baseArray) {
var self = this;
var UNSUPPORTED_MUTATOR_METHODS = ["pop", "push", "reverse", "shift",
@ -86,117 +90,9 @@ function ImmutableArray(baseArray) {
self.__proto__ = baseArray;
}
function WindowWatcher() {
var self = this;
var observer = {
observe: function(window, event) {
if (event == "domwindowopened") {
if (self.onWindowOpened)
self.onWindowOpened(window);
} else
if (self.onWindowClosed)
self.onWindowClosed(window);
}
};
var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]
.getService(Ci.nsIWindowWatcher);
ww.registerNotification(observer);
Extension.addUnloadMethod(
this,
function() {
ww.unregisterNotification(observer);
});
}
// When this object is instantiated, the given onLoad() is called for
// all browser windows, and subsequently for all newly-opened browser
// windows. When a browser window closes, onUnload() is called.
// onUnload() is also called once for each browser window when the
// extension is unloaded.
function BrowserWatcher(options) {
var pendingHandlers = [];
function makeSafeFunc(func) {
function safeFunc(window) {
try {
func(window);
} catch (e) {
Utils.log(e);
}
};
return safeFunc;
}
function addUnloader(chromeWindow, func) {
function onUnload() {
chromeWindow.removeEventListener("unload", onUnload, false);
pendingHandlers.splice(pendingHandlers.indexOf(onUnload), 1);
func(chromeWindow);
}
pendingHandlers.push(onUnload);
chromeWindow.addEventListener("unload", onUnload, false);
}
function loadAndBind(chromeWindow) {
if (options.onLoad)
(makeSafeFunc(options.onLoad))(chromeWindow);
if (options.onUnload)
addUnloader(chromeWindow, makeSafeFunc(options.onUnload));
}
var wm = Cc["@mozilla.org/appshell/window-mediator;1"]
.getService(Ci.nsIWindowMediator);
var enumerator = wm.getEnumerator(XULApp.appWindowType);
while (enumerator.hasMoreElements()) {
var chromeWindow = enumerator.getNext();
if (chromeWindow.gIsDoneLoading)
loadAndBind(chromeWindow);
else
onWindowOpened(chromeWindow);
}
function onWindowOpened(chromeWindow) {
function removeListener() {
chromeWindow.removeEventListener("load", onLoad, false);
pendingHandlers.splice(pendingHandlers.indexOf(removeListener), 1);
}
function onLoad() {
removeListener();
var type = chromeWindow.document.documentElement
.getAttribute("windowtype");
if (type == XULApp.appWindowType)
loadAndBind(chromeWindow);
}
chromeWindow.addEventListener("load", onLoad, false);
pendingHandlers.push(removeListener);
}
var ww = new WindowWatcher();
ww.onWindowOpened = onWindowOpened;
Extension.addUnloadMethod(
this,
function() {
ww.unload();
var handlers = pendingHandlers.slice();
handlers.forEach(function(handler) { handler(); });
});
}
// ##########
// Class: Extension
// Singleton
var Extension = {
// === {{{Extension.addUnloadMethod()}}} ===
//
@ -220,14 +116,8 @@ var Extension = {
}
};
// ##########
// Class: EventListenerMixIns
function EventListenerMixIns(mixInto) {
var mixIns = {};
@ -256,6 +146,8 @@ function EventListenerMixIns(mixInto) {
});
}
// ##########
// Class: EventListenerMixIn
function EventListenerMixIn(options) {
var listeners = [];
@ -578,29 +470,12 @@ window.TabsManager = $.extend(new Subscribable(), {
};
}
/*
var browserWatcher = new BrowserWatcher(
{onLoad: function(chromeWindow) {
var trackedWindow = trackedWindows.get(chromeWindow);
if (!trackedWindow)
trackedWindows.set(chromeWindow,
new BrowserWindow(chromeWindow));
},
onUnload: function(chromeWindow) {
var browserWindow = trackedWindows.get(chromeWindow);
trackedWindows.remove(chromeWindow);
browserWindow.unload();
}
});
*/
this.__defineGetter__("tabs", function() { return tabs; });
Extension.addUnloadMethod(
this,
function() {
tabsMixIns.unload();
/* browserWatcher.unload(); */
});
window.Tabs = tabs;

View File

@ -23,7 +23,7 @@
<script type="text/javascript;version=1.8" src="js/storage.js"></script>
<script type="text/javascript;version=1.8" src="../../js/core/toolbar-button.js"></script>
<script type="text/javascript;version=1.8">
Utils.log('it begins!');
Utils.log('it begins! --------------------');
/* Utils.testLogging(); */
</script>
<script type="text/javascript;version=1.8" src="../../js/core/tabs.js"></script>