[Pkg-mozext-commits] [SCM] Show tabs like a tree branch, master, updated. debian/0.12.2011061701-1-17-gadc4691

Ximin Luo infinity0 at gmx.com
Sat Feb 11 15:35:10 UTC 2012


The following commit has been merged in the master branch:
commit 70df5311d32fc61da4526be789a1e526d6a69032
Author: Ximin Luo <infinity0 at gmx.com>
Date:   Sat Feb 11 15:05:42 2012 +0000

    Imported Upstream Release 0.14.2012021101.

diff --git a/chrome.manifest b/chrome.manifest
index e6e8b29..f5bf343 100644
--- a/chrome.manifest
+++ b/chrome.manifest
@@ -12,6 +12,7 @@ overlay	chrome://browser/content/places/bookmarkProperties.xul	chrome://treestyl
 overlay	chrome://multipletab/content/config.xul	chrome://treestyletab/content/multipletabConfigOverlay.xul
 
 overlay	chrome://browser/content/browser.xul	chrome://treestyletab/content/res/bookmarkMultipleTabs.xul
+overlay	chrome://browser/content/places/bookmarkProperties.xul	chrome://treestyletab/content/res/bookmarkMultipleTabs_bookmarkPropertiesOverlay.xul
 overlay	chrome://browser/content/places/bookmarkProperties2.xul	chrome://treestyletab/content/res/bookmarkMultipleTabs_bookmarkPropertiesOverlay.xul
 
 locale	treestyletab	en-US	jar:chrome/treestyletab.jar!/locale/en-US/treestyletab/
@@ -21,7 +22,7 @@ locale	treestyletab	zh-CN	jar:chrome/treestyletab.jar!/locale/zh-CN/treestyletab
 locale	treestyletab	es-ES	jar:chrome/treestyletab.jar!/locale/es-ES/treestyletab/
 locale	treestyletab	de-DE	jar:chrome/treestyletab.jar!/locale/de-DE/treestyletab/
 locale	treestyletab	zh-TW	jar:chrome/treestyletab.jar!/locale/zh-TW/treestyletab/
-locale	treestyletab	ru-RU	jar:chrome/treestyletab.jar!/locale/ru-RU/treestyletab/
+locale	treestyletab	ru	jar:chrome/treestyletab.jar!/locale/ru/treestyletab/
 locale	treestyletab	pl	jar:chrome/treestyletab.jar!/locale/pl/treestyletab/
 locale	treestyletab	fr-FR	jar:chrome/treestyletab.jar!/locale/fr-FR/treestyletab/
 locale	treestyletab	sv-SE	jar:chrome/treestyletab.jar!/locale/sv-SE/treestyletab/
@@ -32,38 +33,25 @@ skin	treestyletab	classic/1.0	jar:chrome/treestyletab.jar!/skin/classic/treestyl
 override chrome://treestyletab/skin/group/group-icon	chrome://treestyletab/skin/group/group-fx3.png
 override chrome://treestyletab/skin/group/group-icon	chrome://treestyletab/skin/group/group-fx3-aero.png	os=WINNT osversion>=6
 
-override chrome://treestyletab/skin/square/tab-surface.css	chrome://treestyletab/skin/square/tab-surface-3.css
-override chrome://treestyletab/skin/square/tab-surface.css	chrome://treestyletab/skin/square/tab-surface-4.css	appversion>=4.0b5pre
-
-override chrome://treestyletab/skin/metal/tab.css	chrome://treestyletab/skin/metal/tab-3.5.css
-override chrome://treestyletab/skin/metal/tab.css	chrome://treestyletab/skin/metal/tab-4.css	appversion>=4.0b5pre
-override chrome://treestyletab/skin/metal/base-inactive.css	chrome://treestyletab/skin/metal/base-inactive-3.5.css
-override chrome://treestyletab/skin/metal/base-inactive.css	chrome://treestyletab/skin/metal/base-inactive-4.css	appversion>=4.0b5pre
-
-override chrome://treestyletab/skin/sidebar/inactive.css	chrome://treestyletab/skin/sidebar/inactive-3.6.css
-override chrome://treestyletab/skin/sidebar/inactive.css	chrome://treestyletab/skin/sidebar/inactive-4.css	appversion>=4.0b5pre
-
-override chrome://treestyletab/skin/config.css	chrome://treestyletab/skin/config-4.css	appversion>=4.0b5pre
-
-
 override chrome://treestyletab/skin/platform-base.css	chrome://treestyletab/skin/dummy.css	os=Darwin
 override chrome://treestyletab/skin/platform-base.css	chrome://treestyletab/skin/Linux-base.css	os=Linux
 override chrome://treestyletab/skin/platform-base.css	chrome://treestyletab/skin/dummy.css	os=WINNT
 override chrome://treestyletab/skin/platform-styled.css	chrome://treestyletab/skin/Darwin-styled.css	os=Darwin
 override chrome://treestyletab/skin/platform-styled.css	chrome://treestyletab/skin/dummy.css	os=Linux
 override chrome://treestyletab/skin/platform-styled.css	chrome://treestyletab/skin/WINNT-styled.css	os=WINNT
-override chrome://treestyletab/skin/platform-styled-inactive.css	chrome://treestyletab/skin/Darwin-styled-inactive-3.5.css	os=Darwin
-override chrome://treestyletab/skin/platform-styled-inactive.css	chrome://treestyletab/skin/Darwin-styled-inactive-4.css	os=Darwin appversion>=4.0b5pre
 
 override chrome://treestyletab/skin/square/platform.css	chrome://treestyletab/skin/square/Darwin.css	os=Darwin
 override chrome://treestyletab/skin/square/platform.css	chrome://treestyletab/skin/square/Linux.css	os=Linux
 override chrome://treestyletab/skin/square/platform.css	chrome://treestyletab/skin/dummy.css	os=WINNT
-override chrome://treestyletab/skin/square/platform-inactive.css	chrome://treestyletab/skin/square/Darwin-inactive-3.5.css	os=Darwin
-override chrome://treestyletab/skin/square/platform-inactive.css	chrome://treestyletab/skin/square/Darwin-inactive-4.css	os=Darwin appversion>=4.0b5pre
 
 override chrome://treestyletab/skin/metal/platform.css	chrome://treestyletab/skin/metal/Darwin.css	os=Darwin
 override chrome://treestyletab/skin/metal/platform.css	chrome://treestyletab/skin/dummy.css	os=WINNT
 override chrome://treestyletab/skin/metal/platform.css	chrome://treestyletab/skin/dummy.css	os=Linux
+override chrome://treestyletab/skin/metal/tab.css	chrome://treestyletab/skin/metal/tab-legacy.css
+override chrome://treestyletab/skin/metal/tab.css	chrome://treestyletab/skin/metal/tab-base.css	appversion>=12.0a1
+
+override chrome://treestyletab/skin/sidebar/sidebar.css	chrome://treestyletab/skin/sidebar/sidebar-legacy.css
+override chrome://treestyletab/skin/sidebar/sidebar.css	chrome://treestyletab/skin/sidebar/sidebar-base.css	appversion>=12.0a1
 
 override chrome://treestyletab/skin/platform-config.css	chrome://treestyletab/skin/dummy.css	os=Darwin
 override chrome://treestyletab/skin/platform-config.css	chrome://treestyletab/skin/Linux-config.css	os=Linux
diff --git a/chrome/treestyletab.jar!/content/treestyletab/bookmarksOverlay.js b/chrome/treestyletab.jar!/content/treestyletab/bookmarksOverlay.js
index a5ba95a..bc32116 100755
--- a/chrome/treestyletab.jar!/content/treestyletab/bookmarksOverlay.js
+++ b/chrome/treestyletab.jar!/content/treestyletab/bookmarksOverlay.js
@@ -17,13 +17,13 @@ var TreeStyleTabBookmarksService = {
 		if (this._observing) return;
 		this._observing = true;
 
+		aTabs = this.cleanUpTabsArray(aTabs);
+
 		this._addingBookmarks = [];
-		this._addingBookmarkTreeStructure = this
-				.cleanUpTabsArray(aTabs)
-				.map(function(aTab) {
-					var parent = this.getParentTab(aTab);
-					return aTabs.indexOf(parent);
-				}, this);
+		this._addingBookmarkTreeStructure = aTabs.map(function(aTab) {
+			var parent = this.getParentTab(aTab);
+			return aTabs.indexOf(parent);
+		}, this);
 
 		this.BookmarksService.addObserver(this, false);
 	},
@@ -34,32 +34,69 @@ var TreeStyleTabBookmarksService = {
 		this._observing = false;
 
 		this.BookmarksService.removeObserver(this);
-
+		this.handleNewBookmarksFromTabs(this._addingBookmarks, this._addingBookmarkTreeStructure);
+		this._addingBookmarks = [];
+		this._addingBookmarkTreeStructure = [];
+	},
+ 
+	handleNewBookmarksFromTabs : function TSTBMService_handleNewBookmarksFromTabs(aBookarmks, aTreeStructure) 
+	{
 		// this is adding bookmark folder from tabs, so ignroe the first item!
 		if (
-			this._addingBookmarks.length == this._addingBookmarkTreeStructure.length+1 &&
-			this.BookmarksService.getItemType(this._addingBookmarks[0].id) == this.BookmarksService.TYPE_FOLDER
-			)
-			this._addingBookmarks.shift();
+			aBookarmks.length == aTreeStructure.length+1 &&
+			this.BookmarksService.getItemType(aBookarmks[0].id) == this.BookmarksService.TYPE_FOLDER
+			) {
+			aBookarmks.shift();
+		}
+		else if (aBookarmks.length != aTreeStructure.length) {
+			return;
+		}
+
+		for (let i = 0, maxi = aBookarmks.length; i < maxi; i++)
+		{
+			let item = aBookarmks[i];
+			item.position = this.BookmarksService.getItemIndex(item.id);
+		}
+		aBookarmks.sort(function(aA, aB) {
+			return aA.position - aB.position;
+		});
+
+		for (let i = 0, maxi = aBookarmks.length; i < maxi; i++)
+		{
+			let item = aBookarmks[i];
+			if (this.BookmarksService.getItemType(item.id) != this.BookmarksService.TYPE_BOOKMARK)
+				continue;
+
+			let uri = this.BookmarksService.getBookmarkURI(item.id);
+			if (/^about:treestyletab-group\b/.test(uri.spec)) {
+				let title = this.BookmarksService.getItemTitle(item.id);
+				let folderId = this.BookmarksService.createFolder(item.parent, title, item.position);
+				this.BookmarksService.removeItem(item.id);
+				item.id = folderId;
+				item.isFolder = true;
+			}
 
-		if (this._addingBookmarks.length == this._addingBookmarkTreeStructure.length) {
-			this._addingBookmarks.forEach(function(aItem, aIndex) {
-				let index = this._addingBookmarkTreeStructure[aIndex];
-				PlacesUtils.setAnnotationsForItem(aItem.id, [{
+			let index = aTreeStructure[i];
+			let parent = index > -1 ? aBookarmks[index] : null ;
+			if (parent && (parent.folder || parent).isFolder) {
+				let folder = parent.folder || parent;
+				this.BookmarksService.moveItem(item.id, folder.id, -1);
+				item.folder = folder;
+			}
+			if (parent && !parent.isFolder) {
+				PlacesUtils.setAnnotationsForItem(item.id, [{
 					name    : this.kPARENT,
-					value   : (index > -1 ? this._addingBookmarks[index].id : -1 ),
+					value   : parent ? parent.id : -1,
 					expires : PlacesUtils.annotations.EXPIRE_NEVER
 				}]);
-			}, this);
+			}
 		}
-		this._addingBookmarks = [];
-		this._addingBookmarkTreeStructure = [];
 	},
  
 	bookmarkTabSubtree : function TSTBMService_bookmarkTabSubtree(aTabOrTabs) 
 	{
 		var tabs = aTabOrTabs;
-		if (!(tabs instanceof Array)) {
+		if (!Array.isArray(tabs)) {
 			tabs = [aTabOrTabs];
 		}
 
@@ -69,10 +106,12 @@ var TreeStyleTabBookmarksService = {
 
 		var b = this.getTabBrowserFromChild(tabs[0]);
 		var bookmarkedTabs = [];
-		tabs.forEach(function(aTab, aIndex) {
-			if (!this.isGroupTab(aTab, aIndex == 0)) bookmarkedTabs.push(aTab);
-			bookmarkedTabs = bookmarkedTabs.concat(b.treeStyleTab.getDescendantTabs(aTab));
-		}, this);
+		for (let i = 0, maxi = tabs.length; i < maxi; i++)
+		{
+			let tab = tabs[i];
+			if (!this.isGroupTab(tab, i == 0)) bookmarkedTabs.push(tab);
+			bookmarkedTabs = bookmarkedTabs.concat(b.treeStyleTab.getDescendantTabs(tab));
+		}
 
 		this.beginAddBookmarksFromTabs(bookmarkedTabs);
 		try {
@@ -147,7 +186,7 @@ var TreeStyleTabBookmarksService = {
 		if (!aNode || !PlacesUtils.nodeIsContainer(aNode)) return ids;
 
 		var root = aNode;
-		if ('getContainerNodeWithOptions' in PlacesUtils) { // Firefox 3.5 or later
+		if ('getContainerNodeWithOptions' in PlacesUtils) {
 			root = PlacesUtils.getContainerNodeWithOptions(root, false, true);
 		}
 		var oldViewer = root.parentResult.viewer;
@@ -204,13 +243,7 @@ var TreeStyleTabBookmarksService = {
 		if (!('PlacesUIUtils' in window)) return;
 
 		if (!PlacesUIUtils.__treestyletab__done) {
-			var ns;
-			try { // Firefox 4 or later
-				ns = Components.utils.import('resource://gre/modules/PlacesUIUtils.jsm', {});
-			}
-			catch(e) { // Firefox 3.6 or older
-				ns = window;
-			}
+			var ns = Components.utils.import('resource://gre/modules/PlacesUIUtils.jsm', {});
 			var sv = this;
 			with (ns) {
 
@@ -330,12 +363,15 @@ var TreeStyleTabBookmarksService = {
 						TreeStyleTabBookmarksService.beginAddBookmarksFromTabs((function() {
 							var tabs = [];
 							var seen = {};
-							Array.forEach(getBrowser().mTabContainer.childNodes, function(aTab) {
-								let uri = aTab.linkedBrowser.currentURI.spec;
-								if (uri in seen) return;
+							var allTabs = getBrowser().mTabContainer.childNodes;
+							for (let i = 0, maxi = allTabs.length; i < maxi; i++)
+							{
+								let tab = allTabs[i];
+								let uri = tab.linkedBrowser.currentURI.spec;
+								if (uri in seen) continue;
 								seen[uri] = true;
-								tabs.push(aTab);
-							});
+								tabs.push(tab);
+							}
 							return tabs;
 						})());
 						try {
@@ -434,7 +470,8 @@ var TreeStyleTabBookmarksService = {
 	onItemAdded : function TSTBMService_onItemAdded(aID, aFolderID, aPosition)
 	{
 		this._addingBookmarks.push({
-			id  : aID
+			id     : aID,
+			parent : aFolderID
 		});
 	},
 	onItemRemoved : function TSTBMService_onItemRemoved(aID, aFolderID, aPosition) {},
diff --git a/chrome/treestyletab.jar!/content/treestyletab/bookmarksOverlayEditable.js b/chrome/treestyletab.jar!/content/treestyletab/bookmarksOverlayEditable.js
index f0168ca..c25df72 100755
--- a/chrome/treestyletab.jar!/content/treestyletab/bookmarksOverlayEditable.js
+++ b/chrome/treestyletab.jar!/content/treestyletab/bookmarksOverlayEditable.js
@@ -27,8 +27,19 @@ var TreeStyleTabBookmarksServiceEditable = {
 		return document.getElementById('treestyletab-parent-blank-item');
 	},
 
+	get isCreatingMultipleBookmarksInFolder()
+	{
+		return (
+			window.arguments.length &&
+			window.arguments[0] &&
+			window.arguments[0].type == 'folder'
+		);
+	},
+
 	init : function TSTBMEditable_init()
 	{
+		if (this.isCreatingMultipleBookmarksInFolder) return;
+
 		// main browser window
 		if ('StarUI' in window) {
 			if ('_doShowEditBookmarkPanel' in StarUI) {
@@ -69,7 +80,12 @@ var TreeStyleTabBookmarksServiceEditable = {
 
 	initEditUI : function TSTBMEditable_initEditUI()
 	{
-		if (this.editUIInitialized || !('gEditItemOverlay' in window)) return;
+		if (
+			this.editUIInitialized ||
+			!('gEditItemOverlay' in window) ||
+			this.isCreatingMultipleBookmarksInFolder
+			)
+			return;
 
 		var container = document.getElementById('editBookmarkPanelGrid');
 		if (!container) return;
@@ -155,12 +171,13 @@ var TreeStyleTabBookmarksServiceEditable = {
 		}
 
 		var fragment = document.createDocumentFragment();
-		items.forEach(function(aId, aIndex) {
-			let label = PlacesUtils.bookmarks.getItemTitle(aId);
+		for (let [i, id] in Iterator(items))
+		{
+			let label = PlacesUtils.bookmarks.getItemTitle(id);
 			let item = document.createElement('menuitem');
-			item.setAttribute('value', aId);
+			item.setAttribute('value', id);
 
-			let parent = aIndex;
+			let parent = i;
 			let nest = 0;
 			let disabled = false;
 			while ((parent = treeStructure[parent]) != -1)
@@ -170,17 +187,17 @@ var TreeStyleTabBookmarksServiceEditable = {
 			}
 			if (nest) item.setAttribute('style', 'padding-left:'+nest+'em');
 
-			if (disabled || aId == aCurrentItem) {
+			if (disabled || id == aCurrentItem) {
 				item.setAttribute('disabled', true);
-				if (aId == aCurrentItem)
+				if (id == aCurrentItem)
 					label = this.treeBundle.getFormattedString('bookmarkProperty.parent.current.label', [label]);
 			}
-			if (aId == selected) item.setAttribute('selected', true);
+			if (id == selected) item.setAttribute('selected', true);
 
 			item.setAttribute('label', label);
 
 			fragment.appendChild(item);
-		}, this);
+		}
 		return fragment;
 	},
 	_getItemsInFolder : function TSTBMEditable__getItemsInFolder(aId)
diff --git a/chrome/treestyletab.jar!/content/treestyletab/config.js b/chrome/treestyletab.jar!/content/treestyletab/config.js
index f4a055a..e71d7fd 100755
--- a/chrome/treestyletab.jar!/content/treestyletab/config.js
+++ b/chrome/treestyletab.jar!/content/treestyletab/config.js
@@ -85,28 +85,18 @@ function initAppearancePane()
 		sidebar.setAttribute('disabled', true);
 	}
 
-	/* legacy feature for Firefox 3.6 or olders */
-	var hideAllTabsButton = document.getElementById('hideAlltabsButton-box');
-	if (comparator.compare(XULAppInfo.version, '4.0b3') > 0) {
-		hideAllTabsButton.setAttribute('hidden', true);
-	}
-	else {
-		hideAllTabsButton.removeAttribute('hidden');
-	}
-
 	var boxes = [
 			document.getElementById('extensions.treestyletab.tabbar.style-arrowscrollbox'),
 			document.getElementById('extensions.treestyletab.twisty.style-arrowscrollbox')
 		];
-	Array.slice(boxes[0].childNodes).concat(Array.slice(boxes[1].childNodes))
-	.forEach(function(aItem) {
-		var start       = 0;
-		var delta       = 200;
-		var radian      = 90 * Math.PI / 180;
+	Array.slice(boxes[0].childNodes).concat(Array.slice(boxes[1].childNodes)).forEach(function(aItem) {
+		let start       = 0;
+		let delta       = 200;
+		let radian      = 90 * Math.PI / 180;
 		aItem.style.overflow = 'hidden';
 		aItem.width = 0;
 		aItem.style.maxWidth = 0;
-		var task = function(aTime, aBeginning, aChange, aDuration) {
+		let task = function(aTime, aBeginning, aChange, aDuration) {
 			var width;
 			if (aTime >= aDuration) {
 				width = start + delta;
@@ -195,17 +185,20 @@ function onSyncGroupBookmarkUIToPref()
 	if (gGroupBookmarkUnderParent.checked) behavior |= 256;
 	if (gGroupBookmarkType.value == 'true') behavior |= 512;
 
-	[
-		gGroupBookmarkUnderParent,
-		gGroupBookmarkType,
-		gGroupBookmarkType.previousSibling,
-		gGroupBookmarkType.nextSibling
-	].forEach(function(aNode) {
+	var nodes = [
+			gGroupBookmarkUnderParent,
+			gGroupBookmarkType,
+			gGroupBookmarkType.previousSibling,
+			gGroupBookmarkType.nextSibling
+		];
+	for (let i = 0, maxi = nodes.length; i < maxi; i++)
+	{
+		let node = nodes[i];
 		if (behavior & 1)
-			aNode.removeAttribute('disabled');
+			node.removeAttribute('disabled');
 		else
-			aNode.setAttribute('disabled', true);
-	});
+			node.setAttribute('disabled', true);
+	}
 
 	return behavior;
 }
@@ -248,24 +241,18 @@ function onChangeTabbarPosition()
 	var maxTreeLevelV   = document.getElementById('maxTreeLevel-vertical');
 	var collapseCheckH = document.getElementById('extensions.treestyletab.allowSubtreeCollapseExpand.horizontal-check');
 	var collapseCheckV = document.getElementById('extensions.treestyletab.allowSubtreeCollapseExpand.vertical-check');
-	var hideAllTabsCheckH = document.getElementById('extensions.treestyletab.tabbar.hideAlltabsButton.horizontal-check');
-	var hideAllTabsCheckV = document.getElementById('extensions.treestyletab.tabbar.hideAlltabsButton.vertical-check');
 
 	if (pos == 'left' || pos == 'right') {
 		maxTreeLevelH.setAttribute('collapsed', true);
 		maxTreeLevelV.removeAttribute('collapsed');
 		collapseCheckH.setAttribute('collapsed', true);
 		collapseCheckV.removeAttribute('collapsed');
-		hideAllTabsCheckH.setAttribute('collapsed', true);
-		hideAllTabsCheckV.removeAttribute('collapsed');
 	}       
 	else {
 		maxTreeLevelH.removeAttribute('collapsed');
 		maxTreeLevelV.setAttribute('collapsed', true);
 		collapseCheckH.removeAttribute('collapsed');
 		collapseCheckV.setAttribute('collapsed', true);
-		hideAllTabsCheckH.removeAttribute('collapsed');
-		hideAllTabsCheckV.setAttribute('collapsed', true);
 	}
 
 	gTabbarPlacePositionInitialized = true;
diff --git a/chrome/treestyletab.jar!/content/treestyletab/config.xul b/chrome/treestyletab.jar!/content/treestyletab/config.xul
index f764145..83e6d65 100755
--- a/chrome/treestyletab.jar!/content/treestyletab/config.xul
+++ b/chrome/treestyletab.jar!/content/treestyletab/config.xul
@@ -36,16 +36,6 @@
 		<preference id="extensions.treestyletab.allowSubtreeCollapseExpand.vertical"
 			name="extensions.treestyletab.allowSubtreeCollapseExpand.vertical"
 			type="bool"/>
-		<!-- legacy feature for Firefox 3.6 or olders -->
-		<preference id="extensions.treestyletab.tabbar.hideAlltabsButton.horizontal"
-			name="extensions.treestyletab.tabbar.hideAlltabsButton.horizontal"
-			type="bool"
-			inverted="true"/>
-		<!-- legacy feature for Firefox 3.6 or olders -->
-		<preference id="extensions.treestyletab.tabbar.hideAlltabsButton.vertical"
-			name="extensions.treestyletab.tabbar.hideAlltabsButton.vertical"
-			type="bool"
-			inverted="true"/>
 		<preference id="extensions.treestyletab.tabbar.invertClosebox"
 			name="extensions.treestyletab.tabbar.invertClosebox"
 			type="bool"/>
@@ -129,15 +119,6 @@
 			<checkbox id="extensions.treestyletab.allowSubtreeCollapseExpand.vertical-check"
 				preference="extensions.treestyletab.allowSubtreeCollapseExpand.vertical"
 				label="&config.allowSubtreeCollapseExpand;"/>
-			<hbox align="center" id="hideAlltabsButton-box"><!-- legacy feature for Firefox 3.6 or olders -->
-				<checkbox id="extensions.treestyletab.tabbar.hideAlltabsButton.horizontal-check"
-					preference="extensions.treestyletab.tabbar.hideAlltabsButton.horizontal"
-					label="&config.tabbar.hideAlltabsButton;"
-					collapsed="true"/>
-				<checkbox id="extensions.treestyletab.tabbar.hideAlltabsButton.vertical-check"
-					preference="extensions.treestyletab.tabbar.hideAlltabsButton.vertical"
-					label="&config.tabbar.hideAlltabsButton;"/>
-			</hbox>
 		</hbox>
 		<hbox id="maxTreeLevel-horizontal"
 			align="center">
@@ -750,9 +731,9 @@
 		<preference id="extensions.treestyletab.animation.enabled"
 			name="extensions.treestyletab.animation.enabled"
 			type="bool"/>
-		<preference id="extensions.treestyletab.tooltip.includeChildren"
-			name="extensions.treestyletab.tooltip.includeChildren"
-			type="bool"/>
+		<preference id="extensions.treestyletab.tooltip.mode"
+			name="extensions.treestyletab.tooltip.mode"
+			type="int"/>
 		<preference id="extensions.treestyletab.bookmarkDroppedTabs.behavior"
 			name="extensions.treestyletab.bookmarkDroppedTabs.behavior"
 			type="int"/>
@@ -764,9 +745,11 @@
 	<checkbox id="extensions.treestyletab.animation.enabled-check"
 		preference="extensions.treestyletab.animation.enabled"
 		label="&config.animation.enabled;"/>
-	<checkbox id="extensions.treestyletab.tooltip.includeChildren-check"
-		preference="extensions.treestyletab.tooltip.includeChildren"
-		label="&config.tooltip.includeChildren;"/>
+	<checkbox id="extensions.treestyletab.tooltip.mode-check"
+		preference="extensions.treestyletab.tooltip.mode"
+		label="&config.tooltip.includeChildren;"
+		onsynctopreference="return document.getElementById('extensions.treestyletab.tooltip.mode-check').checked ? 2 : 0 ;"
+		onsyncfrompreference="return document.getElementById('extensions.treestyletab.tooltip.mode').value == 2;"/>
 
 	<groupbox>
 		<caption label="&config.bookmarkDroppedTabs.caption;"/>
diff --git a/chrome/treestyletab.jar!/content/treestyletab/group.xul b/chrome/treestyletab.jar!/content/treestyletab/group.xul
index 0089875..ef62343 100755
--- a/chrome/treestyletab.jar!/content/treestyletab/group.xul
+++ b/chrome/treestyletab.jar!/content/treestyletab/group.xul
@@ -1,10 +1,15 @@
 <?xml-stylesheet type="text/css" href="chrome://global/skin/"?>
 <?xml-stylesheet type="text/css" href="chrome://treestyletab/skin/group/group.css"?>
+<?xml-stylesheet type="text/css" href="chrome://treestyletab/skin/pseudo-tree.css"?>
 <!DOCTYPE page SYSTEM "chrome://treestyletab/locale/treestyletab.dtd">
 <page xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-	onclick="onClick(event)"
-	ondblclick="onDblClick(event)"
 	title="&group.default;">
+<commandset>
+	<command id="cmd_enterEdit" oncommand="groupTab.enterEdit()"/>
+</commandset>
+<keyset>
+	<key keycode="VK_F2" command="cmd_enterEdit"/>
+</keyset>
 <stack flex="1">
 	<box class="background-image-container">
 		<image class="icon background-image"/>
@@ -23,86 +28,19 @@
 				<image class="icon"/>
 				<textbox id="editor"
 					flex="1"
-					onkeypress="onKeyPress(event)"
 					value="&group.default;"/>
 			</hbox>
 		</deck>
+		<vbox id="tree"
+			flex="1"/>
 	</vbox>
 </stack>
 <link xmlns="http://www.w3.org/1999/xhtml" rel="icon"
 	href="chrome://treestyletab/skin/group/group-icon"/>
 <script type="application/javascript"><![CDATA[
 
-var gIcon = document.getElementById('icon');
-var gLabel = document.getElementById('label');
-var gEdit = document.getElementById('editor');
-var gDeck = document.getElementById('deck');
-
-function trim(aString)
-{
-	return aString.replace(/^\s+|\s+$/g, '');
-}
-
-var title = location.href.split('?')[1];
-if (location.href.indexOf('?') > -1 && title) {
-	title = trim(decodeURIComponent(title));
-	document.title = title;
-	document.documentElement.setAttribute('title', title);
-	gLabel.value = title;
-	gLabel.setAttribute('tooltiptext', title);
-	gEdit.value = title;
-}
-
-function enterEdit()
-{
-	gEdit.value = gLabel.value;
-	gDeck.selectedIndex = 1;
-	gEdit.focus();
-	gEdit.select();
-}
-
-function exitEdit()
-{
-	if (gDeck.selectedIndex == 0) return;
-
-	var old = trim(gLabel.value);
-	var value = trim(gEdit.value);
-	document.title = gLabel.value = value;
-	gLabel.setAttribute('tooltiptext', value);
-	document.documentElement.setAttribute('title', value);
-
-	if (value != old)
-		location.replace(location.href.split('?')[0]+'?'+encodeURIComponent(value));
-
-	gEdit.blur();
-	gDeck.selectedIndex = 0;
-}
-
-function onClick(aEvent)
-{
-	if (aEvent.target == gEdit) return;
-	if (aEvent.target == gLabel)
-		enterEdit();
-	else
-		exitEdit();
-}
-
-function onDblClick(aEvent)
-{
-	if (aEvent.target == gEdit) return;
-	if (gDeck.selectedIndex == 0)
-		enterEdit();
-	else
-		exitEdit();
-}
-
-function onKeyPress(aEvent)
-{
-	if (aEvent.keyCode == aEvent.DOM_VK_ENTER ||
-		aEvent.keyCode == aEvent.DOM_VK_RETURN ||
-		aEvent.keyCode == aEvent.DOM_VK_ESCAPE)
-		exitEdit();
-}
+Components.utils.import('resource://treestyletab-modules/groupTab.js');
+new GroupTab(window);
 
 ]]></script>
 </page>
diff --git a/chrome/treestyletab.jar!/content/treestyletab/license.txt b/chrome/treestyletab.jar!/content/treestyletab/license.txt
index 61ee6e9..be60760 100755
--- a/chrome/treestyletab.jar!/content/treestyletab/license.txt
+++ b/chrome/treestyletab.jar!/content/treestyletab/license.txt
@@ -14,10 +14,10 @@ License.
 The Original Code is the Tree Style Tab.
 
 The Initial Developer of the Original Code is SHIMODA Hiroshi.
-Portions created by the Initial Developer are Copyright (C) 2007-2011
+Portions created by the Initial Developer are Copyright (C) 2007-2012
 the Initial Developer. All Rights Reserved.
 
-Contributor(s): SHIMODA Hiroshi <piro at p.club.ne.jp>
+Contributor(s): SHIMODA Hiroshi <piro.outsider.reflex at gmail.com>
                 Alice0775 (fixes some compatibility problems)
 
 Alternatively, the contents of these files may be used under the terms of
diff --git a/chrome/treestyletab.jar!/content/treestyletab/res/bookmarkMultipleTabs.xul b/chrome/treestyletab.jar!/content/treestyletab/res/bookmarkMultipleTabs.xul
index 50d97c8..3a41df5 100755
--- a/chrome/treestyletab.jar!/content/treestyletab/res/bookmarkMultipleTabs.xul
+++ b/chrome/treestyletab.jar!/content/treestyletab/res/bookmarkMultipleTabs.xul
@@ -6,17 +6,19 @@
    in chrome.manifest:
      overlay  chrome://browser/content/browser.xul
               chrome://***/content/bookmarkMultipleTabs.xul
+     overlay  chrome://browser/content/places/bookmarkProperties.xul
+              chrome://***/content/bookmarkMultipleTabs_bookmarkPropertiesOverlay.xul
      overlay  chrome://browser/content/places/bookmarkProperties2.xul
               chrome://***/content/bookmarkMultipleTabs_bookmarkPropertiesOverlay.xul
 
    in JS files:
      window['piro.sakura.ne.jp'].bookmarkMultipleTabs.addBookmarkFor(tabsArray, folderName);
 
- license: The MIT License, Copyright (c) 2009-2010 SHIMODA "Piro" Hiroshi
-   http://www.cozmixng.org/repos/piro/fx3-compatibility-lib/trunk/license.txt
+ license: The MIT License, Copyright (c) 2009-2012 SHIMODA "Piro" Hiroshi
+   http://github.com/piroor/fxaddonlibs/blob/master/license.txt
  original:
-   http://www.cozmixng.org/repos/piro/fx3-compatibility-lib/trunk/bookmarkMultipleTabs.xul
-   http://www.cozmixng.org/repos/piro/fx3-compatibility-lib/trunk/bookmarkMultipleTabs_bookmarkPropertiesOverlay.xul
+   http://github.com/piroor/fxaddonlibs/blob/master/bookmarkMultipleTabs.xul
+   http://github.com/piroor/fxaddonlibs/blob/master/bookmarkMultipleTabs_bookmarkPropertiesOverlay.xul
 -->
 <overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 <script type="application/javascript"><![CDATA[
@@ -24,7 +26,7 @@
 window.addEventListener('DOMContentLoaded', function() {
 	window.removeEventListener('DOMContentLoaded', arguments.callee, true);
 
-	const currentRevision = 4;
+	const currentRevision = 5;
 
 	if (!('piro.sakura.ne.jp' in window)) window['piro.sakura.ne.jp'] = {};
 
@@ -57,12 +59,34 @@ window.addEventListener('DOMContentLoaded', function() {
 
 			var b = this.getTabBrowserFromChild(aTabs[0]);
 
-			if ('PlacesUIUtils' in window || 'PlacesUtils' in window) { // Firefox 3
-				if (aFolderName)
-					this.Prefs.setCharPref('temp.showMinimalAddMultiBookmarkUI.folderName', unescape(encodeURIComponent(aFolderName)));
-				var utils = 'PlacesUIUtils' in window ? PlacesUIUtils : PlacesUtils ;
-				utils.showMinimalAddMultiBookmarkUI(Array.slice(aTabs).map(this.addBookmarkTabsFilter));
-				this.Prefs.clearUserPref('temp.showMinimalAddMultiBookmarkUI.folderName');
+			if ('PlacesUIUtils' in window || 'PlacesUtils' in window) { // Firefox 3 or later
+				try {
+					var utils = 'PlacesUIUtils' in window ? PlacesUIUtils : PlacesUtils ;
+					var tabs = Array.slice(aTabs).map(this.addBookmarkTabsFilter);
+					if (aFolderName)
+						this.Prefs.setCharPref('temp.showMinimalAddMultiBookmarkUI.folderName', unescape(encodeURIComponent(aFolderName)));
+					if ('showBookmarkDialog' in utils) { // Firefox 9 or later
+						utils.showBookmarkDialog({
+							action  : 'add',
+							type    : 'folder',
+							// title   : aFolderName, // don't specify it, because Firefox doesn't create bookmarks if the title is given!
+							URIList : tabs,
+							hiddenRows : ['description', 'location', 'loadInSidebar', 'keyword']
+						}, window);
+					}
+					else if ('showMinimalAddMultiBookmarkUI' in utils) { // Firefox 3 - 8
+						utils.showMinimalAddMultiBookmarkUI(tabs);
+					}
+					else {
+						throw new Error('there is no method to create bookmarks from tabs!');
+					}
+				}
+				catch(e) {
+					alert(e.message+'\n'+e.stack);
+				}
+				finally {
+					this.Prefs.clearUserPref('temp.showMinimalAddMultiBookmarkUI.folderName');
+				}
 				return;
 			}
 
diff --git a/chrome/treestyletab.jar!/content/treestyletab/res/bookmarkMultipleTabs_bookmarkPropertiesOverlay.xul b/chrome/treestyletab.jar!/content/treestyletab/res/bookmarkMultipleTabs_bookmarkPropertiesOverlay.xul
index 5eaf4a4..2e15651 100755
--- a/chrome/treestyletab.jar!/content/treestyletab/res/bookmarkMultipleTabs_bookmarkPropertiesOverlay.xul
+++ b/chrome/treestyletab.jar!/content/treestyletab/res/bookmarkMultipleTabs_bookmarkPropertiesOverlay.xul
@@ -6,13 +6,15 @@
    in chrome.manifest:
      overlay  chrome://browser/content/browser.xul
               chrome://***/content/bookmarkMultipleTabs.xul
+     overlay  chrome://browser/content/places/bookmarkProperties.xul
+              chrome://***/content/bookmarkMultipleTabs_bookmarkPropertiesOverlay.xul
      overlay  chrome://browser/content/places/bookmarkProperties2.xul
               chrome://***/content/bookmarkMultipleTabs_bookmarkPropertiesOverlay.xul
 
    in JS files:
      window['piro.sakura.ne.jp'].bookmarkMultipleTabs.addBookmarkFor(tabsArray, folderName);
 
- license: The MIT License, Copyright (c) 2009 SHIMODA "Piro" Hiroshi
+ license: The MIT License, Copyright (c) 2009-2012 SHIMODA "Piro" Hiroshi
    http://www.cozmixng.org/repos/piro/fx3-compatibility-lib/trunk/license.txt
  original:
    http://www.cozmixng.org/repos/piro/fx3-compatibility-lib/trunk/bookmarkMultipleTabs.xul
diff --git a/chrome/treestyletab.jar!/content/treestyletab/res/tabFx2Compatible.css b/chrome/treestyletab.jar!/content/treestyletab/res/tabFx2Compatible.css
deleted file mode 100755
index 08b03b3..0000000
--- a/chrome/treestyletab.jar!/content/treestyletab/res/tabFx2Compatible.css
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- Firefox 2 compatible tab structure library for Firefox 3 or later
-
- Usage:
-   <?xul-overlay href="tabFx2Compatible.xul"?>
-
- license: The MIT License, Copyright (c) 2009-2011 SHIMODA "Piro" Hiroshi
-   http://github.com/piroor/fxaddonlibs/blob/master/license.txt
- original:
-   http://github.com/piroor/fxaddonlibs/blob/master/tabFx2Compatible.xul
-   http://github.com/piroor/fxaddonlibs/blob/master/tabFx2Compatible.xml
-   http://github.com/piroor/fxaddonlibs/blob/master/tabFx2Compatible.css
-*/
-
- at namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-
-:root[tabFx2Compatible="15"]
-  .tabbrowser-tab {
-	-moz-binding: url(tabFx2Compatible.xml#tabbrowser-tab-3) !important;
-}
-
-:root[tabFx2Compatible="15"][tabFx2Compatible-flags~="separate-tabContextMenu"]
-  .tabbrowser-tab {
-	-moz-binding: url(tabFx2Compatible.xml#tabbrowser-tab-4) !important;
-}
-
-:root[tabFx2Compatible="15"]:not([tabFx2Compatible-flags~="png-throbber"])[tabFx2Compatible-flags~="fx3"]
-  .tab-icon-image[busy] {
-	list-style-image: url("chrome://global/skin/throbber/Throbber-small.gif") !important;
-	opacity: 0.6;
-}
-
-:root[tabFx2Compatible="15"][tabFx2Compatible-flags~="png-throbber"][tabFx2Compatible-flags~="fx3"]
-  .tab-icon-image[busy] {
-	list-style-image: url("chrome://global/skin/icons/loading_16.png") !important;
-}
-
-:root[tabFx2Compatible="15"][tabFx2Compatible-flags~="mac"][tabFx2Compatible-flags~="png-throbber"]
-  .tab-icon-image {
-	list-style-image: url("chrome://global/skin/tree/item.png");
-}
-:root[tabFx2Compatible="15"][tabFx2Compatible-flags~="blank-favicon"]
-  .tab-icon-image {
-	list-style-image: url("chrome://mozapps/skin/places/defaultFavicon.png");
-}
-
-:root[tabFx2Compatible="15"][tabFx2Compatible-flags~="mac"]
-  .tabbrowser-tab:not(:hover) .tab-icon-image:not([selected="true"]) {
-	opacity: 0.6;
-}
-
-:root[tabFx2Compatible="15"]
-  .tabbrowser-tab:focus > .tab-image-middle {
-	outline: 1px dotted;
-}
-/* we must split declarations for old Gecko */
-:root[tabFx2Compatible="15"]
-  .tabbrowser-tab:-moz-focusring > .tab-stack {
-	outline: 1px dotted;
-}
-
-
-:root[tabFx2Compatible="15"]
-  .tab-image-left[pinned="true"],
-:root[tabFx2Compatible="15"]
-  .tab-image-right[pinned="true"] {
-	display: none !important;
-}
-
-/* Tab Utilities */
-:root[tabFx2Compatible="15"]
-  .tabbrowser-tabs[highlightLocked][highlightSelected][highlightUnread]
-  > .tabbrowser-tab .tab-icon > .tab-icon-image ~ *,
-:root[tabFx2Compatible="15"]
-  .tabbrowser-tabs[highlightlocked][highlightselected][highlightunread]
-  > .tabbrowser-tab .tab-icon > .tab-icon-image ~ * {
-	background: none !important;
-}
-
diff --git a/chrome/treestyletab.jar!/content/treestyletab/res/tabFx2Compatible.xml b/chrome/treestyletab.jar!/content/treestyletab/res/tabFx2Compatible.xml
deleted file mode 100755
index 3846a91..0000000
--- a/chrome/treestyletab.jar!/content/treestyletab/res/tabFx2Compatible.xml
+++ /dev/null
@@ -1,107 +0,0 @@
-<?xml version="1.0"?>
-<!--
- Firefox 2 compatible tab structure library for Firefox 3 or later
-
- Usage:
-   <?xul-overlay href="tabFx2Compatible.xul"?>
-
- license: The MIT License, Copyright (c) 2009-2011 SHIMODA "Piro" Hiroshi
-   http://github.com/piroor/fxaddonlibs/blob/master/license.txt
- original:
-   http://github.com/piroor/fxaddonlibs/blob/master/tabFx2Compatible.xul
-   http://github.com/piroor/fxaddonlibs/blob/master/tabFx2Compatible.xml
-   http://github.com/piroor/fxaddonlibs/blob/master/tabFx2Compatible.css
--->
-
-<!DOCTYPE bindings [
-<!ENTITY % tabBrowserDTD SYSTEM "chrome://browser/locale/tabbrowser.dtd" >
-%tabBrowserDTD;
-<!ENTITY % globalDTD SYSTEM "chrome://global/locale/global.dtd">
-%globalDTD;
-]>
-
-<bindings id="tabFx2CompatibleBindings"
-	xmlns="http://www.mozilla.org/xbl"
-	xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
-	xmlns:xbl="http://www.mozilla.org/xbl">
-
-	<binding id="tabbrowser-tab-3"
-		extends="chrome://browser/content/tabbrowser.xml#tabbrowser-tab">
-		<content chromedir="&locale.dir;"
-			closetabtext="&closeTab.label;">
-			<xul:hbox xbl:inherits="fadein,pinned,selected"
-				class="tab-image-left"/>
-			<xul:hbox xbl:inherits="fadein,pinned,selected"
-				flex="1"
-				align="center"
-				class="tab-image-middle">
-				<xul:stack class="tab-icon">
-					<xul:image xbl:inherits="validate,src=image,fadein,pinned,busy,stalled,progress,selected"
-						class="tab-icon-image"
-						role="presentation"/>
-					<xul:image class="tab-extra-status"/>
-				</xul:stack>
-				<xul:label xbl:inherits="value=label,crop,accesskey,fadein,pinned,selected"
-					flex="1"
-					class="tab-text"
-					role="presentation"/>
-			</xul:hbox>
-			<xul:toolbarbutton xbl:inherits="fadein,pinned,selected"
-				anonid="close-button"
-				tabindex="-1"
-				clickthrough="never"
-				class="tab-close-button"/>
-			<xul:hbox xbl:inherits="fadein,pinned,selected"
-				class="tab-image-right"/>
-		</content>
-	</binding>
-
-	<binding id="tabbrowser-tab-4"
-		extends="chrome://browser/content/tabbrowser.xml#tabbrowser-tab">
-		<content context="tabContextMenu"
-			closetabtext="&closeTab.label;">
-			<xul:stack class="tab-stack" flex="1">
-				<xul:hbox xbl:inherits="pinned,selected,titlechanged"
-					class="tab-background">
-					<xul:hbox xbl:inherits="pinned,selected,titlechanged"
-						class="tab-background-start"/>
-					<xul:hbox xbl:inherits="pinned,selected,titlechanged"
-						class="tab-background-middle"/>
-					<xul:hbox xbl:inherits="pinned,selected,titlechanged"
-						class="tab-background-end"/>
-				</xul:hbox>
-				<xul:hbox xbl:inherits="pinned,selected,titlechanged"
-					class="tab-content" align="center">
-					<xul:hbox xbl:inherits="fadein,pinned,selected"
-						class="tab-image-left"/>
-					<xul:hbox xbl:inherits="fadein,pinned,selected"
-						flex="1"
-						align="center"
-						class="tab-image-middle">
-						<xul:stack class="tab-icon">
-							<xul:image xbl:inherits="fadein,pinned,busy,progress,selected"
-								class="tab-throbber"
-								role="presentation"/>
-							<xul:image xbl:inherits="validate,src=image,fadein,pinned,busy,selected"
-								class="tab-icon-image"
-								role="presentation"/>
-							<xul:image class="tab-extra-status"/>
-						</xul:stack>
-						<xul:label xbl:inherits="value=label,crop,accesskey,fadein,pinned,selected"
-							flex="1"
-							class="tab-text tab-label"
-							role="presentation"/>
-					</xul:hbox>
-					<xul:toolbarbutton xbl:inherits="fadein,pinned,selected"
-						anonid="close-button"
-						tabindex="-1"
-						clickthrough="never"
-						class="tab-close-button"/>
-					<xul:hbox xbl:inherits="fadein,pinned,selected"
-						class="tab-image-right"/>
-				</xul:hbox>
-			</xul:stack>
-		</content>
-	</binding>
-
-</bindings>
diff --git a/chrome/treestyletab.jar!/content/treestyletab/res/tabFx2Compatible.xul b/chrome/treestyletab.jar!/content/treestyletab/res/tabFx2Compatible.xul
deleted file mode 100755
index b8477e5..0000000
--- a/chrome/treestyletab.jar!/content/treestyletab/res/tabFx2Compatible.xul
+++ /dev/null
@@ -1,92 +0,0 @@
-<?xml version="1.0"?>
-<!--
- Firefox 2 compatible tab structure library for Firefox 3 or later
-
- Usage:
-   <?xul-overlay href="tabFx2Compatible.xul"?>
-
- license: The MIT License, Copyright (c) 2009-2011 SHIMODA "Piro" Hiroshi
-   http://github.com/piroor/fxaddonlibs/blob/master/license.txt
- original:
-   http://github.com/piroor/fxaddonlibs/blob/master/tabFx2Compatible.xul
-   http://github.com/piroor/fxaddonlibs/blob/master/tabFx2Compatible.xml
-   http://github.com/piroor/fxaddonlibs/blob/master/tabFx2Compatible.css
--->
-<?xml-stylesheet href="tabFx2Compatible.css" type="text/css"?>
-<overlay xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
-<script type="application/javascript"><![CDATA[
-
-window.addEventListener('DOMContentLoaded', function() {
-	window.removeEventListener('DOMContentLoaded', arguments.callee, true);
-
-	const currentRevision = 15;
-
-	var b = document.getElementById('content');
-	if (!b || b.localName != 'tabbrowser') return;
-
-	var root = document.documentElement;
-
-	var loadedRevision = root.getAttribute('tabFx2Compatible');
-	if (loadedRevision) {
-		loadedRevision = Number(loadedRevision);
-		if (loadedRevision >= currentRevision) {
-			return;
-		}
-		else if (loadedRevision < currentRevision) {
-			root.setAttribute('tabFx2Compatible', currentRevision);
-			return;
-		}
-	}
-
-	const Cc = Components.classes;
-	const Ci = Components.interfaces;
-
-	const XULAppInfo = Cc['@mozilla.org/xre/app-info;1']
-						.getService(Ci.nsIXULAppInfo)
-						.QueryInterface(Ci.nsIXULRuntime);
-	const Comparator = Cc['@mozilla.org/xpcom/version-comparator;1']
-						.getService(Ci.nsIVersionComparator);
-
-	var url = window.getComputedStyle(b.selectedTab, '').getPropertyValue('-moz-binding');
-	url = url.match(/url\((.+)\)/);
-	if (url) {
-		url = url[1];
-		if (url && url.indexOf('"') == 0)
-			url = url.replace(/^"|"$/g, '');
-		else if (url && url.indexOf("'") == 0)
-			url = url.replace(/^'|'$/g, '');
-	}
-	switch (url)
-	{
-		case 'chrome://browser/skin/browser.xml#tabbrowser-tab': // defied by theme
-			const Pref = Components.classes['@mozilla.org/preferences;1']
-					.getService(Components.interfaces.nsIPrefBranch);
-			var skin = decodeURIComponent(escape(Pref.getCharPref('general.skins.selectedSkin')));
-			switch (skin.toLowerCase())
-			{
-				case 'classic/1.0': // Default
-				case 'chromifox': // Chromifox Basic: https://addons.mozilla.org/firefox/addon/8782
-					break;
-				default:
-					return;
-			}
-		case 'chrome://browser/content/tabbrowser.xml#tabbrowser-tab': // built-in
-			root.setAttribute('tabFx2Compatible', currentRevision);
-			var flags = [];
-			if (XULAppInfo.OS.toLowerCase().indexOf('darwin') > -1)
-				flags.push('mac');
-			if (Comparator.compare(XULAppInfo.version, '3.1') >= 0)
-				flags.push('png-throbber');
-			if (Comparator.compare(XULAppInfo.version, '4.0b1') >= 0)
-				flags.push('separate-tabContextMenu');
-			if (Comparator.compare(XULAppInfo.version, '7.0') > 0)
-				flags.push('blank-favicon');
-			else
-				flags.push('fx3');
-			root.setAttribute('tabFx2Compatible-flags', flags.join(' '));
-			break;
-	}
-}, true);
-
-]]></script>
-</overlay>
diff --git a/chrome/treestyletab.jar!/content/treestyletab/treestyletab.css b/chrome/treestyletab.jar!/content/treestyletab/treestyletab.css
index 0ff4a00..a0d3351 100755
--- a/chrome/treestyletab.jar!/content/treestyletab/treestyletab.css
+++ b/chrome/treestyletab.jar!/content/treestyletab/treestyletab.css
@@ -4,16 +4,25 @@
 
 /* twisty in tabs */
 .treestyletab-twisty,
-.tabbrowser-tabs[treestyletab-twisty-style="none"]
-  .treestyletab-twisty-container,
 .tabbrowser-tabs:not([treestyletab-allow-subtree-collapse="true"])
-  .treestyletab-twisty-container {
-	display: none;
+  .treestyletab-twisty {
+	visibility: hidden;
 }
-.tabbrowser-tabs[treestyletab-allow-subtree-collapse="true"]
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-allow-subtree-collapse="true"]:not([treestyletab-twisty-style="none"])
+  .tabbrowser-tab[treestyletab-children][treestyletab-allow-subtree-collapse="true"]
+  .treestyletab-twisty,
+.tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-allow-subtree-collapse="true"]:not([treestyletab-twisty-style="none"])
   .tabbrowser-tab[treestyletab-children][treestyletab-allow-subtree-collapse="true"]
   .treestyletab-twisty {
-	display: -moz-box;
+	visibility: visible;
+}
+.tabbrowser-tabs[treestyletab-twisty-style="none"]
+  .treestyletab-twisty,
+.tabbrowser-tabs[treestyletab-mode="horizontal"]
+  .treestyletab-twisty,
+.tabbrowser-tab[pinned="true"]
+  .treestyletab-twisty {
+	visibility: collapse;
 }
 
 /* collapsed children counter */
@@ -26,12 +35,6 @@
 	display: -moz-box;
 }
 
-/* drop marker */
-.tabbrowser-tab:not([treestyletab-drop-position])
-  .treestyletab-drop-marker {
-	display: none;
-}
-
 /* collapse/expand tree of tabs */
 .tabbrowser-tabs[treestyletab-allow-subtree-collapse="true"]
   .tabbrowser-tab[treestyletab-collapsed-done="true"] {
@@ -44,6 +47,14 @@
 	position: relative;
 }
 .tabbrowser-tabs[treestyletab-allow-subtree-collapse="true"][treestyletab-stack-collapsed-tabs="true"]
+  .tabbrowser-tab[treestyletab-collapsed="true"][fadein],
+/**
+ * Tab Mix Plus dynamically inserts a CSS rule like
+ * "#tabbrowser-tabs > .tabbrowser-tab { ... }" and it unexpectedly
+ * expands width of "collapsed" tabs. So, to apply our rule prior than
+ * TMP's one, I put the "#tabbrowser-tabs" version also.
+ */
+#tabbrowser-tabs[treestyletab-allow-subtree-collapse="true"][treestyletab-stack-collapsed-tabs="true"]
   .tabbrowser-tab[treestyletab-collapsed="true"][fadein] {
 	visibility: visible;
 	max-width: 20px;
@@ -53,13 +64,7 @@
 	mask: url("res/tabEffects.svg#fadein-mask");
 }
 .tabbrowser-tabs[treestyletab-allow-subtree-collapse="true"][treestyletab-stack-collapsed-tabs="true"]
-  .tabbrowser-tab[treestyletab-collapsed-done="true"] .tab-image-left > *,
-.tabbrowser-tabs[treestyletab-allow-subtree-collapse="true"][treestyletab-stack-collapsed-tabs="true"]
-  .tabbrowser-tab[treestyletab-collapsed-done="true"] .tab-image-middle > *,
-.tabbrowser-tabs[treestyletab-allow-subtree-collapse="true"][treestyletab-stack-collapsed-tabs="true"]
-  .tabbrowser-tab[treestyletab-collapsed-done="true"] .tab-image-right > *,
-.tabbrowser-tabs[treestyletab-allow-subtree-collapse="true"][treestyletab-stack-collapsed-tabs="true"]
-  .tabbrowser-tab[treestyletab-collapsed-done="true"] .tab-close-button {
+  .tabbrowser-tab[treestyletab-collapsed-done="true"] .tab-content > * {
 	visibility: collapse;
 }
 
@@ -118,11 +123,6 @@ tabbrowser[treestyletab-tabbar-autohide-mode="1"][treestyletab-tabbar-autohide="
 	font-size: 0 !important; /* to avoid an useless space above the splitter */
 }
 
-/* Firefox 3.0-3.6 (not for 4.0 or later) */
-#appcontent {
-	margin: 0;
-}
-
 .tabbrowser-tabs[treestyletab-tabbar-autohide]
   .tabs-stack
   > *:first-child
@@ -135,6 +135,22 @@ tabbrowser[treestyletab-tabbar-autohide-mode="1"][treestyletab-tabbar-autohide="
 }
 
 
+#treestyletab-autohide-content-area-screen {
+	/**
+	 * Don't make this panel completely transparent, because
+	 * mousemove event never fire on 100% transparent panel.
+	 */
+	background: rgba(0, 0, 0, 0.01);
+	line-height: 0;
+	margin: 0;
+	padding: 0;
+	-moz-appearance: none;
+	-moz-border-bottom-colors: none;
+	-moz-border-left-colors: none;
+	-moz-border-right-colors: none;
+	-moz-border-top-colors: none;
+}
+
 
 /* vertical tab bar */
 
@@ -164,8 +180,6 @@ toolbar.treestyletab-tabbar-toolbar[treestyletab-mode="vertical"]
 	-moz-box-flex: 0 !important;
 }
 
-.tabbrowser-tabs[treestyletab-mode="vertical"] .tabs-alltabs-button, /* -Firefox 3.6 */
-.tabbrowser-tabs[treestyletab-mode="vertical"] .close-button.tabs-closebutton, /* -Firefox 3.6 */
 .treestyletab-tabbar-toolbar[treestyletab-mode="vertical"] > toolbarbutton,
 .treestyletab-tabbar-toolbar[treestyletab-mode="vertical"] > toolbarpaletteitem > toolbarbutton {
 	max-width: none !important;
@@ -177,7 +191,7 @@ toolbar.treestyletab-tabbar-toolbar[treestyletab-mode="vertical"]
 }
 
 
-/* leftside vertical tab bar (for Firefox 4 or later) */
+/* leftside vertical tab bar */
 
 tabs.tabbrowser-tabs[treestyletab-tabbar-position="left"][treestyletab-invert-scrollbar="true"]
   .tabbrowser-arrowscrollbox
@@ -194,8 +208,7 @@ tabs.tabbrowser-tabs[treestyletab-tabbar-position="left"][treestyletab-invert-sc
 
 /* hide horizontal tab bar UI for vertical tab bar */
 .tabbrowser-tabs[treestyletab-mode="vertical"] .tabbrowser-arrowscrollbox > .scrollbutton-up,
-.tabbrowser-tabs[treestyletab-mode="vertical"] .tabbrowser-arrowscrollbox > .scrollbutton-down-stack,
-.tabbrowser-tabs[treestyletab-mode="vertical"] .tabbrowser-arrowscrollbox > .scrollbutton-down, /* Firefox 3 */
+.tabbrowser-tabs[treestyletab-mode="vertical"] .tabbrowser-arrowscrollbox > .scrollbutton-down:not([treestyletab-notifybgtab-phase]),
 .tabbrowser-tabs[treestyletab-mode="vertical"] .tabs-closebutton-box,
 .tabbrowser-tabs[treestyletab-mode="vertical"] .tab-drop-indicator-bar {
 	visibility: collapse !important;
@@ -412,9 +425,9 @@ toolbar.treestyletab-tabbar-toolbar-ready:not([nowindowdrag="true"]),
 /* separating of groups */
 
 /* horizontal tab bar */
-.tabbrowser-tabs:not([treestyletab-mode="vertical"])
+.tabbrowser-tabs[treestyletab-mode="horizontal"]
   .tabbrowser-tab:not([treestyletab-nest="0"]) + .tabbrowser-tab[treestyletab-nest="0"],
-.tabbrowser-tabs:not([treestyletab-mode="vertical"])
+.tabbrowser-tabs[treestyletab-mode="horizontal"]
   .tabbrowser-tab[treestyletab-nest="0"] + .tabbrowser-tab[treestyletab-nest="0"][treestyletab-children] {
 	margin-left: 0.8em !important;
 }
@@ -433,13 +446,11 @@ toolbar.treestyletab-tabbar-toolbar-ready:not([nowindowdrag="true"]),
 
 /* hide all tabs button (by user's preference) */
 .tabbrowser-tabs[treestyletab-hide-alltabs-button="true"]
-  .tabs-alltabs-stack,
-.tabbrowser-tabs[treestyletab-hide-alltabs-button="true"]
-  .tabbrowser-arrowscrollbox ~ stack /* "all tabs" button in Firefox 3.5 */ {
+  .tabs-alltabs-stack {
 	visibility: collapse !important;
 }
 
-/* pinned tabs on Firefox 4.0 */
+/* pinned tabs */
 .tabbrowser-tabs[treestyletab-mode="vertical"] {
 	-moz-margin-start: 0 !important;
 }
@@ -480,6 +491,30 @@ window[chromehidden~="toolbar"]
 }
 
 
+/* full tooltip */
+
+#treestyletab-full-tree-tooltip[popup-shown="true"] {
+	-moz-transition: margin-left 0.2s ease-out,
+	                 margin-top 0.2s ease-out,
+	                 max-height 0.2s ease-out,
+	                 max-width 0.2s ease-out;
+	transition: margin-left 0.2s ease-out,
+	            margin-top 0.2s ease-out,
+	            max-height 0.2s ease-out,
+	            max-width 0.2s ease-out;
+}
+
+#treestyletab-full-tree-tooltip > arrowscrollbox {
+	opacity: 0;
+}
+
+#treestyletab-full-tree-tooltip[popup-shown="true"] > arrowscrollbox {
+	-moz-transition: opacity 0.2s ease-out;
+	transition: opacity 0.2s ease-out;
+	opacity: 1;
+}
+
+
 /* addon compatibility */
 
 /* some themes */
diff --git a/chrome/treestyletab.jar!/content/treestyletab/treestyletab.js b/chrome/treestyletab.jar!/content/treestyletab/treestyletab.js
index 34aea2d..724cd75 100755
--- a/chrome/treestyletab.jar!/content/treestyletab/treestyletab.js
+++ b/chrome/treestyletab.jar!/content/treestyletab/treestyletab.js
@@ -1,4 +1,22 @@
 (function() {
+	/**
+	 * On secondary (and later) window, SSWindowStateBusy event can be fired
+	 * before DOMContentLoad, on "domwindowopened".
+	 */
+	var SSWindowStateBusyListener = function TSTSSWindowStateBusyListener(aEvent) {
+			window.removeEventListener(aEvent.type, TSTSSWindowStateBusyListener, false);
+			window.__treestyletab__WindowStateBusy = true;
+			SSWindowStateBusyListener = undefined;
+		};
+	window.addEventListener('SSWindowStateBusy', SSWindowStateBusyListener, false);
+	window.addEventListener('DOMContentLoad', function(aEvent) {
+		window.removeEventListener(aEvent.type, arguments.callee, false);
+		if (SSWindowStateBusyListener) {
+			window.removeEventListener('SSWindowStateBusy', TSTSSWindowStateBusyListener, false);
+			SSWindowStateBusyListener = undefined;
+		}
+	}, false);
+
 	var ns = {};
 	Components.utils.import('resource://treestyletab-modules/window.js', ns);
 	new ns.TreeStyleTabWindow(window);
diff --git a/chrome/treestyletab.jar!/content/treestyletab/treestyletab.xml b/chrome/treestyletab.jar!/content/treestyletab/treestyletab.xml
index c39d899..1fe33d6 100755
--- a/chrome/treestyletab.jar!/content/treestyletab/treestyletab.xml
+++ b/chrome/treestyletab.jar!/content/treestyletab/treestyletab.xml
@@ -5,7 +5,7 @@
 	xmlns:xbl="http://www.mozilla.org/xbl">
 
 	<binding id="tab-icon"
-		extends="xul:stack">
+		display="xul:stack">
 		<content>
 			<xul:image xbl:inherits="validate,src" class="tab-icon-image"/>
 			<xbl:children/>
diff --git a/chrome/treestyletab.jar!/content/treestyletab/treestyletab.xul b/chrome/treestyletab.jar!/content/treestyletab/treestyletab.xul
index 244ff32..83a9b7d 100755
--- a/chrome/treestyletab.jar!/content/treestyletab/treestyletab.xul
+++ b/chrome/treestyletab.jar!/content/treestyletab/treestyletab.xul
@@ -7,10 +7,8 @@
 <?xml-stylesheet href="chrome://treestyletab/skin/twisty/twisty.css" type="text/css"?>
 <?xml-stylesheet href="chrome://treestyletab/skin/ui.css" type="text/css"?>
 <?xml-stylesheet href="chrome://treestyletab/skin/tmp.css" type="text/css"?><!-- hacks for Tab Mix Plus -->
-<?xml-stylesheet href="chrome://treestyletab-platform/skin/base.css" type="text/css"?>
-<?xml-stylesheet href="chrome://treestyletab-platform/skin/platform-base.css" type="text/css"?>
-
-<?xul-overlay href="res/tabFx2Compatible.xul"?>
+<?xml-stylesheet href="chrome://treestyletab/skin/platform-base.css" type="text/css"?>
+<?xml-stylesheet href="chrome://treestyletab/skin/pseudo-tree.css" type="text/css"?>
 
 <!DOCTYPE overlay SYSTEM "chrome://treestyletab/locale/treestyletab.dtd">
 <overlay id="treestyletab-overlay"
@@ -151,8 +149,11 @@
 			type="checkbox"
 			autocheck="false"
 			oncommand="TreeStyleTabService.toggleFixed(TreeStyleTabService.getTabBrowserFromChild(this));"/>
-
 	</menupopup>
+	<tooltip id="treestyletab-full-tree-tooltip"/>
+	<panel id="treestyletab-autohide-content-area-screen"
+		onpopupshowing="if ('setConsumeRollupEvent' in this.popupBoxObject) this.popupBoxObject.setConsumeRollupEvent(Components.interfaces.nsIPopupBoxObject.ROLLUP_NO_CONSUME);"
+		onclick="this.hidePopup();"/>
 </popupset>
 
 </overlay>
diff --git a/chrome/treestyletab.jar!/content/treestyletab/windowHelper.js b/chrome/treestyletab.jar!/content/treestyletab/windowHelper.js
index 29438f8..a19f8ac 100755
--- a/chrome/treestyletab.jar!/content/treestyletab/windowHelper.js
+++ b/chrome/treestyletab.jar!/content/treestyletab/windowHelper.js
@@ -75,14 +75,11 @@ var TreeStyleTabWindowHelper = {
 		var strip = this.service.getTabStrip(aObserver) ||
 					gBrowser.mStrip // fallback to the default strip, for Tab Mix Plus;
 
-		// Firefox 4.0 or later
 		if (
 			aObserver.tabContainer &&
-			aObserver.tabContainer.tabbrowser == aObserver &&
-			this.service.isGecko2 // tabbar.tabbrowser can be defined by addons like Tab Mix Plus.
-			) {
+			aObserver.tabContainer.tabbrowser == aObserver
+			)
 			aObserver = aObserver.tabContainer;
-		}
 
 		if ('_setEffectAllowedForDataTransfer' in aObserver) {
 			eval('aObserver._setEffectAllowedForDataTransfer = '+
@@ -204,32 +201,28 @@ var TreeStyleTabWindowHelper = {
 			);
 		}
 
-		this._splitFunctionNames(<![CDATA[
-			window.duplicateTab.handleLinkClick
-			window.duplicatethistab.handleLinkClick
-			window.__treestyletab__highlander__origHandleLinkClick
-			window.__splitbrowser__handleLinkClick
-			window.__ctxextensions__handleLinkClick
-			window.handleLinkClick
-		]]>).some(function(aFunc) {
-			let source = this._getFunctionSource(aFunc);
-			if (!source || !/^\(?function handleLinkClick/.test(source))
-				return false;
-			eval(aFunc+' = '+source.replace( // for Firefox 3.5 - Firefox 3.6
-				/(openNewTabWith\()/g,
-				<![CDATA[
-					if (!TreeStyleTabService.checkToOpenChildTab(event.target.ownerDocument.defaultView))
-						TreeStyleTabService.readyToOpenChildTab(event.target.ownerDocument.defaultView);
-					$1]]>
-			).replace( // for Firefox 4.0-
-				/(charset\s*:\s*doc\.characterSet\s*)/,
-				'$1, event : event, linkNode : linkNode'
-			));
-			source = null;
-			return true;
-		}, this);
+		let (functions = this._splitFunctionNames(<![CDATA[
+				window.duplicateTab.handleLinkClick
+				window.duplicatethistab.handleLinkClick
+				window.__treestyletab__highlander__origHandleLinkClick
+				window.__splitbrowser__handleLinkClick
+				window.__ctxextensions__handleLinkClick
+				window.handleLinkClick
+			]]>)) {
+			for (let i = 0, maxi = functions.length; i < maxi; i++)
+			{
+				let func = functions[i];
+				let source = this._getFunctionSource(func);
+				if (!source || !/^\(?function handleLinkClick/.test(source))
+					continue;
+				eval(func+' = '+source.replace(
+					/(charset\s*:\s*doc\.characterSet\s*)/,
+					'$1, event : event, linkNode : linkNode'
+				));
+				break;
+			}
+		}
 
-		// for Firefox 4.0-
 		if ('openLinkIn' in window) {
 			eval('window.openLinkIn = '+
 				window.openLinkIn.toSource().replace(
@@ -243,84 +236,96 @@ var TreeStyleTabWindowHelper = {
 			);
 		}
 
-		this._splitFunctionNames(<![CDATA[
-			window.permaTabs.utils.wrappedFunctions["window.contentAreaClick"]
-			window.__contentAreaClick
-			window.__ctxextensions__contentAreaClick
-			window.contentAreaClick
-		]]>).forEach(function(aFunc) {
-			let source = this._getFunctionSource(aFunc);
-			if (!source || !/^\(?function contentAreaClick/.test(source))
-				return;
-			eval(aFunc+' = '+source.replace(
-				// for Tab Utilities, etc. Some addons insert openNewTabWith() to the function.
-				// (calls for the function is not included by Firefox default.)
-				/(openNewTabWith\()/g,
-				<![CDATA[
-					if (!TreeStyleTabService.checkToOpenChildTab(event.target.ownerDocument.defaultView)) TreeStyleTabService.readyToOpenChildTab(event.target.ownerDocument.defaultView);
-					$1]]>
-			));
-			source = null;
-		}, this);
-
-		this._splitFunctionNames(<![CDATA[
-			window.duplicateTab.gotoHistoryIndex
-			window.duplicateTab.BrowserBack
-			window.duplicateTab.BrowserForward
-			window.duplicatethistab.gotoHistoryIndex
-			window.duplicatethistab.BrowserBack
-			window.duplicatethistab.BrowserForward
-			window.__rewindforward__BrowserForward
-			window.__rewindforward__BrowserBack
-			window.gotoHistoryIndex
-			window.BrowserForward
-			window.BrowserBack
-		]]>).forEach(function(aFunc) {
-			let source = this._getFunctionSource(aFunc);
-			if (!source || !/^\(?function (gotoHistoryIndex|BrowserForward|BrowserBack)/.test(source))
-				return;
-			eval(aFunc+' = '+source.replace(
-				/((?:openUILinkIn|duplicateTabIn)\()/g,
-				<![CDATA[
-					if (where == 'tab' || where == 'tabshifted')
-						TreeStyleTabService.readyToOpenChildTab();
-					$1]]>
-			));
-			source = null;
-		}, this);
-
-		this._splitFunctionNames(<![CDATA[
-			window.BrowserReloadOrDuplicate
-		]]>).forEach(function(aFunc) {
-			let source = this._getFunctionSource(aFunc);
-			if (!source || !/^\(?function (BrowserReloadOrDuplicate)/.test(source))
-				return;
-			eval(aFunc+' = '+source.replace(
-				/((?:openUILinkIn|duplicateTabIn)\()/g,
-				<![CDATA[
-					if (where == 'tab' || where == 'tabshifted')
-						TreeStyleTabService.onBeforeTabDuplicate(null);
-					$&]]>
-			));
-			source = null;
-		}, this);
-
-		this._splitFunctionNames(<![CDATA[
-			permaTabs.utils.wrappedFunctions["window.BrowserHomeClick"]
-			window.BrowserHomeClick
-			window.BrowserGoHome
-		]]>).forEach(function(aFunc) {
-			let source = this._getFunctionSource(aFunc);
-			if (!source || !/^\(?function (BrowserHomeClick|BrowserGoHome)/.test(source))
-				return;
-			eval(aFunc+' = '+source.replace(
-				'gBrowser.loadTabs(',
-				<![CDATA[
-					TreeStyleTabService.readyToOpenNewTabGroup(gBrowser);
-					$&]]>
-			));
-			source = null;
-		}, this);
+		let (functions = this._splitFunctionNames(<![CDATA[
+				window.permaTabs.utils.wrappedFunctions["window.contentAreaClick"]
+				window.__contentAreaClick
+				window.__ctxextensions__contentAreaClick
+				window.contentAreaClick
+			]]>)) {
+			for (let i = 0, maxi = functions.length; i < maxi; i++)
+			{
+				let func = functions[i];
+				let source = this._getFunctionSource(func);
+				if (!source || !/^\(?function contentAreaClick/.test(source))
+					continue;
+				eval(func+' = '+source.replace(
+					// for Tab Utilities, etc. Some addons insert openNewTabWith() to the function.
+					// (calls for the function is not included by Firefox default.)
+					/(openNewTabWith\()/g,
+					<![CDATA[
+						if (!TreeStyleTabService.checkToOpenChildTab(event.target.ownerDocument.defaultView)) TreeStyleTabService.readyToOpenChildTab(event.target.ownerDocument.defaultView);
+						$1]]>
+				));
+			}
+		}
+
+		let (functions = this._splitFunctionNames(<![CDATA[
+				window.duplicateTab.gotoHistoryIndex
+				window.duplicateTab.BrowserBack
+				window.duplicateTab.BrowserForward
+				window.duplicatethistab.gotoHistoryIndex
+				window.duplicatethistab.BrowserBack
+				window.duplicatethistab.BrowserForward
+				window.__rewindforward__BrowserForward
+				window.__rewindforward__BrowserBack
+				window.gotoHistoryIndex
+				window.BrowserForward
+				window.BrowserBack
+			]]>)) {
+			for (let i = 0, maxi = functions.length; i < maxi; i++)
+			{
+				let func = functions[i];
+				let source = this._getFunctionSource(func);
+				if (!source || !/^\(?function (gotoHistoryIndex|BrowserForward|BrowserBack)/.test(source))
+					continue;
+				eval(func+' = '+source.replace(
+					/((?:openUILinkIn|duplicateTabIn)\()/g,
+					<![CDATA[
+						if (where == 'tab' || where == 'tabshifted')
+							TreeStyleTabService.readyToOpenChildTab();
+						$1]]>
+				));
+			}
+		}
+
+		let (functions = this._splitFunctionNames(<![CDATA[
+				window.BrowserReloadOrDuplicate
+			]]>)) {
+			for (let i = 0, maxi = functions.length; i < maxi; i++)
+			{
+				let func = functions[i];
+				let source = this._getFunctionSource(func);
+				if (!source || !/^\(?function (BrowserReloadOrDuplicate)/.test(source))
+					continue;
+				eval(func+' = '+source.replace(
+					/((?:openUILinkIn|duplicateTabIn)\()/g,
+					<![CDATA[
+						if (where == 'tab' || where == 'tabshifted')
+							TreeStyleTabService.onBeforeTabDuplicate(null);
+						$&]]>
+				));
+			}
+		}
+
+		let (functions = this._splitFunctionNames(<![CDATA[
+				permaTabs.utils.wrappedFunctions["window.BrowserHomeClick"]
+				window.BrowserHomeClick
+				window.BrowserGoHome
+			]]>)) {
+			for (let i = 0, maxi = functions.length; i < maxi; i++)
+			{
+				let func = functions[i];
+				let source = this._getFunctionSource(func);
+				if (!source || !/^\(?function (BrowserHomeClick|BrowserGoHome)/.test(source))
+					continue;
+				eval(func+' = '+source.replace(
+					'gBrowser.loadTabs(',
+					<![CDATA[
+						TreeStyleTabService.readyToOpenNewTabGroup(gBrowser);
+						$&]]>
+				));
+			}
+		}
 
 		eval('FeedHandler.loadFeed = '+
 			FeedHandler.loadFeed.toSource().replace(
@@ -332,23 +337,10 @@ var TreeStyleTabWindowHelper = {
 			)
 		);
 
-		// Firefox 3 full screen
-		eval('FullScreen._animateUp = '+
-			FullScreen._animateUp.toSource().replace(
-				// Firefox 3.6 or older
-				/(gBrowser\.mStrip\.boxObject\.height)/,
-				'((gBrowser.treeStyleTab.position != "top") ? 0 : $1)'
-			)
-		);
 		eval('FullScreen.mouseoverToggle = '+
 			FullScreen.mouseoverToggle.toSource().replace(
-				// Firefox 4.0 or later
 				'this._isChromeCollapsed = !aShow;',
 				'gBrowser.treeStyleTab.updateFloatingTabbar(gBrowser.treeStyleTab.kTABBAR_UPDATE_BY_FULLSCREEN); $&'
-			).replace(
-				// Firefox 3.6 or older
-				'gBrowser.mStrip.setAttribute("moz-collapsed", !aShow);',
-				'if (gBrowser.treeStyleTab.position == "top") { $& }'
 			)
 		);
 		eval('FullScreen.toggle = '+
@@ -377,7 +369,13 @@ var TreeStyleTabWindowHelper = {
 			));
 		}
 
-		if ('TabsOnTop' in window && TabsOnTop.syncCommand) {
+		if ('TabsOnTop' in window && TabsOnTop.syncUI) { // Firefox 12 or later
+			eval('TabsOnTop.syncUI = '+TabsOnTop.syncUI.toSource().replace(
+				/(\}\)?)$/,
+				'gBrowser.treeStyleTab.onTabsOnTopSyncCommand(enabled); $&'
+			));
+		}
+		if ('TabsOnTop' in window && TabsOnTop.syncCommand) { // Firefox 4-11
 			eval('TabsOnTop.syncCommand = '+TabsOnTop.syncCommand.toSource().replace(
 				/(\}\)?)$/,
 				'gBrowser.treeStyleTab.onTabsOnTopSyncCommand(enabled); $&'
@@ -433,8 +431,7 @@ var TreeStyleTabWindowHelper = {
 			));
 		}
 
-		var goButton = document.getElementById('urlbar-go-button') || // Firefox 4 or later
-						document.getElementById('go-button'); // Firefox 3.6
+		var goButton = document.getElementById('urlbar-go-button');
 		if (goButton)
 			goButton.parentNode.addEventListener('click', this.service, true);
 
@@ -447,7 +444,6 @@ var TreeStyleTabWindowHelper = {
 			!(tabbar.compareDocumentPosition(newTabButton) & nsIDOMNode.DOCUMENT_POSITION_CONTAINED_BY))
 			newTabButton.parentNode.addEventListener('click', this.service, true);
 
-		// for Firefox 4.0 or later
 		this.service.updateAllTabsButton(gBrowser);
 
 		var event = document.createEvent('Events');
@@ -457,8 +453,7 @@ var TreeStyleTabWindowHelper = {
  
 	destroyToolbarItems : function TSTWH_destroyToolbarItems() 
 	{
-		var goButton = document.getElementById('urlbar-go-button') || // Firefox 4 or later
-						document.getElementById('go-button'); // Firefox 3.6
+		var goButton = document.getElementById('urlbar-go-button');
 		if (goButton)
 			goButton.parentNode.removeEventListener('click', this, true);
 
@@ -471,7 +466,6 @@ var TreeStyleTabWindowHelper = {
 			!(tabbar.compareDocumentPosition(newTabButton) & Ci.nsIDOMNode.DOCUMENT_POSITION_CONTAINED_BY))
 			newTabButton.parentNode.removeEventListener('click', this.service, true);
 
-		// Firefox 4.0 or later (restore original position)
 		var allTabsButton = document.getElementById('alltabs-button');
 		if (allTabsButton && allTabsButton.hasChildNodes())
 			allTabsButton.firstChild.setAttribute('position', 'after_end');
@@ -568,13 +562,10 @@ var TreeStyleTabWindowHelper = {
 
 		if ('_beginRemoveTab' in b) {
 			eval('b._beginRemoveTab = '+
-				b._beginRemoveTab.toSource().replace( // Firefox 3.5-3.6
-					'if (l == 1) {',
-					'if (l == 1 || this.treeStyleTab.shouldCloseLastTabSubtreeOf(aTab)) {'
-				).replace( // Firefox 4.0-
+				b._beginRemoveTab.toSource().replace(
 					'if (this.tabs.length - this._removingTabs.length == 1) {',
 					'if (this.tabs.length - this._removingTabs.length == 1 || this.treeStyleTab.shouldCloseLastTabSubtreeOf(aTab)) {'
-				).replace( // Firefox 3.5-
+				).replace(
 					'this._removingTabs.length == 0',
 					'(this.treeStyleTab.shouldCloseLastTabSubtreeOf(aTab) || $&)'
 				)
@@ -598,7 +589,7 @@ var TreeStyleTabWindowHelper = {
 					'{',
 					<![CDATA[$&
 						var treeStyleTab = TreeStyleTabService.getTabBrowserFromChild(this).treeStyleTab;
-						if (treeStyleTab.handleAdvanceSelectedTab(arguments[0], arguments[1], this))
+						if (treeStyleTab.handleAdvanceSelectedTab(arguments[0], arguments[1]))
 							return;
 					]]>
 				)
@@ -612,7 +603,9 @@ var TreeStyleTabWindowHelper = {
 					'{',
 					<![CDATA[{
 						var treeStyleTab = TreeStyleTabService.getTabBrowserFromChild(this).treeStyleTab;
-						if (treeStyleTab.scrollToNewTabMode == 0) return;
+						if (treeStyleTab.scrollToNewTabMode == 0 ||
+							treeStyleTab.shouldCancelEnsureElementIsVisible())
+							return;
 					]]>.toString()
 				).replace(
 					/\.screenX/g, '[treeStyleTab.screenPositionProp]'
@@ -625,11 +618,14 @@ var TreeStyleTabWindowHelper = {
 				).replace(
 					'!selected ||',
 					'$& treeStyleTab.scrollToNewTabMode == 1 && '
+				).replace(
+					/(\}\)?)$/,
+					'treeStyleTab.notifyBackgroundTab(); $1'
 				)
 			);
 		}
 
-		if (b.tabContainer && '_getDropIndex' in b.tabContainer) { // Firefox 4.0 or later
+		if (b.tabContainer && '_getDropIndex' in b.tabContainer) {
 			eval('b.tabContainer._getDropIndex = '+
 				b.tabContainer._getDropIndex.toSource().replace(
 					/\.screenX/g, '[this.treeStyleTab.screenPositionProp]'
@@ -638,15 +634,6 @@ var TreeStyleTabWindowHelper = {
 				)
 			);
 		}
-		else if ('getNewIndex' in b) { // Firefox 3.6 or older
-			eval('b.getNewIndex = '+
-				b.getNewIndex.toSource().replace(
-					/\.screenX/g, '[this.treeStyleTab.screenPositionProp]'
-				).replace(
-					/\.width/g, '[this.treeStyleTab.sizeProp]'
-				)
-			);
-		}
 
 		/**
 		 * The default implementation fails to scroll to tab if it is expanding.
@@ -663,6 +650,8 @@ var TreeStyleTabWindowHelper = {
 						'{',
 						<![CDATA[{
 							var treeStyleTab = TreeStyleTabService.getTabBrowserFromChild(this).treeStyleTab;
+							if (treeStyleTab && treeStyleTab.shouldCancelEnsureElementIsVisible())
+								return;
 							if (
 								treeStyleTab &&
 								(arguments.length == 1 || arguments[1])
diff --git a/chrome/treestyletab.jar!/content/treestyletab/windowHelperHacks.js b/chrome/treestyletab.jar!/content/treestyletab/windowHelperHacks.js
index 117fea0..f1cdf9e 100755
--- a/chrome/treestyletab.jar!/content/treestyletab/windowHelperHacks.js
+++ b/chrome/treestyletab.jar!/content/treestyletab/windowHelperHacks.js
@@ -71,7 +71,7 @@ TreeStyleTabWindowHelper.overrideExtensionsPreInit = function TSTWH_overrideExte
 										window.setTimeout(arguments.callee, 100);
 									return;
 								}
-								b.treeStyleTab.restoreStructure(tab);
+								b.treeStyleTab.handleRestoredTab(tab);
 							}, 0);
 						}).call(this, tab, id)
 					$1]]>
@@ -86,16 +86,20 @@ TreeStyleTabWindowHelper.overrideExtensionsPreInit = function TSTWH_overrideExte
 						(function() {
 							var tabsInfo = {};
 							var TST = TreeStyleTabService;
-							Array.slice(getBrowser().mTabContainer.childNodes)
-								.forEach(function(aTab) {
-									var index = this.getPermaTabLocalIndex(aTab);
-									if (index < 0) return;
-									var info = {};
-									TST.extraProperties.forEach(function(aProperty) {
-										info[aProperty] = TST.getTabValue(aTab, aProperty);
-									});
-									tabsInfo[this.permaTabs[index].id] = info;
-								}, this);
+							var allTabs = getBrowser().mTabContainer.childNodes;
+							for (let i = 0, maxi = allTabs.length; i < maxi; i++)
+							{
+								let tab = allTabs[i];
+								let index = this.getPermaTabLocalIndex(tab);
+								if (index < 0) continue;
+								let info = {};
+								for (let i = 0, maxi = TST.extraProperties.length; i < maxi; i++)
+								{
+									let property = TST.extraProperties[i];
+									info[property] = TST.getTabValue(tab, property);
+								}
+								tabsInfo[this.permaTabs[index].id] = info;
+							}
 							TST.setTreePref('permaTabsInfo', tabsInfo.toSource());
 						}).call(this);
 					]]>
@@ -117,16 +121,18 @@ TreeStyleTabWindowHelper.overrideExtensionsPreInit = function TSTWH_overrideExte
 		if ('getTabProperties' in sessionData && 'setTabProperties' in sessionData) {
 			let prefix = sv.kTMP_SESSION_DATA_PREFIX;
 			let sessionManager = window.TabmixSessionManager || window.SessionManager;
-			SessionData.tabTSTProperties = this.extraProperties.map(function(aProperty) {
+			sessionData.tabTSTProperties = this.extraProperties.map(function(aProperty) {
 				return prefix+aProperty;
 			});
 			eval('sessionData.getTabProperties = '+
 				sessionData.getTabProperties.toSource().replace(
 					'return tabProperties;',
 					<![CDATA[
-						this.tabTSTProperties.forEach(function(aProp) {
-							tabProperties += '|' + aProp + '=' + encodeURIComponent(aTab.getAttribute(aProp));
-						});
+						for (let i = 0, maxi = this.tabTSTProperties.length; i < maxi; i++)
+						{
+							let property = this.tabTSTProperties[i];
+							tabProperties += '|' + property + '=' + encodeURIComponent(aTab.getAttribute(property));
+						}
 					$&]]>
 				)
 			);
@@ -136,13 +142,15 @@ TreeStyleTabWindowHelper.overrideExtensionsPreInit = function TSTWH_overrideExte
 					<![CDATA[$&
 						var TSTProps = tabProperties.split('|');
 						tabProperties = TSTProps.shift();
-						TSTProps.forEach(function(aSet) {
-							var index = aSet.indexOf('=');
-							var name = aSet.substring(0, index);
-							var value = decodeURIComponent(aSet.substring(index+1));
+						for (let i = 0, maxi = TSTProps.length; i < maxi; i++)
+						{
+							let property = TSTProps[i];
+							let index = property.indexOf('=');
+							let name = property.substring(0, index);
+							let value = decodeURIComponent(property.substring(index+1));
 							if (name && value)
 								aTab.setAttribute(name, value);
-						});
+						}
 					]]>
 				)
 			);
@@ -151,7 +159,7 @@ TreeStyleTabWindowHelper.overrideExtensionsPreInit = function TSTWH_overrideExte
 					/(\}\))?$/,
 					<![CDATA[
 						if (gBrowser.treeStyleTab.useTMPSessionAPI)
-							gBrowser.treeStyleTab.restoreStructure(aTab);
+							gBrowser.treeStyleTab.handleRestoredTab(aTab);
 					$1]]>
 				)
 			);
@@ -160,7 +168,7 @@ TreeStyleTabWindowHelper.overrideExtensionsPreInit = function TSTWH_overrideExte
 				'return newTab;',
 				<![CDATA[
 					if (this.treeStyleTab.useTMPSessionAPI)
-						this.treeStyleTab.restoreStructure(newTab);
+						this.treeStyleTab.handleRestoredTab(newTab);
 				$&]]>
 			);
 			eval('tablib.init = '+source.join('gBrowser.restoreTab = '));
@@ -197,12 +205,13 @@ TreeStyleTabWindowHelper.overrideExtensionsPreInit = function TSTWH_overrideExte
 				'var tabcount = ',
 				<![CDATA[
 					gBrowser.treeStyleTab.collapseExpandAllSubtree(false, true);
-					gBrowser.treeStyleTab.getTabsArray(gBrowser)
-						.slice(1)
-						.reverse()
-						.forEach(function(aTab, aIndex) {
-							gBrowser.removeTab(aTab);
-						});
+					let (tabs = gBrowser.treeStyleTab.getTabsArray(gBrowser).slice(1).reverse()) {
+						for (let i = 0, maxi = tabs.length; i < maxi; i++)
+						{
+							let tab = tabs[i];
+							gBrowser.removeTab(tab);
+						}
+					}
 					TreeStyleTabService.restoringTree = true;
 				$&]]>
 			));
@@ -213,13 +222,17 @@ TreeStyleTabWindowHelper.overrideExtensionsPreInit = function TSTWH_overrideExte
 	// https://addons.mozilla.org/firefox/addon/4650
 	if ('FS_onFullerScreen' in window &&
 		sv.getTreePref('compatibility.FullerScreen')) {
-		'CheckIfFullScreen,FS_onFullerScreen,FS_onMouseMove'.split(',').forEach(function(aFunc) {
-			if (!(aFunc in window)) return;
-			eval('window.'+aFunc+' = '+window[aFunc].toSource().replace(
-				/FS_data.mTabs.(removeAttribute\("moz-collapsed"\)|setAttribute\("moz-collapsed", "true"\));/g,
-				'if (gBrowser.treeStyleTab.currentTabbarPosition == "top") { $& }'
-			));
-		}, this);
+		let (functions = 'CheckIfFullScreen,FS_onFullerScreen,FS_onMouseMove'.split(',')) {
+			for (let i = 0, maxi = functions.length; i < maxi; i++)
+			{
+				let func = functions[i];
+				if (!(func in window)) continue;
+				eval('window.'+func+' = '+window[func].toSource().replace(
+					/FS_data.mTabs.(removeAttribute\("moz-collapsed"\)|setAttribute\("moz-collapsed", "true"\));/g,
+					'if (gBrowser.treeStyleTab.currentTabbarPosition == "top") { $& }'
+				));
+			}
+		}
 	}
 
 	// TooManyTabs
@@ -233,7 +246,6 @@ TreeStyleTabWindowHelper.overrideExtensionsPreInit = function TSTWH_overrideExte
 	// https://addons.mozilla.org/firefox/addon/dragndrop-toolbars/
 	if ('globDndtb' in window &&
 		globDndtb.setTheStuff &&
-		sv.isGecko2 &&
 		sv.getTreePref('compatibility.DragNDropToolbars')) {
 		let reinitTabbar = function() {
 				TreeStyleTabService.stopRendering();
@@ -272,7 +284,6 @@ TreeStyleTabWindowHelper.overrideExtensionsPreInit = function TSTWH_overrideExte
 	if ('mtSidebarStartup' in window &&
 		'mtSidebarShutdown' in window &&
 		'mtPreventHiding' in window &&
-		sv.isGecko2 &&
 		sv.getTreePref('compatibility.OptimozTweaks')) {
 		eval('window.mtSidebarStartup = '+window.mtSidebarStartup.toSource().replace(
 			'{',
@@ -817,11 +828,13 @@ TreeStyleTabWindowHelper.overrideExtensionsAfterBrowserInit = function TSTWH_ove
 	if ('LinkyContext' in window &&
 		'prototype' in LinkyContext &&
 		sv.getTreePref('compatibility.Linky')) {
-		'doSelected,doSelectedText,doImages,doAll,doAllPics,doValidateAll,doValidateSelected'
-			.split(',').forEach(function(aMethod) {
-				if (!(aMethod in LinkyContext.prototype)) return;
-				eval('LinkyContext.prototype.'+aMethod+' = '+
-					LinkyContext.prototype[aMethod].toSource().replace(
+		let (methods = 'doSelected,doSelectedText,doImages,doAll,doAllPics,doValidateAll,doValidateSelected'.split(',')) {
+			for (let i = 0, maxi = methods.length; i < maxi; i++)
+			{
+				let method = methods[i];
+				if (!(method in LinkyContext.prototype)) continue;
+				eval('LinkyContext.prototype.'+method+' = '+
+					LinkyContext.prototype[method].toSource().replace(
 						'{',
 						'{ TreeStyleTabService.readyToOpenChildTab(null, true);'
 					).replace(
@@ -829,7 +842,8 @@ TreeStyleTabWindowHelper.overrideExtensionsAfterBrowserInit = function TSTWH_ove
 						'TreeStyleTabService.stopToOpenChildTab(); $1'
 					)
 				);
-			});
+			}
+		}
 	}
 
 	// QuickDrag
@@ -1324,16 +1338,19 @@ TreeStyleTabWindowHelper.overrideExtensionsDelayed = function TSTWH_overrideExte
 								break;
 
 							case sv.kEVENT_TYPE_BEFORE_TOOLBAR_CUSTOMIZATION:
-								tabbarToolboxes.forEach(function(aToolbox) {
-									aToolbox.removeAttribute('collapsed');
-								});
+								for (let i = 0, maxi = tabbarToolboxes.length; i < maxi; i++)
+								{
+									tabbarToolboxes[i].removeAttribute('collapsed');
+								}
 								break;
 
 							case sv.kEVENT_TYPE_AFTER_TOOLBAR_CUSTOMIZATION:
-								tabbarToolboxes.forEach(function(aToolbox) {
-									if (!aToolbox.firstChild.hasChildNodes())
-										aToolbox.setAttribute('collapsed', true);
-								});
+								for (let i = 0, maxi = tabbarToolboxes.length; i < maxi; i++)
+								{
+									let toolbox = tabbarToolboxes[i];
+									if (!toolbox.firstChild.hasChildNodes())
+										toolbox.setAttribute('collapsed', true);
+								}
 								break;
 
 							case 'unload':
@@ -1350,10 +1367,12 @@ TreeStyleTabWindowHelper.overrideExtensionsDelayed = function TSTWH_overrideExte
 			document.addEventListener(sv.kEVENT_TYPE_BEFORE_TOOLBAR_CUSTOMIZATION, listener, false);
 			document.addEventListener(sv.kEVENT_TYPE_AFTER_TOOLBAR_CUSTOMIZATION, listener, false);
 			document.addEventListener('unload', listener, false);
-			tabbarToolboxes.forEach(function(aToolbox) {
-				if (!aToolbox.firstChild.hasChildNodes())
-					aToolbox.setAttribute('collapsed', true);
-			});
+			for (let i = 0, maxi = tabbarToolboxes.length; i < maxi; i++)
+			{
+				let toolbox = tabbarToolboxes[i];
+				if (!toolbox.firstChild.hasChildNodes())
+					toolbox.setAttribute('collapsed', true);
+			}
 		}
 	}
 
diff --git a/chrome/treestyletab.jar!/locale/da-DK/treestyletab/treestyletab.dtd b/chrome/treestyletab.jar!/locale/da-DK/treestyletab/treestyletab.dtd
index ef15c4e..50b7d33 100755
--- a/chrome/treestyletab.jar!/locale/da-DK/treestyletab/treestyletab.dtd
+++ b/chrome/treestyletab.jar!/locale/da-DK/treestyletab/treestyletab.dtd
@@ -20,7 +20,6 @@
 <!ENTITY config.maxTreeLevel.before "op til">
 <!ENTITY config.maxTreeLevel.after "niveauer">
 <!ENTITY config.allowSubtreeCollapseExpand "Tillad sammenfold/udvid fanetræ">
-<!ENTITY config.tabbar.hideAlltabsButton "Vis "Se alle faner" knappen">
 
 
 <!ENTITY config.tabs.style "Udseende">
diff --git a/chrome/treestyletab.jar!/locale/da-DK/treestyletab/treestyletab.properties b/chrome/treestyletab.jar!/locale/da-DK/treestyletab/treestyletab.properties
index 8233ee6..07955fc 100755
--- a/chrome/treestyletab.jar!/locale/da-DK/treestyletab/treestyletab.properties
+++ b/chrome/treestyletab.jar!/locale/da-DK/treestyletab/treestyletab.properties
@@ -3,7 +3,9 @@ tooltip.collapseSubtree.labeled=Sammenfold:\n%S
 tooltip.expandSubtree=Udvid træ
 tooltip.expandSubtree.labeled=Udvid:\n%S
 tooltip.closeTree=Sammenfold dette træ
+tooltip.closeTree.labeled=Sammenfold dette træ:\n%S
 tooltip.item.label=%2$S* %1$S
+tooltip.more=...and %1$S more tab(s)
 
 dropLinkOnTab.title=Ã…ben droppede links?
 dropLinkOnTab.text=Et link blev trukket til en eksisterende fane. Vil du åbne linket i denne fane, eller som ny underfane?
@@ -24,10 +26,14 @@ bookmarkDroppedTabs.never=Spørg ikke igen
 bookmarkDroppedTabs.bookmarkAll=Bogmærk alle faner i træet
 bookmarkDroppedTabs.bookmarkOnlyParent=Bogmærk kun hovedfanen.
 
-undoCloseTabSetBehavior.label=Vil du også gendanne følgende %S fane(r)?
-undoCloseTabSetBehavior.never=Spørg ikke igen
-undoCloseTabSetBehavior.set=Gendan faner
-undoCloseTabSetBehavior.separate=Nej tak
+undoCloseTabSetBehavior.label=This tab was closed together with other %S tab(s) in a tree. Do you want them to be restored along?
+undoCloseTabSetBehavior.restoreOnce=Restore tabs
+undoCloseTabSetBehavior.restoreForever=Always resotre tabs
+undoCloseTabSetBehavior.ignoreForever=Never show this notification
+# undoCloseTabSetBehavior.label=Vil du også gendanne følgende %S fane(r)?
+# undoCloseTabSetBehavior.never=Spørg ikke igen
+# undoCloseTabSetBehavior.set=Gendan faner
+# undoCloseTabSetBehavior.separate=Nej tak
 
 openSelectedPlaces.bookmarks=fra %2$S bogmærker, inklussiv "%1$S"
 openSelectedPlaces.history=fra %2$S historik emner, inklussiv "%1$S"
diff --git a/chrome/treestyletab.jar!/locale/de-DE/treestyletab/license.txt b/chrome/treestyletab.jar!/locale/de-DE/treestyletab/license.txt
index c6649a4..9d064b7 100755
--- a/chrome/treestyletab.jar!/locale/de-DE/treestyletab/license.txt
+++ b/chrome/treestyletab.jar!/locale/de-DE/treestyletab/license.txt
@@ -18,7 +18,7 @@ Portions created by the Initial Developer are Copyright (C) 2007-2009
 the Initial Developer. All Rights Reserved.
 
 Contributor(s): Andy Pillip <andy at pillip.eu>
-                SHIMODA Hiroshi <piro at p.club.ne.jp>
+                SHIMODA Hiroshi <piro.outsider.reflex at gmail.com>
 
 Alternatively, the contents of these files may be used under the terms of
 either the GNU General Public License Version 2 or later (the "GPL"), or
diff --git a/chrome/treestyletab.jar!/locale/de-DE/treestyletab/treestyletab.dtd b/chrome/treestyletab.jar!/locale/de-DE/treestyletab/treestyletab.dtd
index 21f899b..6f2c71f 100755
--- a/chrome/treestyletab.jar!/locale/de-DE/treestyletab/treestyletab.dtd
+++ b/chrome/treestyletab.jar!/locale/de-DE/treestyletab/treestyletab.dtd
@@ -20,7 +20,6 @@
 <!ENTITY config.maxTreeLevel.before "bis">
 <!ENTITY config.maxTreeLevel.after  "Level">
 <!ENTITY config.allowSubtreeCollapseExpand  "Auf- und Einklappen von Zweigen erlauben">
-<!ENTITY config.tabbar.hideAlltabsButton    "Button zum Auflisten aller Tabs anzeigen">
 
 
 <!ENTITY config.tabs.style "Style">
diff --git a/chrome/treestyletab.jar!/locale/de-DE/treestyletab/treestyletab.properties b/chrome/treestyletab.jar!/locale/de-DE/treestyletab/treestyletab.properties
index b1699ff..393847c 100755
--- a/chrome/treestyletab.jar!/locale/de-DE/treestyletab/treestyletab.properties
+++ b/chrome/treestyletab.jar!/locale/de-DE/treestyletab/treestyletab.properties
@@ -3,7 +3,9 @@ tooltip.collapseSubtree.labeled=Zweig zuklappen:\n%S
 tooltip.expandSubtree=Zweig aufklappen
 tooltip.expandSubtree.labeled=Zweig aufklappen:\n%S
 tooltip.closeTree=Diesen Zweig schließen
+tooltip.closeTree.labeled=Diesen Zweig schließen:\n%S
 tooltip.item.label=%2$S* %1$S
+tooltip.more=...and %1$S more tab(s)
 
 dropLinkOnTab.title=Wie soll der Link geöffnet werden?
 dropLinkOnTab.text=Ein Link wurde auf einen bestehenden Tab gezogen. TreeStyleTab kann den Link in einem neuen, untergeordneten Tab öffnen. Wie soll der Link geöffnet werden?
@@ -24,15 +26,19 @@ bookmarkDroppedTabs.never=Nicht mehr nachfragen
 bookmarkDroppedTabs.bookmarkAll=Alle Tabs im Zweig als Lesezeichen speichern
 bookmarkDroppedTabs.bookmarkOnlyParent=Nur das gezogene Tab als Lesezeichen speichern
 
-#undoCloseTabSetBehavior.title=Möchten Sie andere geschlossene Tabs auch wieder herstellen?
-#undoCloseTabSetBehavior.text=Dieses Tab wurde gemeinsam mit %S anderen geschlossen. Wie sollen diese behandelt werden?
-#openGroupBookmarkBehavior.never=Künftig nicht mehr nachfragen, und die angegebene Aktion ausführen
-#undoCloseTabSetBehavior.set=Alle Tabs wieder herstellen, die gemeinsam geschlossen wurden
-#undoCloseTabSetBehavior.separate=Ignorieren, nur dieses eine Tab soll wieder hergestellt werden (Firefox Standard)
-undoCloseTabSetBehavior.label=Sollen auch die folgenden %S Tabs wiederhergestellt werden?
-undoCloseTabSetBehavior.never=Nicht mehr nachfragen
-undoCloseTabSetBehavior.set=Tabs wieder herstellen
-undoCloseTabSetBehavior.separate=Nein danke
+undoCloseTabSetBehavior.label=This tab was closed together with other %S tab(s) in a tree. Do you want them to be restored along?
+undoCloseTabSetBehavior.restoreOnce=Restore tabs
+undoCloseTabSetBehavior.restoreForever=Always resotre tabs
+undoCloseTabSetBehavior.ignoreForever=Never show this notification
+# #undoCloseTabSetBehavior.title=Möchten Sie andere geschlossene Tabs auch wieder herstellen?
+# #undoCloseTabSetBehavior.text=Dieses Tab wurde gemeinsam mit %S anderen geschlossen. Wie sollen diese behandelt werden?
+# #openGroupBookmarkBehavior.never=Künftig nicht mehr nachfragen, und die angegebene Aktion ausführen
+# #undoCloseTabSetBehavior.set=Alle Tabs wieder herstellen, die gemeinsam geschlossen wurden
+# #undoCloseTabSetBehavior.separate=Ignorieren, nur dieses eine Tab soll wieder hergestellt werden (Firefox Standard)
+# undoCloseTabSetBehavior.label=Sollen auch die folgenden %S Tabs wiederhergestellt werden?
+# undoCloseTabSetBehavior.never=Nicht mehr nachfragen
+# undoCloseTabSetBehavior.set=Tabs wieder herstellen
+# undoCloseTabSetBehavior.separate=Nein danke
 
 openSelectedPlaces.bookmarks=von %2$S Lesezeichen, inklusive "%1$S"
 openSelectedPlaces.history=von %2$S Seiten im Verlauf, inklusive "%1$S"
diff --git a/chrome/treestyletab.jar!/locale/en-US/treestyletab/license.txt b/chrome/treestyletab.jar!/locale/en-US/treestyletab/license.txt
index 0c2f853..a02e38e 100755
--- a/chrome/treestyletab.jar!/locale/en-US/treestyletab/license.txt
+++ b/chrome/treestyletab.jar!/locale/en-US/treestyletab/license.txt
@@ -14,10 +14,10 @@ License.
 The Original Code is the Tree Style Tab.
 
 The Initial Developer of the Original Code is SHIMODA Hiroshi.
-Portions created by the Initial Developer are Copyright (C) 2007-2011
+Portions created by the Initial Developer are Copyright (C) 2007-2012
 the Initial Developer. All Rights Reserved.
 
-Contributor(s): SHIMODA Hiroshi <piro at p.club.ne.jp>
+Contributor(s): SHIMODA Hiroshi <piro.outsider.reflex at gmail.com>
 
 Alternatively, the contents of these files may be used under the terms of
 either the GNU General Public License Version 2 or later (the "GPL"), or
diff --git a/chrome/treestyletab.jar!/locale/en-US/treestyletab/treestyletab.dtd b/chrome/treestyletab.jar!/locale/en-US/treestyletab/treestyletab.dtd
index 288e32c..527ea3a 100755
--- a/chrome/treestyletab.jar!/locale/en-US/treestyletab/treestyletab.dtd
+++ b/chrome/treestyletab.jar!/locale/en-US/treestyletab/treestyletab.dtd
@@ -20,7 +20,6 @@
 <!ENTITY config.maxTreeLevel.before "until">
 <!ENTITY config.maxTreeLevel.after  "level(s)">
 <!ENTITY config.allowSubtreeCollapseExpand  "Allow to collapse/expand tree of tabs">
-<!ENTITY config.tabbar.hideAlltabsButton    "Show "List all tabs" button">
 
 
 <!ENTITY config.tabs.style "Style">
diff --git a/chrome/treestyletab.jar!/locale/en-US/treestyletab/treestyletab.properties b/chrome/treestyletab.jar!/locale/en-US/treestyletab/treestyletab.properties
index 192e788..61e33dd 100755
--- a/chrome/treestyletab.jar!/locale/en-US/treestyletab/treestyletab.properties
+++ b/chrome/treestyletab.jar!/locale/en-US/treestyletab/treestyletab.properties
@@ -3,7 +3,9 @@ tooltip.collapseSubtree.labeled=Collapse Tree:\n%S
 tooltip.expandSubtree=Expand Tree
 tooltip.expandSubtree.labeled=Expand Tree:\n%S
 tooltip.closeTree=Close this Tree
+tooltip.closeTree.labeled=Close this Tree:\n%S
 tooltip.item.label=%2$S* %1$S
+tooltip.more=...and %1$S more tab(s)
 
 dropLinkOnTab.title=How to open the dropped link?
 dropLinkOnTab.text=A link has been dropped onto existing tab. Tree Style Tab can open the link as a new child tab. How to deal with the link?
@@ -24,10 +26,10 @@ bookmarkDroppedTabs.never=Never ask me again
 bookmarkDroppedTabs.bookmarkAll=Bookmark All Tabs in the tree
 bookmarkDroppedTabs.bookmarkOnlyParent=Bookmark the Parent Tab Only.
 
-undoCloseTabSetBehavior.label=Do you want following %S tab(s) to be restored along?
-undoCloseTabSetBehavior.never=Never ask me again
-undoCloseTabSetBehavior.set=Restore tabs
-undoCloseTabSetBehavior.separate=No thank you
+undoCloseTabSetBehavior.label=This tab was closed together with other %S tab(s) in a tree. Do you want them to be restored along?
+undoCloseTabSetBehavior.restoreOnce=Restore tabs
+undoCloseTabSetBehavior.restoreForever=Always resotre tabs
+undoCloseTabSetBehavior.ignoreForever=Never show this notification
 
 openSelectedPlaces.bookmarks=from %2$S bookmarks, including "%1$S"
 openSelectedPlaces.history=from %2$S history entries, including "%1$S"
diff --git a/chrome/treestyletab.jar!/locale/es-ES/treestyletab/treestyletab.dtd b/chrome/treestyletab.jar!/locale/es-ES/treestyletab/treestyletab.dtd
index 40ab9f0..483aa25 100755
--- a/chrome/treestyletab.jar!/locale/es-ES/treestyletab/treestyletab.dtd
+++ b/chrome/treestyletab.jar!/locale/es-ES/treestyletab/treestyletab.dtd
@@ -20,7 +20,6 @@
 <!ENTITY config.maxTreeLevel.before "hasta">
 <!ENTITY config.maxTreeLevel.after  "nivel(es)">
 <!ENTITY config.allowSubtreeCollapseExpand  "Permitir colapsar/expandir los sub-árboles de las pestañas">
-<!ENTITY config.tabbar.hideAlltabsButton    "Mostrar el botón "Listar todas las pestañas"">
 
 
 <!ENTITY config.tabs.style "Estilo">
diff --git a/chrome/treestyletab.jar!/locale/es-ES/treestyletab/treestyletab.properties b/chrome/treestyletab.jar!/locale/es-ES/treestyletab/treestyletab.properties
index daa6d0e..975c943 100755
--- a/chrome/treestyletab.jar!/locale/es-ES/treestyletab/treestyletab.properties
+++ b/chrome/treestyletab.jar!/locale/es-ES/treestyletab/treestyletab.properties
@@ -3,7 +3,9 @@ tooltip.collapseSubtree.labeled=Colapsar árbol:\n%S
 tooltip.expandSubtree=Expandir árbol
 tooltip.expandSubtree.labeled=Expandir árbol:\n%S
 tooltip.closeTree=Cerrar este árbol
+tooltip.closeTree.labeled=Cerrar este árbol:\n%S
 tooltip.item.label=%2$S* %1$S
+tooltip.more=...and %1$S more tab(s)
 
 dropLinkOnTab.title=How to open the dropped link?
 dropLinkOnTab.text=A link has been dropped onto existing tab. Tree Style Tab can open the link as a new child tab. How to deal with the link?
@@ -24,15 +26,19 @@ bookmarkDroppedTabs.never=Never ask me again
 bookmarkDroppedTabs.bookmarkAll=Bookmark All Tabs in the tree
 bookmarkDroppedTabs.bookmarkOnlyParent=Bookmark the Parent Tab Only.
 
-#undoCloseTabSetBehavior.title=Do you want other closed tabs to be restored too?
-#undoCloseTabSetBehavior.text=This tab was closed with other %S tab(s) together. How treat them?
-#openGroupBookmarkBehavior.never=Never ask me, and do same operation hereafter
-#undoCloseTabSetBehavior.set=Restore all tabs closed with this tab
-#undoCloseTabSetBehavior.separate=Ignore, only this tab should be restored (Firefox default)
-undoCloseTabSetBehavior.label=Do you want following %S tab(s) to be restored along?
-undoCloseTabSetBehavior.never=Never ask me again
-undoCloseTabSetBehavior.set=Restore tabs
-undoCloseTabSetBehavior.separate=No thank you
+undoCloseTabSetBehavior.label=This tab was closed together with other %S tab(s) in a tree. Do you want them to be restored along?
+undoCloseTabSetBehavior.restoreOnce=Restore tabs
+undoCloseTabSetBehavior.restoreForever=Always resotre tabs
+undoCloseTabSetBehavior.ignoreForever=Never show this notification
+# #undoCloseTabSetBehavior.title=Do you want other closed tabs to be restored too?
+# #undoCloseTabSetBehavior.text=This tab was closed with other %S tab(s) together. How treat them?
+# #openGroupBookmarkBehavior.never=Never ask me, and do same operation hereafter
+# #undoCloseTabSetBehavior.set=Restore all tabs closed with this tab
+# #undoCloseTabSetBehavior.separate=Ignore, only this tab should be restored (Firefox default)
+# undoCloseTabSetBehavior.label=Do you want following %S tab(s) to be restored along?
+# undoCloseTabSetBehavior.never=Never ask me again
+# undoCloseTabSetBehavior.set=Restore tabs
+# undoCloseTabSetBehavior.separate=No thank you
 
 openSelectedPlaces.bookmarks=from %2$S bookmarks, including "%1$S"
 openSelectedPlaces.history=from %2$S history entries, including "%1$S"
diff --git a/chrome/treestyletab.jar!/locale/fr-FR/treestyletab/treestyletab.dtd b/chrome/treestyletab.jar!/locale/fr-FR/treestyletab/treestyletab.dtd
index a05b7d5..1cc438a 100755
--- a/chrome/treestyletab.jar!/locale/fr-FR/treestyletab/treestyletab.dtd
+++ b/chrome/treestyletab.jar!/locale/fr-FR/treestyletab/treestyletab.dtd
@@ -20,7 +20,6 @@
 <!ENTITY config.maxTreeLevel.before "until">
 <!ENTITY config.maxTreeLevel.after  "level(s)">
 <!ENTITY config.allowSubtreeCollapseExpand  "Autoriser le repliage/dépliage des arborescences d'onglets">
-<!ENTITY config.tabbar.hideAlltabsButton    "Afficher le bouton "Lister tous les onglets"">
 
 
 <!ENTITY config.tabs.style "Style">
diff --git a/chrome/treestyletab.jar!/locale/fr-FR/treestyletab/treestyletab.properties b/chrome/treestyletab.jar!/locale/fr-FR/treestyletab/treestyletab.properties
index 9da388a..82dac03 100755
--- a/chrome/treestyletab.jar!/locale/fr-FR/treestyletab/treestyletab.properties
+++ b/chrome/treestyletab.jar!/locale/fr-FR/treestyletab/treestyletab.properties
@@ -3,7 +3,9 @@ tooltip.collapseSubtree.labeled=Replier l'arborescence :\n%S
 tooltip.expandSubtree=Déplier l'arborescence
 tooltip.expandSubtree.labeled=Déplier l'arborescence :\n%S
 tooltip.closeTree=Fermer cette arborescence
+tooltip.closeTree.labeled=Fermer cette arborescence:\n%S
 tooltip.item.label=%2$S* %1$S
+tooltip.more=...and %1$S more tab(s)
 
 dropLinkOnTab.title=Comment ouvrir un lien déposé ?
 dropLinkOnTab.text=Un lien a été déposé sur un onglet existant. Tree Style Tab peut ouvrir le lien comme un nouveau onglet enfant. Comment gérer le lien ?
@@ -24,15 +26,19 @@ bookmarkDroppedTabs.never=Never ask me again
 bookmarkDroppedTabs.bookmarkAll=Bookmark All Tabs in the tree
 bookmarkDroppedTabs.bookmarkOnlyParent=Bookmark the Parent Tab Only.
 
-#undoCloseTabSetBehavior.title=Voulez-vous que la fermeture des autres onglets soit aussi annulée ?
-#undoCloseTabSetBehavior.text=Cet onglet a été fermé avec %S autres. Comment les traiter ?
-#openGroupBookmarkBehavior.never=Ne plus me demander, et appliquer désormais la même opération
-#undoCloseTabSetBehavior.set=Réouvrir tous les onglets fermés avec celui-ci
-#undoCloseTabSetBehavior.separate=Ignorer, et réouvrir uniquement celui-ci (défaut Firefox)
-undoCloseTabSetBehavior.label=Do you want following %S tab(s) to be restored along?
-undoCloseTabSetBehavior.never=Never ask me again
-undoCloseTabSetBehavior.set=Restore tabs
-undoCloseTabSetBehavior.separate=No thank you
+undoCloseTabSetBehavior.label=This tab was closed together with other %S tab(s) in a tree. Do you want them to be restored along?
+undoCloseTabSetBehavior.restoreOnce=Restore tabs
+undoCloseTabSetBehavior.restoreForever=Always resotre tabs
+undoCloseTabSetBehavior.ignoreForever=Never show this notification
+# #undoCloseTabSetBehavior.title=Voulez-vous que la fermeture des autres onglets soit aussi annulée ?
+# #undoCloseTabSetBehavior.text=Cet onglet a été fermé avec %S autres. Comment les traiter ?
+# #openGroupBookmarkBehavior.never=Ne plus me demander, et appliquer désormais la même opération
+# #undoCloseTabSetBehavior.set=Réouvrir tous les onglets fermés avec celui-ci
+# #undoCloseTabSetBehavior.separate=Ignorer, et réouvrir uniquement celui-ci (défaut Firefox)
+# undoCloseTabSetBehavior.label=Do you want following %S tab(s) to be restored along?
+# undoCloseTabSetBehavior.never=Never ask me again
+# undoCloseTabSetBehavior.set=Restore tabs
+# undoCloseTabSetBehavior.separate=No thank you
 
 openSelectedPlaces.bookmarks=à partir de %2$S marque-pages, dont "%1$S"
 openSelectedPlaces.history=à partir de %2$S entréess d'historique, dont "%1$S"
diff --git a/chrome/treestyletab.jar!/locale/it-IT/treestyletab/treestyletab.dtd b/chrome/treestyletab.jar!/locale/it-IT/treestyletab/treestyletab.dtd
index 22c4401..6a79cb0 100755
--- a/chrome/treestyletab.jar!/locale/it-IT/treestyletab/treestyletab.dtd
+++ b/chrome/treestyletab.jar!/locale/it-IT/treestyletab/treestyletab.dtd
@@ -20,7 +20,6 @@
 <!ENTITY config.maxTreeLevel.before "until">
 <!ENTITY config.maxTreeLevel.after  "level(s)">
 <!ENTITY config.allowSubtreeCollapseExpand  "Permetti di contrarre/espandere sottoalberi delle schede">
-<!ENTITY config.tabbar.hideAlltabsButton    "Visualizza la maniglia per elencare tutte le schede">
 
 
 <!ENTITY config.tabs.style "Style">
diff --git a/chrome/treestyletab.jar!/locale/it-IT/treestyletab/treestyletab.properties b/chrome/treestyletab.jar!/locale/it-IT/treestyletab/treestyletab.properties
index 78429b7..7b77252 100755
--- a/chrome/treestyletab.jar!/locale/it-IT/treestyletab/treestyletab.properties
+++ b/chrome/treestyletab.jar!/locale/it-IT/treestyletab/treestyletab.properties
@@ -3,7 +3,9 @@ tooltip.collapseSubtree.labeled=Contrai tutti:\n%S
 tooltip.expandSubtree=Espandi tutti
 tooltip.expandSubtree.labeled=Espandi tutti:\n%S
 tooltip.closeTree=Chiudi questo sottoalbero
+tooltip.closeTree.labeled=Chiudi questo sottoalbero:\n%S
 tooltip.item.label=%2$S* %1$S
+tooltip.more=...and %1$S more tab(s)
 
 dropLinkOnTab.title=How to open the dropped link?
 dropLinkOnTab.text=A link has been dropped onto existing tab. Tree Style Tab can open the link as a new child tab. How to deal with the link?
@@ -24,15 +26,19 @@ bookmarkDroppedTabs.never=Never ask me again
 bookmarkDroppedTabs.bookmarkAll=Bookmark All Tabs in the tree
 bookmarkDroppedTabs.bookmarkOnlyParent=Bookmark the Parent Tab Only.
 
-#undoCloseTabSetBehavior.title=Do you want other closed tabs to be restored too?
-#undoCloseTabSetBehavior.text=This tab was closed with other %S tab(s) together. How treat them?
-#openGroupBookmarkBehavior.never=Never ask me, and do same operation hereafter
-#undoCloseTabSetBehavior.set=Restore all tabs closed with this tab
-#undoCloseTabSetBehavior.separate=Ignore, only this tab should be restored (Firefox default)
-undoCloseTabSetBehavior.label=Do you want following %S tab(s) to be restored along?
-undoCloseTabSetBehavior.never=Never ask me again
-undoCloseTabSetBehavior.set=Restore tabs
-undoCloseTabSetBehavior.separate=No thank you
+undoCloseTabSetBehavior.label=This tab was closed together with other %S tab(s) in a tree. Do you want them to be restored along?
+undoCloseTabSetBehavior.restoreOnce=Restore tabs
+undoCloseTabSetBehavior.restoreForever=Always resotre tabs
+undoCloseTabSetBehavior.ignoreForever=Never show this notification
+# #undoCloseTabSetBehavior.title=Do you want other closed tabs to be restored too?
+# #undoCloseTabSetBehavior.text=This tab was closed with other %S tab(s) together. How treat them?
+# #openGroupBookmarkBehavior.never=Never ask me, and do same operation hereafter
+# #undoCloseTabSetBehavior.set=Restore all tabs closed with this tab
+# #undoCloseTabSetBehavior.separate=Ignore, only this tab should be restored (Firefox default)
+# undoCloseTabSetBehavior.label=Do you want following %S tab(s) to be restored along?
+# undoCloseTabSetBehavior.never=Never ask me again
+# undoCloseTabSetBehavior.set=Restore tabs
+# undoCloseTabSetBehavior.separate=No thank you
 
 openSelectedPlaces.bookmarks=from %2$S bookmarks, including "%1$S"
 openSelectedPlaces.history=from %2$S history entries, including "%1$S"
diff --git a/chrome/treestyletab.jar!/locale/ja/treestyletab/license.txt b/chrome/treestyletab.jar!/locale/ja/treestyletab/license.txt
index 0c2f853..a02e38e 100755
--- a/chrome/treestyletab.jar!/locale/ja/treestyletab/license.txt
+++ b/chrome/treestyletab.jar!/locale/ja/treestyletab/license.txt
@@ -14,10 +14,10 @@ License.
 The Original Code is the Tree Style Tab.
 
 The Initial Developer of the Original Code is SHIMODA Hiroshi.
-Portions created by the Initial Developer are Copyright (C) 2007-2011
+Portions created by the Initial Developer are Copyright (C) 2007-2012
 the Initial Developer. All Rights Reserved.
 
-Contributor(s): SHIMODA Hiroshi <piro at p.club.ne.jp>
+Contributor(s): SHIMODA Hiroshi <piro.outsider.reflex at gmail.com>
 
 Alternatively, the contents of these files may be used under the terms of
 either the GNU General Public License Version 2 or later (the "GPL"), or
diff --git a/chrome/treestyletab.jar!/locale/ja/treestyletab/treestyletab.dtd b/chrome/treestyletab.jar!/locale/ja/treestyletab/treestyletab.dtd
index b2c3ecc..fa9da9e 100755
--- a/chrome/treestyletab.jar!/locale/ja/treestyletab/treestyletab.dtd
+++ b/chrome/treestyletab.jar!/locale/ja/treestyletab/treestyletab.dtd
@@ -20,7 +20,6 @@
 <!ENTITY config.maxTreeLevel.before "(">
 <!ENTITY config.maxTreeLevel.after  "階層まで)">
 <!ENTITY config.allowSubtreeCollapseExpand  "ツリーを折りたためるようにする">
-<!ENTITY config.tabbar.hideAlltabsButton    "「タブの一覧を表示」ボタンを表示する">
 
 
 <!ENTITY config.tabs.style "スタイル">
diff --git a/chrome/treestyletab.jar!/locale/ja/treestyletab/treestyletab.properties b/chrome/treestyletab.jar!/locale/ja/treestyletab/treestyletab.properties
index 5e77ece..f340706 100755
--- a/chrome/treestyletab.jar!/locale/ja/treestyletab/treestyletab.properties
+++ b/chrome/treestyletab.jar!/locale/ja/treestyletab/treestyletab.properties
@@ -3,7 +3,9 @@ tooltip.collapseSubtree.labeled=ツリーをたたむ:\n%S
 tooltip.expandSubtree=ツリーを展開する
 tooltip.expandSubtree.labeled=ツリーを展開する:\n%S
 tooltip.closeTree=このツリーを閉じる
+tooltip.closeTree.labeled=このツリーを閉じる:\n%S
 tooltip.item.label=%2$S* %1$S
+tooltip.more=...(省略されたタブ:%1$S個)
 
 dropLinkOnTab.title=ドロップされたリンクをどのように開きますか?
 dropLinkOnTab.text=リンクがタブにドロップされました。ツリー型タブは、タブにドロップされたリンクを新しい子タブとして開くことができます。どのように扱いますか?
@@ -24,10 +26,10 @@ bookmarkDroppedTabs.never=今後も同様に処理する
 bookmarkDroppedTabs.bookmarkAll=すべてのタブをブックマークする
 bookmarkDroppedTabs.bookmarkOnlyParent=親のタブだけをブックマークする
 
-undoCloseTabSetBehavior.label=このタブと同時に閉じられた%S個のタブも開き直しますか?
-undoCloseTabSetBehavior.never=今後も同様に処理する
-undoCloseTabSetBehavior.set=はい(&y)
-undoCloseTabSetBehavior.separate=いいえ(&n)
+undoCloseTabSetBehavior.label=このタブは同じツリーの他の%S個のタブと同時に閉じられました。他のタブも開き直しますか?
+undoCloseTabSetBehavior.restoreOnce=開き直す(&r)
+undoCloseTabSetBehavior.restoreForever=今後は常に他のタブも開き直す(&f)
+undoCloseTabSetBehavior.ignoreForever=今後一切この通知を表示しない(&i)
 
 openSelectedPlaces.bookmarks=%1$S を含む %2$S 件のブックマークから
 openSelectedPlaces.history=%1$S を含む %2$S 件の履歴から
diff --git a/chrome/treestyletab.jar!/locale/pl/treestyletab/treestyletab.dtd b/chrome/treestyletab.jar!/locale/pl/treestyletab/treestyletab.dtd
index 4cd2069..a4536cc 100755
--- a/chrome/treestyletab.jar!/locale/pl/treestyletab/treestyletab.dtd
+++ b/chrome/treestyletab.jar!/locale/pl/treestyletab/treestyletab.dtd
@@ -20,7 +20,6 @@
 <!ENTITY config.maxTreeLevel.before "until">
 <!ENTITY config.maxTreeLevel.after  "level(s)">
 <!ENTITY config.allowSubtreeCollapseExpand  "Zezwalaj na zwijanie/rozwijanie drzewa kart">
-<!ENTITY config.tabbar.hideAlltabsButton    "Wyświetlaj przycisk „Pokaż wszystkie karty”">
 
 <!ENTITY config.tabs.style "Style">
 
diff --git a/chrome/treestyletab.jar!/locale/pl/treestyletab/treestyletab.properties b/chrome/treestyletab.jar!/locale/pl/treestyletab/treestyletab.properties
index cf32649..1171b76 100755
--- a/chrome/treestyletab.jar!/locale/pl/treestyletab/treestyletab.properties
+++ b/chrome/treestyletab.jar!/locale/pl/treestyletab/treestyletab.properties
@@ -3,7 +3,9 @@ tooltip.collapseSubtree.labeled=Zwiń drzewo:\n%S
 tooltip.expandSubtree=Rozwiń drzewo
 tooltip.expandSubtree.labeled=Rozwiń drzewo:\n%S
 tooltip.closeTree=Zamknij to drzewo
+tooltip.closeTree.labeled=Zamknij to drzewo:\n%S
 tooltip.item.label=%2$S* %1$S
+tooltip.more=...and %1$S more tab(s)
 
 dropLinkOnTab.title=Jak otworzyć upuszczony odnośnik?
 dropLinkOnTab.text=Odnośnik został upuszczony na istniejącą kartę. Tree Style Tab może otworzyć ten odnośnik jako kartę potomną. Jak go potraktować?
@@ -24,15 +26,19 @@ bookmarkDroppedTabs.never=Never ask me again
 bookmarkDroppedTabs.bookmarkAll=Bookmark All Tabs in the tree
 bookmarkDroppedTabs.bookmarkOnlyParent=Bookmark the Parent Tab Only.
 
-#undoCloseTabSetBehavior.title=Czy chcesz przywrócić również inne zamknięte karty?
-#undoCloseTabSetBehavior.text=Ta karta została zamknięta razem z innymi kartami: (&S). Jak je potraktować?
-#openGroupBookmarkBehavior.never=Nigdy nie pytaj
-#undoCloseTabSetBehavior.set=Przywróć wszystkie karty zamknięte razem z tą kartą
-#undoCloseTabSetBehavior.separate=Odtwórz tylko tę kartę (domyślne)
-undoCloseTabSetBehavior.label=Do you want following %S tab(s) to be restored along?
-undoCloseTabSetBehavior.never=Never ask me again
-undoCloseTabSetBehavior.set=Restore tabs
-undoCloseTabSetBehavior.separate=No thank you
+undoCloseTabSetBehavior.label=This tab was closed together with other %S tab(s) in a tree. Do you want them to be restored along?
+undoCloseTabSetBehavior.restoreOnce=Restore tabs
+undoCloseTabSetBehavior.restoreForever=Always resotre tabs
+undoCloseTabSetBehavior.ignoreForever=Never show this notification
+# #undoCloseTabSetBehavior.title=Czy chcesz przywrócić również inne zamknięte karty?
+# #undoCloseTabSetBehavior.text=Ta karta została zamknięta razem z innymi kartami: (&S). Jak je potraktować?
+# #openGroupBookmarkBehavior.never=Nigdy nie pytaj
+# #undoCloseTabSetBehavior.set=Przywróć wszystkie karty zamknięte razem z tą kartą
+# #undoCloseTabSetBehavior.separate=Odtwórz tylko tę kartę (domyślne)
+# undoCloseTabSetBehavior.label=Do you want following %S tab(s) to be restored along?
+# undoCloseTabSetBehavior.never=Never ask me again
+# undoCloseTabSetBehavior.set=Restore tabs
+# undoCloseTabSetBehavior.separate=No thank you
 
 openSelectedPlaces.bookmarks=z %2$S zakładek, łącznie z „%1$S”
 openSelectedPlaces.history=z %2$S wpisów historii, łącznie z „%1$S”
diff --git a/chrome/treestyletab.jar!/locale/ru-RU/treestyletab/treestyletab.dtd b/chrome/treestyletab.jar!/locale/ru-RU/treestyletab/treestyletab.dtd
deleted file mode 100755
index 11b42ef..0000000
--- a/chrome/treestyletab.jar!/locale/ru-RU/treestyletab/treestyletab.dtd
+++ /dev/null
@@ -1,194 +0,0 @@
-<!ENTITY config.title        "Настройки древовидного стиля вкладок">
-
-<!ENTITY config.scale.min "min">
-<!ENTITY config.scale.max "max">
-
-
-<!ENTITY config.tabs.appearance "Внешний вид">
-
-<!ENTITY config.tabbar.position.caption "Расположение панели вкладок">
-<!ENTITY config.tabbar.position.left    "Слева">
-<!ENTITY config.tabbar.position.right   "Справа">
-<!ENTITY config.tabbar.position.top     "Сверху (в Firefox по умолчанию)">
-<!ENTITY config.tabbar.position.bottom  "Снизу">
-<!ENTITY config.tabbar.invertClosebox.left  "Показывать кнопку закрытия с левой стороны каждой вкладки">
-<!ENTITY config.tabbar.invertClosebox.right "Показывать кнопку закрытия с правой стороны каждой вкладки">
-<!ENTITY config.tabbar.invertTab            "Инвертировать вид вкладок">
-<!ENTITY config.tabbar.invertTabContents    "Инвертировать содержимое вкладок">
-<!ENTITY config.tabbar.narrowScrollbar      "Narrow scrollbar">
-<!ENTITY config.enableSubtreeIndent         "Отступы вкладок">
-<!ENTITY config.maxTreeLevel.before "until">
-<!ENTITY config.maxTreeLevel.after  "level(s)">
-<!ENTITY config.allowSubtreeCollapseExpand  "Разрешить сворачивать/разворачивать поддеревья вкладок">
-<!ENTITY config.tabbar.hideAlltabsButton    "Показывать кнопку "Список всех вкладок"">
-
-
-<!ENTITY config.tabs.style "Стиль">
-
-<!ENTITY config.tabbar.style.caption "Стиль вкладок на панели">
-<!ENTITY config.tabbar.style.plain   "Plain">
-<!ENTITY config.tabbar.style.flat    "Flat">
-<!ENTITY config.tabbar.style.mixed   "Mixed">
-<!ENTITY config.tabbar.style.vertigo "Vertigo">
-<!ENTITY config.tabbar.style.metal   "Metal">
-<!ENTITY config.tabbar.style.sidebar "Sidebar">
-<!ENTITY config.tabbar.style.none    "По умолчанию (определяется темой)">
-
-<!ENTITY config.twisty.style.caption "Вид узлов дерева">
-<!ENTITY config.twisty.style.auto    "Авто">
-<!ENTITY config.twisty.style.none    "Нет">
-<!ENTITY config.twisty.style.retro   "Ретро">
-<!ENTITY config.twisty.style.modern.black "Черный новый">
-<!ENTITY config.twisty.style.modern.white "Белый новый">
-<!ENTITY config.twisty.style.osx     "OS X">
-
-
-<!ENTITY config.tabs.menu "Меню">
-
-<!ENTITY config.show.tabContextMenu.caption "Добавить следующие элементы в контекстное меню вкладок">
-
-
-<!ENTITY config.tabs.tab "Новые вкладки">
-
-<!ENTITY config.autoAttach.newTabCommand.label_before "Open new blank tab as">
-<!ENTITY config.autoAttach.newTabCommand.independent "an independent tab">
-<!ENTITY config.autoAttach.newTabCommand.child       "a child of the current tab">
-<!ENTITY config.autoAttach.newTabCommand.sibling     "a sibling of the current tab">
-<!ENTITY config.autoAttach.newTabCommand.nextSibling "the next sibling of the current tab">
-<!ENTITY config.autoAttach.newTabCommand.label_after "">
-
-<!ENTITY config.autoAttach.newTabButton.label_before "For middle click on the "New Tab" button, open new blank tab as">
-<!ENTITY config.autoAttach.newTabButton.independent "an independent tab">
-<!ENTITY config.autoAttach.newTabButton.child       "a child of the current tab">
-<!ENTITY config.autoAttach.newTabButton.sibling     "a sibling of the current tab">
-<!ENTITY config.autoAttach.newTabButton.nextSibling "the next sibling of the current tab">
-<!ENTITY config.autoAttach.newTabButton.label_after "">
-
-<!ENTITY config.autoAttach.duplicateTabCommand.label_before "For middle click on the "Reload" button, duplicate the tab as">
-<!ENTITY config.autoAttach.duplicateTabCommand.independent "an independent tab">
-<!ENTITY config.autoAttach.duplicateTabCommand.child       "a child of the source tab">
-<!ENTITY config.autoAttach.duplicateTabCommand.sibling     "a sibling of the source tab">
-<!ENTITY config.autoAttach.duplicateTabCommand.nextSibling "the next sibling of the source tab">
-<!ENTITY config.autoAttach.duplicateTabCommand.label_after "">
-
-<!ENTITY config.autoAttach.goButton.label_before "For middle click on the "Go" button, open new tab as">
-<!ENTITY config.autoAttach.goButton.independent "an independent tab">
-<!ENTITY config.autoAttach.goButton.child       "a child of the current tab">
-<!ENTITY config.autoAttach.goButton.sibling     "a sibling of the current tab">
-<!ENTITY config.autoAttach.goButton.nextSibling "the next sibling of the current tab">
-<!ENTITY config.autoAttach.goButton.label_after "">
-
-<!ENTITY config.openGroupBookmark.caption     "При операции  "Открыть все в вкладках" из папок закладок">
-<!ENTITY config.openGroupBookmark.ask         "Всегда спрашивать">
-<!ENTITY config.openGroupBookmark.subtree     "Открывать как дерево (рекомендуется)">
-<!ENTITY config.openGroupBookmark.subtree.type.before  "">
-<!ENTITY config.openGroupBookmark.subtree.type.restore "Восстановить">
-<!ENTITY config.openGroupBookmark.subtree.type.flat    "Игнорировать">
-<!ENTITY config.openGroupBookmark.subtree.type.after   "структуру дерева вкладок, сохраненную в закладках">
-<!ENTITY config.openGroupBookmark.flat        "Открывать как раздельные вкладки (в Firefox по умолчанию)">
-<!ENTITY config.openGroupBookmark.replace     "Окрывать с заменой текущей вкладки">
-<!ENTITY config.openGroupBookmark.underParent "Создавать для вкладок 'титульную' родительскую вкладку">
-
-<!ENTITY config.dropLinksOnTab.caption "Dropped link, URL, bookmark or file to existing tab">
-<!ENTITY config.dropLinksOnTab.ask     "Always ask me how to load it">
-<!ENTITY config.dropLinksOnTab.load    "Load in the tab (Firefox default)">
-<!ENTITY config.dropLinksOnTab.newTab  "Open as a new child tab">
-<!--
-<!ENTITY config.dropLinksOnTab.caption "Действие при перетаскивании ссылок или URL-ов в имеющуюся вкладку">
-<!ENTITY config.dropLinksOnTab.ask     "Всегда спрашивать">
-<!ENTITY config.dropLinksOnTab.load    "Загрузить ссылку во вкладке (в Firefox по умолчанию)">
-<!ENTITY config.dropLinksOnTab.newTab  "Открыть ссылку в новой вкладке дочерней от текущей">
--->
-
-
-<!ENTITY config.tabs.autohide "Автоскрытие/показ панели">
-
-<!ENTITY config.autoHide.mode.normal.caption     "for Normal Window Mode">
-<!ENTITY config.autoHide.mode.fullscreen.caption "for Full Screen Mode">
-<!ENTITY config.autoHide.mode.0 "Показывать панель вкладок всегда">
-<!ENTITY config.autoHide.mode.1 "Автоскрытие панели вкладок">
-<!ENTITY config.autoHide.mode.2 "Автосжатие панели вкладок">
-<!ENTITY config.autoShow.caption "Автоматически показывать панель вкладок при">
-<!ENTITY config.autoShow.mousemove "Перемещении мышки к краю окна / панели вкладок">
-<!ENTITY config.autoHide.area.before "Область срабатывания:">
-<!ENTITY config.autoHide.area.after "пикселов от края окна / панели вкладок">
-<!ENTITY config.autoHide.delay.before "Задержка:">
-<!ENTITY config.autoHide.delay.after "мсек.">
-<!ENTITY config.autoShow.accelKeyDown "Нажати и удержания кнопки Ctrl">
-<!ENTITY config.autoShow.accelKeyDown.delay.before "Показывать после">
-<!ENTITY config.autoShow.accelKeyDown.delay.after  "мсек.">
-<!ENTITY config.autoShow.tabSwitch   "Переключании вкладок через Ctrl+Tab ">
-<!ENTITY config.autoShow.feedback    "Закрытии вкладок или открытии новых">
-<!ENTITY config.autoShow.feedback.delay.before "Скрыть после">
-<!ENTITY config.autoShow.feedback.delay.after  "мсек.">
-
-
-<!ENTITY config.tabs.tree "Дерево">
-
-<!ENTITY config.autoCollapseExpandSubtreeOnSelect "Когда вкладка выбрана, развернуть ее дерево и автоматически сжать другие">
-<!ENTITY config.autoCollapseExpandSubtreeOnSelect.onCurrentTabRemove "Исключая смещение выбора вкладки, в случае закрытия текущей вкладки">
-<!ENTITY config.collapseExpandSubtree.dblclick "Сворачивать/разворачивать дерево вкладок по двойному клику">
-<!ENTITY config.autoExpandSubtreeOnAppendChild "Разворачивать дерево автоматически, когда вкладки вставляются в дерево">
-
-<!ENTITY config.closeParentBehavior.caption       "Если родительская вкладка закрыта">
-<!ENTITY config.closeParentBehavior.close         "Закрыть также дочерние вкладки">
-<!ENTITY config.closeParentBehavior.promoteFirst "Назначить первую дочернюю вкладку как новую родительскую">
-<!ENTITY config.closeParentBehavior.promoteAll   "Назначить все дочерние вкладки на уровень закрытой родительской вкладки">
-<!ENTITY config.closeParentBehavior.detach        "пренести дочерние вкладки из дерева">
-<!ENTITY config.closeRootBehavior.promoteFirst   "Назначить первую дочернюю вкладку как новую родительскую, если закрытая родительская вкладка не имела родителя">
-
-<!ENTITY config.focusMode "Переходить по Ctrl+Tab на следующую/предыдущую вкладку, если очередная отсутствует">
-
-<!ENTITY config.insertNewChildAt.caption "Позиция вставки новых дочерних вкладок">
-<!ENTITY config.insertNewChildAt.first "Вставлять первой в начало дерева">
-<!ENTITY config.insertNewChildAt.last "Добавлять в конце дерева">
-
-<!ENTITY config.undoCloseTabSet.caption  "Если элемент дерева восстанавливается через "Восстановить закрытую вкладку"">
-<!ENTITY config.undoCloseTabSet.ask      "Спрашивать всегда">
-<!ENTITY config.undoCloseTabSet.set      "Восстановить все дерево">
-<!ENTITY config.undoCloseTabSet.separate "Восстановить только одну вкладку (в Firefox по умолчанию)">
-
-<!ENTITY config.tabs.advanced "Дополнительно">
-
-<!ENTITY config.animation.enabled "Использование эффектов анимации">
-
-<!ENTITY config.tooltip.includeChildren        "Показывать содержимое дерева в всплывающем окне вкладок">
-
-<!ENTITY config.bookmarkDroppedTabs.caption "Action for drag and drop of a parent tab to the bookmarks tree">
-<!ENTITY config.bookmarkDroppedTabs.ask     "Ask me always">
-<!ENTITY config.bookmarkDroppedTabs.all     "Bookmark all tabs in the tree">
-<!ENTITY config.bookmarkDroppedTabs.parent  "Bookmark only the dragged one tab">
-
-
-
-
-
-<!ENTITY selection.removeTabSubtree.label     "Закрыть выбранные деревья">
-<!ENTITY selection.removeTabSubtree.accesskey "s">
-<!ENTITY selection.createSubtree.label          "Собрать в новое дерево">
-<!ENTITY selection.createSubtree.accesskey      "g">
-
-<!ENTITY context.reloadTabSubtree.label     "Перезагрузить это дерево">
-<!ENTITY context.reloadTabSubtree.accesskey "r">
-<!ENTITY context.reloadDescendantTabs.label     "Перезагрузить дочерние вкладки">
-<!ENTITY context.reloadDescendantTabs.accesskey "r">
-<!ENTITY context.removeTabSubtree.label     "Закрыть это дерево">
-<!ENTITY context.removeTabSubtree.accesskey "s">
-<!ENTITY context.removeDescendantTabs.label     "Закрыть дочерние вкладки">
-<!ENTITY context.removeDescendantTabs.accesskey "d">
-<!ENTITY context.removeAllTabsBut.label         "Close Other Tabs except this Tree">
-<!ENTITY context.removeAllTabsBut.accesskey     "a">
-<!ENTITY context.collapseAllSubtree.label     "Свернуть все деревья">
-<!ENTITY context.collapseAllSubtree.accesskey "c">
-<!ENTITY context.expandAllSubtree.label     "Раскрыть все деревья">
-<!ENTITY context.expandAllSubtree.accesskey "e">
-<!ENTITY context.toggleAutoHide.label     "Автоскрытие панели вкладок">
-<!ENTITY context.toggleAutoHide.accesskey "h">
-<!ENTITY context.toggleFixed.label            "Зафиксировать позицию и ширину/высоту панели вкладок">
-<!ENTITY context.toggleFixed.label.horizontal "Зафиксировать позицию и высоту панели вкладок">
-<!ENTITY context.toggleFixed.label.vertical   "Зафиксировать позицию и ширину панели вкладок">
-<!ENTITY context.toggleFixed.accesskey "f">
-<!ENTITY context.bookmarkTabSubtree.label     "Добавить это дерево в закладки...">
-<!ENTITY context.bookmarkTabSubtree.accesskey "t">
-
-<!ENTITY group.default "Новая группа">
diff --git a/chrome/treestyletab.jar!/locale/ru-RU/treestyletab/license.txt b/chrome/treestyletab.jar!/locale/ru/treestyletab/license.txt
similarity index 95%
rename from chrome/treestyletab.jar!/locale/ru-RU/treestyletab/license.txt
rename to chrome/treestyletab.jar!/locale/ru/treestyletab/license.txt
index 98b8dbb..932f28d 100755
--- a/chrome/treestyletab.jar!/locale/ru-RU/treestyletab/license.txt
+++ b/chrome/treestyletab.jar!/locale/ru/treestyletab/license.txt
@@ -14,10 +14,11 @@ License.
 The Original Code is the Tree Style Tab.
 
 The Initial Developer of the Original Code is L'Autour.
-Portions created by the Initial Developer are Copyright (C) 2008
+Portions created by the Initial Developer are Copyright (C) 2008-2012
 the Initial Developer. All Rights Reserved.
 
 Contributor(s): L'Autour <LAutour at yandex.ru>
+                Infocatcher
 
 Alternatively, the contents of these files may be used under the terms of
 either the GNU General Public License Version 2 or later (the "GPL"), or
diff --git a/chrome/treestyletab.jar!/locale/ru/treestyletab/treestyletab.dtd b/chrome/treestyletab.jar!/locale/ru/treestyletab/treestyletab.dtd
new file mode 100755
index 0000000..2c2c523
--- /dev/null
+++ b/chrome/treestyletab.jar!/locale/ru/treestyletab/treestyletab.dtd
@@ -0,0 +1,193 @@
+<!ENTITY config.title        "Настройки древовидного стиля вкладок">
+
+<!ENTITY config.scale.min "min">
+<!ENTITY config.scale.max "max">
+
+
+<!ENTITY config.tabs.appearance "Внешний вид">
+
+<!ENTITY config.tabbar.position.caption "Расположение панели вкладок">
+<!ENTITY config.tabbar.position.left    "Слева">
+<!ENTITY config.tabbar.position.right   "Справа">
+<!ENTITY config.tabbar.position.top     "Сверху (по умолчанию в Firefox)">
+<!ENTITY config.tabbar.position.bottom  "Снизу">
+<!ENTITY config.tabbar.invertClosebox.left  "Показывать кнопку закрытия с левой стороны каждой вкладки">
+<!ENTITY config.tabbar.invertClosebox.right "Показывать кнопку закрытия с правой стороны каждой вкладки">
+<!ENTITY config.tabbar.invertTab            "Инвертировать вид вкладок">
+<!ENTITY config.tabbar.invertTabContents    "Инвертировать содержимое вкладок">
+<!ENTITY config.tabbar.narrowScrollbar      "Узкая полоса прокрутки">
+<!ENTITY config.enableSubtreeIndent         "Отступы вкладок">
+<!ENTITY config.maxTreeLevel.before "пока уровней меньше">
+<!ENTITY config.maxTreeLevel.after  "">
+<!ENTITY config.allowSubtreeCollapseExpand  "Разрешить сворачивать/разворачивать поддеревья вкладок">
+
+
+<!ENTITY config.tabs.style "Стиль">
+
+<!ENTITY config.tabbar.style.caption "Стиль вкладок на панели">
+<!ENTITY config.tabbar.style.plain   "Plain">
+<!ENTITY config.tabbar.style.flat    "Flat">
+<!ENTITY config.tabbar.style.mixed   "Mixed">
+<!ENTITY config.tabbar.style.vertigo "Vertigo">
+<!ENTITY config.tabbar.style.metal   "Metal">
+<!ENTITY config.tabbar.style.sidebar "Sidebar">
+<!ENTITY config.tabbar.style.none    "По умолчанию (определяется темой)">
+
+<!ENTITY config.twisty.style.caption "Вид узлов дерева">
+<!ENTITY config.twisty.style.auto    "Авто">
+<!ENTITY config.twisty.style.none    "Нет">
+<!ENTITY config.twisty.style.retro   "Ретро">
+<!ENTITY config.twisty.style.modern.black "Чёрный новый">
+<!ENTITY config.twisty.style.modern.white "Белый новый">
+<!ENTITY config.twisty.style.osx     "OS X">
+
+
+<!ENTITY config.tabs.menu "Меню">
+
+<!ENTITY config.show.tabContextMenu.caption "Добавить следующие элементы в контекстное меню вкладок">
+
+
+<!ENTITY config.tabs.tab "Новые вкладки">
+
+<!ENTITY config.autoAttach.newTabCommand.label_before "Открывать новую пустую вкладку">
+<!ENTITY config.autoAttach.newTabCommand.independent "как отдельную вкладку">
+<!ENTITY config.autoAttach.newTabCommand.child       "как дочернюю к текущей вкладке">
+<!ENTITY config.autoAttach.newTabCommand.sibling     "на том же уровне, что и текущая">
+<!ENTITY config.autoAttach.newTabCommand.nextSibling "рядом с текущей вкладкой">
+<!ENTITY config.autoAttach.newTabCommand.label_after "">
+
+<!ENTITY config.autoAttach.newTabButton.label_before "По клику средней кнопкой мыши на кнопке «Новая вкладка» открывать новую вкладку">
+<!ENTITY config.autoAttach.newTabButton.independent "как отдельную вкладку">
+<!ENTITY config.autoAttach.newTabButton.child       "как дочернюю к текущей вкладке">
+<!ENTITY config.autoAttach.newTabButton.sibling     "на том же уровне, что и текущая">
+<!ENTITY config.autoAttach.newTabButton.nextSibling "рядом с текущей вкладкой">
+<!ENTITY config.autoAttach.newTabButton.label_after "">
+
+<!ENTITY config.autoAttach.duplicateTabCommand.label_before "По клику средней кнопкой мыши на кнопке «Обновить» клонировать вкладку">
+<!ENTITY config.autoAttach.duplicateTabCommand.independent "как отдельную вкладку">
+<!ENTITY config.autoAttach.duplicateTabCommand.child       "как дочернюю к текущей вкладке">
+<!ENTITY config.autoAttach.duplicateTabCommand.sibling     "на том же уровне, что и текущая">
+<!ENTITY config.autoAttach.duplicateTabCommand.nextSibling "рядом с текущей вкладкой">
+<!ENTITY config.autoAttach.duplicateTabCommand.label_after "">
+
+<!ENTITY config.autoAttach.goButton.label_before "По клику средней кнопкой мыши на кнопке «Перейти» открывать новую вкладку">
+<!ENTITY config.autoAttach.goButton.independent "как отдельную вкладку">
+<!ENTITY config.autoAttach.goButton.child       "как дочернюю к текущей вкладке">
+<!ENTITY config.autoAttach.goButton.sibling     "на том же уровне, что и текущая">
+<!ENTITY config.autoAttach.goButton.nextSibling "рядом с текущей вкладкой">
+<!ENTITY config.autoAttach.goButton.label_after "">
+
+<!ENTITY config.openGroupBookmark.caption     "Поведение команды «Открыть всё во вкладках» для папок закладок">
+<!ENTITY config.openGroupBookmark.ask         "Всегда спрашивать">
+<!ENTITY config.openGroupBookmark.subtree     "Открывать как дерево (рекомендуется)">
+<!ENTITY config.openGroupBookmark.subtree.type.before  "">
+<!ENTITY config.openGroupBookmark.subtree.type.restore "Восстановить">
+<!ENTITY config.openGroupBookmark.subtree.type.flat    "Игнорировать">
+<!ENTITY config.openGroupBookmark.subtree.type.after   "структуру дерева вкладок, сохраненную в закладках">
+<!ENTITY config.openGroupBookmark.flat        "Открывать как раздельные вкладки (по умолчанию в Firefox)">
+<!ENTITY config.openGroupBookmark.replace     "Открывать с заменой текущей вкладки">
+<!ENTITY config.openGroupBookmark.underParent "Поместить вкладки в «титульную» родительскую вкладку">
+
+<!ENTITY config.dropLinksOnTab.caption "При перетаскивании ссылки, закладки или файла на существующую вкладку">
+<!ENTITY config.dropLinksOnTab.ask     "Всегда спрашивать">
+<!ENTITY config.dropLinksOnTab.load    "Загружать в текущую вкладку (по умолчанию в Firefox)">
+<!ENTITY config.dropLinksOnTab.newTab  "Открывать как дочернюю вкладку">
+<!--
+<!ENTITY config.dropLinksOnTab.caption "Действие при перетаскивании ссылок или URL-ов в имеющуюся вкладку">
+<!ENTITY config.dropLinksOnTab.ask     "Всегда спрашивать">
+<!ENTITY config.dropLinksOnTab.load    "Загрузить ссылку во вкладке (по умолчанию в Firefox)">
+<!ENTITY config.dropLinksOnTab.newTab  "Открыть ссылку в новой вкладке дочерней от текущей">
+-->
+
+
+<!ENTITY config.tabs.autohide "Автоскрытие">
+
+<!ENTITY config.autoHide.mode.normal.caption     "В нормальном режиме">
+<!ENTITY config.autoHide.mode.fullscreen.caption "В полноэкранном режиме">
+<!ENTITY config.autoHide.mode.0 "Показывать панель вкладок всегда">
+<!ENTITY config.autoHide.mode.1 "Автоскрытие панели вкладок">
+<!ENTITY config.autoHide.mode.2 "Автосжатие панели вкладок">
+<!ENTITY config.autoShow.caption "Автоматически показывать панель вкладок при">
+<!ENTITY config.autoShow.mousemove "Перемещении мышки к краю окна или панели вкладок">
+<!ENTITY config.autoHide.area.before "Область срабатывания:">
+<!ENTITY config.autoHide.area.after "пикселов от края окна или панели вкладок">
+<!ENTITY config.autoHide.delay.before "Задержка:">
+<!ENTITY config.autoHide.delay.after "мсек.">
+<!ENTITY config.autoShow.accelKeyDown "Нажатии и удержания кнопки Ctrl">
+<!ENTITY config.autoShow.accelKeyDown.delay.before "Показывать после">
+<!ENTITY config.autoShow.accelKeyDown.delay.after  "мсек.">
+<!ENTITY config.autoShow.tabSwitch   "Переключении вкладок через Ctrl+Tab">
+<!ENTITY config.autoShow.feedback    "Закрытии вкладок или открытии новых">
+<!ENTITY config.autoShow.feedback.delay.before "Скрыть после">
+<!ENTITY config.autoShow.feedback.delay.after  "мсек.">
+
+
+<!ENTITY config.tabs.tree "Дерево">
+
+<!ENTITY config.autoCollapseExpandSubtreeOnSelect "При выборе вкладки развернуть её дерево и автоматически свернуть остальные">
+<!ENTITY config.autoCollapseExpandSubtreeOnSelect.onCurrentTabRemove "Исключая выбор вкладки после закрытия текущей вкладки">
+<!ENTITY config.collapseExpandSubtree.dblclick "Сворачивать/разворачивать дерево вкладок по двойному клику">
+<!ENTITY config.autoExpandSubtreeOnAppendChild "Разворачивать дерево автоматически, когда вкладки вставляются в дерево">
+
+<!ENTITY config.closeParentBehavior.caption       "При закрытии родительской вкладки">
+<!ENTITY config.closeParentBehavior.close         "Также закрыть дочерние вкладки">
+<!ENTITY config.closeParentBehavior.promoteFirst "Сделать первую дочернюю вкладку новой родительской">
+<!ENTITY config.closeParentBehavior.promoteAll   "Переместить все дочерние вкладки на уровень закрытой родительской вкладки">
+<!ENTITY config.closeParentBehavior.detach        "Переместить дочерние вкладки из дерева">
+<!ENTITY config.closeRootBehavior.promoteFirst   "Сделать первую дочернюю вкладку новой родительской, если закрытая родительская вкладка не имела родителя">
+
+<!ENTITY config.focusMode "Переходить по Ctrl+Tab на следующую/предыдущую вкладку даже если она скрыта">
+
+<!ENTITY config.insertNewChildAt.caption "Позиция добавления новых дочерних вкладок">
+<!ENTITY config.insertNewChildAt.first "Добавлять в начало дерева">
+<!ENTITY config.insertNewChildAt.last "Добавлять в конец дерева">
+
+<!ENTITY config.undoCloseTabSet.caption  "При восстановлении элемента дерева через «Восстановить закрытую вкладку»">
+<!ENTITY config.undoCloseTabSet.ask      "Всегда спрашивать">
+<!ENTITY config.undoCloseTabSet.set      "Восстановить всё дерево">
+<!ENTITY config.undoCloseTabSet.separate "Восстановить только одну вкладку (по умолчанию в Firefox)">
+
+<!ENTITY config.tabs.advanced "Дополнительно">
+
+<!ENTITY config.animation.enabled "Включить эффекты анимации">
+
+<!ENTITY config.tooltip.includeChildren        "Показывать содержимое дерева во всплывающих подсказках вкладок">
+
+<!ENTITY config.bookmarkDroppedTabs.caption "Действие при перетаскивания родительской вкладки в закладки">
+<!ENTITY config.bookmarkDroppedTabs.ask     "Всегда спрашивать">
+<!ENTITY config.bookmarkDroppedTabs.all     "Добавить в закладки все вкладки в дереве">
+<!ENTITY config.bookmarkDroppedTabs.parent  "Добавить в закладки только перетаскиваемую вкладку">
+
+
+
+
+
+<!ENTITY selection.removeTabSubtree.label     "Закрыть выбранные деревья">
+<!ENTITY selection.removeTabSubtree.accesskey "в">
+<!ENTITY selection.createSubtree.label          "Переместить в новое дерево">
+<!ENTITY selection.createSubtree.accesskey      "П">
+
+<!ENTITY context.reloadTabSubtree.label     "Обновить это дерево">
+<!ENTITY context.reloadTabSubtree.accesskey "О">
+<!ENTITY context.reloadDescendantTabs.label     "Обновить дочерние вкладки">
+<!ENTITY context.reloadDescendantTabs.accesskey "д">
+<!ENTITY context.removeTabSubtree.label     "Закрыть это дерево">
+<!ENTITY context.removeTabSubtree.accesskey "З">
+<!ENTITY context.removeDescendantTabs.label     "Закрыть дочерние вкладки">
+<!ENTITY context.removeDescendantTabs.accesskey "д">
+<!ENTITY context.removeAllTabsBut.label         "Закрыть все вкладки, кроме этого дерева">
+<!ENTITY context.removeAllTabsBut.accesskey     "к">
+<!ENTITY context.collapseAllSubtree.label     "Свернуть все деревья">
+<!ENTITY context.collapseAllSubtree.accesskey "С">
+<!ENTITY context.expandAllSubtree.label     "Развернуть все деревья">
+<!ENTITY context.expandAllSubtree.accesskey "Р">
+<!ENTITY context.toggleAutoHide.label     "Автоскрытие панели вкладок">
+<!ENTITY context.toggleAutoHide.accesskey "А">
+<!ENTITY context.toggleFixed.label            "Зафиксировать положение и ширину/высоту панели вкладок">
+<!ENTITY context.toggleFixed.label.horizontal "Зафиксировать положение и высоту панели вкладок">
+<!ENTITY context.toggleFixed.label.vertical   "Зафиксировать положение и ширину панели вкладок">
+<!ENTITY context.toggleFixed.accesskey "Ñ„">
+<!ENTITY context.bookmarkTabSubtree.label     "Добавить это дерево в закладки…">
+<!ENTITY context.bookmarkTabSubtree.accesskey "з">
+
+<!ENTITY group.default "Новая группа">
diff --git a/chrome/treestyletab.jar!/locale/ru-RU/treestyletab/treestyletab.properties b/chrome/treestyletab.jar!/locale/ru/treestyletab/treestyletab.properties
similarity index 53%
rename from chrome/treestyletab.jar!/locale/ru-RU/treestyletab/treestyletab.properties
rename to chrome/treestyletab.jar!/locale/ru/treestyletab/treestyletab.properties
index 57741da..8336be9 100755
--- a/chrome/treestyletab.jar!/locale/ru-RU/treestyletab/treestyletab.properties
+++ b/chrome/treestyletab.jar!/locale/ru/treestyletab/treestyletab.properties
@@ -3,36 +3,33 @@ tooltip.collapseSubtree.labeled=Свернуть дерево:\n%S
 tooltip.expandSubtree=Развернуть дерево
 tooltip.expandSubtree.labeled=Развернуть дерево:\n%S
 tooltip.closeTree=Закрыть это дерево
+tooltip.closeTree.labeled=Закрыть это дерево:\n%S
 tooltip.item.label=%2$S* %1$S
+tooltip.more=…и еще %1$S вкладок
 
 dropLinkOnTab.title=Как открыть брошенную ссылку?
-dropLinkOnTab.text=Ссылка была брошена в существующую вкладку. Tree Style Tab может открыть ссылку как новую дочернюю вкладку. Как поступить с ссылкой?
-dropLinkOnTab.never=Больше не спрашивать, и использовать эту операцию в дальнейшем
-dropLinkOnTab.loadInTheTab=Загрузить в вкладку (в Firefox по умолчанию)
+dropLinkOnTab.text=Ссылка была брошена в существующую вкладку. Tree Style Tab может открыть ссылку как новую дочернюю вкладку. Как поступить со ссылкой?
+dropLinkOnTab.never=Больше не спрашивать и использовать эту операцию в дальнейшем
+dropLinkOnTab.loadInTheTab=Загрузить во вкладку (по умолчанию в Firefox)
 dropLinkOnTab.openNewChildTab=Открыть как новую дочернюю вкладку
 
 openGroupBookmarkBehavior.title=Как открыть набор закладок?
 openGroupBookmarkBehavior.text=Сейчас будет открыт набор вкладок из закладок. Как поступить?
-openGroupBookmarkBehavior.never=Больше не спрашивать, и использовать эту операцию в дальнейшем
+openGroupBookmarkBehavior.never=Больше не спрашивать и использовать эту операцию в дальнейшем
 openGroupBookmarkBehavior.subTree=Открыть как новое дерево
-openGroupBookmarkBehavior.separate=Открыть как отдельные вкладки (в Firefox по умолчанию)
+openGroupBookmarkBehavior.separate=Открыть как отдельные вкладки (по умолчанию в Firefox)
 openGroupBookmarkBehavior.replace=Заменить текущую вкладку
 
-bookmarkDroppedTabs.title=How to bookmark a tree of tabs?
-bookmarkDroppedTabs.text=The dragged tab has children. How to bookmark them?
-bookmarkDroppedTabs.never=Never ask me again
-bookmarkDroppedTabs.bookmarkAll=Bookmark All Tabs in the tree
-bookmarkDroppedTabs.bookmarkOnlyParent=Bookmark the Parent Tab Only.
-
-#undoCloseTabSetBehavior.title=Восстановить также другие закрытые вкладки ?
-#undoCloseTabSetBehavior.text=С этой вкладкой были закрыты также другие вкладки: %S шт. Как поступить с ними?
-#openGroupBookmarkBehavior.never=Больше не спрашивать, и использовать эту операцию в дальнейшем
-#undoCloseTabSetBehavior.set=Восстановить все вкладки закрытые вместе с этой вкладкой
-#undoCloseTabSetBehavior.separate=Игнорировать, только эта вкладка должна быть восстановлена (в Firefox по умолчанию)
-undoCloseTabSetBehavior.label=Do you want following %S tab(s) to be restored along?
-undoCloseTabSetBehavior.never=Never ask me again
-undoCloseTabSetBehavior.set=Restore tabs
-undoCloseTabSetBehavior.separate=No thank you
+bookmarkDroppedTabs.title=Как добавить в закладки дерево вкладок?
+bookmarkDroppedTabs.text=У перетаскиваемой вкладки есть дочерние. Что добавить в закладки?
+bookmarkDroppedTabs.never=Больше не спрашивать
+bookmarkDroppedTabs.bookmarkAll=&Все вкладки в дереве
+bookmarkDroppedTabs.bookmarkOnlyParent=Только &родительскую вкладку
+
+undoCloseTabSetBehavior.label=Эта вкладка была закрыта вместе с другими вкладками (%S шт.). Восстановить другие вкладки?
+undoCloseTabSetBehavior.restoreOnce=&Восстановить вкладки
+undoCloseTabSetBehavior.restoreForever=В&сегда восстанавливать вкладки
+undoCloseTabSetBehavior.ignoreForever=Больше &не показывать это сообщение
 
 openSelectedPlaces.bookmarks=из %2$S закладок, включая "%1$S"
 openSelectedPlaces.history=из %2$S из истории ссылок, включая "%1$S"
@@ -47,8 +44,8 @@ toolbarCustomizing_tabbar_horizontal=This toolbar becomes a tab bar.
 toolbarCustomizing_tabbar_vertical=This toolbar becomes a vertical tab bar.
 
 
-compatibility_STM_warning_title=Совместная работа Super Tab Mode  и  Tree Style Tab
-compatibility_STM_warning_text=Новые вкладки, открываемые из ссылок (или по другому), не могут быть дочерними для текущей вкладки, так как позиция новых вкладок определяется в Super Tab Mode. Какие уставки включить?\n(*Можно вручную сменить эти уставки в окне конфигурации Super Tab Mode.)
+compatibility_STM_warning_title=Совместная работа Super Tab Mode и Tree Style Tab
+compatibility_STM_warning_text=Новые вкладки, открываемые из ссылок (или по-другому), не могут быть дочерними для текущей вкладки, так как позиция новых вкладок определяется в Super Tab Mode. Какие уставки включить?\n(*Можно вручную изменить эти уставки в окне настроек Super Tab Mode.)
 compatibility_STM_warning_use_TST=Сделать вкладки дочерними для текущей вкладки
-compatibility_STM_warning_use_STM=Поместить вкладки в позицию определенную в  Super Tab Mode
+compatibility_STM_warning_use_STM=Поместить вкладки в позицию, определенную в Super Tab Mode
 compatibility_STM_warning_never=Больше не показывать этот диалог.
diff --git a/chrome/treestyletab.jar!/locale/sv-SE/treestyletab/license.txt b/chrome/treestyletab.jar!/locale/sv-SE/treestyletab/license.txt
index 0c2f853..c40b8ab 100755
--- a/chrome/treestyletab.jar!/locale/sv-SE/treestyletab/license.txt
+++ b/chrome/treestyletab.jar!/locale/sv-SE/treestyletab/license.txt
@@ -17,7 +17,7 @@ The Initial Developer of the Original Code is SHIMODA Hiroshi.
 Portions created by the Initial Developer are Copyright (C) 2007-2011
 the Initial Developer. All Rights Reserved.
 
-Contributor(s): SHIMODA Hiroshi <piro at p.club.ne.jp>
+Contributor(s): SHIMODA Hiroshi <piro.outsider.reflex at gmail.com>
 
 Alternatively, the contents of these files may be used under the terms of
 either the GNU General Public License Version 2 or later (the "GPL"), or
diff --git a/chrome/treestyletab.jar!/locale/sv-SE/treestyletab/treestyletab.dtd b/chrome/treestyletab.jar!/locale/sv-SE/treestyletab/treestyletab.dtd
index a733e2d..f78c044 100755
--- a/chrome/treestyletab.jar!/locale/sv-SE/treestyletab/treestyletab.dtd
+++ b/chrome/treestyletab.jar!/locale/sv-SE/treestyletab/treestyletab.dtd
@@ -20,7 +20,6 @@
 <!ENTITY config.maxTreeLevel.before "t.o.m. den">
 <!ENTITY config.maxTreeLevel.after  "nivån">
 <!ENTITY config.allowSubtreeCollapseExpand  "Tillåt att flikträd kan minimeras/expanderas">
-<!ENTITY config.tabbar.hideAlltabsButton    "Visa knappen "Visa upp alla flikar"">
 
 
 <!ENTITY config.tabs.style "Format">
diff --git a/chrome/treestyletab.jar!/locale/sv-SE/treestyletab/treestyletab.properties b/chrome/treestyletab.jar!/locale/sv-SE/treestyletab/treestyletab.properties
index c98b3d6..266bad2 100755
--- a/chrome/treestyletab.jar!/locale/sv-SE/treestyletab/treestyletab.properties
+++ b/chrome/treestyletab.jar!/locale/sv-SE/treestyletab/treestyletab.properties
@@ -3,7 +3,9 @@ tooltip.collapseSubtree.labeled=Minimera träd:\n%S
 tooltip.expandSubtree=Expandera träd
 tooltip.expandSubtree.labeled=Expandera träd:\n%S
 tooltip.closeTree=Stäng detta träd
+tooltip.closeTree.labeled=Stäng detta träd:\n%S
 tooltip.item.label=%2$S* %1$S
+tooltip.more=...and %1$S more tab(s)
 
 dropLinkOnTab.title=Hur skall den släppta länken öppnas?
 dropLinkOnTab.text=En länk har släppts på en befintlig flik. Tree Style Tab kan öppna länken som en ny underordnad flik. Hur skall länken hanteras?
@@ -24,10 +26,14 @@ bookmarkDroppedTabs.never=Fråga mig inte igen
 bookmarkDroppedTabs.bookmarkAll=Bokmärke för alla flikar i trädet
 bookmarkDroppedTabs.bookmarkOnlyParent=Bokmärke endast för den överordnade fliken.
 
-undoCloseTabSetBehavior.label=Vill du att följande %S flik(ar) skall återställas?
-undoCloseTabSetBehavior.never=Fråga mig inte igen
-undoCloseTabSetBehavior.set=Återställ flikar
-undoCloseTabSetBehavior.separate=Nej
+undoCloseTabSetBehavior.label=This tab was closed together with other %S tab(s) in a tree. Do you want them to be restored along?
+undoCloseTabSetBehavior.restoreOnce=Restore tabs
+undoCloseTabSetBehavior.restoreForever=Always resotre tabs
+undoCloseTabSetBehavior.ignoreForever=Never show this notification
+# undoCloseTabSetBehavior.label=Vill du att följande %S flik(ar) skall #å terställas?
+# undoCloseTabSetBehavior.never=Fråga mig inte igen
+# undoCloseTabSetBehavior.set=Återställ flikar
+# undoCloseTabSetBehavior.separate=Nej
 
 openSelectedPlaces.bookmarks=från %2$S bokmärken, inklusive "%1$S"
 openSelectedPlaces.history=från %2$S historikposter, inklusive "%1$S"
diff --git a/chrome/treestyletab.jar!/locale/zh-CN/treestyletab/treestyletab.dtd b/chrome/treestyletab.jar!/locale/zh-CN/treestyletab/treestyletab.dtd
index da2c2dd..7822f8a 100755
--- a/chrome/treestyletab.jar!/locale/zh-CN/treestyletab/treestyletab.dtd
+++ b/chrome/treestyletab.jar!/locale/zh-CN/treestyletab/treestyletab.dtd
@@ -20,7 +20,6 @@
 <!ENTITY config.maxTreeLevel.before "最多">
 <!ENTITY config.maxTreeLevel.after  "层">
 <!ENTITY config.allowSubtreeCollapseExpand  "允许折叠/展开标签子树">
-<!ENTITY config.tabbar.hideAlltabsButton    "显示“列出所有标签”按钮">
 
 
 <!ENTITY config.tabs.style "样式">
diff --git a/chrome/treestyletab.jar!/locale/zh-CN/treestyletab/treestyletab.properties b/chrome/treestyletab.jar!/locale/zh-CN/treestyletab/treestyletab.properties
index 83faf51..3505971 100755
--- a/chrome/treestyletab.jar!/locale/zh-CN/treestyletab/treestyletab.properties
+++ b/chrome/treestyletab.jar!/locale/zh-CN/treestyletab/treestyletab.properties
@@ -3,7 +3,9 @@ tooltip.collapseSubtree.labeled=折叠树:\n%S
 tooltip.expandSubtree=展开树
 tooltip.expandSubtree.labeled=展开树:\n%S
 tooltip.closeTree=关闭此树
+tooltip.closeTree.labeled=关闭此树:\n%S
 tooltip.item.label=%2$S* %1$S
+tooltip.more=...and %1$S more tab(s)
 
 dropLinkOnTab.title=如何打开拖曳的链接?
 dropLinkOnTab.text=你把一链接拖放到现有标签上,Tree Style Tab 能够将该链接打开到当前标签的一个新子标签中。你希望怎么处理呢?
@@ -24,10 +26,14 @@ bookmarkDroppedTabs.never=以后都按此处理,不再提问
 bookmarkDroppedTabs.bookmarkAll=将整个标签树加入书签
 bookmarkDroppedTabs.bookmarkOnlyParent=仅将该标签加入书签
 
-undoCloseTabSetBehavior.label=你要恢复的标签是跟其他 %S 个标签一起被关闭的,是否一并恢复?
-undoCloseTabSetBehavior.never=以后都按此处理,不再提问
-undoCloseTabSetBehavior.set=一并恢复吧
-undoCloseTabSetBehavior.separate=不用了
+undoCloseTabSetBehavior.label=This tab was closed together with other %S tab(s) in a tree. Do you want them to be restored along?
+undoCloseTabSetBehavior.restoreOnce=Restore tabs
+undoCloseTabSetBehavior.restoreForever=Always resotre tabs
+undoCloseTabSetBehavior.ignoreForever=Never show this notification
+# undoCloseTabSetBehavior.label=你要恢复的标签是跟其他 %S 个标签一起被关闭的,是否一并恢复?
+# undoCloseTabSetBehavior.never=以后都按此处理,不再提问
+# undoCloseTabSetBehavior.set=一并恢复吧
+# undoCloseTabSetBehavior.separate=不用了
 
 openSelectedPlaces.bookmarks=打开 %2$S 个书签,包括:"%1$S"
 openSelectedPlaces.history=打开 %2$S 个历史项,包括:"%1$S"
diff --git a/chrome/treestyletab.jar!/locale/zh-TW/treestyletab/treestyletab.dtd b/chrome/treestyletab.jar!/locale/zh-TW/treestyletab/treestyletab.dtd
index 3370cd3..1b5f2fa 100755
--- a/chrome/treestyletab.jar!/locale/zh-TW/treestyletab/treestyletab.dtd
+++ b/chrome/treestyletab.jar!/locale/zh-TW/treestyletab/treestyletab.dtd
@@ -20,7 +20,6 @@
 <!ENTITY config.maxTreeLevel.before "(最多">
 <!ENTITY config.maxTreeLevel.after  "層)">
 <!ENTITY config.allowSubtreeCollapseExpand  "允許摺疊 / 展開樹狀子目錄">
-<!ENTITY config.tabbar.hideAlltabsButton    "顯示「列出所有分頁」按鈕">
 
 
 <!ENTITY config.tabs.style "樣式">
diff --git a/chrome/treestyletab.jar!/locale/zh-TW/treestyletab/treestyletab.properties b/chrome/treestyletab.jar!/locale/zh-TW/treestyletab/treestyletab.properties
index fef6a63..0e9e5b3 100755
--- a/chrome/treestyletab.jar!/locale/zh-TW/treestyletab/treestyletab.properties
+++ b/chrome/treestyletab.jar!/locale/zh-TW/treestyletab/treestyletab.properties
@@ -3,7 +3,9 @@ tooltip.collapseSubtree.labeled=摺疊此樹:\n%S
 tooltip.expandSubtree=展開此樹
 tooltip.expandSubtree.labeled=展開此樹:\n%S
 tooltip.closeTree=關閉此樹
+tooltip.closeTree.labeled=關閉此樹:\n%S
 tooltip.item.label=%2$S* %1$S
+tooltip.more=...and %1$S more tab(s)
 
 dropLinkOnTab.title=如何開啟拖曳的鏈結?
 dropLinkOnTab.text=有一個鏈結被拖曳到目前分頁。Tree Style Tab 可將此鏈結開啟為新的子分頁,您打算怎麼處理?
@@ -24,10 +26,14 @@ bookmarkDroppedTabs.never=不要再問我,以後都照此辦理
 bookmarkDroppedTabs.bookmarkAll=將所有分頁加為書籤
 bookmarkDroppedTabs.bookmarkOnlyParent=只加入父分頁
 
-undoCloseTabSetBehavior.label=您要一併復原以下 %S 個同時關閉的分頁嗎?
-undoCloseTabSetBehavior.never=不要再問我,以後都照此辦理
-undoCloseTabSetBehavior.set=全部復原
-undoCloseTabSetBehavior.separate=不,謝謝
+undoCloseTabSetBehavior.label=This tab was closed together with other %S tab(s) in a tree. Do you want them to be restored along?
+undoCloseTabSetBehavior.restoreOnce=Restore tabs
+undoCloseTabSetBehavior.restoreForever=Always resotre tabs
+undoCloseTabSetBehavior.ignoreForever=Never show this notification
+# undoCloseTabSetBehavior.label=您要一併復原以下 %S 個同時關閉的分頁嗎?
+# undoCloseTabSetBehavior.never=不要再問我,以後都照此辦理
+# undoCloseTabSetBehavior.set=全部復原
+# undoCloseTabSetBehavior.separate=不,謝謝
 
 openSelectedPlaces.bookmarks=始於包含 %1$S 的 %2$S 個書籤
 openSelectedPlaces.history=始於包含 %1$S 的 %2$S 個歷史項目
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/Darwin-styled-inactive-3.5.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/Darwin-styled-inactive-3.5.css
deleted file mode 100755
index 4e19e73..0000000
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/Darwin-styled-inactive-3.5.css
+++ /dev/null
@@ -1,44 +0,0 @@
- at namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-
-/* horizontal tree */
-
-#main-window:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
-  .tabbrowser-tab:not([selected="true"])
-  .tab-image-middle,
-#main-window:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
-  .tabbrowser-tab:not([selected="true"])
-  .tab-close-button,
-#main-window:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
-  .tabbrowser-tab[selected="true"]
-  .tab-image-middle,
-#main-window:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
-  .tabbrowser-tab[selected="true"]
-  .tab-image-middle {
-	background-position: left bottom;
-	background-repeat: repeat-x;
-}
-
-#main-window:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
-  .tabbrowser-tab:not([selected="true"])
-  .tab-image-left,
-#main-window:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
-  .tabbrowser-tab:not([selected="true"])
-  .tab-image-left,
-#main-window:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
-  .tabbrowser-tab[selected="true"]
-  .tab-image-left,
-#main-window:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
-  .tabbrowser-tab[selected="true"]
-  .tab-image-left {
-	background-position: left bottom;
-	background-repeat: no-repeat;
-}
-
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/Darwin-styled-inactive-4.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/Darwin-styled-inactive-4.css
deleted file mode 100755
index f46bdaf..0000000
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/Darwin-styled-inactive-4.css
+++ /dev/null
@@ -1,44 +0,0 @@
- at namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-
-/* horizontal tree */
-
-#main-window:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
-  .tabbrowser-tab:not([selected="true"])
-  .tab-image-middle,
-#main-window:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
-  .tabbrowser-tab:not([selected="true"])
-  .tab-close-button,
-#main-window:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
-  .tabbrowser-tab[selected="true"]
-  .tab-close-button,
-#main-window:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
-  .tabbrowser-tab[selected="true"]
-  .tab-close-button {
-	background-position: left bottom;
-	background-repeat: repeat-x;
-}
-
-#main-window:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
-  .tabbrowser-tab:not([selected="true"])
-  .tab-image-right,
-#main-window:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
-  .tabbrowser-tab:not([selected="true"])
-  .tab-image-right,
-#main-window:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
-  .tabbrowser-tab[selected="true"]
-  .tab-image-right,
-#main-window:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
-  .tabbrowser-tab[selected="true"]
-  .tab-image-right {
-	background-position: left bottom;
-	background-repeat: no-repeat;
-}
-
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/Darwin-styled.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/Darwin-styled.css
index 4fc6c41..f941805 100755
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/Darwin-styled.css
+++ b/chrome/treestyletab.jar!/skin/classic/treestyletab/Darwin-styled.css
@@ -1,5 +1,3 @@
- at import url("platform-styled-inactive.css");
-
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 
 /* horizontal tree */
@@ -17,40 +15,28 @@
 #main-window
   .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
   .tabbrowser-tab:not([selected="true"])
-  .tab-image-middle,
-#main-window
-  .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
-  .tabbrowser-tab:not([selected="true"])
   .tab-close-button,
 #main-window
   .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
   .tabbrowser-tab[selected="true"]
-  .tab-image-middle,
-#main-window
-  .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
-  .tabbrowser-tab[selected="true"]
   .tab-close-button {
 	background-position: left bottom;
 	background-repeat: repeat-x;
 }
 
-#main-window
+#main-window:-moz-window-inactive
   .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
   .tabbrowser-tab:not([selected="true"])
-  .tab-image-left,
-#main-window
-  .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
-  .tabbrowser-tab:not([selected="true"])
-  .tab-image-right,
-#main-window
+  .tab-close-button,
+#main-window:-moz-window-inactive
   .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
   .tabbrowser-tab[selected="true"]
-  .tab-image-left,
-#main-window
+  .tab-close-button,
+#main-window:-moz-window-inactive
   .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-tabs-indented="true"]
   .tabbrowser-tab[selected="true"]
-  .tab-image-right {
+  .tab-close-button {
 	background-position: left bottom;
-	background-repeat: no-repeat;
+	background-repeat: repeat-x;
 }
 
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/Linux-base.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/Linux-base.css
index 700d9e4..9ba7b10 100755
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/Linux-base.css
+++ b/chrome/treestyletab.jar!/skin/classic/treestyletab/Linux-base.css
@@ -6,3 +6,17 @@
 	-moz-appearance: none;
 }
 
+#treestyletab-autohide-content-area-screen {
+	background: transparent;
+}
+/**
+ * We have to set both left and right borders to make the "window"
+ * not rectangle, because rectangle "window"s have dropshadows on Linux.
+ */
+:root[treestyletab-tabbar-position="left"]
+  #treestyletab-autohide-content-area-screen,
+:root[treestyletab-tabbar-position="right"]
+  #treestyletab-autohide-content-area-screen  {
+	border-right: 1px solid ThreeDShadow;
+	border-left: 1px solid ThreeDShadow;
+}
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/base.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/base.css
index 3d15f04..1cc2568 100755
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/base.css
+++ b/chrome/treestyletab.jar!/skin/classic/treestyletab/base.css
@@ -3,11 +3,7 @@
 
 /* buttons in the tab bar */
 
-/* Firefox 3.6 or older */
 .tabbrowser-tabs[treestyletab-mode="vertical"] .tabs-newtab-button,
-.tabbrowser-tabs[treestyletab-mode="vertical"] .tabs-alltabs-button,
-.tabbrowser-tabs[treestyletab-mode="vertical"] .tabs-container > .tabs-closebutton,
-/* Firefox 4.0 or later */
 .treestyletab-tabbar-toolbar[treestyletab-mode="vertical"] > toolbarbutton,
 .treestyletab-tabbar-toolbar[treestyletab-mode="vertical"] > toolbarpaletteitem > toolbarbutton {
 	-moz-appearance: none !important;
@@ -16,20 +12,16 @@
 	-moz-border-right-colors: none !important;
 	-moz-border-bottom-colors: none !important;
 	-moz-border-left-colors: none !important;
-	-moz-border-radius: 0; /* Firefox 4.0 or later */
+	-moz-border-radius: 0;
 	border-top: 1px solid ThreeDShadow !important;
 	background: ThreeDFace !important;
 }
-/* Firefox 3.6 or older */
 .tabbrowser-tabs[treestyletab-mode="vertical"] .tabs-newtab-button:hover,
-.tabbrowser-tabs[treestyletab-mode="vertical"] .tabs-alltabs-button:hover,
-.tabbrowser-tabs[treestyletab-mode="vertical"] .tabs-container > .tabs-closebutton:hover,
-/* Firefox 4.0 or later */
 .treestyletab-tabbar-toolbar[treestyletab-mode="vertical"] > toolbarbutton:hover {
 	background: ThreeDHighlight !important;
 }
 
-/* for Mac OS X, Firefox 4 */
+/* for Mac OS X */
 .tabbrowser-tabs[treestyletab-mode="vertical"]
   .tabs-newtab-button
   .toolbarbutton-icon {
@@ -43,7 +35,7 @@
 	padding: 0 !important;
 }
 
-/* Support customizable tab bar on Firefox 4.0 or later */
+/* Support customizable tab bar */
 .treestyletab-tabbar-toolbar[treestyletab-mode="vertical"] > toolbarpaletteitem > toolbarbutton {
 	-moz-box-flex: 1;
 }
@@ -59,13 +51,7 @@
 }
 
 
-/* Firefox 3.6 or older */
 .tabbrowser-tabs[treestyletab-mode="vertical"] .tabs-newtab-button,
-.tabbrowser-tabs[treestyletab-mode="vertical"] .tabs-alltabs-box,
-.tabbrowser-tabs[treestyletab-mode="vertical"] .tabs-alltabs-box-animate,
-.tabbrowser-tabs[treestyletab-mode="vertical"] .tabs-alltabs-button,
-.tabbrowser-tabs[treestyletab-mode="vertical"] .tabs-container > .tabs-closebutton,
-/* Firefox 4.0 or later */
 .treestyletab-tabbar-toolbar[treestyletab-mode="vertical"] > toolbarbutton,
 .treestyletab-tabbar-toolbar[treestyletab-mode="vertical"] > toolbarpaletteitem > toolbarbutton {
 	background-image: none !important;
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/config-4.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/config-4.css
deleted file mode 100755
index a89f4a7..0000000
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/config-4.css
+++ /dev/null
@@ -1,9 +0,0 @@
- at import url("chrome://treestyletab/skin/config-base.css");
-
-radio[pane] {
-	list-style-image: url("resource:///chrome/browser/skin/classic/browser/preferences/Options.png");
-}
-
-radio[pane="prefpane-tree"] {
-	list-style-image: url("chrome://treestyletab/content/res/icon.png");
-}
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/config-base.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/config-base.css
deleted file mode 100755
index 2661aee..0000000
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/config-base.css
+++ /dev/null
@@ -1,55 +0,0 @@
- at namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-
-radio.image .radio-label-box,
-radio.image label.radio-label {
-	-moz-box-align: center;
-}
-
-
-radio[pane] {
-	list-style-image: url("jar:resource:///chrome/classic.jar!/skin/classic/browser/preferences/Options.png");
-}
-
-radio[pane="prefpane-appearance"] {
-	-moz-image-region: rect(0px, 32px, 32px, 0px);
-}
-radio[pane="prefpane-style"] {
-	-moz-image-region: rect(0px, 32px, 32px, 0px);
-}
-radio[pane="prefpane-menu"] {
-	-moz-image-region: rect(0px, 32px, 32px, 0px);
-}
-radio[pane="prefpane-tab"] {
-	-moz-image-region: rect(0px, 64px, 32px, 32px);
-}
-radio[pane="prefpane-autohide"] {
-	-moz-image-region: rect(0px, 64px, 32px, 32px);
-}
-radio[pane="prefpane-advanced"] {
-	-moz-image-region: rect(0px, 224px, 32px, 192px);
-}
-radio[pane="prefpane-tree"] {
-	list-style-image: url("chrome://treestyletab/content/res/icon.png");
-}
-
-label.scale-label {
-	min-width: 0;
-	margin: 0;
-	font-size: smaller;
-}
-
-label[scale-selected="true"] {
-	font-weight: bold;
-}
-
-
-separator.hr {
-	border: 0 none;
-	border-top: 2px groove -moz-field;
-	height: 0;
-	margin-top: 0;
-	margin-bottom: 0;
-	max-height: none;
-	min-height: 0;
-	padding: 0;
-}
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/config.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/config.css
index 3d331bb..859d7ac 100755
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/config.css
+++ b/chrome/treestyletab.jar!/skin/classic/treestyletab/config.css
@@ -1,2 +1,55 @@
- at import url("chrome://treestyletab/skin/config-base.css");
- at import url("chrome://treestyletab/skin/config-legacy.css");
+ at namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
+
+radio.image .radio-label-box,
+radio.image label.radio-label {
+	-moz-box-align: center;
+}
+
+
+radio[pane] {
+	list-style-image: url("resource:///chrome/browser/skin/classic/browser/preferences/Options.png");
+}
+
+radio[pane="prefpane-appearance"] {
+	-moz-image-region: rect(0px, 32px, 32px, 0px);
+}
+radio[pane="prefpane-style"] {
+	-moz-image-region: rect(0px, 32px, 32px, 0px);
+}
+radio[pane="prefpane-menu"] {
+	-moz-image-region: rect(0px, 32px, 32px, 0px);
+}
+radio[pane="prefpane-tab"] {
+	-moz-image-region: rect(0px, 64px, 32px, 32px);
+}
+radio[pane="prefpane-autohide"] {
+	-moz-image-region: rect(0px, 64px, 32px, 32px);
+}
+radio[pane="prefpane-advanced"] {
+	-moz-image-region: rect(0px, 224px, 32px, 192px);
+}
+radio[pane="prefpane-tree"] {
+	list-style-image: url("chrome://treestyletab/content/res/icon.png");
+}
+
+label.scale-label {
+	min-width: 0;
+	margin: 0;
+	font-size: smaller;
+}
+
+label[scale-selected="true"] {
+	font-weight: bold;
+}
+
+
+separator.hr {
+	border: 0 none;
+	border-top: 2px groove -moz-field;
+	height: 0;
+	margin-top: 0;
+	margin-bottom: 0;
+	max-height: none;
+	min-height: 0;
+	padding: 0;
+}
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/dropmarker-down.png b/chrome/treestyletab.jar!/skin/classic/treestyletab/dropmarker-down.png
deleted file mode 100755
index eed51ec..0000000
Binary files a/chrome/treestyletab.jar!/skin/classic/treestyletab/dropmarker-down.png and /dev/null differ
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/dropmarker-left.png b/chrome/treestyletab.jar!/skin/classic/treestyletab/dropmarker-left.png
deleted file mode 100755
index 9d381dd..0000000
Binary files a/chrome/treestyletab.jar!/skin/classic/treestyletab/dropmarker-left.png and /dev/null differ
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/dropmarker-right.png b/chrome/treestyletab.jar!/skin/classic/treestyletab/dropmarker-right.png
deleted file mode 100755
index b1b0ea3..0000000
Binary files a/chrome/treestyletab.jar!/skin/classic/treestyletab/dropmarker-right.png and /dev/null differ
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/dropmarker-up.png b/chrome/treestyletab.jar!/skin/classic/treestyletab/dropmarker-up.png
deleted file mode 100755
index 5c564f0..0000000
Binary files a/chrome/treestyletab.jar!/skin/classic/treestyletab/dropmarker-up.png and /dev/null differ
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/group/group.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/group/group.css
index 9156830..332d3df 100755
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/group/group.css
+++ b/chrome/treestyletab.jar!/skin/classic/treestyletab/group/group.css
@@ -57,3 +57,16 @@
 	bottom: 0;
 	left: auto;
 }
+
+
+#tree {
+	height: 80%;
+	margin-top: 1em;
+	max-height: 80%;
+	overflow: auto;
+	-moz-box-flex: 1;
+}
+
+.treestyletab-pseudo-tree-root-item {
+	display: none;
+}
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/license.txt b/chrome/treestyletab.jar!/skin/classic/treestyletab/license.txt
index 0c2f853..a02e38e 100755
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/license.txt
+++ b/chrome/treestyletab.jar!/skin/classic/treestyletab/license.txt
@@ -14,10 +14,10 @@ License.
 The Original Code is the Tree Style Tab.
 
 The Initial Developer of the Original Code is SHIMODA Hiroshi.
-Portions created by the Initial Developer are Copyright (C) 2007-2011
+Portions created by the Initial Developer are Copyright (C) 2007-2012
 the Initial Developer. All Rights Reserved.
 
-Contributor(s): SHIMODA Hiroshi <piro at p.club.ne.jp>
+Contributor(s): SHIMODA Hiroshi <piro.outsider.reflex at gmail.com>
 
 Alternatively, the contents of these files may be used under the terms of
 either the GNU General Public License Version 2 or later (the "GPL"), or
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/metal/base-inactive-3.5.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/metal/base-inactive-3.5.css
deleted file mode 100755
index f25eb52..0000000
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/metal/base-inactive-3.5.css
+++ /dev/null
@@ -1,102 +0,0 @@
- at namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-
-/* tab bar */
-
-:root:not([active="true"]) 
-  .tabbrowser-strip[treestyletab-mode="vertical"] {
-	background: #acacac !important;
-	border-color: #797979 !important;
-}
-:root:not([active="true"])
-  .tabbrowser-strip[treestyletab-mode="vertical"][treestyletab-style~="aero"] {
-	background: transparent !important;
-}
-
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]:not([overflow="true"])
-  .tabbrowser-arrowscrollbox,
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"][overflow="true"]
-  .tabbrowser-arrowscrollbox
-  .scrollbox-innerbox {
-	background: url("shadow-inactive-l.png") repeat-y top right !important;
-}
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]:not([overflow="true"])
-  .tabbrowser-arrowscrollbox,
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"][overflow="true"]
-  .tabbrowser-arrowscrollbox
-  .scrollbox-innerbox {
-	background: url("shadow-inactive-r.png") repeat-y top left !important;
-}
-
-:root:not([active="true"])
-  tabbrowser
-  .treestyletab-splitter {
-	border-color: #666666 !important;
-	background: #e4e4e4 !important;
-}
-
-
-/* buttons in the tab bar */
-
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabs-newtab-button,
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabs-newtab-button:hover,
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabs-alltabs-button,
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabs-alltabs-button:hover,
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabs-container
-  > .tabs-closebutton,
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  > .tabs-closebutton,
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabs-container
-  > .tabs-closebutton:hover,
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  > .tabs-closebutton:hover {
-	background: #e4e4e4 !important;
-	border-color: #666666 !important;
-}
-
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]:not([treestyletab-tab-inverted="true"])
-  .tabbrowser-arrowscrollbox
-  .tabs-newtab-button {
-	background: #cecece url("shadow-inactive-l.png") repeat-y top right !important;
-	border-color: #9a9a9a !important;
-}
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tabbrowser-arrowscrollbox
-  .tabs-newtab-button {
-	background: #cecece url("shadow-inactive-r.png") repeat-y top left !important;
-	border-color: #9a9a9a !important;
-}
-
-
-/* hacks for Tab Mix Plus */
-
-:root[treestyletab-enable-compatibility-tmp="true"]:not([active="true"])
-  tabbrowser[treestyletab-mode="vertical"]
-  .tabs-closebutton-topbox
-  > .tabs-closebutton,
-:root[treestyletab-enable-compatibility-tmp="true"]:not([active="true"])
-  tabbrowser[treestyletab-mode="vertical"]
-  .tabs-closebutton-topbox
-  > .tabs-closebutton:hover {
-	background: #e4e4e4 !important;
-	border-color: #666666 !important;
-}
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/metal/base-inactive-4.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/metal/base-inactive-4.css
deleted file mode 100755
index f5d4de8..0000000
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/metal/base-inactive-4.css
+++ /dev/null
@@ -1,93 +0,0 @@
- at namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-
-/* tab bar */
-
-:root:-moz-window-inactive
-  .tabbrowser-strip[treestyletab-mode="vertical"] {
-	background: #acacac !important;
-	border-color: #797979 !important;
-}
-:root:-moz-window-inactive
-  .tabbrowser-strip[treestyletab-mode="vertical"][treestyletab-style~="aero"] {
-	background: transparent !important;
-}
-
-:root:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="vertical"]:not([overflow="true"])
-  .tabbrowser-arrowscrollbox,
-:root:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="vertical"][overflow="true"]
-  .tabbrowser-arrowscrollbox .scrollbox-innerbox {
-	background: url("shadow-inactive-l.png") repeat-y top right !important;
-}
-:root:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]:not([overflow="true"])
-  .tabbrowser-arrowscrollbox,
-:root:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"][overflow="true"]
-  .tabbrowser-arrowscrollbox
-  .scrollbox-innerbox {
-	background: url("shadow-inactive-r.png") repeat-y top left !important;
-}
-
-:root:-moz-window-inactive
-  tabbrowser
-  .treestyletab-splitter,
-:root:-moz-window-inactive
-  .treestyletab-tabbar-toolbar
-  .treestyletab-splitter {
-	border-color: #666666 !important;
-	background: #e4e4e4 !important;
-}
-
-
-/* buttons in the tab bar */
-
-:root:-moz-window-inactive
-  .treestyletab-tabbar-toolbar[treestyletab-mode="vertical"]
-  > toolbarbutton,
-:root:-moz-window-inactive
-  .treestyletab-tabbar-toolbar[treestyletab-mode="vertical"]
-  > toolbarbutton:hover,
-:root:-moz-window-inactive
-  .treestyletab-tabbar-toolbar[treestyletab-mode="vertical"]
-  > toolbarpaletteitem
-  > toolbarbutton,
-:root:-moz-window-inactive
-  .treestyletab-tabbar-toolbar[treestyletab-mode="vertical"]
-  > toolbarpaletteitem
-  > toolbarbutton:hover {
-	background: #e4e4e4 !important;
-	border-color: #666666 !important;
-}
-
-:root:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="vertical"]:not([treestyletab-tab-inverted="true"])
-  .tabbrowser-arrowscrollbox
-  .tabs-newtab-button {
-	background: #cecece url("shadow-inactive-l.png") repeat-y top right !important;
-	border-color: #9a9a9a !important;
-}
-:root:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tabbrowser-arrowscrollbox
-  .tabs-newtab-button {
-	background: #cecece url("shadow-inactive-r.png") repeat-y top left !important;
-	border-color: #9a9a9a !important;
-}
-
-
-
-/* hacks for Tab Mix Plus */
-
-:root[treestyletab-enable-compatibility-tmp="true"]:-moz-window-inactive
-  tabbrowser[treestyletab-mode="vertical"]
-  .tabs-closebutton-topbox
-  > .tabs-closebutton,
-:root[treestyletab-enable-compatibility-tmp="true"]:-moz-window-inactive
-  tabbrowser[treestyletab-mode="vertical"]
-  .tabs-closebutton-topbox
-  > .tabs-closebutton:hover {
-	background: #e4e4e4 !important;
-	border-color: #666666 !important;
-}
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/metal/base.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/metal/base.css
index f5899a0..b9dc83f 100755
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/metal/base.css
+++ b/chrome/treestyletab.jar!/skin/classic/treestyletab/metal/base.css
@@ -92,16 +92,47 @@ tabbrowser[treestyletab-tabbar-position="right"]
 	border-left: 1px solid #666666 !important;
 }
 
+:root:-moz-window-inactive
+  .tabbrowser-strip[treestyletab-mode="vertical"] {
+	background: #acacac !important;
+	border-color: #797979 !important;
+}
+:root:-moz-window-inactive
+  .tabbrowser-strip[treestyletab-mode="vertical"][treestyletab-style~="aero"] {
+	background: transparent !important;
+}
 
-/* tab contents */
+:root:-moz-window-inactive
+  .tabbrowser-tabs[treestyletab-mode="vertical"]:not([overflow="true"])
+  .tabbrowser-arrowscrollbox,
+:root:-moz-window-inactive
+  .tabbrowser-tabs[treestyletab-mode="vertical"][overflow="true"]
+  .tabbrowser-arrowscrollbox .scrollbox-innerbox {
+	background: url("shadow-inactive-l.png") repeat-y top right !important;
+}
+:root:-moz-window-inactive
+  .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]:not([overflow="true"])
+  .tabbrowser-arrowscrollbox,
+:root:-moz-window-inactive
+  .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"][overflow="true"]
+  .tabbrowser-arrowscrollbox
+  .scrollbox-innerbox {
+	background: url("shadow-inactive-r.png") repeat-y top left !important;
+}
 
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab
-  .tab-icon {
-	margin: -10px -5px !important;
-	padding: 10px 5px !important;
+:root:-moz-window-inactive
+  tabbrowser
+  .treestyletab-splitter,
+:root:-moz-window-inactive
+  .treestyletab-tabbar-toolbar
+  .treestyletab-splitter {
+	border-color: #666666 !important;
+	background: #e4e4e4 !important;
 }
 
+
+/* tab contents */
+
 .tabbrowser-tabs[treestyletab-mode="vertical"]
   .tabbrowser-tab
   label {
@@ -166,18 +197,10 @@ tabbrowser[treestyletab-tabbar-position="right"]
 	padding: 3px 0 4px !important;
 	text-align: center !important;
 }
-/* this is not required on Firefox 4 */
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab
-  > .tab-close-button {
-	margin-top: 0 !important;
-	margin-bottom: 0 !important;
-}
 
 
 /* twisty */
 
-
 .tabbrowser-tabs[treestyletab-twisty-style][treestyletab-mode="vertical"]
   .tabbrowser-tab:not([pinned="true"])
   .treestyletab-twisty-container {
@@ -192,7 +215,7 @@ tabbrowser[treestyletab-tabbar-position="right"]
 .tabbrowser-tabs[treestyletab-twisty-style="retro"]:not([treestyletab-tab-contents-inverted="true"])
   .tabbrowser-tab:not([pinned="true"])
   .tab-icon {
-	margin-left: -6px !important;
+	margin-left: 6px !important;
 }
 .tabbrowser-tabs[treestyletab-twisty-style][treestyletab-tab-contents-inverted="true"]
   .tabbrowser-tab:not([pinned="true"])
@@ -207,33 +230,17 @@ tabbrowser[treestyletab-tabbar-position="right"]
 .tabbrowser-tabs[treestyletab-twisty-style="retro"][treestyletab-tab-contents-inverted="true"]
   .tabbrowser-tab:not([pinned="true"])
   .tab-icon {
-	margin-right: -6px !important;
+	margin-right: 6px !important;
 }
 
 
 
 /* buttons in the tab bar */
 
-/* Firefox 3.6 or older */
 .tabbrowser-tabs[treestyletab-mode="vertical"]
   .tabs-newtab-button,
 .tabbrowser-tabs[treestyletab-mode="vertical"]
   .tabs-newtab-button:hover,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabs-alltabs-button,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabs-alltabs-button:hover,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabs-container
-  > .tabs-closebutton,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  > .tabs-closebutton,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabs-container
-  > .tabs-closebutton:hover,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  > .tabs-closebutton:hover,
-/* Firefox 4.0 or later */
 .treestyletab-tabbar-toolbar[treestyletab-mode="vertical"]
   > toolbarbutton,
 .treestyletab-tabbar-toolbar[treestyletab-mode="vertical"]
@@ -271,16 +278,8 @@ tabbrowser[treestyletab-tabbar-position="right"]
 	-moz-border-radius: 0 6px 6px 0;
 }
 
-/* Firefox 3.6 or older */
 .tabbrowser-tabs[treestyletab-tabbar-position="left"]
   .tabs-newtab-button,
-.tabbrowser-tabs[treestyletab-tabbar-position="left"]
-  .tabs-alltabs-button,
-.tabbrowser-tabs[treestyletab-tabbar-position="left"]
-  .tabs-container > .tabs-closebutton,
-.tabbrowser-tabs[treestyletab-tabbar-position="left"]
-  > .tabs-closebutton,
-/* Firefox 4.0 or later */
 .treestyletab-tabbar-toolbar[treestyletab-tabbar-position="left"]
   > toolbarbutton,
 .treestyletab-tabbar-toolbar[treestyletab-tabbar-position="left"]
@@ -289,17 +288,8 @@ tabbrowser[treestyletab-tabbar-position="right"]
 	border-right: 1px solid #666666 !important;
 }
 
-/* Firefox 3.6 or older */
 .tabbrowser-tabs[treestyletab-tabbar-position="right"]
   .tabs-newtab-button,
-.tabbrowser-tabs[treestyletab-tabbar-position="right"]
-  .tabs-alltabs-button,
-.tabbrowser-tabs[treestyletab-tabbar-position="right"]
-  .tabs-container
-  > .tabs-closebutton,
-.tabbrowser-tabs[treestyletab-tabbar-position="right"]
-  > .tabs-closebutton,
-/* Firefox 4.0 or later */
 .treestyletab-tabbar-toolbar[treestyletab-tabbar-position="right"]
   > toolbarbutton,
 .treestyletab-tabbar-toolbar[treestyletab-tabbar-position="right"]
@@ -309,6 +299,40 @@ tabbrowser[treestyletab-tabbar-position="right"]
 }
 
 
+:root:-moz-window-inactive
+  .treestyletab-tabbar-toolbar[treestyletab-mode="vertical"]
+  > toolbarbutton,
+:root:-moz-window-inactive
+  .treestyletab-tabbar-toolbar[treestyletab-mode="vertical"]
+  > toolbarbutton:hover,
+:root:-moz-window-inactive
+  .treestyletab-tabbar-toolbar[treestyletab-mode="vertical"]
+  > toolbarpaletteitem
+  > toolbarbutton,
+:root:-moz-window-inactive
+  .treestyletab-tabbar-toolbar[treestyletab-mode="vertical"]
+  > toolbarpaletteitem
+  > toolbarbutton:hover {
+	background: #e4e4e4 !important;
+	border-color: #666666 !important;
+}
+
+:root:-moz-window-inactive
+  .tabbrowser-tabs[treestyletab-mode="vertical"]:not([treestyletab-tab-inverted="true"])
+  .tabbrowser-arrowscrollbox
+  .tabs-newtab-button {
+	background: #cecece url("shadow-inactive-l.png") repeat-y top right !important;
+	border-color: #9a9a9a !important;
+}
+:root:-moz-window-inactive
+  .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
+  .tabbrowser-arrowscrollbox
+  .tabs-newtab-button {
+	background: #cecece url("shadow-inactive-r.png") repeat-y top left !important;
+	border-color: #9a9a9a !important;
+}
+
+
 
 /* hacks for Tab Mix Plus */
 
@@ -339,3 +363,15 @@ tabbrowser[treestyletab-tabbar-position="right"]
   > .tabs-closebutton {
 	border-left: 1px solid #666666 !important;
 }
+
+:root[treestyletab-enable-compatibility-tmp="true"]:-moz-window-inactive
+  tabbrowser[treestyletab-mode="vertical"]
+  .tabs-closebutton-topbox
+  > .tabs-closebutton,
+:root[treestyletab-enable-compatibility-tmp="true"]:-moz-window-inactive
+  tabbrowser[treestyletab-mode="vertical"]
+  .tabs-closebutton-topbox
+  > .tabs-closebutton:hover {
+	background: #e4e4e4 !important;
+	border-color: #666666 !important;
+}
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/metal/tab-3.5.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/metal/tab-3.5.css
deleted file mode 100755
index b238412..0000000
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/metal/tab-3.5.css
+++ /dev/null
@@ -1,338 +0,0 @@
- at namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab:hover,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[selected="true"],
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[selected="true"]:hover {
-	background: none transparent !important;
-	border: 2px solid transparent !important;
-	color: black !important;
-	height: auto !important;
-	max-height: none !important;
-	min-height: 6px !important;
-	margin-top: -2px !important;
-	margin-right: 0;
-	margin-bottom: -2px !important;
-	margin-left: 0;
-	padding: 0 !important;
-	-moz-appearance: none !important;
-	-moz-border-top-colors: transparent transparent !important;
-	-moz-border-right-colors: transparent transparent !important;
-	-moz-border-bottom-colors: transparent transparent !important;
-	-moz-border-left-colors: transparent transparent !important;
-	-moz-border-radius: 0 !important;
-}
-
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-image-left,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-image-middle,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-close-button,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-image-right {
-	border: 10px solid transparent;
-	margin: 0 !important;
-	position: relative !important;
-	-moz-appearance: none !important;
-}
-
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-image-middle > .tab-icon {
-	margin-top: -16px !important;
-	margin-bottom: -14px !important;
-}
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-image-middle > .tab-text,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-image-middle > *,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-close-button > * {
-	margin-top: -10px !important;
-	margin-bottom: -10px !important;
-}
-
-
-.tabbrowser-tabs[treestyletab-mode="vertical"]:not([treestyletab-tab-inverted="true"])
-  .tabbrowser-tab:not([treestyletab-drop-position="self"]) {
-	border-right: 0 none !important;
-	-moz-border-right-colors: none !important;
-}
-.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tabbrowser-tab:not([treestyletab-drop-position="self"]) {
-	border-left: 0 none !important;
-	-moz-border-left-colors: none !important;
-}
-.tabbrowser-tabs[treestyletab-mode="vertical"]:not([treestyletab-tab-inverted="true"])
-  .tabbrowser-tab:not([treestyletab-drop-position="self"]) .tab-image-right,
-.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tabbrowser-tab:not([treestyletab-drop-position="self"]) .tab-image-left {
-	padding-right: 2px !important;
-}
-
-
-
-/* background, left */
-
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-image-left {
-	border-right-width: 0;
-	-moz-border-image: url("tab-active-l.png") 10 / 10px 0 10px 10px;
-}
-
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-image-middle,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-close-button {
-	border-left-width: 0;
-	border-right-width: 0;
-	-moz-border-image: url("tab-active-l.png") 10 / 10px 0 10px 0;
-}
-
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-image-right {
-	border-left-width: 0;
-	-moz-border-image: url("tab-active-l.png") 10 5 10 10 / 10px 5px 10px 0;
-}
-
-
-
-/* background, right */
-
-.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tab-image-left {
-	-moz-border-image: url("tab-active-r.png") 10 10 10 5 / 10px 0 10px 5px;
-}
-
-.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tab-image-middle,
-.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tab-close-button {
-	-moz-border-image: url("tab-active-r.png") 10 / 10px 0 10px 0;
-}
-
-.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tab-image-right {
-	-moz-border-image: url("tab-active-r.png") 10 / 10px 10px 10px 0;
-}
-
-
-/* foreground, left */
-
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-image-left[selected="true"] {
-	-moz-border-image: url("tab-active-selected-l.png") 10 / 10px 0 10px 10px;
-}
-
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-image-middle[selected="true"],
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  [selected="true"] .tab-close-button {
-	-moz-border-image: url("tab-active-selected-l.png") 10 / 10px 0 10px 0;
-}
-
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-image-right[selected="true"] {
-	-moz-border-image: url("tab-active-selected-l.png") 10 5 10 10 / 10px 5px 10px 0;
-}
-
-
-
-/* foreground, right */
-
-.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tab-image-left[selected="true"] {
-	-moz-border-image: url("tab-active-selected-r.png") 10 10 10 5 / 10px 0 10px 5px;
-}
-
-.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tab-image-middle[selected="true"],
-.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  [selected="true"] .tab-close-button {
-	-moz-border-image: url("tab-active-selected-r.png") 10 / 10px 0 10px 0;
-}
-
-.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tab-image-right[selected="true"] {
-	-moz-border-image: url("tab-active-selected-r.png") 10 / 10px 10px 10px 0;
-}
-
-
-
-/* pinned tabs */
-
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[pinned="true"]
-  > .tab-image-middle,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[pinned="true"]:hover
-  > .tab-image-middle,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[pinned="true"][selected]
-  > .tab-image-middle,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[pinned="true"][selected]:hover
-  > .tab-image-middle {
-	background: none !important;
-	-moz-border-image: none !important;
-	margin: 0 !important;
-	padding: 0 !important;
-}
-
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[pinned="true"],
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[pinned="true"]:hover,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[pinned="true"][selected="true"],
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[pinned="true"][selected="true"]:hover {
-	background: none !important;
-	border: none !important;
-	padding: 0 !important;
-	-moz-border-radius: 0 !important;
-}
-
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[pinned="true"]
-  > .tab-image-middle
-  > * {
-	margin: 0 !important;
-	padding: 0 !important;
-}
-
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[pinned="true"]
-  > .tab-image-middle,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[pinned="true"]:hover
-  > .tab-image-middle,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[pinned="true"][selected="true"]
-  > .tab-image-middle,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[pinned="true"][selected="true"]:hover
-  > .tab-image-middle {
-	background: #9d9d9d !important;
-	border: 1px solid #666666 !important;
-	margin: 1px 0 0 1px !important;
-	padding: 2px 0 !important;
-	-moz-border-radius: 4px !important;
-}
-
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[pinned="true"][selected="true"]
-  > .tab-image-middle,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[pinned="true"][selected="true"]:hover
-  > .tab-image-middle {
-	background-color: #b3b2b3 !important;
-}
-
-
-
-
-/* inactive */
-
-/* background, left */
-
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-image-left {
-	-moz-border-image: url("tab-inactive-l.png") 10 / 10px 0 10px 10px;
-}
-
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-image-middle,
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-close-button {
-	-moz-border-image: url("tab-inactive-l.png") 10 / 10px 0 10px 0;
-}
-
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-image-right {
-	-moz-border-image: url("tab-inactive-l.png") 10 5 10 10 / 10px 5px 10px 0;
-}
-
-
-
-/* background, right */
-
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tab-image-left {
-	-moz-border-image: url("tab-inactive-r.png") 10 10 10 5 / 10px 0 10px 5px;
-}
-
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tab-image-middle,
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tab-close-button {
-	-moz-border-image: url("tab-inactive-r.png") 10 / 10px 0 10px 0;
-}
-
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tab-image-right {
-	-moz-border-image: url("tab-inactive-r.png") 10 / 10px 10px 10px 0;
-}
-
-
-
-/* foreground, left */
-
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-image-left[selected="true"] {
-	-moz-border-image: url("tab-inactive-selected-l.png") 10 / 10px 0 10px 10px;
-}
-
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-image-middle[selected="true"],
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  [selected="true"] .tab-close-button {
-	-moz-border-image: url("tab-inactive-selected-l.png") 10 / 10px 0 10px 0;
-}
-
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-image-right[selected="true"] {
-	-moz-border-image: url("tab-inactive-selected-l.png") 10 5 10 10 / 10px 5px 10px 0;
-}
-
-
-
-/* foreground, right */
-
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tab-image-left[selected="true"] {
-	-moz-border-image: url("tab-inactive-selected-r.png") 10 10 10 5 / 10px 0 10px 5px;
-}
-
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tab-image-middle[selected="true"],
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  [selected="true"] .tab-close-button {
-	-moz-border-image: url("tab-inactive-selected-r.png") 10 / 10px 0 10px 0;
-}
-
-:root:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tab-image-right[selected="true"] {
-	-moz-border-image: url("tab-inactive-selected-r.png") 10 / 10px 10px 10px 0;
-}
-
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/metal/tab-4.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/metal/tab-base.css
similarity index 87%
rename from chrome/treestyletab.jar!/skin/classic/treestyletab/metal/tab-4.css
rename to chrome/treestyletab.jar!/skin/classic/treestyletab/metal/tab-base.css
index ca65573..7e8f14c 100755
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/metal/tab-4.css
+++ b/chrome/treestyletab.jar!/skin/classic/treestyletab/metal/tab-base.css
@@ -38,7 +38,7 @@
 	background: none transparent !important;
 }
 
-/* for Mac OS X, Firefox 4 */
+/* for Mac OS X */
 .tabbrowser-tabs[treestyletab-mode="vertical"]
   :-moz-any(.tab-content:not([pinned]):not([selected="true"]),
             .tab-content[pinned]:not([titlechanged]):not([selected="true"]),
@@ -74,29 +74,14 @@
 }
 .tabbrowser-tabs[treestyletab-mode="vertical"]
   .tab-content {
-	margin-left: 0 !important;
-	margin-right: 0 !important;
-}
-
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-content {
 	border: 10px solid transparent;
 	margin: 0 !important;
+	padding: 2px 5px 2px 10px;
 	-moz-appearance: none !important;
 }
-
-/*
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-icon {
-	margin-top: -16px !important;
-	margin-bottom: -14px !important;
-}
-*/
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-content > * {
-	position: relative !important;
-	margin-top: -10px !important;
-	margin-bottom: -10px !important;
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
+  .tab-content {
+	padding: 2px 10px 2px 5px;
 }
 
 
@@ -110,37 +95,41 @@
 	border-left: 0 none !important;
 	-moz-border-left-colors: none !important;
 }
-.tabbrowser-tabs[treestyletab-mode="vertical"]:not([treestyletab-tab-inverted="true"])
-  .tabbrowser-tab:not([treestyletab-drop-position="self"]) .tab-image-right,
-.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tabbrowser-tab:not([treestyletab-drop-position="self"]) .tab-image-left {
-	padding-right: 2px !important;
-}
 
 
 
 /* background, left */
 .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-content {
+  .tab-stack {
 	-moz-border-image: url("tab-active-l.png") 10 5 10 10 / 10px 5px 10px 10px !important;
+	/**
+	 * For Firefox 11 and olders, "fill" is not available in "-moz-border-image".
+	 * However, on Firefox 12, we must put "fill" to fill the background.
+	 * So, now we write "-moz-border-image-slice" with "fill" after "-moz-boder-image"
+	 * because "-slice" works only on Firefox 12.
+	 */
+	-moz-border-image-slice: 10 5 10 10 fill !important;
 }
 
 /* background, right */
 .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tab-content {
+  .tab-stack {
 	-moz-border-image: url("tab-active-r.png") 10 10 10 5 / 10px 10px 10px 5px !important;
+	-moz-border-image-slice: 10 10 10 5 fill !important;
 }
 
 /* foreground, left */
 .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-content[selected="true"] {
+  .tabbrowser-tab[selected="true"] .tab-stack {
 	-moz-border-image: url("tab-active-selected-l.png") 10 5 10 10 / 10px 5px 10px 10px !important;
+	-moz-border-image-slice: 10 5 10 10 fill !important;
 }
 
 /* foreground, right */
 .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tab-content[selected="true"] {
+  .tabbrowser-tab[selected="true"] .tab-stack {
 	-moz-border-image: url("tab-active-selected-r.png") 10 10 10 5 / 10px 10px 10px 5px !important;
+	-moz-border-image-slice: 10 10 10 5 fill !important;
 }
 
 
@@ -258,29 +247,33 @@
 /* background, left */
 :root:-moz-window-inactive
   .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-content {
+  .tab-stack {
 	-moz-border-image: url("tab-inactive-l.png") 10 5 10 10 / 10px 5px 10px 10px !important;
+	-moz-border-image-slice: 10 5 10 10 fill !important;
 }
 
 /* background, right */
 :root:-moz-window-inactive
   .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tab-content {
+  .tab-stack {
 	-moz-border-image: url("tab-inactive-r.png") 10 10 10 5 / 10px 10px 10px 5px !important;
+	-moz-border-image-slice: 10 10 10 5 fill !important;
 }
 
 /* foreground, left */
 :root:-moz-window-inactive
   .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tab-content[selected="true"] {
+  .tabbrowser-tab[selected="true"] .tab-stack{
 	-moz-border-image: url("tab-inactive-selected-l.png") 10 5 10 10 / 10px 5px 10px 10px !important;
+	-moz-border-image-slice: 10 5 10 10 fill !important;
 }
 
 /* foreground, right */
 :root:-moz-window-inactive
   .tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
-  .tab-content[selected="true"] {
+  .tabbrowser-tab[selected="true"] .tab-stack{
 	-moz-border-image: url("tab-inactive-selected-r.png") 10 10 10 5 / 10px 10px 10px 5px !important;
+	-moz-border-image-slice: 10 10 10 5 fill !important;
 }
 
 
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/metal/tab-legacy.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/metal/tab-legacy.css
new file mode 100755
index 0000000..abd97a1
--- /dev/null
+++ b/chrome/treestyletab.jar!/skin/classic/treestyletab/metal/tab-legacy.css
@@ -0,0 +1,17 @@
+ at import url("tab-base.css");
+
+ at namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
+
+/* background images */
+
+.tabbrowser-tabs[treestyletab-mode="vertical"]
+  .tab-content {
+	position: relative !important;
+	margin: -10px -5px -10px -10px !important;
+}
+
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-inverted="true"]
+  .tab-content {
+	margin-left: -5px !important;
+	margin-right: -10px !important;
+}
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/pseudo-tree.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/pseudo-tree.css
new file mode 100755
index 0000000..2e3e2b5
--- /dev/null
+++ b/chrome/treestyletab.jar!/skin/classic/treestyletab/pseudo-tree.css
@@ -0,0 +1,22 @@
+ at namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
+
+.treestyletab-pseudo-tree-favicon {
+	height: 16px;
+	max-width: 16px;
+	max-height: 16px;
+	width: 16px;
+}
+
+.treestyletab-pseudo-tree-row {
+	-moz-box-align: center;
+}
+
+.treestyletab-pseudo-tree-row label.text-link {
+	-moz-box-crop: end;
+}
+
+.treestyletab-pseudo-tree-children {
+	margin-left: 1.5em;
+	-moz-box-align: stretch;
+}
+
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/sidebar/inactive-3.6.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/sidebar/inactive-3.6.css
deleted file mode 100755
index 3673965..0000000
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/sidebar/inactive-3.6.css
+++ /dev/null
@@ -1,63 +0,0 @@
- at namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-
-/* Unset bottom border, instead let's have a border on the right-hand
-   side, much like the sidebar does. */
-#main-window:not([active="true"])
-  .tabbrowser-strip:not([treestyletab-style~="aero"])[treestyletab-mode="vertical"] {
-	border-top: 1px solid #868686;
-}
-
-/* Background colour for the tree sidebar (light blue when window is
-   active, grey otherwise) */
-#main-window:not([active="true"])
-  .tabbrowser-strip:not([treestyletab-style~="aero"])[treestyletab-mode="vertical"] {
-	background-color: #e8e8e8 !important;
-}
-/* autohide */
-#main-window:not([active="true"])
-  .treestyletab-tabbar-toolbar[treestyletab-tabbar-autohide]:not([treestyletab-style~="aero"])[treestyletab-mode="vertical"]
-  #treestyletab-tabbar-resizer-box {
-	background: rgba(232, 232, 232, 0.75);
-}
-
-/* Use the splitter to display the border of .tabbrowser-strip */
-#main-window:not([active="true"])
-  tabbrowser:not([treestyletab-style~="aero"])[treestyletab-mode="vertical"]
-  .treestyletab-splitter {
-	background-color: #868686;
-}
-#main-window:not([active="true"])
-  .tabbrowser-strip[treestyletab-tabbar-position="left"][treestyletab-tabbar-fixed="true"] {
-	border-right-color: #868686;
-}
-#main-window:not([active="true"])
-  .tabbrowser-strip[treestyletab-tabbar-position="right"][treestyletab-tabbar-fixed="true"] {
-	border-left-color: #868686;
-}
-
-/* Style tabs themselves.  Get rid of most of the initial XUL styling */
-#main-window:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[selected="true"] {
-	border-top: 1px solid #979797 !important;
-	background: -moz-linear-gradient(top, #B4B4B4, #8A8A8A) repeat-x !important;  
-}
-
-/* Make the tab counter look like the bubbles in Mail.app et.al. */
-#main-window:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .treestyletab-counter-container {
-	background-color: #b5b5b5 !important;
-}
-#main-window:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[selected="true"]
-  .treestyletab-counter-container {
-	background-color: #ffffff !important;
-}
-#main-window:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[selected="true"]
-  .treestyletab-counter {
-	color: #929292 !important;
-}
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/sidebar/inactive-4.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/sidebar/inactive-4.css
deleted file mode 100755
index dad6763..0000000
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/sidebar/inactive-4.css
+++ /dev/null
@@ -1,68 +0,0 @@
- at namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-
-/* Unset bottom border, instead let's have a border on the right-hand
-   side, much like the sidebar does. */
-#main-window:-moz-window-inactive
-  .tabbrowser-strip:not(.treestyletab-tabbar-placeholder):not([treestyletab-style~="aero"])[treestyletab-mode="vertical"],
-#main-window:-moz-window-inactive
-  .treestyletab-tabbar-toolbar:not([treestyletab-style~="aero"])[treestyletab-mode="vertical"] {
-	border-top: 1px solid #868686;
-}
-
-/* Background colour for the tree sidebar (light blue when window is
-   active, grey otherwise) */
-#main-window:-moz-window-inactive
-  .tabbrowser-strip:not([treestyletab-style~="aero"])[treestyletab-mode="vertical"] {
-	background-color: #e8e8e8 !important;
-}
-/* autohide */
-#main-window:-moz-window-inactive
-  .treestyletab-tabbar-toolbar[treestyletab-tabbar-autohide]:not([treestyletab-style~="aero"])[treestyletab-mode="vertical"]
-  #treestyletab-tabbar-resizer-box {
-	background: rgba(232, 232, 232, 0.75);
-}
-
-/* Use the splitter to display the border of .tabbrowser-strip */
-#main-window:-moz-window-inactive
-  tabbrowser:not([treestyletab-style~="aero"])[treestyletab-mode="vertical"]
-  .treestyletab-splitter,
-#main-window:-moz-window-inactive
-  .treestyletab-tabbar-toolbar:not([treestyletab-style~="aero"])[treestyletab-mode="vertical"]
-  .treestyletab-splitter {
-	background-color: #868686;
-}
-#main-window:-moz-window-inactive
-  .tabbrowser-strip[treestyletab-tabbar-position="left"][treestyletab-tabbar-fixed="true"] {
-	border-right-color: #868686;
-}
-#main-window:-moz-window-inactive
-  .tabbrowser-strip[treestyletab-tabbar-position="right"][treestyletab-tabbar-fixed="true"] {
-	border-left-color: #868686;
-}
-
-/* Style tabs themselves.  Get rid of most of the initial XUL styling */
-#main-window:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[selected="true"] {
-	border-top: 1px solid #979797 !important;
-	background: -moz-linear-gradient(top, #B4B4B4, #8A8A8A) repeat-x !important;  
-}
-
-/* Make the tab counter look like the bubbles in Mail.app et.al. */
-#main-window:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .treestyletab-counter-container {
-	background-color: #b5b5b5 !important;
-}
-#main-window:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[selected="true"]
-  .treestyletab-counter-container {
-	background-color: #ffffff !important;
-}
-#main-window:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[selected="true"]
-  .treestyletab-counter {
-	color: #929292 !important;
-}
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/sidebar/license.txt b/chrome/treestyletab.jar!/skin/classic/treestyletab/sidebar/license.txt
index 731b43e..ebb427b 100755
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/sidebar/license.txt
+++ b/chrome/treestyletab.jar!/skin/classic/treestyletab/sidebar/license.txt
@@ -14,11 +14,11 @@ License.
 The Original Code is the SidebarStyleTab.
 
 The Initial Developer of the Original Code is SHIMODA Hiroshi.
-Portions created by the Initial Developer are Copyright (C) 2010
+Portions created by the Initial Developer are Copyright (C) 2010-2012
 the Initial Developer. All Rights Reserved.
 
 Contributor(s): Philipp von Weitershausen <philipp at weitershausen.de>
-                SHIMODA Hiroshi <piro at p.club.ne.jp>
+                SHIMODA Hiroshi <piro.outsider.reflex at gmail.com>
 
 Alternatively, the contents of these files may be used under the terms of
 either the GNU General Public License Version 2 or later (the "GPL"), or
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/sidebar/base.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/sidebar/sidebar-base.css
similarity index 71%
rename from chrome/treestyletab.jar!/skin/classic/treestyletab/sidebar/base.css
rename to chrome/treestyletab.jar!/skin/classic/treestyletab/sidebar/sidebar-base.css
index 3ca991c..2633228 100755
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/sidebar/base.css
+++ b/chrome/treestyletab.jar!/skin/classic/treestyletab/sidebar/sidebar-base.css
@@ -7,6 +7,13 @@
 	border-top: 1px solid #404040;
 	border-bottom: none !important;
 }
+#main-window:-moz-window-inactive
+  .tabbrowser-strip:not(.treestyletab-tabbar-placeholder):not([treestyletab-style~="aero"])[treestyletab-mode="vertical"],
+#main-window:-moz-window-inactive
+  .treestyletab-tabbar-toolbar:not([treestyletab-style~="aero"])[treestyletab-mode="vertical"] {
+	border-top: 1px solid #868686;
+}
+
 
 /* Background colour for the tree sidebar (light blue when window is
    active, grey otherwise) */
@@ -14,11 +21,20 @@
 	background: transparent !important;
 	background-color: #d4dde5 !important;
 }
+#main-window:-moz-window-inactive
+  .tabbrowser-strip:not([treestyletab-style~="aero"])[treestyletab-mode="vertical"] {
+	background-color: #e8e8e8 !important;
+}
 /* autohide */
 .treestyletab-tabbar-toolbar[treestyletab-tabbar-autohide][treestyletab-mode="vertical"]
   #treestyletab-tabbar-resizer-box {
 	background: rgba(212, 221, 229, 0.75);
 }
+#main-window:-moz-window-inactive
+  .treestyletab-tabbar-toolbar[treestyletab-tabbar-autohide]:not([treestyletab-style~="aero"])[treestyletab-mode="vertical"]
+  #treestyletab-tabbar-resizer-box {
+	background: rgba(232, 232, 232, 0.75);
+}
 
 /* Don't display unnecessary clutter */
 .tabbrowser-tabs[treestyletab-mode="vertical"]
@@ -44,12 +60,28 @@ tabbrowser[treestyletab-mode="vertical"]
 	background-image: none;
 	background-color: #404040;
 }
+#main-window:-moz-window-inactive
+  tabbrowser:not([treestyletab-style~="aero"])[treestyletab-mode="vertical"]
+  .treestyletab-splitter,
+#main-window:-moz-window-inactive
+  .treestyletab-tabbar-toolbar:not([treestyletab-style~="aero"])[treestyletab-mode="vertical"]
+  .treestyletab-splitter {
+	background-color: #868686;
+}
 .tabbrowser-strip[treestyletab-tabbar-position="left"][treestyletab-tabbar-fixed="true"] {
 	border-right: 1px solid #404040;
 }
+#main-window:-moz-window-inactive
+  .tabbrowser-strip[treestyletab-tabbar-position="left"][treestyletab-tabbar-fixed="true"] {
+	border-right-color: #868686;
+}
 .tabbrowser-strip[treestyletab-tabbar-position="right"][treestyletab-tabbar-fixed="true"] {
 	border-left: 1px solid #404040;
 }
+#main-window:-moz-window-inactive
+  .tabbrowser-strip[treestyletab-tabbar-position="right"][treestyletab-tabbar-fixed="true"] {
+	border-left-color: #868686;
+}
 
 /* Style tabs themselves.  Get rid of most of the initial XUL styling */
 .tabbrowser-tabs[treestyletab-mode="vertical"]
@@ -65,7 +97,7 @@ tabbrowser[treestyletab-mode="vertical"]
 	-moz-border-radius-bottomright : 0 !important;
 	-moz-box-align: stretch !important;
 	margin: 0 !important;
-	padding: 0 3px 2px 10px !important;
+	padding: 1px 3px 2px 10px !important;
 	height: 21px !important;     /* height including border! */
 	text-align: left !important;
 	border: none;
@@ -102,6 +134,13 @@ tabbrowser[treestyletab-mode="vertical"]
 	background: -moz-linear-gradient(top, #A0B0CF, #7386AB) repeat-x !important;
 }
 
+#main-window:-moz-window-inactive
+  .tabbrowser-tabs[treestyletab-mode="vertical"]
+  .tabbrowser-tab[selected="true"] {
+	border-top: 1px solid #979797 !important;
+	background: -moz-linear-gradient(top, #B4B4B4, #8A8A8A) repeat-x !important;  
+}
+
 /* Keep the close button at a safe distance from the tab label. */
 .tabbrowser-tabs[treestyletab-mode="vertical"]
   .tab-close-button {
@@ -185,6 +224,23 @@ tabbrowser[treestyletab-mode="vertical"]
 	color: #91a0c0 !important;
 }
 
+#main-window:-moz-window-inactive
+  .tabbrowser-tabs[treestyletab-mode="vertical"]
+  .treestyletab-counter-container {
+	background-color: #b5b5b5 !important;
+}
+#main-window:-moz-window-inactive
+  .tabbrowser-tabs[treestyletab-mode="vertical"]
+  .tabbrowser-tab[selected="true"]
+  .treestyletab-counter-container {
+	background-color: #ffffff !important;
+}
+#main-window:-moz-window-inactive
+  .tabbrowser-tabs[treestyletab-mode="vertical"]
+  .tabbrowser-tab[selected="true"]
+  .treestyletab-counter {
+	color: #929292 !important;
+}
 
 
 
@@ -207,65 +263,37 @@ tabbrowser[treestyletab-mode="vertical"]
 }
 
 /* Round blue rectangle around tabs that are dropping targets. */
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[treestyletab-drop-position="self"]:not([selected="true"]) {
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="self"]:not([selected="true"]) {
 	border: 2px solid #577bf3 !important; /* not OSX's colour but Firefox's */
 	background: #d0def5 !important;
 	-moz-border-radius: 8px !important;
+	padding: 0 1px 0 8px !important;
 }
 
 /* White-blue-white separator for drop indicator. */
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[treestyletab-drop-position="before"][selected="true"],
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[treestyletab-drop-position="before"][selected="true"]:hover,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[treestyletab-drop-position="before"]:not([selected="true"]),
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[treestyletab-drop-position="before"]:not([selected="true"]):hover {
-	border-top: 4px solid red !important;
-	-moz-border-top-colors: #ffffff #577bf3 #577bf3 #ffffff !important;
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="before"][selected="true"],
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="before"][selected="true"]:hover,
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="before"]:not([selected="true"]),
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="before"]:not([selected="true"]):hover {
+	-moz-border-image: url("dropmarker.png") 12 0 0 11 fill / 12px 0 0 11px !important;
+	-moz-border-image-outset: 6px 0 0 0 !important;
 }
 
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[treestyletab-drop-position="after"][selected="true"],
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[treestyletab-drop-position="after"][selected="true"]:hover,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[treestyletab-drop-position="after"]:not([selected="true"]),
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[treestyletab-drop-position="after"]:not([selected="true"]):hover {
-	border-bottom: 4px solid #577bf3 !important;
-	-moz-border-bottom-colors: #ffffff #577bf3 #577bf3 #ffffff !important;
-}
-
-/* Let's hack in the little round end of the drop indicator using the
-   drop marker image. */
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[treestyletab-drop-position="before"]
-  .treestyletab-drop-marker,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[treestyletab-drop-position="after"]
-  .treestyletab-drop-marker {
-	list-style-image: url("dropmarker.png");
-}
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[treestyletab-drop-position="before"]
-  .treestyletab-drop-marker-container {
-	margin: -11px 22px 11px -22px;
-}
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[treestyletab-drop-position="after"]
-  .treestyletab-drop-marker-container {
-	margin: 12px 22px -12px -22px;
-}
-.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-allow-subtree-collapse="true"]
-  .tabbrowser-tab[treestyletab-drop-position="before"]
-  .treestyletab-drop-marker-container,
-.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-allow-subtree-collapse="true"]
-  .tabbrowser-tab[treestyletab-drop-position="after"]
-  .treestyletab-drop-marker-container {
-	margin-left: -30px;
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="after"][selected="true"],
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="after"][selected="true"]:hover,
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="after"]:not([selected="true"]),
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="after"]:not([selected="true"]):hover {
+	-moz-border-image: url("dropmarker.png") 0 0 12 11 fill / 0 0 12px 11px !important;
+	-moz-border-image-outset: 0 0 6px 0 !important;
 }
 
 
@@ -288,26 +316,10 @@ tabbrowser[treestyletab-mode="vertical"]
 	display: none !important;
 }
 
-/* Firefox 3.6 or older */
 .tabbrowser-tabs[treestyletab-mode="vertical"]
   .tabs-newtab-button:not(:hover),
 .tabbrowser-tabs[treestyletab-mode="vertical"]
   .tabs-newtab-button:hover,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabs-alltabs-button:not(:hover),
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabs-alltabs-button:hover,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabs-container
-  > .tabs-closebutton:not(:hover),
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  > .tabs-closebutton:not(:hover),
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabs-container
-  > .tabs-closebutton:hover,
-.tabbrowser-tabs[treestyletab-mode="vertical"]
-  > .tabs-closebutton:hover,
-/* Firefox 4.0 or later */
 .treestyletab-tabbar-toolbar[treestyletab-mode="vertical"]
   > toolbarbutton:not(:hover),
 .treestyletab-tabbar-toolbar[treestyletab-mode="vertical"]
@@ -364,7 +376,7 @@ tabbrowser[treestyletab-mode="vertical"]
 	-moz-appearance: none !important;
 }
 
-/* for Mac OS X, Firefox 4 */
+/* for Mac OS X */
 .tabbrowser-tabs[treestyletab-mode="vertical"]
   :-moz-any(.tab-content:not([selected="true"]):not([pinned]),
             .tab-content:not([selected="true"])[pinned]:not([titlechanged]),
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/sidebar/sidebar-legacy.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/sidebar/sidebar-legacy.css
new file mode 100755
index 0000000..aeba454
--- /dev/null
+++ b/chrome/treestyletab.jar!/skin/classic/treestyletab/sidebar/sidebar-legacy.css
@@ -0,0 +1,90 @@
+ at import url("sidebar-base.css");
+
+ at namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
+
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="before"][selected="true"],
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="before"][selected="true"]:hover,
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="before"]:not([selected="true"]),
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="before"]:not([selected="true"]):hover,
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="after"][selected="true"],
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="after"][selected="true"]:hover,
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="after"]:not([selected="true"]),
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="after"]:not([selected="true"]):hover {
+	border: 0 none !important;
+}
+
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="before"][selected="true"]
+  .tab-stack,
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="before"][selected="true"]:hover
+  .tab-stack,
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="before"]:not([selected="true"])
+  .tab-stack,
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="before"]:not([selected="true"]):hover
+  .tab-stack {
+	position: relative !important;
+	-moz-border-image: url("dropmarker.png") 12 0 0 11 / 12px 0 0 11px !important;
+	margin-top: -7px !important;
+	margin-left: -11px !important;
+}
+
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="before"][selected="true"]
+  .tab-content,
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="before"][selected="true"]:hover
+  .tab-content,
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="before"]:not([selected="true"])
+  .tab-content,
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="before"]:not([selected="true"]):hover
+  .tab-content {
+	position: relative !important;
+	margin-top: -4px !important;
+}
+
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="after"][selected="true"]
+  .tab-stack,
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="after"][selected="true"]:hover
+  .tab-stack,
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="after"]:not([selected="true"])
+  .tab-stack,
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="after"]:not([selected="true"]):hover
+  .tab-stack {
+	position: relative !important;
+	-moz-border-image: url("dropmarker.png") 0 0 12 11 / 0 0 12px 11px !important;
+	margin-bottom: -7px !important;
+	margin-left: -11px !important;
+}
+
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="after"][selected="true"]
+  .tab-content,
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="after"][selected="true"]:hover
+  .tab-content,
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="after"]:not([selected="true"])
+  .tab-content,
+.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-style]
+  .tabbrowser-tab:not([pinned="true"])[treestyletab-drop-position="after"]:not([selected="true"]):hover
+  .tab-content {
+	position: relative !important;
+	margin-bottom: -4px !important;
+}
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/square/Darwin-inactive-3.5.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/square/Darwin-inactive-3.5.css
deleted file mode 100755
index fa511ad..0000000
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/square/Darwin-inactive-3.5.css
+++ /dev/null
@@ -1,42 +0,0 @@
- at namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-
-/* Square */
-
-#main-window:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab
-  .tab-image-middle,
-#main-window:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab
-  .tab-close-button,
-#main-window:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[selected="true"]
-  .tab-image-middle,
-#main-window:not([active="true"])
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[selected="true"]
-  .tab-close-button,
-#main-window:not([active="true"])
-  .tabbrowser-tabs[treestyletab-tabbar-position="bottom"]
-  .tabbrowser-tab
-  .tab-image-middle,
-#main-window:not([active="true"])
-  .tabbrowser-tabs[treestyletab-tabbar-position="bottom"]
-  .tabbrowser-tab
-  .tab-close-button,
-#main-window:not([active="true"])
-  .tabbrowser-tabs[treestyletab-tabbar-position="bottom"]
-  .tabbrowser-tab[selected="true"]
-  .tab-image-middle,
-#main-window:not([active="true"])
-  .tabbrowser-tabs[treestyletab-tabbar-position="bottom"]
-  .tabbrowser-tab[selected="true"]
-  .tab-close-button {
-	height: auto;
-	margin: 0 !important;
-	padding: 0 !important;
-	background: transparent;
-	width: 0;
-}
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/square/Darwin-inactive-4.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/square/Darwin-inactive-4.css
deleted file mode 100755
index b1346ff..0000000
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/square/Darwin-inactive-4.css
+++ /dev/null
@@ -1,42 +0,0 @@
- at namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-
-/* Square */
-
-#main-window:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab
-  .tab-image-middle,
-#main-window:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab
-  .tab-close-button,
-#main-window:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[selected="true"]
-  .tab-image-middle,
-#main-window:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-mode="vertical"]
-  .tabbrowser-tab[selected="true"]
-  .tab-close-button,
-#main-window:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-tabbar-position="bottom"]
-  .tabbrowser-tab
-  .tab-image-middle,
-#main-window:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-tabbar-position="bottom"]
-  .tabbrowser-tab
-  .tab-close-button,
-#main-window:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-tabbar-position="bottom"]
-  .tabbrowser-tab[selected="true"]
-  .tab-image-middle,
-#main-window:-moz-window-inactive
-  .tabbrowser-tabs[treestyletab-tabbar-position="bottom"]
-  .tabbrowser-tab[selected="true"]
-  .tab-close-button {
-	height: auto;
-	margin: 0 !important;
-	padding: 0 !important;
-	background: transparent;
-	width: 0;
-}
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/square/Darwin.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/square/Darwin.css
index 51df66a..0d9af46 100755
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/square/Darwin.css
+++ b/chrome/treestyletab.jar!/skin/classic/treestyletab/square/Darwin.css
@@ -1,5 +1,3 @@
- at import url("platform-inactive.css");
-
 @namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
 
 /* Square */
@@ -23,3 +21,26 @@ tabbrowser:not([treestyletab-style="vertigo"])[treestyletab-mode="vertical"]
   .tabbrowser-tab:not([pinned="true"]) {
 	position: relative !important;
 }
+
+#main-window:-moz-window-inactive
+  .tabbrowser-tabs[treestyletab-mode="vertical"]
+  .tabbrowser-tab
+  .tab-close-button,
+#main-window:-moz-window-inactive
+  .tabbrowser-tabs[treestyletab-mode="vertical"]
+  .tabbrowser-tab[selected="true"]
+  .tab-close-button,
+#main-window:-moz-window-inactive
+  .tabbrowser-tabs[treestyletab-tabbar-position="bottom"]
+  .tabbrowser-tab
+  .tab-close-button,
+#main-window:-moz-window-inactive
+  .tabbrowser-tabs[treestyletab-tabbar-position="bottom"]
+  .tabbrowser-tab[selected="true"]
+  .tab-close-button {
+	height: auto;
+	margin: 0 !important;
+	padding: 0 !important;
+	background: transparent;
+	width: 0;
+}
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/square/base.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/square/base.css
index a07ce39..2e6a71f 100755
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/square/base.css
+++ b/chrome/treestyletab.jar!/skin/classic/treestyletab/square/base.css
@@ -87,7 +87,9 @@
 }
 .tabbrowser-tabs:not([treestyletab-tabbar-position="top"])
   :-moz-any(.tabbrowser-tab[pinned]:not([titlechanged]),
-            .tabbrowser-tab[pinned]:not([titlechanged]):not([selected="true"])),
+            .tabbrowser-tab[pinned]:not([titlechanged]):not([selected="true"]),
+            .tabbrowser-tab[pinned][titlechanged]:not(.treestyletab-faviconized),
+            .tabbrowser-tab[pinned][titlechanged]:not(.treestyletab-faviconized):not([selected="true"])),
 :root[tabFx2Compatible-flags~="mac"]
   .tabbrowser-tabs:not([treestyletab-tabbar-position="top"])
   :-moz-any(.tabbrowser-tab[pinned],
@@ -99,7 +101,7 @@
 	-moz-border-top-colors: ThreeDShadow transparent !important;
 }
 
-/* for Mac OS X, Firefox 4 */
+/* for Mac OS X */
 .tabbrowser-tabs[treestyletab-mode="vertical"]
   :-moz-any(.tab-content:not([selected="true"]),
             .tab-content[selected="true"]) {
@@ -159,38 +161,9 @@
 	background-color: ThreeDHighlight !important;
 }
 
-.tabbrowser-tabs:not([treestyletab-tabbar-position="top"])
-  .tabbrowser-tab
-  .tab-image-left,
-.tabbrowser-tabs:not([treestyletab-tabbar-position="top"])
-  .tabbrowser-tab
-  .tab-image-right,
-.tabbrowser-tabs:not([treestyletab-tabbar-position="top"])
-  .tabbrowser-tab:not([selected="true"])
-  .tab-image-left,
-.tabbrowser-tabs:not([treestyletab-tabbar-position="top"])
-  .tabbrowser-tab:not([selected="true"])
-  .tab-image-right {
-	height: auto;
-	margin: 0 !important;
-	padding: 0 !important;
-	background: transparent;
-	width: 0;
-}
-
 
 .tabbrowser-tabs:not([treestyletab-tabbar-position="top"])
   .tabbrowser-tab
-  .tab-image-middle,
-.tabbrowser-tabs:not([treestyletab-tabbar-position="top"])
-  .tabbrowser-tab
-  .tab-close-button,
-.tabbrowser-tabs:not([treestyletab-tabbar-position="top"])
-  .tabbrowser-tab:not([selected="true"]):not(:hover)
-  .tab-image-middle,
-.tabbrowser-tabs:not([treestyletab-tabbar-position="top"])
-  .tabbrowser-tab:not([selected="true"]):not(:hover)
-  .tab-image-middle
   .tab-close-button {
 	height: auto;
 	margin: 0 !important;
@@ -199,9 +172,6 @@
 }
 .tabbrowser-tabs:not([treestyletab-tabbar-position="top"])
   .tabbrowser-tab[selected="true"]
-  .tab-image-middle,
-.tabbrowser-tabs:not([treestyletab-tabbar-position="top"])
-  .tabbrowser-tab[selected="true"]
   .tab-close-button {
 	background: transparent;
 }
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/square/tab-surface-3.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/square/tab-surface-3.css
deleted file mode 100755
index 852103b..0000000
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/square/tab-surface-3.css
+++ /dev/null
@@ -1,32 +0,0 @@
- at namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
-
-/* surface */
-
-.tabbrowser-tabs:not([treestyletab-tabbar-position="top"])
-  .tabbrowser-tab,
-.tabbrowser-tabs:not([treestyletab-tabbar-position="top"])
-  .tabbrowser-tab:not([selected="true"]) {
-	background-image: url("tab-bg.png") !important;
-	background-repeat: repeat-x !important;
-	background-position: 1px 1px !important;
-}
-
-.tabbrowser-tabs:not([treestyletab-tabbar-position="top"])
-  .tabbrowser-tab[selected="true"] {
-	background-image: url("tab-bg-highlighted.png") !important;
-}
-
-/* hover */
-
-.tabbrowser-tabs:not([treestyletab-tabbar-position="top"])
-  .tabbrowser-tab:not([selected="true"]):hover {
-	background-color: ThreeDFace !important;
-	background-image: url("tab-bg-hover.png") !important;
-}
-
-.tabbrowser-tabs:not([treestyletab-tabbar-position="top"])
-  .tabbrowser-tab[selected="true"]:hover {
-	background-color: #c1d2ee !important;
-	background-image: url("tab-bg-selected-hover.png") !important;
-}
-
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/square/tab-surface-4.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/square/tab-surface.css
similarity index 100%
rename from chrome/treestyletab.jar!/skin/classic/treestyletab/square/tab-surface-4.css
rename to chrome/treestyletab.jar!/skin/classic/treestyletab/square/tab-surface.css
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/square/vertigo.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/square/vertigo.css
index 27661f5..d3541a2 100755
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/square/vertigo.css
+++ b/chrome/treestyletab.jar!/skin/classic/treestyletab/square/vertigo.css
@@ -7,7 +7,9 @@
   .tabbrowser-tab:not([pinned]):not([selected="true"]),
 .tabbrowser-tabs:not([treestyletab-tabbar-position="top"])
   :-moz-any(.tabbrowser-tab[pinned]:not([titlechanged]),
-            .tabbrowser-tab[pinned]:not([titlechanged]):not([selected="true"])),
+            .tabbrowser-tab[pinned]:not([titlechanged]):not([selected="true"]),
+            .tabbrowser-tab[pinned][titlechanged]:not(.treestyletab-faviconized),
+            .tabbrowser-tab[pinned][titlechanged]:not(.treestyletab-faviconized):not([selected="true"])),
 :root[tabFx2Compatible-flags~="mac"]
   .tabbrowser-tabs:not([treestyletab-tabbar-position="top"])
   :-moz-any(.tabbrowser-tab[pinned],
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/twisty/twisty.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/twisty/twisty.css
index f81816f..c86dc9c 100755
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/twisty/twisty.css
+++ b/chrome/treestyletab.jar!/skin/classic/treestyletab/twisty/twisty.css
@@ -2,98 +2,72 @@
 
 .tabbrowser-tabs[treestyletab-mode="vertical"]
   .tabbrowser-tab:not([pinned="true"])
-  .treestyletab-twisty-container,
+  .treestyletab-twisty,
 .tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-allow-subtree-collapse="true"]
   .tabbrowser-tab[treestyletab-allow-subtree-collapse="true"][treestyletab-children]:not([pinned="true"])
-  .treestyletab-twisty-container {
-	margin: 0 3px 0 -3px;
+  .treestyletab-twisty {
+	position: relative;
+	margin: 0 -13px 0 -3px;
+	max-height: 16px;
+	max-width: 16px;
+	min-height: 16px;
+	min-width: 16px;
 	-moz-box-pack: start;
 	-moz-box-align: center;
 	-moz-box-flex: 1;
 }
 
-.tabbrowser-tabs[treestyletab-mode="vertical"][treestyletab-tab-contents-inverted="true"]
-  .tabbrowser-tab:not([pinned="true"])
-  .treestyletab-twisty-container,
-.tabbrowser-tabs[treestyletab-mode="horizontal"][treestyletab-allow-subtree-collapse="true"][treestyletab-tab-contents-inverted="true"]
-  .tabbrowser-tab[treestyletab-allow-subtree-collapse="true"][treestyletab-children]:not([pinned="true"])
-  .treestyletab-twisty-container {
-	margin: 0 -3px 0 3px;
-}
 .tabbrowser-tabs[treestyletab-twisty-style^="modern"][treestyletab-mode="vertical"]
   .tabbrowser-tab:not([pinned="true"])
-  .treestyletab-twisty-container,
+  .treestyletab-twisty,
 .tabbrowser-tabs[treestyletab-twisty-style^="osx"][treestyletab-mode="vertical"]
   .tabbrowser-tab:not([pinned="true"])
-  .treestyletab-twisty-container,
-.tabbrowser-tabs[treestyletab-twisty-style^="modern"][treestyletab-mode="horizontal"][treestyletab-allow-subtree-collapse="true"]
-  .tabbrowser-tab[treestyletab-allow-subtree-collapse="true"][treestyletab-children]:not([pinned="true"])
-  .treestyletab-twisty-container,
-.tabbrowser-tabs[treestyletab-twisty-style^="osx"][treestyletab-mode="horizontal"][treestyletab-allow-subtree-collapse="true"]
-  .tabbrowser-tab[treestyletab-allow-subtree-collapse="true"][treestyletab-children]:not([pinned="true"])
-  .treestyletab-twisty-container {
-	position: relative;
-	margin: 0 14px 0 -14px;
+  .treestyletab-twisty {
+	margin: 0 -2px 0 -5px;
 }
 .tabbrowser-tabs[treestyletab-twisty-style^="modern"][treestyletab-mode="vertical"][treestyletab-tab-contents-inverted="true"]
   .tabbrowser-tab:not([pinned="true"])
-  .treestyletab-twisty-container,
+  .treestyletab-twisty,
 .tabbrowser-tabs[treestyletab-twisty-style^="osx"][treestyletab-mode="vertical"][treestyletab-tab-contents-inverted="true"]
   .tabbrowser-tab:not([pinned="true"])
-  .treestyletab-twisty-container,
-.tabbrowser-tabs[treestyletab-twisty-style^="modern"][treestyletab-mode="horizontal"][treestyletab-allow-subtree-collapse="true"][treestyletab-tab-contents-inverted="true"]
-  .tabbrowser-tab[treestyletab-allow-subtree-collapse="true"][treestyletab-children]:not([pinned="true"])
-  .treestyletab-twisty-container,
-.tabbrowser-tabs[treestyletab-twisty-style^="osx"][treestyletab-mode="horizontal"][treestyletab-allow-subtree-collapse="true"][treestyletab-tab-contents-inverted="true"]
-  .tabbrowser-tab[treestyletab-allow-subtree-collapse="true"][treestyletab-children]:not([pinned="true"])
-  .treestyletab-twisty-container {
-	margin: 0 -14px 0 14px;
+  .treestyletab-twisty {
+	margin: 0 -5px 0 -2px;
 }
 
-
-.tabbrowser-tabs[treestyletab-twisty-style="retro"][treestyletab-mode="horizontal"][treestyletab-allow-subtree-collapse="true"]
+.tabbrowser-tabs[treestyletab-twisty-style^="modern"]:not([treestyletab-style])[treestyletab-allow-subtree-collapse="true"]
   .tabbrowser-tab[treestyletab-allow-subtree-collapse="true"][treestyletab-children]:not([pinned="true"])
-  .treestyletab-twisty-container {
-	position: relative;
-	margin: 0 16px 0 -16px;
-}
-
-.tabbrowser-tabs[treestyletab-twisty-style="retro"][treestyletab-mode="horizontal"][treestyletab-allow-subtree-collapse="true"]
+  .treestyletab-twisty,
+.tabbrowser-tabs[treestyletab-twisty-style^="modern"][treestyletab-tabbar-position="top"][treestyletab-allow-subtree-collapse="true"]
   .tabbrowser-tab[treestyletab-allow-subtree-collapse="true"][treestyletab-children]:not([pinned="true"])
-  .tab-icon {
-	margin-left: 16px;
+  .treestyletab-twisty {
+	margin: 0 -3px 0 -2px;
 }
-.tabbrowser-tabs[treestyletab-twisty-style^="modern"][treestyletab-mode="horizontal"][treestyletab-allow-subtree-collapse="true"]
+.tabbrowser-tabs[treestyletab-twisty-style^="osx"]:not([treestyletab-style])[treestyletab-allow-subtree-collapse="true"]
   .tabbrowser-tab[treestyletab-allow-subtree-collapse="true"][treestyletab-children]:not([pinned="true"])
-  .tab-icon,
-.tabbrowser-tabs[treestyletab-twisty-style^="osx"][treestyletab-mode="horizontal"][treestyletab-allow-subtree-collapse="true"]
+  .treestyletab-twisty,
+.tabbrowser-tabs[treestyletab-twisty-style^="osx"][treestyletab-tabbar-position="top"][treestyletab-allow-subtree-collapse="true"]
   .tabbrowser-tab[treestyletab-allow-subtree-collapse="true"][treestyletab-children]:not([pinned="true"])
-  .tab-icon {
-	margin-left: 12px;
+  .treestyletab-twisty {
+	margin: 0 -5px 0 1px;
 }
-.tabbrowser-tabs[treestyletab-twisty-style^="modern"][treestyletab-mode="vertical"][treestyletab-allow-subtree-collapse="true"]:not([treestyletab-tab-contents-inverted="true"])
-  .tabbrowser-tab:not([pinned="true"])
-  .tab-icon,
-.tabbrowser-tabs[treestyletab-twisty-style^="osx"][treestyletab-mode="vertical"][treestyletab-allow-subtree-collapse="true"]:not([treestyletab-tab-contents-inverted="true"])
-  .tabbrowser-tab:not([pinned="true"])
-  .tab-icon,
-.tabbrowser-tabs[treestyletab-twisty-style^="modern"][treestyletab-mode="horizontal"][treestyletab-allow-subtree-collapse="true"]
+.tabbrowser-tabs[treestyletab-twisty-style^="modern"]:not([treestyletab-style])[treestyletab-allow-subtree-collapse="true"][treestyletab-tab-contents-inverted="true"]
   .tabbrowser-tab[treestyletab-allow-subtree-collapse="true"][treestyletab-children]:not([pinned="true"])
-  .tab-icon,
-.tabbrowser-tabs[treestyletab-twisty-style^="osx"][treestyletab-mode="horizontal"][treestyletab-allow-subtree-collapse="true"]
+  .treestyletab-twisty,
+.tabbrowser-tabs[treestyletab-twisty-style^="modern"][treestyletab-tabbar-position="top"][treestyletab-allow-subtree-collapse="true"][treestyletab-tab-contents-inverted="true"]
   .tabbrowser-tab[treestyletab-allow-subtree-collapse="true"][treestyletab-children]:not([pinned="true"])
-  .tab-icon {
-	margin-left: 9px;
+  .treestyletab-twisty {
+	margin: 0 -2px 0 -3px;
 }
-.tabbrowser-tabs[treestyletab-twisty-style^="modern"][treestyletab-mode="vertical"][treestyletab-allow-subtree-collapse="true"][treestyletab-tab-contents-inverted="true"]
-  .tabbrowser-tab:not([pinned="true"])
-  .tab-icon,
-.tabbrowser-tabs[treestyletab-twisty-style^="osx"][treestyletab-mode="vertical"][treestyletab-allow-subtree-collapse="true"][treestyletab-tab-contents-inverted="true"]
-  .tabbrowser-tab:not([pinned="true"])
-  .tab-icon {
-	margin-right: 9px;
+.tabbrowser-tabs[treestyletab-twisty-style^="osx"]:not([treestyletab-style])[treestyletab-allow-subtree-collapse="true"][treestyletab-tab-contents-inverted="true"]
+  .tabbrowser-tab[treestyletab-allow-subtree-collapse="true"][treestyletab-children]:not([pinned="true"])
+  .treestyletab-twisty,
+.tabbrowser-tabs[treestyletab-twisty-style^="osx"][treestyletab-tabbar-position="top"][treestyletab-allow-subtree-collapse="true"][treestyletab-tab-contents-inverted="true"]
+  .tabbrowser-tab[treestyletab-allow-subtree-collapse="true"][treestyletab-children]:not([pinned="true"])
+  .treestyletab-twisty {
+	margin: 0 1px 0 -5px;
 }
 
+
 .treestyletab-twisty {
 	list-style-image: url("twisty-retro.png");
 	-moz-image-region: rect(0, 32px, 16px, 16px);
@@ -136,13 +110,13 @@
   .treestyletab-twisty {
 	-moz-image-region: rect(0, 16px, 16px, 0);
 }
-tabbrowser:not([treestyletab-twisty-style="osx"])
+.tabbrowser-tabs:not([treestyletab-twisty-style="osx"])
   .tabbrowser-tab[treestyletab-twisty-hover="true"] .treestyletab-twisty,
 .tabbrowser-tabs[treestyletab-twisty-style="osx"]
   .tabbrowser-tab[selected="true"] .treestyletab-twisty {
 	-moz-image-region: rect(16px, 32px, 32px, 16px);
 }
-tabbrowser:not([treestyletab-twisty-style="osx"])
+.tabbrowser-tabs:not([treestyletab-twisty-style="osx"])
   .tabbrowser-tab[treestyletab-subtree-collapsed="true"][treestyletab-twisty-hover="true"] .treestyletab-twisty,
 .tabbrowser-tabs[treestyletab-twisty-style="osx"]
   .tabbrowser-tab[treestyletab-subtree-collapsed="true"][selected="true"] .treestyletab-twisty {
diff --git a/chrome/treestyletab.jar!/skin/classic/treestyletab/ui.css b/chrome/treestyletab.jar!/skin/classic/treestyletab/ui.css
index db5d3b6..27fcd77 100755
--- a/chrome/treestyletab.jar!/skin/classic/treestyletab/ui.css
+++ b/chrome/treestyletab.jar!/skin/classic/treestyletab/ui.css
@@ -18,12 +18,6 @@
 
 /* drop markers */
 
-.treestyletab-drop-marker-container {
-	-moz-box-align: center;
-	-moz-box-pack: center;
-}
-
-
 .tabbrowser-tabs[treestyletab-tabbar-position="bottom"]
   .tabbrowser-tab[treestyletab-drop-position="before"][selected="true"],
 .tabbrowser-tabs[treestyletab-tabbar-position="bottom"]
@@ -149,88 +143,8 @@
 }
 
 
-/* drop marker by icon (for horizontal tab bar or the default theme) */
-
-.tabbrowser-tabs[treestyletab-tabbar-position="top"]
-  .tabbrowser-tab[treestyletab-drop-position="self"]
-  .treestyletab-drop-marker,
-.tabbrowser-tabs[treestyletab-mode="vertical"]:not([treestyletab-style])
-  .tabbrowser-tab[treestyletab-drop-position="after"]
-  .treestyletab-drop-marker {
-	list-style-image: url("dropmarker-down.png");
-}
-
-.tabbrowser-tabs[treestyletab-mode="vertical"]:not([treestyletab-style])
-  .tabbrowser-tab[treestyletab-drop-position="before"]
-  .treestyletab-drop-marker {
-	list-style-image: url("dropmarker-up.png");
-}
-
-.tabbrowser-tabs[treestyletab-mode="horizontal"]:not([treestyletab-style])
-  .tabbrowser-tab[treestyletab-drop-position="before"]
-  .treestyletab-drop-marker {
-	list-style-image: url("dropmarker-left.png");
-}
+/* drop marker for horizontal tab bar or the default theme */
 
-.tabbrowser-tabs[treestyletab-mode="horizontal"]:not([treestyletab-style])
-  .tabbrowser-tab[treestyletab-drop-position="after"]
-  .treestyletab-drop-marker {
-	list-style-image: url("dropmarker-right.png");
-}
-
-.tabbrowser-tabs[treestyletab-tabbar-position="top"]
-  .tabbrowser-tab[treestyletab-children][treestyletab-drop-position="self"]
-  .treestyletab-twisty,
-.tabbrowser-tabs:not([treestyletab-style])
-  .tabbrowser-tab[treestyletab-children][treestyletab-drop-position="before"]
-  .treestyletab-twisty,
-.tabbrowser-tabs:not([treestyletab-style])
-  .tabbrowser-tab[treestyletab-children][treestyletab-drop-position="after"]
-  .treestyletab-twisty,
-.tabbrowser-tabs[treestyletab-tabbar-position="top"]
-  .tabbrowser-tab[treestyletab-drop-position="self"]
-  .tab-icon-image,
-.tabbrowser-tabs:not([treestyletab-style])
-  .tabbrowser-tab[treestyletab-drop-position="before"]
-  .tab-icon-image,
-.tabbrowser-tabs:not([treestyletab-style])
-  .tabbrowser-tab[treestyletab-drop-position="after"]
-  .tab-icon-image,
-.tabbrowser-tabs[treestyletab-tabbar-position="top"]
-  .tabbrowser-tab[treestyletab-drop-position="self"]
-  .tab-throbber,
-.tabbrowser-tabs:not([treestyletab-style])
-  .tabbrowser-tab[treestyletab-drop-position="before"]
-  .tab-throbber,
-.tabbrowser-tabs:not([treestyletab-style])
-  .tabbrowser-tab[treestyletab-drop-position="after"]
-  .tab-throbber,
-.tabbrowser-tabs[treestyletab-tabbar-position="top"]
-  .tabbrowser-tab[treestyletab-drop-position="self"]
-  .tab-extra-status,
-.tabbrowser-tabs:not([treestyletab-style])
-  .tabbrowser-tab[treestyletab-drop-position="before"]
-  .tab-extra-status,
-.tabbrowser-tabs:not([treestyletab-style])
-  .tabbrowser-tab[treestyletab-drop-position="after"]
-  .tab-extra-status {
-	visibility: hidden;
-}
-
-/* for Firefox 3.6 or older */
-.tabbrowser-tabs[treestyletab-tabbar-position="top"]
-  .tabbrowser-tab[treestyletab-drop-position="self"][selected="true"]
-  > .tab-image-middle,
-.tabbrowser-tabs[treestyletab-tabbar-position="top"]
-  .tabbrowser-tab[treestyletab-drop-position="self"][selected="true"]:hover
-  > .tab-image-middle,
-.tabbrowser-tabs[treestyletab-tabbar-position="top"]
-  .tabbrowser-tab[treestyletab-drop-position="self"]:not([selected="true"])
-  > .tab-image-middle,
-.tabbrowser-tabs[treestyletab-tabbar-position="top"]
-  .tabbrowser-tab[treestyletab-drop-position="self"]:not([selected="true"]):hover
-  > .tab-image-middle,
-/* for Firefox 4 or later */
 .tabbrowser-tabs[treestyletab-tabbar-position="top"]
   .tabbrowser-tab[treestyletab-drop-position="self"][selected="true"]
   .tab-content,
@@ -305,7 +219,10 @@ tabbrowser[treestyletab-drop-position="left"]:not([treestyletab-tabbar-position=
 	display: none !important;
 }
 
-
+.tabbrowser-tabs[treestyletab-mode="vertical"]
+  .tab-stack {
+	max-height: 999999px; /* by favicons, this box can be shrunken to 16px height. */
+}
 
 /* transaprent tab bar */
 
@@ -360,3 +277,56 @@ tabbrowser[treestyletab-tabbar-position="bottom"]
 .treestyletab-tabbar-toolbar-ready {
 	border: 2px solid -moz-fieldtext !important;
 }
+
+
+
+/* pinned tabs */
+.tabbrowser-tabs[treestyletab-mode="vertical"]
+  .tabbrowser-tab[pinned="true"] {
+	height: 24px;
+	max-height: 24px;
+}
+
+/* disable highlighting of pinned tabs whici is not faviconized */
+
+.tabbrowser-tabs[treestyletab-mode="vertical"]
+  .tabbrowser-tab[pinned][titlechanged]:not([selected="true"]):not(.treestyletab-faviconized) {
+	background-image: none;
+}
+.tabbrowser-tabs[treestyletab-mode="vertical"]
+  .tabbrowser-tab[pinned][titlechanged]:not([selected="true"]):not(.treestyletab-faviconized):hover {
+	background-image: none;
+}
+
+
+/* notification of newly opened tabs in background */
+
+.tabbrowser-tabs[treestyletab-mode="vertical"]
+  .tabbrowser-arrowscrollbox
+  > .scrollbutton-down[treestyletab-notifybgtab-phase] {
+	background: -moz-linear-gradient(-90deg, rgba(255,255,255,0), Highlight);
+	border: 0 none;
+	height: 2em;
+	margin-top: -2em;
+	visibility: visible;
+	opacity: 0;
+	pointer-events: none;
+	-moz-box-shadow: none;
+	     box-shadow: none;
+	-moz-transition: 1s opacity ease-out;
+	     transition: 1s opacity ease-out;
+	-moz-user-focus: ignore;
+}
+
+.tabbrowser-tabs[treestyletab-mode="vertical"]
+  .tabbrowser-arrowscrollbox
+  > .scrollbutton-down[treestyletab-notifybgtab-phase="notifying"] {
+	opacity: 1;
+}
+
+.tabbrowser-tabs[treestyletab-mode="vertical"]
+  .tabbrowser-arrowscrollbox
+  > .scrollbutton-down > * {
+	display: none;
+}
+
diff --git a/components/AboutGroup.js b/components/AboutGroup.js
index 5340068..a280cfa 100755
--- a/components/AboutGroup.js
+++ b/components/AboutGroup.js
@@ -14,10 +14,10 @@
  * The Original Code is the Tree Style Tab.
  *
  * The Initial Developer of the Original Code is SHIMODA Hiroshi.
- * Portions created by the Initial Developer are Copyright (C) 2009
+ * Portions created by the Initial Developer are Copyright (C) 2009-2012
  * the Initial Developer. All Rights Reserved.
  *
- * Contributor(s): SHIMODA Hiroshi <piro at p.club.ne.jp>
+ * Contributor(s): SHIMODA Hiroshi <piro.outsider.reflex at gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -60,7 +60,4 @@ AboutGroup.prototype = {
 	QueryInterface : XPCOMUtils.generateQI([Components.interfaces.nsIAboutModule])
 };
 
-if (XPCOMUtils.generateNSGetFactory)
-	var NSGetFactory = XPCOMUtils.generateNSGetFactory([AboutGroup]);
-else
-	var NSGetModule = XPCOMUtils.generateNSGetModule([AboutGroup]);
+var NSGetFactory = XPCOMUtils.generateNSGetFactory([AboutGroup]);
diff --git a/defaults/preferences/legacy.js b/defaults/preferences/legacy.js
deleted file mode 100755
index d4fabe4..0000000
--- a/defaults/preferences/legacy.js
+++ /dev/null
@@ -1,8 +0,0 @@
-// prefs for leacy features
-pref("extensions.treestyletab.tabbar.hideAlltabsButton.horizontal", false);
-pref("extensions.treestyletab.tabbar.hideAlltabsButton.vertical",   true);
-pref("extensions.treestyletab.tabbar.transparent.partialTransparency", "0.25");
-
-// for compatibility with old FoxSplitter.
-pref("extensions.treestyletab.tabbar.position.subbrowser.enabled", false);
-
diff --git a/defaults/preferences/treestyletab.js b/defaults/preferences/treestyletab.js
index aedf81f..e7804e5 100755
--- a/defaults/preferences/treestyletab.js
+++ b/defaults/preferences/treestyletab.js
@@ -4,7 +4,7 @@
 pref("extensions.treestyletab.animation.enabled",           true);
 /**
  * Duration of animations.
- * DO NOT CHANGE THE PREFS ON FIREFOX 4 OR LATER, because actual duration of
+ * DO NOT CHANGE THE PREFS, because actual duration of
  * animations are defined in CSS. (CSS Transitions)
  * These prefs are used by the JavaScript implementation.
  */
@@ -13,7 +13,7 @@ pref("extensions.treestyletab.animation.collapse.duration", 150);
 
 /**
  * Size of resizable tab bar. They are completely ignored if "Tabs on Top"
- * is activated on Firefox 4 or later.
+ * is activated.
  */
 pref("extensions.treestyletab.tabbar.width",           200);
 pref("extensions.treestyletab.tabbar.height",          32);
@@ -57,8 +57,7 @@ pref("extensions.treestyletab.tabbar.scroll.duration", 250);
 pref("extensions.treestyletab.tabbar.scrollToNewTab.mode", 1);
 /**
  * Scrollbar in the leftside vertical tab bar should be shown leftmost position
- * instead of between tabs and the content area. This option works only for
- * Firefox 4 or later.
+ * instead of between tabs and the content area.
  */
 pref("extensions.treestyletab.tabbar.invertScrollbar", true);
 
@@ -70,6 +69,16 @@ pref("extensions.treestyletab.tabbar.narrowScrollbar", true);
 pref("extensions.treestyletab.tabbar.narrowScrollbar.size", "10px");
 
 /**
+ * On some environments (ex. GNOME3 on Linux), "narrow scrollbar" cannot get
+ * narrow width because system appearance possibly expand the size of scrollbar
+ * elements. To prevent this issue, we have to override "-moz-appeearance" defined
+ * by Firefox's default theme.
+ */
+// pref("extensions.treestyletab.tabbar.narrowScrollbar.overrideSystemAppearance", false);
+pref("extensions.treestyletab.platform.default.tabbar.narrowScrollbar.overrideSystemAppearance", false);
+pref("extensions.treestyletab.platform.Linux.tabbar.narrowScrollbar.overrideSystemAppearance", true);
+
+/**
  * The skin of the tab bar. Available styles are:
  *  "default", "flat", "mixed", "vertigo", "metal" and "sidebar".
  * To change the default style for each platform, use "platform.default.tabbar.style"
@@ -106,6 +115,15 @@ pref("extensions.treestyletab.tabbar.autoHide.mode.fullscreen",        1);
 pref("extensions.treestyletab.tabbar.autoHide.mode.toggle",            2);
 pref("extensions.treestyletab.tabbar.autoHide.mode.toggle.fullscreen", 1);
 /**
+ * When the tab bar is shown, content area must receive mousemove events
+ * to hide the tab bar. However, rectangle drawn by plugins (like <embed>)
+ * doesn't fire mousemove event even if mouse pointer moves on it. If this
+ * preference is "true", TST showns transparent screen on the content area
+ * to receive mousemove events anyway. If the screen is annoying for you,
+ * (actually it prevents click events on the content area)
+ */
+pref("extensions.treestyletab.tabbar.autoHide.contentAreaScreen.enabled", true);
+/**
  * Triggers for the "Auto Hide" feature. They can be controlled via the
  * configuration dialog.
  */
@@ -189,6 +207,14 @@ pref("extensions.treestyletab.stackCollapsedTabs", true);
 pref("extensions.treestyletab.showBorderForFirstTab",  false);
 
 /**
+ * The role of the "counter" in each tab.
+ *  1 = Indicate number of all tabs in the tree (including the parent tab itself)
+ *  2 = Indicate number of contained tabs in the collapsed tree (imitating file managers)
+ */
+pref("extensions.treestyletab.counter.role.horizontal", 1);
+pref("extensions.treestyletab.counter.role.vertical", 2);
+
+/**
  * Activates "auto-expand/collapse of tabs while dragging".
  * When you're dragging something, a collapsed tree will be expanded
  * automatically by staying on the tree for a while.
@@ -301,11 +327,22 @@ pref("extensions.treestyletab.twisty.expandSensitiveArea", true);
 pref("extensions.treestyletab.clickOnIndentSpaces.enabled", true);
 
 /**
- * If this is "true", TST shows all titles of tabs in the tree by the tooltip
- * for collapsed tree. If this is "false", or the tree is not collapsed,
- * tooltip will say only the title of the single tab.
+ * Contents of the tooltip on tabs.
+ * 0 = Firefox default (show the title of the one tab)
+ * 1 = show all titles of tabs in the tree only for collapsed tree
+ * 2 = show all titles of tabs in the tree always
+ */
+pref("extensions.treestyletab.tooltip.mode", 2);
+/**
+ * Maximum count of tabs in a tooltip. Tabs over this limit are
+ * not shown in the tooltip.
+ */
+pref("extensions.treestyletab.tooltip.maxCount", 10);
+/**
+ * After this delay, TST shows "full tooltip" to show whole tree.
+ * Negative value means "do not show full tooltip".
  */
-pref("extensions.treestyletab.tooltip.includeChildren",  true);
+pref("extensions.treestyletab.tooltip.fullTooltipDelay", 2000);
 
 /**
  * Visibility of extra menu items for the context menu on tabs, inserted by TST.
@@ -385,14 +422,18 @@ pref("extensions.treestyletab.autoCollapseExpandSubtreeOnSelect",      true);
 pref("extensions.treestyletab.autoCollapseExpandSubtreeOnSelect.onCurrentTabRemove", true);
 /**
  * When you press Ctrl-Tab/Shift-Ctrl-Tab, Firefox advances focus of tabs.
- * If this is "true", TST doesn't collapse/expand trees while you are switching
+ * If this is "true", TST expands focused tree after a delay specified
+ * by another preference "autoExpandSubtreeOnSelect.whileFocusMovingByShortcut.delay".
+ * (If the delay is "0", TST dynamiclaly expands focused tree even if
+ * you are browsing tabs by those shortcuts.)
+ * If this is "false", TST doesn't expand trees while you are switching
  * tab focus by those keyboard shortcuts. And then, after you release the Ctrl
  * key, TST will expand the tree if the newly selected tab have its collapsed
  * tree.
- * If this is "false", TST dynamiclaly collapses/expands focused tree even if
- * you are browsing tabs by those shortcuts.
  */
-pref("extensions.treestyletab.autoCollapseExpandSubtreeOnSelect.whileFocusMovingByShortcut", false);
+pref("extensions.treestyletab.autoExpandSubtreeOnSelect.whileFocusMovingByShortcut", true);
+pref("extensions.treestyletab.autoExpandSubtreeOnSelect.whileFocusMovingByShortcut.collapseOthers", true);
+pref("extensions.treestyletab.autoExpandSubtreeOnSelect.whileFocusMovingByShortcut.delay", 800);
 /**
  * If this is "true", TST expands/collapses tree by double-clicking on tabs.
  * Otherwise TST simply ignores such actions.
@@ -450,8 +491,6 @@ pref("extensions.treestyletab.autoAttach.newTabCommand", 0);
 /**
  * How to treat new tabs from middle click (or Ctrl-click) on the "New Tab" button.
  *  Options are same to extensions.treestyletab.autoAttach.newTabCommand.
- * NOTE: This pref affects only on Firefox 4 or later. Firefox 3.6 doesn't open
- *       new blank tabs by middle click on the "New Tab" button.
  */
 pref("extensions.treestyletab.autoAttach.newTabButton", 1);
 /**
@@ -470,7 +509,7 @@ pref("extensions.treestyletab.autoAttach.goButton", 1);
  *  0 = Focus to both visible and collapsed tabs. (If a collapsed tab is
  *      focused, the tree will be expanded by another pref "autoExpandSubtreeOnCollapsedChildFocused".
  *  1 = Focus to visible tabs. Collapsed tabs will be skipped. (But if the tree 
- *      is expanded by "autoCollapseExpandSubtreeOnSelect.whileFocusMovingByShortcut",
+ *      is expanded by "autoExpandSubtreeOnSelect.whileFocusMovingByShortcut",
  *      visible tabs in the tree can be focused.)
  */
 pref("extensions.treestyletab.focusMode", 1);
@@ -519,7 +558,7 @@ pref("extensions.treestyletab.closeRootBehavior", 3);
 pref("extensions.treestyletab.undoCloseTabSet.behavior", 3);
 
 /**
- * On Firefox 4 or later, status panel possibly covers the tab bar. If "true",
+ * Status panel possibly covers the tab bar. If "true",
  * TST repositions (and resizes) the status panel automatically.
  * For compatibility, you can set this to "false". Then TST doesn't controll
  * the status panel.
@@ -527,12 +566,16 @@ pref("extensions.treestyletab.undoCloseTabSet.behavior", 3);
 pref("extensions.treestyletab.repositionStatusPanel", true);
 
 /**
- * EXPERIMENTAL, DON'T SET THIS "true" !!
- * If this is "true", TST restores tree structure before SSTabRestoring events
- * are fired. Otherwise TST restores tree structure based on SSTabRestoring
- * events.
+ * On Firefox 8 or later, TST can restore tree structure before SSTabRestoring
+ * events. SSTabRestoring based restore can break tree for duplicated tabs via
+ * the SessionStore service, so, "1" and "2" are recommended.
+ * ("2" will take much time on the startup if there are too many background groups.)
+ *  0 = Restore trees on SSTabRestoring. (disable "fast restore")
+ *  1 = Restore trees before SSTabRestoring.
+ *      Trees in background groups are restored when they are shown.
+ *  2 = Restore all trees before SSTabRestoring including background groups.
  */
-pref("extensions.treestyletab.restoreTreeOnStartup", false);
+pref("extensions.treestyletab.restoreTree.level", 1);
 
 /**
  * TST overrides some internal prefs of Firefox itself, because they can
@@ -558,10 +601,10 @@ pref("extensions.treestyletab.createSubtree.underParent", true);
 
 /**
  * Size of pinned tabs in the vertical tab bar.
- * "width" can accept a special value "-1" which means "expand to the width of the tab bar".
+ * If true, they will be faviconized. Otherwise, they expand to the width
+ * of the tab bar.
  */
-pref("extensions.treestyletab.pinnedTab.width", 24);
-pref("extensions.treestyletab.pinnedTab.height", 24);
+pref("extensions.treestyletab.pinnedTab.faviconized", true);
 
 /**
  * Compatibility hack flags for other addons. They can be disabled by each
diff --git a/install.rdf b/install.rdf
index 031dbd1..9bf34b6 100644
--- a/install.rdf
+++ b/install.rdf
@@ -5,7 +5,7 @@
   <RDF:Description RDF:about="urn:mozilla:install-manifest"
                    em:id="treestyletab at piro.sakura.ne.jp"
                    em:name="Tree Style Tab"
-                   em:version="0.12.2011110101"
+                   em:version="0.14.2012021101"
                    em:creator="SHIMODA Hiroshi"
                    em:description="Show tabs like a tree."
                    em:homepageURL="http://piro.sakura.ne.jp/xul/_treestyletab.html.en"
@@ -103,7 +103,7 @@
       </RDF:Description>
     </em:localized>
     <em:localized>
-      <RDF:Description em:locale="ru-RU"
+      <RDF:Description em:locale="ru"
                        em:name="Tree Style Tab (Древовидный стиль вкладок)"
                        em:description="Отображение вкладок в виде дерева"
                        em:homepageURL="http://piro.sakura.ne.jp/xul/_treestyletab.html.en"
@@ -111,7 +111,8 @@
           <em:contributor>Zusukar (auto-shrink mode)</em:contributor>
           <em:contributor>Alice0775 (compatibility problem)</em:contributor>
           <em:contributor>Philipp von Weitershausen (Sidebar style)</em:contributor>
-          <em:translator>L'Autour (ru-RU locale)</em:translator>
+          <em:translator>L'Autour (ru locale)</em:translator>
+          <em:translator>Infocatcher (ru locale)</em:translator>
       </RDF:Description>
     </em:localized>
     <em:localized>
@@ -166,8 +167,8 @@
 
     <em:targetApplication>
       <RDF:Description em:id="{ec8030f7-c20a-464f-9b0e-13a3a9e97384}"
-                       em:minVersion="3.6"
-                       em:maxVersion="10.0a1" />
+                       em:minVersion="4.0"
+                       em:maxVersion="13.0a1" />
     </em:targetApplication>
   </RDF:Description>
 </RDF:RDF>
diff --git a/modules/autoHide.js b/modules/autoHide.js
index 29c13f8..91c45f0 100755
--- a/modules/autoHide.js
+++ b/modules/autoHide.js
@@ -14,10 +14,10 @@
  * The Original Code is the Tree Style Tab.
  *
  * The Initial Developer of the Original Code is SHIMODA Hiroshi.
- * Portions created by the Initial Developer are Copyright (C) 2010-2011
+ * Portions created by the Initial Developer are Copyright (C) 2010-2012
  * the Initial Developer. All Rights Reserved.
  *
- * Contributor(s): SHIMODA Hiroshi <piro at p.club.ne.jp>
+ * Contributor(s): SHIMODA Hiroshi <piro.outsider.reflex at gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -123,6 +123,13 @@ AutoHideBrowser.prototype = {
   
 	togglerSize : 0, 
 	sensitiveArea : 7,
+	contentAreaScreenEnabled : true,
+
+	closeButtonsMode : -1,
+	CLOSE_BUTTONS_ONLY_ON_CURRENT_TAB : 0,
+	CLOSE_BUTTONS_ON_ALL_TABS         : 1,
+	CLOSE_BUTTONS_DISABLED            : 2,
+	CLOSE_BUTTONS_ON_TABBAR           : 3,
  
 	get XOffset() 
 	{
@@ -134,8 +141,16 @@ AutoHideBrowser.prototype = {
 
 			case this.kMODE_HIDE:
 				let offset = this.width + this.splitterWidth;
+				let resizer = this.resizer;
 				if (sv.position == 'left') {
+					offset += this.togglerSize;
+					if (resizer)
+						offset += resizer.boxObject.width;
+				}
+				else if (sv.position == 'right') {
 					offset -= this.togglerSize;
+					if (resizer)
+						offset -= resizer.boxObject.width;
 				}
 				return offset;
 
@@ -171,6 +186,15 @@ AutoHideBrowser.prototype = {
 			) ? this.YOffset : 0 ;
 	},
  
+	get screen()
+	{
+		return this.document.getElementById('treestyletab-autohide-content-area-screen');
+	},
+	get resizer()
+	{
+		return this.document.getElementById('treestyletab-tabbar-resizer-splitter');
+	},
+ 
 	start : function AHB_start() 
 	{
 		if (this.enabled) return;
@@ -180,27 +204,23 @@ AutoHideBrowser.prototype = {
 		var b  = this.browser;
 		var w  = this.window;
 
+		this.screen.hidePopup();
+
 		sv.setTabbrowserAttribute(this.kSTATE, this.kSTATE_EXPANDED);
 
 		b.addEventListener('mousedown', this, true);
 		b.addEventListener('mouseup', this, true);
 		b.addEventListener('dragover', this, true);
 		b.addEventListener('dragleave', this, true);
-		if (sv.isFloating) {
-			sv.tabStrip.addEventListener('mousedown', this, true);
-			sv.tabStrip.addEventListener('mouseup', this, true);
-		}
-		w.addEventListener('resize', this, true);
+		sv.tabStrip.addEventListener('mousedown', this, true);
+		sv.tabStrip.addEventListener('mouseup', this, true);
 		w.addEventListener(sv.kEVENT_TYPE_PRINT_PREVIEW_ENTERED, this, false);
 		w.addEventListener(sv.kEVENT_TYPE_PRINT_PREVIEW_EXITED, this, false);
-		b.addEventListener('load', this, true);
-		b.mPanelContainer.addEventListener('scroll', this, true);
 		if (this.shouldListenMouseMove)
 			this.startListenMouseMove();
 		if (b == w.gBrowser && sv.shouldListenKeyEventsForAutoHide)
 			w.TreeStyleTabService.startListenKeyEventsFor(sv.LISTEN_FOR_AUTOHIDE);
 
-		this.clearBG(); /* legacy feature for Firefox 3.6 or olders */
 		this.updateTransparency();
 
 		this.showHideInternal();
@@ -219,28 +239,22 @@ AutoHideBrowser.prototype = {
 
 		this.show();
 
+		this.screen.hidePopup();
+
 		b.removeEventListener('mousedown', this, true);
 		b.removeEventListener('mouseup', this, true);
 		b.removeEventListener('dragover', this, true);
 		b.removeEventListener('dragleave', this, true);
-		if (sv.isFloating) {
-			sv.tabStrip.removeEventListener('mousedown', this, true);
-			sv.tabStrip.removeEventListener('mouseup', this, true);
-		}
-		w.removeEventListener('resize', this, true);
+		sv.tabStrip.removeEventListener('mousedown', this, true);
+		sv.tabStrip.removeEventListener('mouseup', this, true);
 		w.removeEventListener(sv.kEVENT_TYPE_PRINT_PREVIEW_ENTERED, this, false);
 		w.removeEventListener(sv.kEVENT_TYPE_PRINT_PREVIEW_EXITED, this, false);
-		b.removeEventListener('load', this, true);
-		b.mPanelContainer.removeEventListener('scroll', this, true);
 		this.endListenMouseMove();
 		if (b == w.gBrowser)
 			w.TreeStyleTabService.endListenKeyEventsFor(sv.LISTEN_FOR_AUTOHIDE);
 
-		this.clearBG(); /* legacy feature for Firefox 3.6 or olders */
 		this.updateTransparency();
 
-		if (!sv.isFloating)
-			sv.container.style.margin = 0;
 		sv.removeTabbrowserAttribute(this.kAUTOHIDE);
 		sv.removeTabbrowserAttribute(this.kSTATE);
 
@@ -280,9 +294,8 @@ AutoHideBrowser.prototype = {
 		if (this.mouseMoveListening) return;
 
 		this.browser.addEventListener('mousemove', this, true);
-
-		if (this.treeStyleTab.isFloating)
-			this.treeStyleTab.tabStrip.addEventListener('mousemove', this, true);
+		this.screen.addEventListener('mousemove', this, true);
+		this.treeStyleTab.tabStrip.addEventListener('mousemove', this, true);
 
 		this.mouseMoveListening = true;
 	},
@@ -292,9 +305,8 @@ AutoHideBrowser.prototype = {
 		if (!this.mouseMoveListening) return;
 
 		this.browser.removeEventListener('mousemove', this, true);
-
-		if (this.treeStyleTab.isFloating)
-			this.treeStyleTab.tabStrip.removeEventListener('mousemove', this, true);
+		this.screen.removeEventListener('mousemove', this, true);
+		this.treeStyleTab.tabStrip.removeEventListener('mousemove', this, true);
 
 		this.mouseMoveListening = false;
 	},
@@ -310,13 +322,14 @@ AutoHideBrowser.prototype = {
 				this.treeStyleTab.getTreePref('tabbar.autoShow.tabSwitch');
 	},
  
-	showHideOnMousemove : function AHB_showHideOnMousemove(aEvent) 
+	showHideOnMouseMove : function AHB_showHideOnMouseMove(aEvent) 
 	{
 		var position = this.getMousePosition(aEvent);
 		if (position == this.MOUSE_POSITION_UNKNOWN)
 			return;
 
-		this.cancelShowHideOnMousemove();
+		this.cancelShowHideOnMouseMove();
+		this.showHideContentsAreaScreen();
 
 		var sv = this.treeStyleTab;
 		var b  = this.browser;
@@ -337,7 +350,7 @@ AutoHideBrowser.prototype = {
 				!shouldShow &&
 				sv.getTreePref('tabbar.autoShow.mousemove')
 				) {
-				this.showHideOnMousemoveTimer = w.setTimeout(
+				this.showHideOnMouseMoveTimer = w.setTimeout(
 					function(aSelf) {
 						aSelf.cancelDelayedShowForShortcut();
 						if (aSelf.showHideReason == aSelf.kSHOWN_BY_MOUSEMOVE)
@@ -349,7 +362,7 @@ AutoHideBrowser.prototype = {
 			}
 		}
 		else if (shouldShow) {
-			this.showHideOnMousemoveTimer = w.setTimeout(
+			this.showHideOnMouseMoveTimer = w.setTimeout(
 				function(aSelf) {
 					aSelf.cancelDelayedShowForShortcut();
 					aSelf.cancelHideForFeedback();
@@ -371,58 +384,123 @@ AutoHideBrowser.prototype = {
 		var sv  = this.treeStyleTab;
 		var b   = this.browser;
 		var pos = sv.position;
-		var box = b.mCurrentBrowser.boxObject;
-
-		if (sv.isFloating && this.expanded) { // Firefox 4.0-
-			box = {
-				screenX : box.screenX + (pos == 'left' ? this.XOffset : 0 ),
-				screenY : box.screenY,
-				width   : box.width - this.XOffset,
-				height  : box.height
-			};
-		}
+		var box = this.getContentsAreaBox();
 
 		var sensitiveArea = this.sensitiveArea;
-		/* For resizing of shrunken tab bar and clicking closeboxes,
-
-		   we have to shrink sensitive area a little. */
-		if (this.shrunken) sensitiveArea -= 20;
+		if (this.shrunken) {
+			let clickable;
+			if (this.widthFromMode > 24 &&
+				(clickable = this.getNearestClickableBox(aEvent))) {
+				/* For resizing of shrunken tab bar and clicking closeboxes,
+				   we have to shrink sensitive area. */
+				sensitiveArea = -(clickable.width + clickable.padding);
+			}
+			else if (this.resizer)
+				sensitiveArea = -this.resizer.boxObject.width;
+			else
+				sensitiveArea = 0;
+		}
 
 		if (
 			pos == 'left' ?
-				(aEvent.screenX <= box.screenX) :
+				(aEvent.screenX > box.screenX + sensitiveArea) :
 			pos == 'right' ?
-				(aEvent.screenX >= box.screenX + box.width) :
+				(aEvent.screenX < box.screenX + box.width - sensitiveArea) :
 			pos == 'bottom' ?
-				(aEvent.screenY >= box.screenY + box.height) :
-				(aEvent.screenY <= box.screenY)
-			)
-			return this.MOUSE_POSITION_INSIDE;
+				(aEvent.screenY < box.screenY + box.height - sensitiveArea) :
+				(aEvent.screenY > box.screenY + sensitiveArea)
+			) {
+			return this.MOUSE_POSITION_OUTSIDE;
+		}
 
 		if (
 			pos == 'left' ?
-				(aEvent.screenX <= box.screenX + sensitiveArea) :
+				(aEvent.screenX <= box.screenX - sensitiveArea) :
 			pos == 'right' ?
-				(aEvent.screenX >= box.screenX + box.width - sensitiveArea) :
+				(aEvent.screenX >= box.screenX + box.width + sensitiveArea) :
 			pos == 'bottom' ?
-				(aEvent.screenY >= box.screenY + box.height - sensitiveArea) :
-				(aEvent.screenY <= box.screenY + sensitiveArea)
-			)
-			return this.MOUSE_POSITION_NEAR;
+				(aEvent.screenY >= box.screenY + box.height + sensitiveArea) :
+				(aEvent.screenY <= box.screenY - sensitiveArea)
+			) {
+			return this.MOUSE_POSITION_INSIDE;
+		}
 
-		return this.MOUSE_POSITION_OUTSIDE;
+		return this.MOUSE_POSITION_NEAR;
+	},
+	getContentsAreaBox : function AHB_getContentsAreaBox()
+	{
+		var sv  = this.treeStyleTab;
+		var b   = this.browser;
+		var box = b.mCurrentBrowser.boxObject;
+		var xoffset = (this.shrunken || this.hidden) ? 0 : this.XOffset ;
+		box = {
+			screenX : box.screenX + (sv.position == 'left' ? xoffset : 0 ),
+			screenY : box.screenY,
+			width   : box.width - xoffset,
+			height  : box.height
+		};
+		return box;
 	},
 	MOUSE_POSITION_UNKNOWN : 0,
 	MOUSE_POSITION_OUTSIDE : (1 << 0),
 	MOUSE_POSITION_INSIDE  : (1 << 1),
 	MOUSE_POSITION_NEAR    : (1 << 2),
 	MOUSE_POSITION_SENSITIVE : (1 << 1) | (1 << 2),
+	getNearestClickableBox : function AHB_getNearestClickableBox(aEvent)
+	{
+		var sv = this.treeStyleTab;
+		var tab = sv.getTabFromCoordinate(aEvent[sv.screenPositionProp]);
+		if (!tab)
+			return null;
+
+		var position = sv.invertedScreenPositionProp;
+		var size = sv.invertedSizeProp;
+		var coordinate = aEvent[sv.invertedScreenPositionProp];
+		var tabbox = tab.boxObject;
+
+		var closebox;
+		if (this.closeButtonsMode != this.CLOSE_BUTTONS_DISABLED &&
+			this.closeButtonsMode != this.CLOSE_BUTTONS_ON_TABBAR &&
+			(closebox = sv.getTabClosebox(tab)) &&
+			(closebox = closebox.boxObject) &&
+			closebox.width && closebox.height) {
+			let padding = Math.min(
+					closebox[position] - tabbox[position],
+					(tabbox[position] + tabbox[size]) - (closebox[position] + closebox[size])
+				);
+			if (closebox[position] - padding <= coordinate &&
+				closebox[position] + closebox[size] + padding >= coordinate)
+				return {
+					padding   : padding,
+					__proto__ : closebox
+				};
+		}
+
+		var twisty;
+		if (sv.canCollapseSubtree(tab) &&
+			(twisty = sv.getTabTwisty(tab)) &&
+			(twisty = twisty.boxObject) &&
+			twisty.width && twisty.height) {
+			let padding = Math.min(
+					twisty[position] - tabbox[position],
+					(tabbox[position] + tabbox[size]) - (twisty[position] + twisty[size])
+				);
+			if (twisty[position] - padding <= coordinate &&
+				twisty[position] + twisty[size] + padding >= coordinate)
+				return {
+					padding   : padding,
+					__proto__ : twisty
+				};
+		}
+
+		return null;
+	},
  
-	cancelShowHideOnMousemove : function AHB_cancelShowHideOnMousemove() 
+	cancelShowHideOnMouseMove : function AHB_cancelShowHideOnMouseMove() 
 	{
-		if (this.showHideOnMousemoveTimer) {
-			this.window.clearTimeout(this.showHideOnMousemoveTimer);
-			this.showHideOnMousemoveTimer = null;
+		if (this.showHideOnMouseMoveTimer) {
+			this.window.clearTimeout(this.showHideOnMouseMoveTimer);
+			this.showHideOnMouseMoveTimer = null;
 		}
 	},
   
@@ -553,17 +631,13 @@ AutoHideBrowser.prototype = {
  
 	showHideInternal : function AHB_showHideInternal(aReason) 
 	{
-		var sv = this.treeStyleTab;
-		if (!sv.isFloating)
-			sv.stopRendering();
-
+		var sv  = this.treeStyleTab;
 		var b   = this.browser;
 		var pos = sv.position;
 
 		if (this.expanded) { // to be hidden or shrunken
 			this.onHiding();
 			this.showHideReason = aReason || this.kSHOWN_BY_UNKNOWN;
-			this.resetContentAreas(); /* legacy feature for Firefox 3.6 or olders */
 		}
 		else { // to be shown or expanded
 			this.onShowing();
@@ -572,20 +646,48 @@ AutoHideBrowser.prototype = {
 
 		this.fireStateChangingEvent();
 
-		if (this.expanded) {
+		if (this.expanded)
 			sv.setTabbrowserAttribute(this.kAUTOHIDE, 'show');
-			this.redrawContentArea(); /* legacy feature for Firefox 3.6 or olders */
-		}
 		b.mTabContainer.adjustTabstrip();
 		sv.checkTabsIndentOverflow();
 
 		this.window.setTimeout(function(aSelf) {
-			aSelf.redrawContentArea(); /* legacy feature for Firefox 3.6 or olders */
 			aSelf.fireStateChangeEvent();
-			if (!sv.isFloating)
-				sv.startRendering();
+			aSelf.showHideContentsAreaScreen();
 		}, 0, this);
 	},
+	showHideContentsAreaScreen : function AHB_showHideContentsAreaScreen()
+	{
+		if (
+			this.expanded &&
+			this.contentAreaScreenEnabled &&
+			this.treeStyleTab.FocusManager.activeWindow &&
+			this.treeStyleTab.FocusManager.activeWindow.top == this.window &&
+			this.findPluginArea(this.browser.contentWindow)
+			) {
+			let box = this.getContentsAreaBox();
+			let style = this.screen.style;
+			let width = Math.min(box.width, this.window.screen.availWidth - box.screenX);
+			let height = Math.min(box.height, this.window.screen.availHeight - box.screenY);
+			style.width = width+'px';
+			style.height = height+'px';
+			if (this.screen.state == 'open')
+				this.screen.moveTo(box.screenX, box.screenY);
+			else
+				this.screen.openPopupAtScreen(box.screenX, box.screenY, false);
+			this.screen.setAttribute('popup-shown', true);
+		}
+		else {
+			this.screen.removeAttribute('popup-shown');
+			if (this.screen.state != 'close')
+				this.screen.hidePopup();
+		}
+	},
+	findPluginArea : function AHB_findPluginArea(aFrame)
+	{
+		return aFrame.document.querySelector('embed, object') ||
+				Array.some(aFrame.frames, arguments.callee);
+	},
 	
 	show : function AHB_show(aReason) /* PUBLIC API */ 
 	{
@@ -604,23 +706,6 @@ AutoHideBrowser.prototype = {
 		var sv  = this.treeStyleTab;
 		var b   = this.browser;
 		var pos = sv.position;
-		if (!sv.isFloating) { // -Firefox 3.6
-			switch (pos)
-			{
-				case 'left':
-					sv.container.style.marginRight = '-'+this.XOffset+'px';
-					break;
-				case 'right':
-					sv.container.style.marginLeft = '-'+this.XOffset+'px';
-					break;
-				case 'bottom':
-					sv.container.style.marginTop = '-'+this.YOffset+'px';
-					break;
-				default:
-					sv.container.style.marginBottom = '-'+this.YOffset+'px';
-					break;
-			}
-		}
 
 		sv.setTabbrowserAttribute(this.kSTATE, this.kSTATE_EXPANDED);
 
@@ -630,18 +715,14 @@ AutoHideBrowser.prototype = {
 				break;
 
 			case this.kMODE_HIDE:
-				if (sv.isFloating)
-					sv.updateFloatingTabbar(sv.kTABBAR_UPDATE_BY_AUTOHIDE);
+				sv.updateFloatingTabbar(sv.kTABBAR_UPDATE_BY_AUTOHIDE);
 				break;
 
 			default:
 			case this.kMODE_SHRINK:
 				if (pos == 'left' || pos == 'right') {
 					let width = sv.maxTabbarWidth(sv.getTreePref('tabbar.width'));
-					if (sv.isFloating) // Firefox 4.0-
-						sv.updateFloatingTabbar(sv.kTABBAR_UPDATE_BY_AUTOHIDE);
-					else // -Firefox 3.6
-						sv.setTabStripAttribute('width', width);
+					sv.updateFloatingTabbar(sv.kTABBAR_UPDATE_BY_AUTOHIDE);
 				}
 				break;
 		}
@@ -660,9 +741,6 @@ AutoHideBrowser.prototype = {
 		var splitter = this.document.getAnonymousElementByAttribute(b, 'class', sv.kSPLITTER);
 		this.splitterWidth = (splitter ? splitter.boxObject.width : 0 );
 
-		if (!sv.isFloating) // -Firefox 3.6
-			sv.container.style.margin = 0;
-
 		switch (this.mode)
 		{
 			case this.kMODE_DISABLED:
@@ -715,244 +793,9 @@ AutoHideBrowser.prototype = {
 		this.treeStyleTab.fireDataContainerEvent(this.treeStyleTab.kEVENT_TYPE_AUTO_HIDE_STATE_CHANGE.replace(/^nsDOM/, ''), this.browser, true, false, data);
 	},
   
-	redrawContentArea : function AHB_redrawContentArea() /* legacy feature for Firefox 3.6 or olders */ 
-	{
-		var sv = this.treeStyleTab;
-		if (sv.isFloating)
-			return;
-
-		var pos = sv.position;
-		var w = this.window;
-		try {
-			var v = this.browser.markupDocumentViewer;
-			if (this.shouldRedraw) {
-				this.drawBG();
-
-				v.move(w.outerWidth, w.outerHeight);
-				v.move(
-					(
-						pos == 'left' ? -this.XOffset :
-						pos == 'right' ? this.XOffset :
-						0
-					) - this.extraXOffset,
-					(
-						pos == 'top' ? -this.YOffset :
-						pos == 'bottom' ? this.YOffset :
-						0
-					) - this.extraYOffset
-				);
-			}
-			else {
-				this.clearBG();
-				v.move(w.outerWidth, w.outerHeight);
-				v.move(-this.extraXOffset, -this.extraYOffset);
-			}
-		}
-		catch(e) {
-			dump(e);
-		}
-	},
-	redrawContentAreaWithDelay : function AHB_redrawContentAreaWithDelay() /* legacy feature for Firefox 3.6 or olders */
-	{
-		if (this.treeStyleTab.isFloating)
-			return;
-
-		this.window.setTimeout(function(aSelf) {
-			aSelf.redrawContentArea();
-		}, 0, this);
-	},
- 
-	resetContentAreas : function AHB_resetContentAreas() /* legacy feature for Firefox 3.6 or olders */ 
-	{
-		if (this.treeStyleTab.isFloating)
-			return;
-
-		this.treeStyleTab.getTabsArray(this.browser).forEach(function(aTab) {
-			try {
-				aTab.linkedBrowser.markupDocumentViewer.move(0, 0);
-			}
-			catch(e) {
-			}
-		}, this);
-	},
- 
-	get shouldRedraw() /* legacy feature for Firefox 3.6 or olders */ 
-	{
-		return !this.treeStyleTab.isFloating && this.enabled && this.expanded;
-	},
- 
-	drawBG : function AHB_drawBG() /* legacy feature for Firefox 3.6 or olders */ 
-	{
-		var sv = this.treeStyleTab;
-		var b  = this.browser;
-		var canvas = this.tabbarCanvas;
-		if (sv.isFloating || !canvas || this.isResizing)
-			return;
-
-		var alpha = Number(sv.getTreePref('tabbar.transparent.partialTransparency'));
-		if (isNaN(alpha)) alpha = 0.25;
-		if (alpha >= 1)
-			return;
-
-		canvas.style.width = (canvas.width = 1)+'px';
-		canvas.style.height = (canvas.height = 1)+'px';
-
-		var pos = sv.position;
-
-		var frame = b.contentWindow;
-		var tabContainerBox = b.mTabContainer.boxObject;
-		var browserBox = b.mCurrentBrowser.boxObject;
-		var contentBox = sv.getBoxObjectFor(frame.document.documentElement);
-
-		var zoom = this.getZoomForFrame(frame);
-
-		var x = (pos == 'right') ? browserBox.width - this.XOffset : 0 ;
-		var y = (pos == 'bottom') ? browserBox.height - this.YOffset : 0 ;
-		if (pos == 'left' && this.mode == this.kMODE_HIDE)
-			x -= this.togglerSize;
-		x += this.extraXOffset;
-		y += this.extraYOffset;
-
-		var xOffset = (zoom == 1 && (pos == 'top' || pos == 'bottom')) ?
-				Math.max(0, contentBox.screenX + frame.scrollX - browserBox.screenX) :
-				0 ;
-		var yOffset = (zoom == 1 && (pos == 'left' || pos == 'right')) ?
-				Math.max(0, contentBox.screenY + frame.scrollY - browserBox.screenY) :
-				0 ;
-
-		var w = tabContainerBox.width - xOffset;
-		var h = tabContainerBox.height - yOffset;
-		w -= this.extraXOffset;
-		h -= this.extraYOffset;
-
-		var canvasXOffset = 0;
-		var canvasYOffset = 0;
-		if (pos == 'top' || pos == 'bottom')
-			canvasXOffset = tabContainerBox.screenX - b.boxObject.screenX;
-		else
-			canvasYOffset = tabContainerBox.screenY - b.boxObject.screenY;
-
-		for (let node = canvas;
-		     node != b.mTabBox;
-		     node = node.parentNode)
-		{
-			let style = this.window.getComputedStyle(node, null);
-			'border-left-width,border-right-width,margin-left,margin-right,padding-left,padding-right'
-				.split(',').forEach(function(aProperty) {
-					let value = sv.getPropertyPixelValue(style, aProperty);
-					w -= value;
-					if (aProperty.indexOf('left') < -1) x += value;
-				}, this);
-			'border-top-width,border-bottom-width,margin-top,margin-bottom,padding-left,padding-right'
-				.split(',').forEach(function(aProperty) {
-					let value = sv.getPropertyPixelValue(style, aProperty);
-					h -= value;
-					if (aProperty.indexOf('top') < -1) y += value;
-				}, this);
-		}
-
-		// zero width (heigh) canvas becomes wrongly size!!
-		w = Math.max(1, w);
-		h = Math.max(1, h);
-
-		canvas.style.display = 'inline';
-		canvas.style.margin = (yOffset)+'px 0 0 '+(xOffset)+'px';
-		canvas.style.width = (canvas.width = w)+'px';
-		canvas.style.height = (canvas.height = h)+'px';
-
-		w += this.extraXOffset;
-		h += this.extraYOffset;
-
-		var ctx = canvas.getContext('2d');
-		ctx.clearRect(0, 0, w, h);
-		ctx.save();
-		if (this.mode == this.kMODE_SHRINK) {
-			var offset = sv.getTreePref('tabbar.shrunkenWidth') + this.splitterWidth;
-			if (pos == 'left')
-				ctx.translate(offset, 0);
-			else
-				x += this.splitterWidth;
-			w -= offset;
-		}
-		ctx.globalAlpha = 1;
-		if (pos == 'left' || pos == 'right') {
-			ctx.fillStyle = this.splitterBorderColor;
-			ctx.fillRect((pos == 'left' ? -1 : w+1 ), 0, 1, h);
-		}
-		ctx.save();
-		ctx.scale(zoom, zoom);
-		ctx.drawWindow(
-			frame,
-			(x / zoom)+frame.scrollX+canvasXOffset,
-			(y / zoom)+frame.scrollY+canvasYOffset,
-			w / zoom,
-			h / zoom,
-			'-moz-field'
-		);
-		ctx.restore();
-		ctx.globalAlpha = alpha;
-		ctx.fillStyle = 'black';
-		ctx.fillRect(0, 0, w, h);
-		ctx.restore();
-	},
 	
-	get splitterBorderColor() /* legacy feature for Firefox 3.6 or olders */ 
-	{
-		var sv = this.treeStyleTab;
-		var b  = this.browser;
-		var w  = this.window;
-		var borderNode = sv.getTreePref(
-					sv.isVertical ?
-						'tabbar.fixed.vertical' :
-						'tabbar.fixed.horizontal'
-				) ?
-				sv.tabStrip :
-				this.document.getAnonymousElementByAttribute(b, 'class', sv.kSPLITTER) ;
-
-		var pos = sv.position;
-		var prop = pos == 'left' ? 'right' :
-				pos == 'right' ? 'left' :
-				pos == 'top' ? 'bottom' :
-				'top' ;
-
-		var borderColor = w.getComputedStyle(borderNode, null).getPropertyValue('-moz-border-'+prop+'-colors');
-		if (borderColor == 'none')
-			borderRight = w.getComputedStyle(borderNode, null).getPropertyValue('border-'+prop+'-color');
-
-		/rgba?\(([^,]+),([^,]+),([^,]+)(,.*)?\)/.test(borderColor);
-
-		return 'rgb('+[
-				parseInt(parseInt(RegExp.$1) * 0.8),
-				parseInt(parseInt(RegExp.$2) * 0.8),
-				parseInt(parseInt(RegExp.$3) * 0.8)
-			].join(',')+')';
-	},
  
-	getZoomForFrame : function AHB_getZoomForFrame(aFrame) /* legacy feature for Firefox 3.6 or olders */ 
-	{
-		var zoom = aFrame
-				.QueryInterface(Ci.nsIInterfaceRequestor)
-				.getInterface(Ci.nsIWebNavigation)
-				.QueryInterface(Ci.nsIDocShell)
-				.contentViewer
-				.QueryInterface(Ci.nsIMarkupDocumentViewer)
-				.fullZoom;
-		return (zoom * 1000 % 1) ? zoom+0.025 : zoom ;
-	},
   
-	clearBG : function AHB_clearBG() /* legacy feature for Firefox 3.6 or olders */ 
-	{
-		var canvas = this.tabbarCanvas;
-		if (this.treeStyleTab.isFloating || !canvas)
-			return;
-
-		canvas.style.display = 'none';
-		canvas.style.margin = 0;
-		// zero width (heigh) canvas becomes wrongly size!!
-		canvas.style.width = canvas.style.height = '1px';
-		canvas.width = canvas.height = 1;
-	},
- 
 	updateTransparency : function AHB_updateTransparency() 
 	{
 		var sv  = this.treeStyleTab;
@@ -976,11 +819,16 @@ AutoHideBrowser.prototype = {
 	
 	domains : [ 
 		'extensions.treestyletab.',
-		'browser.fullscreen.autohide'
+		'browser.fullscreen.autohide',
+		'browser.tabs.closeButtons'
 	],
  
 	onPrefChange : function AHB_onPrefChange(aPrefName) 
 	{
+		// ignore after destruction
+		if (!this.window || !this.window.TreeStyleTabService)
+			return;
+
 		var value = this.treeStyleTab.getPref(aPrefName);
 		switch (aPrefName)
 		{
@@ -1009,13 +857,6 @@ AutoHideBrowser.prototype = {
 				this.sensitiveArea = value;
 				return;
 
-			case 'extensions.treestyletab.tabbar.width':
-			case 'extensions.treestyletab.tabbar.shrunkenWidth':
-				this.window.setTimeout(function(aSelf) {
-					aSelf.onTabbarResized();
-				}, 0, this);
-				return;
-
 			case 'extensions.treestyletab.tabbar.togglerSize':
 				this.togglerSize = value;
 				var toggler = this.document.getAnonymousElementByAttribute(this.browser, 'class', this.treeStyleTab.kTABBAR_TOGGLER);
@@ -1026,6 +867,9 @@ AutoHideBrowser.prototype = {
 					toggler.removeAttribute('collapsed');
 				return;
 
+			case 'extensions.treestyletab.tabbar.autoHide.contentAreaScreen.enabled':
+				return this.contentAreaScreenEnabled = value;
+
 			case 'browser.fullscreen.autohide':
 				if (!this.window.fullScreen) return;
 				this.end();
@@ -1036,6 +880,9 @@ AutoHideBrowser.prototype = {
 					this.start();
 				return;
 
+			case 'browser.tabs.closeButtons':
+				return this.closeButtonsMode = value;
+
 			default:
 				return;
 		}
@@ -1052,17 +899,7 @@ AutoHideBrowser.prototype = {
 				return this.onMouseUp(aEvent);
 
 			case 'mousemove':
-				if (this.handleMouseMove(aEvent)) return;
-			case 'resize':
-				return this.onResize(aEvent);
-
-			case 'scroll':
-				return this.onScroll(aEvent);
-
-			case 'load':
-				if (this.shouldRedraw)
-					this.redrawContentArea();
-				return;
+				return this.handleMouseMove(aEvent);
 
 			case 'TabOpen':
 			case 'TabClose':
@@ -1074,8 +911,6 @@ AutoHideBrowser.prototype = {
 				return;
 
 			case 'select':
-				if (this.shouldRedraw)
-					this.redrawContentArea();
 				if (!this.window.TreeStyleTabService.accelKeyPressed)
 					this.showForFeedback();
 				return;
@@ -1088,9 +923,6 @@ AutoHideBrowser.prototype = {
 
 			case this.treeStyleTab.kEVENT_TYPE_TABBAR_POSITION_CHANGING:
 				this.isResizing = false;
-				this.clearBG(); /* legacy feature for Firefox 3.6 or olders */
-				if (this.shouldRedraw) /* legacy feature for Firefox 3.6 or olders */
-					this.hide();
 				return;
 
 			case this.treeStyleTab.kEVENT_TYPE_TABBAR_POSITION_CHANGED:
@@ -1153,28 +985,9 @@ AutoHideBrowser.prototype = {
 			).booleanValue
 			) {
 			this.isResizing = true;
-			this.clearBG(); /* legacy feature for Firefox 3.6 or olders */
 			sv.setTabbrowserAttribute(sv.kRESIZING, true);
-			/* canvas‚ð”ñ•\Ž¦‚É‚µ‚½‚Ì‚Æ“¯‚¶ƒ^ƒCƒ~ƒ“ƒO‚ŃŠƒTƒCƒY‚ðs‚¤‚ƁA
-			   ‚Ü‚¾“à•”“I‚Écanvas‚Ì‘å‚«‚³‚ªŽc‚Á‚½‚܂܂Ȃ̂ŁA‚»‚Ì‘å‚«‚³ˆÈ‰º‚É
-			   ƒ^ƒuƒo[‚Ì•‚ðk‚ß‚ç‚ê‚È‚­‚È‚éBŽè“®‚ŃCƒxƒ“ƒg‚ðÄ‘—‚µ‚Ä‚â‚é‚Æ
-			   ‚±‚Ì–â‘è‚ð–h‚®‚±‚Æ‚ª‚Å‚«‚éB */
-			aEvent.preventDefault();
-			aEvent.stopPropagation();
-			var flags = 0;
-			const nsIDOMNSEvent = Ci.nsIDOMNSEvent;
-			if (aEvent.altKey) flags |= nsIDOMNSEvent.ALT_MASK;
-			if (aEvent.ctrlKey) flags |= nsIDOMNSEvent.CONTROL_MASK;
-			if (aEvent.shiftKey) flags |= nsIDOMNSEvent.SHIFT_MASK;
-			if (aEvent.metaKey) flags |= nsIDOMNSEvent.META_MASK;
-			w.setTimeout(function(aX, aY, aButton, aDetail) {
-				w.QueryInterface(Ci.nsIInterfaceRequestor)
-					.getInterface(Ci.nsIDOMWindowUtils)
-					.sendMouseEvent('mousedown', aX, aY, aButton, aDetail, flags);
-				flags = null;
-			}, 0, aEvent.clientX, aEvent.clientY, aEvent.button, aEvent.detail);
 		}
-		this.cancelShowHideOnMousemove();
+		this.cancelShowHideOnMouseMove();
 		if (
 			this.enabled &&
 			this.expanded &&
@@ -1198,13 +1011,8 @@ AutoHideBrowser.prototype = {
 			).booleanValue) {
 			this.isResizing = false;
 			sv.removeTabbrowserAttribute(sv.kRESIZING);
-			this.window.setTimeout(function(aSelf) { /* legacy feature for Firefox 3.6 or olders */
-				if (!aSelf.shouldRedraw) return;
-				aSelf.redrawContentArea();
-				aSelf.drawBG();
-			}, 0, this);
 		}
-		this.cancelShowHideOnMousemove();
+		this.cancelShowHideOnMouseMove();
 		this.lastMouseDownTarget = null;
 	},
  
@@ -1216,72 +1024,18 @@ AutoHideBrowser.prototype = {
 			return true;
 
 		if (
+			!aEvent.shiftKey &&
 			!sv.isPopupShown() &&
 			(
 				!this.expanded ||
 				this.showHideReason & this.kKEEP_SHOWN_ON_MOUSEOVER
+			) &&
+			!this.lastMouseDownTarget
 			)
-			)
-			this.showHideOnMousemove(aEvent);
+			this.showHideOnMouseMove(aEvent);
 		return true;
 	},
  
-	onResize : function AHB_onResize(aEvent) /* legacy feature for Firefox 3.6 or olders */ 
-	{
-		if (
-			aEvent.originalTarget &&
-			(
-				aEvent.originalTarget.ownerDocument == this.document ||
-				aEvent.originalTarget == this.window
-			)
-			)
-			this.onTabbarResized();
-	},
- 
-	onTabbarResized : function AHB_onTabbarResized() /* legacy feature for Firefox 3.6 or olders */ 
-	{
-		var sv = this.treeStyleTab;
-		if (sv.isFloating || !this.shouldRedraw)
-			return;
-
-		switch (sv.position)
-		{
-			case 'left':
-				sv.container.style.marginRight = '-'+this.XOffset+'px';
-				break;
-			case 'right':
-				sv.container.style.marginLeft = '-'+this.XOffset+'px';
-				break;
-			case 'bottom':
-				sv.container.style.marginTop = '-'+this.YOffset+'px';
-				break;
-			default:
-				sv.container.style.marginBottom = '-'+this.YOffset+'px';
-				break;
-		}
-		this.redrawContentArea();
-	},
- 
-	onScroll : function AHB_onScroll(aEvent) 
-	{
-		var node = aEvent.originalTarget;
-		if ((node && node.ownerDocument == this.document) || !this.shouldRedraw) return;
-
-		var tabbarBox, nodeBox;
-		if (
-			!(node instanceof Ci.nsIDOMElement) ||
-			(
-				(tabbarBox = this.treeStyleTab.getBoxObjectFor(this.browser.mTabContainer)) &&
-				(nodeBox = this.treeStyleTab.getBoxObjectFor(node)) &&
-				tabbarBox.screenX <= nodeBox.screenX + nodeBox.width &&
-				tabbarBox.screenX + tabbarBox.width >= nodeBox.screenX &&
-				tabbarBox.screenY <= nodeBox.screenY + nodeBox.height &&
-				tabbarBox.screenY + tabbarBox.height >= nodeBox.screenY
-			)
-			)
-			this.redrawContentArea();
-	},
- 
 	onDragOver : function AHB_onDragOver(aEvent) 
 	{
 		if (this.expanded)
@@ -1356,7 +1110,8 @@ AutoHideBrowser.prototype = {
 			}
 		}
 		else {
-			if (this.enabled)
+			if (this.enabled &&
+				this.showHideReason == this.kSHOWN_BY_SHORTCUT)
 				this.hide();
 		}
 	},
@@ -1388,14 +1143,16 @@ AutoHideBrowser.prototype = {
 		this.lastMouseDownTarget = null;
 		this.isResizing = false;
 
-		this.showHideOnMousemoveTimer = null;
+		this.showHideOnMouseMoveTimer = null;
 		this.delayedShowForFeedbackTimer = null;
 
 		b.setAttribute(this.kMODE+'-normal', sv.getTreePref('tabbar.autoHide.mode'));
 		b.setAttribute(this.kMODE+'-fullscreen', sv.getTreePref('tabbar.autoHide.mode.fullscreen'));
 		sv.addPrefListener(this);
+		this.onPrefChange('browser.tabs.closeButtons');
 		this.onPrefChange('extensions.treestyletab.tabbar.autoHide.area');
 		this.onPrefChange('extensions.treestyletab.tabbar.togglerSize');
+		this.onPrefChange('extensions.treestyletab.tabbar.autoHide.contentAreaScreen.enabled');
 		this.window.setTimeout(function(aSelf) {
 			aSelf.onPrefChange('extensions.treestyletab.tabbar.autoHide.mode');
 		}, 0, this);
@@ -1409,17 +1166,6 @@ AutoHideBrowser.prototype = {
 		b.addEventListener(sv.kEVENT_TYPE_TAB_FOCUS_SWITCHING_KEY_DOWN, this, false);
 		b.addEventListener(sv.kEVENT_TYPE_TAB_FOCUS_SWITCHING_START, this, false);
 		b.addEventListener(sv.kEVENT_TYPE_TAB_FOCUS_SWITCHING_END, this, false);
-
-		if (!sv.isFloating) { /* legacy feature for Firefox 3.6 or olders */
-			let stack = this.document.getAnonymousElementByAttribute(b.mTabContainer, 'class', 'tabs-stack');
-			if (stack) {
-				let canvas = this.document.createElementNS('http://www.w3.org/1999/xhtml', 'canvas');
-				canvas.setAttribute('style', 'display:none;width:1;height:1;');
-				stack.firstChild.appendChild(canvas);
-				this.tabbarCanvas = canvas;
-				this.clearBG();
-			}
-		}
 	},
  
 	destroy : function AHB_destroy() 
@@ -1522,6 +1268,10 @@ AutoHideWindow.prototype = {
 	
 	updateKeyListeners : function AHW_updateKeyListeners() 
 	{
+		// ignore after destruction
+		if (!this.window || !this.window.TreeStyleTabService)
+			return;
+
 		if (
 			this.getMode() &&
 			this.shouldListenKeyEvents
diff --git a/modules/browser.js b/modules/browser.js
index 323aad2..8c6a497 100755
--- a/modules/browser.js
+++ b/modules/browser.js
@@ -14,10 +14,10 @@
  * The Original Code is the Tree Style Tab.
  *
  * The Initial Developer of the Original Code is SHIMODA Hiroshi.
- * Portions created by the Initial Developer are Copyright (C) 2011
+ * Portions created by the Initial Developer are Copyright (C) 2011-2012
  * the Initial Developer. All Rights Reserved.
  *
- * Contributor(s): SHIMODA Hiroshi <piro at p.club.ne.jp>
+ * Contributor(s): SHIMODA Hiroshi <piro.outsider.reflex at gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -38,9 +38,6 @@ const EXPORTED_SYMBOLS = ['TreeStyleTabBrowser'];
 const Cc = Components.classes;
 const Ci = Components.interfaces;
 
-// Components.utils.import('resource://treestyletab-modules/rap.js');
-// rap();
-
 Components.utils.import('resource://treestyletab-modules/window.js');
  
 function TreeStyleTabBrowser(aWindowService, aTabBrowser) 
@@ -88,6 +85,8 @@ TreeStyleTabBrowser.prototype = {
 	endProp                    : 'bottom',
 
 	maxTreeLevelPhisical : false,
+
+	needRestoreTree : false,
  
 /* elements */ 
 	
@@ -136,12 +135,6 @@ TreeStyleTabBrowser.prototype = {
 	{
 		return (this._tabStripPlaceHolder = value);
 	},
- 
-	get tabTooltip() 
-	{
-		return this.document.getElementById('tabbrowser-tab-tooltip') || // Firefox 4.0-
-				this.evaluateXPath('descendant::xul:tooltip', this.mTabBrowser.mStrip, Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE).singleNodeValue; // -Firefox 3.6
-	},
   
 /* properties */ 
 	
@@ -182,18 +175,6 @@ TreeStyleTabBrowser.prototype = {
 	},
 	_allowSubtreeCollapseExpand : true,
  
-	get hideAlltabsButton() /* legacy feature for Firefox 3.6 or olders */ 
-	{
-		return this._hideAlltabsButton;
-	},
-	set hideAlltabsButton(aValue)
-	{
-		this._hideAlltabsButton = aValue;
-		this.setTabbrowserAttribute(this.kHIDE_ALLTABS, this._hideAlltabsButton ? 'true' : null);
-		return aValue;
-	},
-	_hideAlltabsButton : true,
- 
 	get fixed() 
 	{
 		var orient = this.isVertical ? 'vertical' : 'horizontal' ;
@@ -266,7 +247,7 @@ TreeStyleTabBrowser.prototype = {
 		this.Deferred.next(function() {
 			self.checkTabsIndentOverflow();
 			self.fireTabbarPositionEvent(false, oldPosition, aNewPosition);
-		});
+		}).error(this.defaultDeferredErrorHandler);
 	},
   
 /* status getters */ 
@@ -286,10 +267,7 @@ TreeStyleTabBrowser.prototype = {
 		return (box.getAttribute('orient') || this.window.getComputedStyle(box, '').getPropertyValue('-moz-box-orient')) == 'vertical';
 	},
  
-	get isFloating() 
-	{
-		return this._tabStripPlaceHolder;
-	},
+	isFloating : true, // for backward compatibility (but this should be removed) 
  
 	get ownerToolbar() 
 	{
@@ -303,12 +281,21 @@ TreeStyleTabBrowser.prototype = {
 	get canStackTabs() 
 	{
 		return (
-			this.isGecko2 &&
 			!this.isVertical &&
 			this.canCollapseSubtree() &&
 			this.getTreePref('stackCollapsedTabs')
 		);
 	},
+ 
+	get counterRole() 
+	{
+		return this.isVertical ? this.counterRoleVertical : this.counterRoleHorizontal ;
+	},
+ 
+	get isDestroying()
+	{
+		return !this.mTabBrowser || !this.mTabBrowser.mTabContainer;
+	},
   
 /* utils */ 
 	
@@ -322,8 +309,7 @@ TreeStyleTabBrowser.prototype = {
 						this.getTreePref('compatibility.TMP') &&
 						d.getAnonymousElementByAttribute(aTab, 'class', 'tab-text-container')
 					) ||
-					d.getAnonymousElementByAttribute(aTab, 'class', 'tab-text tab-label') || // Firefox 4.0-
-					d.getAnonymousElementByAttribute(aTab, 'class', 'tab-text'); // Firefox 3.5 - Firefox 3.6
+					d.getAnonymousElementByAttribute(aTab, 'class', 'tab-text tab-label');
 		return label;
 	},
  
@@ -337,21 +323,64 @@ TreeStyleTabBrowser.prototype = {
 					d.getAnonymousElementByAttribute(aTab, 'class', 'tab-close-button');
 		return close;
 	},
+ 
+	getTabTwisty : function TSTBrowser_getTabTwisty(aTab) 
+	{
+		return this.document.getAnonymousElementByAttribute(aTab, 'class', this.kTWISTY);
+	},
+ 
+	getTabTwistyAnchorNode : function TSTBrowser_getTabTwistyAnchorNode(aTab) 
+	{
+		return this.document.getAnonymousElementByAttribute(aTab, 'class', 'tab-icon') || // Tab Mix Plus
+			this.document.getAnonymousElementByAttribute(aTab, 'class', 'tab-throbber');
+	},
   
+	getTabFromTabbarEvent : function TSTBrowser_getTabFromTabbarEvent(aEvent) 
+	{
+		if (
+			!this.shouldDetectClickOnIndentSpaces ||
+			!this.getAncestorTabbarFromEvent(aEvent) ||
+			this.isEventFiredOnClickable(aEvent) ||
+			this.getSplitterFromEvent(aEvent)
+			)
+			return null;
+		return this.getTabFromCoordinate(aEvent[this.screenPositionProp]);
+	},
+	getTabFromCoordinate : function TSTBrowser_getTabFromCoordinate(aCoordinate)
+	{
+		var tab = null;
+		this.getTabsArray(this.mTabBrowser).some(function(aTab) {
+			var box = aTab.boxObject;
+			if (box[this.screenPositionProp] > aCoordinate ||
+				box[this.screenPositionProp] + box[this.sizeProp] < aCoordinate) {
+				return false;
+			}
+			tab = aTab;
+			return true;
+		}, this);
+		return tab;
+	},
+ 
+	getNextFocusedTab : function TSTBrowser_getNextFocusedTab(aTab) 
+	{
+		return this.getNextSiblingTab(aTab) ||
+				this.getPreviousVisibleTab(aTab);
+	},
+ 
 	isTabInViewport : function TSTBrowser_isTabInViewport(aTab) 
 	{
 		if (!this.windowService.preInitialized || !aTab)
 			return false;
 		if (aTab.getAttribute('pinned') == 'true')
 			return true;
-		var tabBox = aTab.boxObject;
+		var tabBox = this.getFutureBoxObject(aTab);
 		var barBox = this.scrollBox.boxObject;
-		var xOffset = this.getXOffsetOfTab(aTab);
-		var yOffset = this.getYOffsetOfTab(aTab);
-		return (tabBox.screenX + xOffset >= barBox.screenX &&
-			tabBox.screenX + xOffset + tabBox.width <= barBox.screenX + barBox.width &&
-			tabBox.screenY + yOffset >= barBox.screenY &&
-			tabBox.screenY + yOffset + tabBox.height <= barBox.screenY + barBox.height);
+		return (
+			tabBox.screenX >= barBox.screenX &&
+			tabBox.screenX + tabBox.width <= barBox.screenX + barBox.width &&
+			tabBox.screenY >= barBox.screenY &&
+			tabBox.screenY + tabBox.height <= barBox.screenY + barBox.height
+		);
 	},
  
 	isMultiRow : function TSTBrowser_isMultiRow() 
@@ -375,7 +404,8 @@ TreeStyleTabBrowser.prototype = {
 			)
 			return;
 
-		if (!this.isVertical) {
+		var count = this.pinnedTabsCount;
+		if (!this.isVertical || !count) {
 			this.resetPinnedTabs();
 			b.mTabContainer._positionPinnedTabs();
 			return;
@@ -386,19 +416,16 @@ TreeStyleTabBrowser.prototype = {
 
 		var maxWidth = tabbarPlaceHolderWidth || tabbarWidth;
 
-		var count  = this.pinnedTabsCount;
-		var width  = Math.min(maxWidth, aWidth || this.window.TreeStyleTabService.pinnedTabWidth);
-		if (width < 0)
-			width = maxWidth;
-		else
-			width = Math.max(this.MIN_PINNED_TAB_WIDTH, width);
-		var height = Math.max(this.MIN_PINNED_TAB_HEIGHT, aHeight || this.window.TreeStyleTabService.pinnedTabHeight);
+		var faviconized = this.getTreePref('pinnedTab.faviconized');
+		var faviconizedSize = tabbar.childNodes[0].boxObject.height;
+
+		var width  = faviconized ? faviconizedSize : maxWidth ;
+		var height = faviconizedSize;
 		var maxCol = Math.floor(maxWidth / width);
 		var maxRow = Math.ceil(count / maxCol);
 		var col    = 0;
 		var row    = 0;
 
-		var faviconized = width <= this.MIN_PINNED_TAB_WIDTH;
 		var baseX = this.tabStrip.boxObject.screenX - this.document.documentElement.boxObject.screenX;
 
 		/**
@@ -434,7 +461,7 @@ TreeStyleTabBrowser.prototype = {
 			if (className != item.className)
 				item.className = className;
 
-			style.width = width+'px';
+			style.maxWidth = style.width = width+'px';
 			if (needToInvertDirection) {
 				let margin = (width * (maxCol - col - 1)) + remainder + shrunkenOffset;
 				style.setProperty('margin-right', margin+'px', 'important');
@@ -453,7 +480,7 @@ TreeStyleTabBrowser.prototype = {
 			if (aJustNow)
 				this.Deferred.next(function() { // "transition" must be cleared after the reflow.
 					style.MozTransition = style.transition = transitionStyleBackup;
-				});
+				}).error(this.defaultDeferredErrorHandler);
 
 			col++;
 			if (col >= maxCol) {
@@ -478,7 +505,7 @@ TreeStyleTabBrowser.prototype = {
 			aSelf.Deferred.next(function() {
 				// do with delay again, after Firefox's reposition was completely finished.
 				aSelf.positionPinnedTabs.apply(aSelf, aSelf._positionPinnedTabsWithDelayTimerArgs);
-			});
+			}).error(aSelf.defaultDeferredErrorHandler);
 			aSelf._positionPinnedTabsWithDelayTimer = null;
 			aSelf._positionPinnedTabsWithDelayTimerArgs = null;
 		}, 0, this);
@@ -492,7 +519,7 @@ TreeStyleTabBrowser.prototype = {
 		for (var i = 0, count = this.pinnedTabsCount; i < count; i++)
 		{
 			let style = tabbar.childNodes[i].style;
-			style.width = style.left = style.right =
+			style.maxWidth = style.width = style.left = style.right =
 				style.MozMarginStart = style.marginLeft = style.marginRight = style.marginTop = '';
 		}
 	},
@@ -501,20 +528,18 @@ TreeStyleTabBrowser.prototype = {
 	{
 		var tabs = this.getTabsArray(this.mTabBrowser);
 		var count = tabs.length;
-		tabs.forEach(
-			aStacked ?
-				function(aTab, aIndex) {
-					aTab.style.zIndex = count * 1000 - aIndex;
-				} :
-				function(aTab, aIndex) {
-					aTab.style.zIndex = '';
-				}
-		);
+		for (let i = 0; i < count; i++)
+		{
+			let tab = tabs[i];
+			if (aStacked)
+				tab.style.zIndex = count * 1000 - i;
+			else
+				tab.style.zIndex = '';
+		}
 	},
  
 	fixTooNarrowTabbar : function TSTBrowser_fixTooNarrowTabbar() 
 	{
-		if (!this.isFloating) return;
 		/**
 		 * The tab bar can become smaller than the actual size of the
 		 * floating tab bar, and then, we cannot resize tab bar by
@@ -549,7 +574,6 @@ TreeStyleTabBrowser.prototype = {
 	
 	init : function TSTBrowser_init() 
 	{
-// rap('browser/init start');
 		this.stopRendering();
 
 		var w = this.window;
@@ -568,6 +592,13 @@ TreeStyleTabBrowser.prototype = {
 		this.subTreeChildrenMovingCount = 0;
 		this._treeViewEnabled = true;
 
+		/**
+		 * On secondary (and later) window, SSWindowStateBusy event can be fired
+		 * before DOMContentLoad, on "domwindowopened".
+		 */
+		this.needRestoreTree = w.__treestyletab__WindowStateBusy || false;
+		delete w.__treestyletab__WindowStateBusy;
+
 		this._initTabbrowserExtraContents();
 
 		let position = this.position;
@@ -585,7 +616,7 @@ TreeStyleTabBrowser.prototype = {
 		 *   https://bugzilla.mozilla.org/show_bug.cgi?id=558585
 		 *   http://hg.mozilla.org/mozilla-central/rev/e90bdd97d168
 		 */
-		if (b.style.backgroundColor && this.isFloating) {
+		if (b.style.backgroundColor) {
 			let color = b.style.backgroundColor;
 			let pi = d.createProcessingInstruction(
 					'xml-stylesheet',
@@ -609,7 +640,9 @@ TreeStyleTabBrowser.prototype = {
 		w.addEventListener('customizationchange', this, false);
 		w.addEventListener(this.kEVENT_TYPE_PRINT_PREVIEW_ENTERED, this, false);
 		w.addEventListener(this.kEVENT_TYPE_PRINT_PREVIEW_EXITED,  this, false);
-		w.addEventListener('tabviewhidden', this, true);
+		w.addEventListener('tabviewframeinitialized', this, false);
+		w.addEventListener(this.kEVENT_TYPE_TAB_FOCUS_SWITCHING_END, this, false);
+		w.addEventListener('SSWindowStateBusy', this, false);
 
 		b.addEventListener('nsDOMMultipleTabHandlerTabsClosing', this, false);
 
@@ -635,8 +668,6 @@ TreeStyleTabBrowser.prototype = {
 		this.ObserverService.addObserver(this, this.kTOPIC_INDENT_MODIFIED, false);
 		this.ObserverService.addObserver(this, this.kTOPIC_COLLAPSE_EXPAND_ALL, false);
 		this.ObserverService.addObserver(this, this.kTOPIC_CHANGE_TREEVIEW_AVAILABILITY, false);
-		this.ObserverService.addObserver(this, 'sessionstore-windows-restored', false);
-		this.ObserverService.addObserver(this, 'sessionstore-browser-state-restored', false);
 		this.ObserverService.addObserver(this, 'private-browsing-change-granted', false);
 		this.ObserverService.addObserver(this, 'lightweight-theme-styling-update', false);
 		this.addPrefListener(this);
@@ -656,7 +687,6 @@ TreeStyleTabBrowser.prototype = {
 		this.fireTabbarPositionEvent(false, 'top', position); /* PUBLIC API */
 
 		this.startRendering();
-// rap('browser/init end');
 	},
 	
 	_initTabbrowserExtraContents : function TSTBrowser_initTabbrowserExtraContents() 
@@ -697,21 +727,24 @@ TreeStyleTabBrowser.prototype = {
 		if (!('MultipleTabService' in w)) {
 			w.setTimeout(function(aSelf, aTabBrowser, aPopup) {
 				let suffix = '-tabbrowser-'+(aTabBrowser.id || 'instance-'+parseInt(Math.random() * 65000));
-				[
-					aSelf.kMENUITEM_RELOADSUBTREE,
-					aSelf.kMENUITEM_RELOADCHILDREN,
-					aSelf.kMENUITEM_REMOVESUBTREE,
-					aSelf.kMENUITEM_REMOVECHILDREN,
-					aSelf.kMENUITEM_REMOVEALLTABSBUT,
-					aSelf.kMENUITEM_COLLAPSEEXPAND_SEPARATOR,
-					aSelf.kMENUITEM_COLLAPSE,
-					aSelf.kMENUITEM_EXPAND,
-					aSelf.kMENUITEM_AUTOHIDE_SEPARATOR,
-					aSelf.kMENUITEM_AUTOHIDE,
-					aSelf.kMENUITEM_FIXED,
-					aSelf.kMENUITEM_BOOKMARKSUBTREE
-				].forEach(function(aID) {
-					let item = d.getElementById(aID).cloneNode(true);
+				let ids = [
+						aSelf.kMENUITEM_RELOADSUBTREE,
+						aSelf.kMENUITEM_RELOADCHILDREN,
+						aSelf.kMENUITEM_REMOVESUBTREE,
+						aSelf.kMENUITEM_REMOVECHILDREN,
+						aSelf.kMENUITEM_REMOVEALLTABSBUT,
+						aSelf.kMENUITEM_COLLAPSEEXPAND_SEPARATOR,
+						aSelf.kMENUITEM_COLLAPSE,
+						aSelf.kMENUITEM_EXPAND,
+						aSelf.kMENUITEM_AUTOHIDE_SEPARATOR,
+						aSelf.kMENUITEM_AUTOHIDE,
+						aSelf.kMENUITEM_FIXED,
+						aSelf.kMENUITEM_BOOKMARKSUBTREE
+					];
+				for (let i = 0, maxi = ids.length; i < maxi; i++)
+				{
+					let id = ids[i];
+					let item = d.getElementById(id).cloneNode(true);
 					item.setAttribute('id', item.getAttribute('id')+suffix);
 
 					let refNode = void(0);
@@ -732,7 +765,7 @@ TreeStyleTabBrowser.prototype = {
 						}
 					}
 					aPopup.insertBefore(item, refNode || null);
-				});
+				}
 				tabContextMenu = null;
 			}, 0, this, b, tabContextMenu);
 		}
@@ -749,6 +782,16 @@ TreeStyleTabBrowser.prototype = {
 		}
 	},
  
+	_initTooltipManager : function TSTBrowser_initTooltipManager() 
+	{
+		if (this.tooltipManager)
+			return;
+
+		var ns = {};
+		Components.utils.import('resource://treestyletab-modules/fullTooltip.js', ns);
+		this.tooltipManager = new ns.FullTooltipManager(this);
+	},
+ 
 	_readyToInitDNDObservers : function TSTBrowser_readyToInitDNDObservers() 
 	{
 		var w = this.window;
@@ -766,8 +809,8 @@ TreeStyleTabBrowser.prototype = {
 		this.panelDNDObserver;
 
 		var w = this.window;
-		w.addEventListener('mouseover', this, true);
-		w.addEventListener('dragover', this, true);
+		w.removeEventListener('mouseover', this, true);
+		w.removeEventListener('dragover', this, true);
 		this._DNDObserversInitialized = true;
 	},
   
@@ -780,33 +823,66 @@ TreeStyleTabBrowser.prototype = {
 			aTab.setAttribute(this.kALLOW_COLLAPSE, true);
 			let self = this;
 			this.Deferred.next(function() {
+				// changed by someone!
+				if (aTab.getAttribute(self.kID) != id)
+					return;
+
 				if (!self.getTabValue(aTab, self.kID)) {
 					self.setTabValue(aTab, self.kID, id);
 					if (!(id in self.tabsHash))
 						self.tabsHash[id] = aTab;
 				}
-			});
+			}).error(this.defaultDeferredErrorHandler);
 			if (!(id in this.tabsHash))
 				this.tabsHash[id] = aTab;
 		}
 
 		aTab.__treestyletab__linkedTabBrowser = this.mTabBrowser;
 
+		/**
+		 * XXX dity hack!!! there is no way to know when the tab is readied to be restored...
+		 */
+		aTab.linkedBrowser.__treestyletab__toBeRestored = false;
+		var b = aTab.linkedBrowser;
+		if (!b.__treestyletab__stop) {
+			b.__treestyletab__stop = b.stop;
+			b.stop = function TSTBrowser_stopHook() {
+				try {
+					var stack = Components.stack;
+					while (stack)
+					{
+						if (stack.name == 'sss_restoreHistoryPrecursor') {
+							this.__treestyletab__toBeRestored = true;
+							break;
+						}
+						stack = stack.caller;
+					}
+				}
+				catch(e) {
+					dump(e+'\n'+e.stack+'\n');
+				}
+				return this.__treestyletab__stop.apply(this, arguments);
+			};
+		}
+
 		this.initTabAttributes(aTab);
 		this.initTabContents(aTab);
 
-		aTab.setAttribute(this.kNEST, 0);
+		if (!aTab.hasAttribute(this.kNEST))
+			aTab.setAttribute(this.kNEST, 0);
 	},
-	isTabInitialized : function TSTBrowser_isTabInitialized(aTab)
+	
+	isTabInitialized : function TSTBrowser_isTabInitialized(aTab) 
 	{
 		return aTab.getAttribute(this.kID);
 	},
-	ensureTabInitialized : function TSTBrowser_ensureTabInitialized(aTab)
+ 
+	ensureTabInitialized : function TSTBrowser_ensureTabInitialized(aTab) 
 	{
 		if (!aTab || this.isTabInitialized(aTab)) return;
 		this.initTab(aTab);
 	},
-	
+ 
 	initTabAttributes : function TSTBrowser_initTabAttributes(aTab) 
 	{
 		var pos = this.position;
@@ -825,14 +901,6 @@ TreeStyleTabBrowser.prototype = {
 			aTab.removeAttribute('align');
 			aTab.removeAttribute('maxwidth');
 			aTab.removeAttribute('minwidth');
-			if (!this.isGecko2) { // Firefox 3.6 or older
-				aTab.setAttribute('maxwidth', 250);
-				aTab.setAttribute('minwidth', this.mTabBrowser.mTabContainer.mTabMinWidth);
-				aTab.setAttribute('width', '0');
-				aTab.maxWidth = 250;
-				aTab.minWidth = this.mTabBrowser.mTabContainer.mTabMinWidth;
-				aTab.setAttribute('flex', 100);
-			}
 			if (this.getTreePref('compatibility.TMP'))
 				aTab.removeAttribute('dir'); // Tab Mix Plus
 		}
@@ -842,29 +910,17 @@ TreeStyleTabBrowser.prototype = {
 	{
 		var d = this.document;
 
-		var icon  = d.getAnonymousElementByAttribute(aTab, 'class', 'tab-icon');
-		var twisty = d.getAnonymousElementByAttribute(aTab, 'class', this.kTWISTY);
-		if (icon && !twisty) {
+		var twisty = this.getTabTwisty(aTab);
+		var anchor = this.getTabTwistyAnchorNode(aTab);
+		if (anchor  && !twisty) {
 			twisty = d.createElement('image');
 			twisty.setAttribute('class', this.kTWISTY);
-			let container = d.createElement('hbox');
-			container.setAttribute('class', this.kTWISTY_CONTAINER);
-			container.appendChild(twisty);
-
-			icon.appendChild(container);
-
-			let marker = d.createElement('image');
-			marker.setAttribute('class', this.kDROP_MARKER);
-			container = d.createElement('hbox');
-			container.setAttribute('class', this.kDROP_MARKER_CONTAINER);
-			container.appendChild(marker);
-
-			icon.appendChild(container);
+			anchor.parentNode.appendChild(twisty);
 		}
 
 		var label = this.getTabLabel(aTab);
 		var counter = d.getAnonymousElementByAttribute(aTab, 'class', this.kCOUNTER_CONTAINER);
-		if (label && label.parentNode != aTab && !counter) {
+		if (label && !counter) {
 			counter = d.createElement('hbox');
 			counter.setAttribute('class', this.kCOUNTER_CONTAINER);
 
@@ -891,76 +947,139 @@ TreeStyleTabBrowser.prototype = {
 			label.parentNode.appendChild(counter);
 		}
 
-		var tabContentBox = d.getAnonymousElementByAttribute(aTab, 'class', 'tab-content');
-		if (tabContentBox &&
-			(tabContentBox.firstChild.className || '').indexOf('tab-image-') > -1) {
-			// Set stretched only if the tabFx2Compatible.xml is applied.
-			// Tab Mix Plus overrides the binding so icons are wrongly stretched.
-			tabContentBox.setAttribute('align', this.isVertical ? 'stretch' : 'center' );
-		}
-
-		this.initTabContentsOrder(aTab);
+		this.initTabContentsOrder(aTab, true);
 	},
  
-	initTabContentsOrder : function TSTBrowser_initTabContentsOrder(aTab) 
+	initTabContentsOrder : function TSTBrowser_initTabContentsOrder(aTab, aForce) 
 	{
 		var d = this.document;
 
-		var label = this.getTabLabel(aTab);
-		var close = this.getTabClosebox(aTab);
-		var inverted = this.mTabBrowser.getAttribute(this.kTAB_CONTENTS_INVERTED) == 'true';
+		var namedNodes = {
+				label        : this.getTabLabel(aTab),
+				close        : this.getTabClosebox(aTab),
+				twistyAnchor : this.getTabTwistyAnchorNode(aTab),
+				twisty       : this.getTabTwisty(aTab),
+				counter      : d.getAnonymousElementByAttribute(aTab, 'class', this.kCOUNTER_CONTAINER)
+			};
 
-		var nodesContainer = d.getAnonymousElementByAttribute(aTab, 'class', 'tab-content') || aTab;
-		var nodes = Array.slice(d.getAnonymousNodes(nodesContainer) || nodesContainer.childNodes);
+		namedNodes.closeAnchor = namedNodes.label;
+		if (namedNodes.closeAnchor.parentNode != namedNodes.close.parentNode) {
+			let containerFinder = d.createRange();
+			containerFinder.selectNode(namedNodes.closeAnchor);
+			containerFinder.setEndAfter(namedNodes.close);
+			let container = containerFinder.getCommonAncestor();
+			while (namedNodes.closeAnchor.parentNode != container)
+			{
+				namedNodes.closeAnchor = namedNodes.closeAnchor.parentNode;
+			}
+			while (namedNodes.close.parentNode != container)
+			{
+				namedNodes.close = namedNodes.close.parentNode;
+			}
+		}
 
-		// reset order
-		nodes.forEach(function(aNode, aIndex) {
-			aNode.setAttribute('ordinal', aIndex);
-		}, this);
+		namedNodes.counterAnchor = namedNodes.label;
 
-		// rearrange top-level contents
-		nodes.splice(nodes.indexOf(close), 1);
-		if (inverted) {
-			if (this.mTabBrowser.getAttribute(this.kCLOSEBOX_INVERTED) == 'true')
-				nodes.splice(nodes.indexOf(label.parentNode)+1, 0, close);
-			else
-				nodes.splice(nodes.indexOf(label.parentNode), 0, close);
+		var foundContainers = [];
+		var containers = [
+				namedNodes.twistyAnchor.parentNode,
+				namedNodes.label.parentNode,
+				namedNodes.counter.parentNode,
+				namedNodes.closeAnchor.parentNode
+			];
+		for (let i = 0, maxi = containers.length; i < maxi; i++)
+		{
+			let container = containers[i];
+			if (foundContainers.indexOf(container) > -1)
+				continue;
+			this.initTabContentsOrderInternal(container, namedNodes, aForce);
+			foundContainers.push(container);
 		}
-		else {
+	},
+	initTabContentsOrderInternal : function TSTBrowser_initTabContentsOrderInternal(aContainer, aNamedNodes, aForce) 
+	{
+		if (this.window.getComputedStyle(aContainer, '').getPropertyValue('-moz-box-orient') == 'vertical')
+			return;
+
+		var nodes = Array.slice(this.document.getAnonymousNodes(aContainer) || aContainer.childNodes);
+
+		// reset order at first!
+		for (let i = 0, maxi = nodes.length; i < maxi; i++)
+		{
+			let node = nodes[i];
+			if (node.getAttribute('class') == 'informationaltab-thumbnail-container')
+				continue;
+			node.setAttribute('ordinal', i);
+		}
+
+		// after that, rearrange contents
+
+		var index = nodes.indexOf(aNamedNodes.close);
+		if (index > -1) {
+			nodes.splice(index, 1);
 			if (this.mTabBrowser.getAttribute(this.kCLOSEBOX_INVERTED) == 'true')
-				nodes.splice(nodes.indexOf(label.parentNode), 0, close);
+				nodes.splice(nodes.indexOf(aNamedNodes.closeAnchor), 0, aNamedNodes.close);
 			else
-				nodes.splice(nodes.indexOf(label.parentNode)+1, 0, close);
+				nodes.splice(nodes.indexOf(aNamedNodes.closeAnchor)+1, 0, aNamedNodes.close);
 		}
-		var count = nodes.length;
-		Array.slice(nodes).reverse()
-			.forEach(function(aNode, aIndex) {
-				aNode.setAttribute('ordinal', (count - aIndex + 1) * 100);
-			}, this);
 
-		// rearrange contents in "tab-image-middle"
-		nodes = Array.slice(label.parentNode.childNodes);
+		index = nodes.indexOf(aNamedNodes.twisty);
+		if (index > -1) {
+			nodes.splice(index, 1);
+			nodes.splice(nodes.indexOf(aNamedNodes.twistyAnchor), 0, aNamedNodes.twisty);
+		}
 
-		if (inverted)
+		if (this.mTabBrowser.getAttribute(this.kTAB_CONTENTS_INVERTED) == 'true')
 			nodes.reverse();
 
-		var counter = d.getAnonymousElementByAttribute(aTab, 'class', this.kCOUNTER_CONTAINER);
-		if (counter) {
-			nodes.splice(nodes.indexOf(counter), 1);
-			nodes.splice(nodes.indexOf(label)+1, 0, counter);
+		// counter must rightside of the label!
+		index = nodes.indexOf(aNamedNodes.counter);
+		if (index > -1) {
+			nodes.splice(index, 1);
+			nodes.splice(nodes.indexOf(aNamedNodes.counterAnchor)+1, 0, aNamedNodes.counter);
 		}
 
-		count = nodes.length;
-		nodes.reverse().forEach(function(aNode, aIndex) {
-			if (aNode.getAttribute('class') == 'informationaltab-thumbnail-container')
-				return;
-			aNode.setAttribute('ordinal', (count - aIndex + 1) * 100);
-		}, this);
+		var count = nodes.length;
+		nodes.reverse();
+		for (let i = 0, maxi = nodes.length; i < maxi; i++)
+		{
+			let node = nodes[i];
+			if (node.getAttribute('class') == 'informationaltab-thumbnail-container')
+				continue;
+			node.setAttribute('ordinal', (count - i + 1) * 100);
+		}
+
+		if (aForce) {
+			/**
+			 * After the order of contents are changed dynamically,
+			 * Gecko doesn't re-render them in the new order.
+			 * Changing of "display" or "position" can fix this problem.
+			 */
+			let shouldHideTemporaryState = (
+					'TabmixTabbar' in this.window || // Tab Mix Plus
+					'InformationalTabService' in this.window // Informational Tab
+				);
+			for (let i = 0, maxi = nodes.length; i < maxi; i++)
+			{
+				let node = nodes[i];
+				if (shouldHideTemporaryState)
+					node.style.visibility = 'hidden';
+				node.style.position = 'fixed';
+			}
+			this.Deferred.wait(0.1).next(function() {
+				for (let i = 0, maxi = nodes.length; i < maxi; i++)
+				{
+					let node = nodes[i];
+					node.style.position = '';
+					if (shouldHideTemporaryState)
+						node.style.visibility = '';
+				}
+			}).error(this.defaultDeferredErrorHandler);
+		}
 	},
  
 	updateInvertedTabContentsOrder : function TSTBrowser_updateInvertedTabContentsOrder(aTarget) 
 	{
-		if (!this.getTreePref('tabbar.invertTabContents')) return;
 		var self = this;
 		this.Deferred.next(function() {
 			var b = self.mTabBrowser;
@@ -971,10 +1090,11 @@ TreeStyleTabBrowser.prototype = {
 					(typeof aTarget == 'object' && 'length' in aTarget) ?
 						Array.slice(aTarget) :
 						self.getAllTabsArray(b);
-			tabs.forEach(function(aTab) {
-				this.initTabContentsOrder(aTab);
-			}, self);
-		});
+			for (let i = 0, maxi = tabs.length; i < maxi; i++)
+			{
+				self.initTabContentsOrder(tabs[i]);
+			}
+		}).error(this.defaultDeferredErrorHandler);
 	},
   
 	initTabbar : function TSTBrowser_initTabbar(aNewPosition, aOldPosition) 
@@ -1018,7 +1138,6 @@ TreeStyleTabBrowser.prototype = {
 		var placeHolder = this.tabStripPlaceHolder || strip;
 		var splitter = this._ensureNewSplitter();
 		var toggler = d.getAnonymousElementByAttribute(b, 'class', this.kTABBAR_TOGGLER);
-		var indicator = b.mTabDropIndicatorBar || b.tabContainer._tabDropIndicator;
 
 		// Tab Mix Plus
 		var scrollFrame, newTabBox, tabBarMode;
@@ -1048,7 +1167,6 @@ TreeStyleTabBrowser.prototype = {
 		var delayedPostProcess;
 
 		if (pos & this.kTABBAR_VERTICAL) {
-
 			this.collapseTarget             = 'top';
 			this.screenPositionProp         = 'screenY';
 			this.sizeProp                   = 'height';
@@ -1089,13 +1207,16 @@ TreeStyleTabBrowser.prototype = {
 			b.mPanelContainer.removeAttribute('height');
 
 			if (strip.localName == 'toolbar') {
-				Array.forEach(strip.childNodes, function(aNode) {
-					if (aNode.localName == 'tabs')
-						return;
-					if (aNode.hasAttribute('flex'))
-						aNode.setAttribute('treestyletab-backup-flex', aNode.getAttribute('flex'));
-					aNode.removeAttribute('flex');
-				}, this);
+				let nodes = strip.childNodes;
+				for (let i = 0, maxi = nodes.length; i < maxi; i++)
+				{
+					let node = nodes[i];
+					if (node.localName == 'tabs')
+						continue;
+					if (node.hasAttribute('flex'))
+						node.setAttribute('treestyletab-backup-flex', node.getAttribute('flex'));
+					node.removeAttribute('flex');
+				}
 			}
 
 			if (pos == this.kTABBAR_RIGHT) {
@@ -1113,8 +1234,6 @@ TreeStyleTabBrowser.prototype = {
 					   unexpectedly becomes 0 on the startup. so, we have
 					   to set the width again. */
 					aSelf.setTabStripAttribute('width', width);
-					if (!aSelf.isFloating)
-						indicator.setAttribute('ordinal', 1);
 					aSelf.setTabStripAttribute('ordinal', 30);
 					aSplitter.setAttribute('ordinal', 20);
 					aToggler.setAttribute('ordinal', 40);
@@ -1127,8 +1246,6 @@ TreeStyleTabBrowser.prototype = {
 				this.removeTabbrowserAttribute(this.kTAB_INVERTED);
 				this.indentTarget = 'left';
 				delayedPostProcess = function(aSelf, aTabBrowser, aSplitter, aToggler) {
-					if (!aSelf.isFloating)
-						indicator.setAttribute('ordinal', 1);
 					aSelf.setTabStripAttribute('ordinal', 10);
 					aSplitter.setAttribute('ordinal', 20);
 					aToggler.setAttribute('ordinal', 5);
@@ -1172,23 +1289,24 @@ TreeStyleTabBrowser.prototype = {
 			this.removeTabbrowserAttribute(this.kTAB_INVERTED);
 
 			if (strip.localName == 'toolbar') {
-				Array.forEach(strip.childNodes, function(aNode) {
-					if (aNode.localName == 'tabs')
-						return;
-					var flex = aNode.hasAttribute('treestyletab-backup-flex');
+				let nodes = strip.childNodes;
+				for (let i = 0, maxi = nodes.length; i < maxi; i++)
+				{
+					let node = nodes[i];
+					if (node.localName == 'tabs')
+						continue;
+					let flex = node.hasAttribute('treestyletab-backup-flex');
 					if (!flex)
-						return;
-					aNode.setAttribute('flex', flex);
-					aNode.removeAttribute('treestyletab-backup-flex');
-				}, this);
+						continue;
+					node.setAttribute('flex', flex);
+					node.removeAttribute('treestyletab-backup-flex');
+				}
 			}
 
 			if (pos == this.kTABBAR_BOTTOM) {
 				this.setTabbrowserAttribute(this.kTABBAR_POSITION, 'bottom');
 				this.indentTarget = 'bottom';
 				delayedPostProcess = function(aSelf, aTabBrowser, aSplitter, aToggler) {
-					if (!aSelf.isFloating)
-						indicator.setAttribute('ordinal', 1);
 					aSelf.setTabStripAttribute('ordinal', 30);
 					aSplitter.setAttribute('ordinal', 20);
 					aToggler.setAttribute('ordinal', 40);
@@ -1199,8 +1317,6 @@ TreeStyleTabBrowser.prototype = {
 				this.setTabbrowserAttribute(this.kTABBAR_POSITION, 'top');
 				this.indentTarget = 'top';
 				delayedPostProcess = function(aSelf, aTabBrowser, aSplitter, aToggler) {
-					if (!aSelf.isFloating)
-						indicator.setAttribute('ordinal', 1);
 					aSelf.setTabStripAttribute('ordinal', 10);
 					aSplitter.setAttribute('ordinal', 20);
 					aToggler.setAttribute('ordinal', 5);
@@ -1210,18 +1326,29 @@ TreeStyleTabBrowser.prototype = {
 		}
 
 		var tabs = this.getAllTabsArray(b);
-		tabs.forEach(function(aTab) {
-			aTab.style.removeProperty(this.indentCSSProp);
-			aTab.style.removeProperty(this.collapseCSSProp);
-		}, this);
+		for (let i = 0, maxi = tabs.length; i < maxi; i++)
+		{
+			let tab = tabs[i];
+			tab.style.removeProperty(this.indentCSSProp);
+			tab.style.removeProperty(this.collapseCSSProp);
+		}
 
 		this.indentProp = this.getTreePref('indent.property');
 		this.indentCSSProp = this.indentProp+'-'+this.indentTarget;
 		this.collapseCSSProp = 'margin-'+this.collapseTarget;
 
-		tabs.forEach(function(aTab) {
-			this.updateTabCollapsed(aTab, aTab.getAttribute(this.kCOLLAPSED) == 'true', true);
-		}, this);
+		for (let i = 0, maxi = tabs.length; i < maxi; i++)
+		{
+			let tab = tabs[i];
+			this.updateTabCollapsed(tab, tab.getAttribute(this.kCOLLAPSED) == 'true', true);
+		}
+
+		// for updateTabbarOverflow(), we should reset the "overflow" now.
+		b.mTabContainer.removeAttribute('overflow');
+		let (container = this.document.getAnonymousElementByAttribute(b.mTabContainer, 'class', 'tabs-container')) {
+			if (container)
+				container.removeAttribute('overflow');
+		}
 
 		this.updateTabbarState(false);
 
@@ -1230,6 +1357,7 @@ TreeStyleTabBrowser.prototype = {
 			delayedPostProcess(self, b, splitter, toggler);
 			self.updateTabbarOverflow();
 			self.updateAllTabsButton(b);
+			self.updateAllTabsCount();
 			delayedPostProcess = null;
 			self.mTabBrowser.style.visibility = '';
 
@@ -1238,7 +1366,7 @@ TreeStyleTabBrowser.prototype = {
 			self.mTabBrowser.dispatchEvent(event);
 
 			self.startRendering();
-		});
+		}).error(this.defaultDeferredErrorHandler);
 
 		pos = null;
 		scrollFrame = null;
@@ -1263,8 +1391,6 @@ TreeStyleTabBrowser.prototype = {
 		tabContainer.addEventListener('SSTabRestored',  this, true);
 		tabContainer.addEventListener('TabPinned',      this, true);
 		tabContainer.addEventListener('TabUnpinned',    this, true);
-		if (!this.isGecko2 && 'tabutils' in this.window)
-			tabContainer.addEventListener('DOMAttrModified', this, true); // Tab Utilities
 		tabContainer.addEventListener('mouseover', this, true);
 		tabContainer.addEventListener('dblclick',  this, true);
 		tabContainer.addEventListener('select', this, true);
@@ -1274,11 +1400,10 @@ TreeStyleTabBrowser.prototype = {
 		strip.addEventListener('MozMouseHittest', this, true); // to block default behaviors of the tab bar
 		strip.addEventListener('mousedown',       this, true);
 		strip.addEventListener('click',           this, true);
+		strip.addEventListener('DOMMouseScroll',  this, true);
 
 		this.scrollBox.addEventListener('overflow', this, true);
 		this.scrollBox.addEventListener('underflow', this, true);
-
-		this.tabTooltip.addEventListener('popupshowing', this, true);
 	},
  
 	_ensureNewSplitter : function TSTBrowser__ensureNewSplitter() 
@@ -1368,14 +1493,14 @@ TreeStyleTabBrowser.prototype = {
 					b.mPanelContainer.removeAttribute('height');
 				}
 				// remove ordinal for "tabs on top" https://bugzilla.mozilla.org/show_bug.cgi?id=544815
-				if (this.isFloating && this.position == 'top') {
+				if (this.position == 'top') {
 					this.removeTabStripAttribute('ordinal');
-					if (TabsOnTop) {
+					if (TabsOnTop && !this.windowService.isPopupWindow) {
 						// workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=555987
 						TabsOnTop.enabled = !TabsOnTop.enabled;
 						this.Deferred.next(function() {
 							TabsOnTop.enabled = !TabsOnTop.enabled;
-						});
+						}).error(this.defaultDeferredErrorHandler);
 					}
 				}
 			}
@@ -1391,7 +1516,7 @@ TreeStyleTabBrowser.prototype = {
 			}
 		}
 
-		if (TabsOnTop) {
+		if (TabsOnTop && !this.windowService.isPopupWindow) {
 			let tabsWasOnTop = TabsOnTop.enabled;
 			TabsOnTop.enabled = TabsOnTop.enabled && this.position == 'top' && this.fixed;
 			if (tabsWasOnTop && !TabsOnTop.enabled)
@@ -1403,7 +1528,7 @@ TreeStyleTabBrowser.prototype = {
 			self.updateFloatingTabbar(self.kTABBAR_UPDATE_BY_APPEARANCE_CHANGE);
 			self._fireTabbarStateChangedEvent();
 			self.startRendering();
-		});
+		}).error(this.defaultDeferredErrorHandler);
 
 		this.allowSubtreeCollapseExpand = this.getTreePref('allowSubtreeCollapseExpand.'+orient) ;
 		this.maxTreeLevel = this.getTreePref('maxTreeLevel.'+orient);
@@ -1411,9 +1536,6 @@ TreeStyleTabBrowser.prototype = {
 		this.setTabbrowserAttribute(this.kALLOW_STACK, this.canStackTabs ? 'true' : null);
 		this.updateTabsZIndex(this.canStackTabs);
 
-		if (!this.ownerToolbar) /* legacy feature for Firefox 3.6 or olders */
-			this.hideAlltabsButton = this.getTreePref('tabbar.hideAlltabsButton.'+orient);
-
 		if (this.maxTreeLevelPhisical)
 			this.promoteTooDeepLevelTabs();
 
@@ -1430,26 +1552,17 @@ TreeStyleTabBrowser.prototype = {
 				indented      : this.maxTreeLevel != 0,
 				canCollapse   : b.getAttribute(this.kALLOW_COLLAPSE) == 'true'
 			};
-		if (!this.ownerToolbar) { /* legacy feature for Firefox 3.6 or olders */
-			oldState.alltabsButton = b.getAttribute(this.kHIDE_ALLTABS) != 'true';
-			oldState.allTabsButton = oldState.alltabsButton;
-		}
 		var newState = {
 				fixed         : this.getTreePref('tabbar.fixed.'+orient),
 				maxTreeLevel  : this.getTreePref('maxTreeLevel.'+orient),
 				indented      : this.getTreePref('maxTreeLevel.'+orient) != 0,
 				canCollapse   : this.getTreePref('allowSubtreeCollapseExpand.'+orient)
 			};
-		if (!this.ownerToolbar) { /* legacy feature for Firefox 3.6 or olders */
-			newState.alltabsButton = !this.getTreePref('tabbar.hideAlltabsButton.'+orient);
-			newState.allTabsButton = newState.alltabsButton;
-		}
 
 		if (oldState.fixed == newState.fixed &&
 			oldState.maxTreeLevel == newState.maxTreeLevel &&
 			oldState.indented == newState.indented &&
-			oldState.canCollapse == newState.canCollapse &&
-			oldState.alltabsButton == newState.alltabsButton)
+			oldState.canCollapse == newState.canCollapse)
 			return false;
 
 		var data = {
@@ -1474,10 +1587,6 @@ TreeStyleTabBrowser.prototype = {
 				indented      : this.maxTreeLevel != 0,
 				canCollapse   : b.getAttribute(this.kALLOW_COLLAPSE) == 'true'
 			};
-		if (!this.ownerToolbar) { /* legacy feature for Firefox 3.6 or olders */
-			state.alltabsButton = b.getAttribute(this.kHIDE_ALLTABS) != 'true';
-			state.allTabsButton = state.alltabsButton;
-		}
 
 		var data = {
 				state : state
@@ -1493,9 +1602,6 @@ TreeStyleTabBrowser.prototype = {
   
 	updateFloatingTabbar : function TSTBrowser_updateFloatingTabbar(aReason) 
 	{
-		// this method is just for Firefox 4.0 or later
-		if (!this.isFloating) return;
-
 		var w = this.window;
 		if (this._updateFloatingTabbarTimer) {
 			w.clearTimeout(this._updateFloatingTabbarTimer);
@@ -1696,54 +1802,48 @@ TreeStyleTabBrowser.prototype = {
 	{
 		var d = this.document;
 		var b = this.mTabBrowser;
-		b.mTabContainer.removeAttribute('overflow'); // Firefox 4.0
-		var container = d.getAnonymousElementByAttribute(b.mTabContainer, 'class', 'tabs-container');
-
-		if (!container) {
-			if (this.ownerToolbar)
-				container = b.mTabContainer;
-			else
-				return;
-		}
+		b.mTabContainer.removeAttribute('overflow');
+		var container = d.getAnonymousElementByAttribute(b.mTabContainer, 'class', 'tabs-container') || b.mTabContainer;
 
-		container.removeAttribute('overflow');
+		if (container != b.mTabContainer)
+			container.removeAttribute('overflow');
 
 		var scrollBox = this.scrollBox;
-		this.window.setTimeout(function() {
-			scrollBox = d.getAnonymousElementByAttribute(scrollBox, 'anonid', 'scrollbox');
-			if (scrollBox) scrollBox = d.getAnonymousNodes(scrollBox)[0];
-			if (
-				scrollBox &&
-				(
-					scrollBox.boxObject.width > container.boxObject.width ||
-					scrollBox.boxObject.height > container.boxObject.height
-				)
-				) {
-				b.mTabContainer.setAttribute('overflow', true); // Firefox 4.0
+		scrollBox = d.getAnonymousElementByAttribute(scrollBox, 'anonid', 'scrollbox');
+		if (scrollBox) scrollBox = d.getAnonymousNodes(scrollBox)[0];
+		if (
+			scrollBox &&
+			(
+				scrollBox.boxObject.width > container.boxObject.width ||
+				scrollBox.boxObject.height > container.boxObject.height
+			)
+			) {
+			b.mTabContainer.setAttribute('overflow', true);
+			if (container != b.mTabContainer)
 				container.setAttribute('overflow', true);
-			}
-			else {
-				b.mTabContainer.removeAttribute('overflow'); // Firefox 4.0
+		}
+		else {
+			b.mTabContainer.removeAttribute('overflow');
+			if (container != b.mTabContainer)
 				container.removeAttribute('overflow');
-			}
-		}, 100);
+		}
 	},
  
 	reinitAllTabs : function TSTBrowser_reinitAllTabs(aSouldUpdateCount) 
 	{
 		var tabs = this.getAllTabsArray(this.mTabBrowser);
-		tabs.forEach(function(aTab) {
-			this.initTabAttributes(aTab);
-			this.initTabContents(aTab);
+		for (let i = 0, maxi = tabs.length; i < maxi; i++)
+		{
+			let tab = tabs[i];
+			this.initTabAttributes(tab);
+			this.initTabContents(tab);
 			if (aSouldUpdateCount)
-				this.updateTabsCount(aTab);
-		}, this);
+				this.updateTabsCount(tab);
+		}
 	},
   
 	destroy : function TSTBrowser_destroy() 
 	{
-		this.saveTreeStructure();
-
 		this.animationManager.removeTask(this.smoothScrollTask);
 
 		this.autoHide.destroy();
@@ -1755,16 +1855,24 @@ TreeStyleTabBrowser.prototype = {
 		this.panelDNDObserver.destroy();
 		delete this._panelDNDObserver;
 
+		if (this.tooltipManager) {
+			this.tooltipManager.destroy();
+			delete this.tooltipManager;
+		}
+
 		var w = this.window;
 		var d = this.document;
 		var b = this.mTabBrowser;
 		delete b.tabContainer.treeStyleTab;
 
-		this.getAllTabsArray(b).forEach(function(aTab) {
-			this.stopTabIndentAnimation(aTab);
-			this.stopTabCollapseAnimation(aTab);
-			this.destroyTab(aTab);
-		}, this);
+		var tabs = this.getAllTabsArray(b);
+		for (let i = 0, maxi = tabs.length; i < maxi; i++)
+		{
+			let tab = tabs[i];
+			this.stopTabIndentAnimation(tab);
+			this.stopTabCollapseAnimation(tab);
+			this.destroyTab(tab);
+		}
 
 		this._endListenTabbarEvents();
 
@@ -1774,7 +1882,9 @@ TreeStyleTabBrowser.prototype = {
 		w.removeEventListener('customizationchange', this, false);
 		w.removeEventListener(this.kEVENT_TYPE_PRINT_PREVIEW_ENTERED, this, false);
 		w.removeEventListener(this.kEVENT_TYPE_PRINT_PREVIEW_EXITED,  this, false);
-		w.removeEventListener('tabviewhidden', this, true);
+		w.removeEventListener('tabviewframeinitialized', this, false);
+		w.removeEventListener(this.kEVENT_TYPE_TAB_FOCUS_SWITCHING_END, this, false);
+		w.removeEventListener('SSWindowStateBusy', this, false);
 
 		b.removeEventListener('nsDOMMultipleTabHandlerTabsClosing', this, false);
 
@@ -1792,8 +1902,6 @@ TreeStyleTabBrowser.prototype = {
 		this.ObserverService.removeObserver(this, this.kTOPIC_INDENT_MODIFIED);
 		this.ObserverService.removeObserver(this, this.kTOPIC_COLLAPSE_EXPAND_ALL);
 		this.ObserverService.removeObserver(this, this.kTOPIC_CHANGE_TREEVIEW_AVAILABILITY);
-		this.ObserverService.removeObserver(this, 'sessionstore-windows-restored');
-		this.ObserverService.removeObserver(this, 'sessionstore-browser-state-restored');
 		this.ObserverService.removeObserver(this, 'private-browsing-change-granted');
 		this.ObserverService.removeObserver(this, 'lightweight-theme-styling-update');
 		this.removePrefListener(this);
@@ -1828,8 +1936,6 @@ TreeStyleTabBrowser.prototype = {
 		tabContainer.removeEventListener('SSTabRestored',  this, true);
 		tabContainer.removeEventListener('TabPinned',      this, true);
 		tabContainer.removeEventListener('TabUnpinned',    this, true);
-		if (!this.ownerToolbar && 'tabutils' in this.window)
-			b.mTabContainer.removeEventListener('DOMAttrModified', this, true); // Tab Utilites
 		tabContainer.removeEventListener('mouseover', this, true);
 		tabContainer.removeEventListener('dblclick',  this, true);
 		tabContainer.removeEventListener('select', this, true);
@@ -1839,11 +1945,10 @@ TreeStyleTabBrowser.prototype = {
 		strip.removeEventListener('MozMouseHittest', this, true);
 		strip.removeEventListener('mousedown',       this, true);
 		strip.removeEventListener('click',           this, true);
+		strip.removeEventListener('DOMMouseScroll',  this, true);
 
 		this.scrollBox.removeEventListener('overflow', this, true);
 		this.scrollBox.removeEventListener('underflow', this, true);
-
-		this.tabTooltip.removeEventListener('popupshowing', this, true);
 	},
  
 	saveCurrentState : function TSTBrowser_saveCurrentState() 
@@ -1868,7 +1973,7 @@ TreeStyleTabBrowser.prototype = {
 		this.position = this.position;
 	},
    
-/* toolbar customization on Firefox 4 or later */ 
+/* toolbar customization */ 
 	
 	syncDestroyTabbar : function TSTBrowser_syncDestroyTabbar() 
 	{
@@ -1888,7 +1993,6 @@ TreeStyleTabBrowser.prototype = {
 		}
 
 		this.maxTreeLevel = 0;
-		this.hideAlltabsButton = false; /* legacy feature for Firefox 3.6 or olders */
 		this.fixed = true;
 		this._lastTreeViewEnabledBeforeDestroyed = this.treeViewEnabled;
 		this.treeViewEnabled = false;
@@ -1934,9 +2038,7 @@ TreeStyleTabBrowser.prototype = {
 		this.ownerToolbar.classList.add(this.kTABBAR_TOOLBAR);
 		this.ownerToolbar.classList.remove(this.kTABBAR_TOOLBAR_READY);
 		Array.slice(this.document.querySelectorAll('.'+this.kTABBAR_TOOLBAR_READY_POPUP))
-			.forEach(function(aPanel) {
-				this.safeRemovePopup(aPanel);
-			}, this);
+			.forEach(this.safeRemovePopup, this);
 
 		var position = this._lastTabbarPositionBeforeDestroyed || this.position;
 		delete this._lastTabbarPositionBeforeDestroyed;
@@ -2038,10 +2140,6 @@ TreeStyleTabBrowser.prototype = {
 				}
 				return;
 
-			case 'sessionstore-windows-restored':
-			case 'sessionstore-browser-state-restored':
-				return this.onWindowStateRestored();
-
 			case 'private-browsing-change-granted':
 				this.collapseExpandAllSubtree(false, true);
 				this.updateFloatingTabbar(this.kTABBAR_UPDATE_BY_PRIVATE_BROWSING);
@@ -2063,6 +2161,10 @@ TreeStyleTabBrowser.prototype = {
  
 	onPrefChange : function TSTBrowser_onPrefChange(aPrefName) 
 	{
+		// ignore after destruction
+		if (!this.window || !this.window.TreeStyleTabService)
+			return;
+
 		var b = this.mTabBrowser;
 		var value = this.getPref(aPrefName);
 		var tabContainer = b.mTabContainer;
@@ -2078,22 +2180,25 @@ TreeStyleTabBrowser.prototype = {
 			case 'extensions.treestyletab.tabbar.multirow':
 				this.initTabbar();
 				this.updateAllTabsIndent();
-				tabs.forEach(function(aTab) {
-					this.initTabContents(aTab);
-				}, this);
+				for (let i = 0, maxi = tabs.length; i < maxi; i++)
+				{
+					this.initTabContents(tabs[i]);
+				}
 				return;
 			case 'extensions.treestyletab.tabbar.invertTabContents':
 				this.setTabbrowserAttribute(this.kTAB_CONTENTS_INVERTED, value);
-				tabs.forEach(function(aTab) {
-					this.initTabContents(aTab);
-				}, this);
+				for (let i = 0, maxi = tabs.length; i < maxi; i++)
+				{
+					this.initTabContents(tabs[i]);
+				}
 				return;
 
 			case 'extensions.treestyletab.tabbar.invertClosebox':
 				this.setTabbrowserAttribute(this.kCLOSEBOX_INVERTED, value);
-				tabs.forEach(function(aTab) {
-					this.initTabContents(aTab);
-				}, this);
+				for (let i = 0, maxi = tabs.length; i < maxi; i++)
+				{
+					this.initTabContents(tabs[i]);
+				}
 				return;
 
 			case 'extensions.treestyletab.tabbar.style':
@@ -2113,7 +2218,6 @@ TreeStyleTabBrowser.prototype = {
 				this.setTabbrowserAttribute(this.kFIXED+'-horizontal', value ? 'true' : null, b);
 			case 'extensions.treestyletab.maxTreeLevel.horizontal':
 			case 'extensions.treestyletab.allowSubtreeCollapseExpand.horizontal':
-			case 'extensions.treestyletab.tabbar.hideAlltabsButton.horizontal': /* legacy feature for Firefox 3.6 or olders */
 				if (!this.isVertical)
 					this.updateTabbarState(true);
 				return;
@@ -2123,7 +2227,6 @@ TreeStyleTabBrowser.prototype = {
 				this.setTabbrowserAttribute(this.kFIXED+'-vertical', value ? 'true' : null, b);
 			case 'extensions.treestyletab.maxTreeLevel.vertical':
 			case 'extensions.treestyletab.allowSubtreeCollapseExpand.vertical':
-			case 'extensions.treestyletab.tabbar.hideAlltabsButton.vertical': /* legacy feature for Firefox 3.6 or olders */
 				if (this.isVertical)
 					this.updateTabbarState(true);
 				return;
@@ -2133,13 +2236,8 @@ TreeStyleTabBrowser.prototype = {
 				if (!this.shouldApplyNewPref) return;
 				if (!this.autoHide.isResizing && this.isVertical) {
 					this.removeTabStripAttribute('width');
-					if (this.isFloating) {
-						this.setTabStripAttribute('width', this.autoHide.placeHolderWidthFromMode);
-						this.updateFloatingTabbar(this.kTABBAR_UPDATE_BY_PREF_CHANGE);
-					}
-					else {
-						this.setTabStripAttribute('width', this.autoHide.widthFromMode);
-					}
+					this.setTabStripAttribute('width', this.autoHide.placeHolderWidthFromMode);
+					this.updateFloatingTabbar(this.kTABBAR_UPDATE_BY_PREF_CHANGE);
 				}
 				this.checkTabsIndentOverflow();
 				return;
@@ -2197,10 +2295,26 @@ TreeStyleTabBrowser.prototype = {
 			case 'extensions.treestyletab.tabbar.autoHide.mode.fullscreen':
 				return this.autoHide; // ensure initialized
 
-			case 'extensions.treestyletab.pinnedTab.width':
-			case 'extensions.treestyletab.pinnedTab.height':
+			case 'extensions.treestyletab.pinnedTab.faviconized':
 				return this.positionPinnedTabsWithDelay();
 
+			case 'extensions.treestyletab.counter.role.horizontal':
+				if (!this.isVertical) {
+					let self = this;
+					this.Deferred
+						.next(function() { self.updateAllTabsCount(); })
+						.error(this.defaultDeferredErrorHandler);
+				}
+				return;
+			case 'extensions.treestyletab.counter.role.vertical':
+				if (this.isVertical) {
+					let self = this;
+					this.Deferred
+						.next(function() { self.updateAllTabsCount(); })
+						.error(this.defaultDeferredErrorHandler);
+				}
+				return;
+
 			default:
 				return;
 		}
@@ -2213,12 +2327,6 @@ TreeStyleTabBrowser.prototype = {
 		if (aStyle.indexOf('default') == 0) { // old name (for compatibility)
 			this.setTreePref('tabbar.style', aStyle = aStyle.replace('default', 'plain'));
 		}
-		else if (// dropshadow is available only on Firefox 3.5 or later.
-			aStyle.indexOf('mixed') == 0 &&
-			this.Comparator.compare(this.XULAppInfo.version, '3.5') < 0
-			) {
-			this.setTreePref('tabbar.style', aStyle = aStyle.replace('mixed', 'flat'));
-		}
 
 		if (aStyle) {
 			let additionalValues = [];
@@ -2272,82 +2380,6 @@ TreeStyleTabBrowser.prototype = {
 
 		this.setTabbrowserAttribute(this.kTWISTY_STYLE, aStyle);
 	},
- 
-	onWindowStateRestored : function TSTBrowser_onWindowStateRestored() 
-	{
-		if (!this.window.__SS_tabsToRestore)
-			return;
-	},
- 
-	saveTreeStructureWithDelay : function TSTBrowser_saveTreeStructureWithDelay() 
-	{
-		if (this.restoringTree || this.saveTreeStructureWithDelayTimer)
-			return;
-
-		this.saveTreeStructureWithDelayTimer = this.window.setTimeout(function(aSelf) {
-			aSelf.saveTreeStructureWithDelayTimer = null;
-			aSelf.saveTreeStructure();
-		}, this.getPref('browser.sessionstore.interval'), this);
-	},
-	saveTreeStructureWithDelayTimer : null,
-	saveTreeStructure : function TSTBrowser_saveTreeStructure()
-	{
-		if (!this.getTreePref('restoreTreeOnStartup'))
-			return;
-
-		var treeStructures = JSON.parse(this.SessionStore.getWindowValue(this.window, this.kSTRUCTURE) || '{}');
-		var id = this.mTabBrowser.getAttribute('id');
-		var tabs = this.getAllTabsArray(this.mTabBrowser);
-		treeStructures[id] = {
-			tree : this.getTreeStructureFromTabs(tabs),
-			collapsed : tabs.filter(function(aTab) {
-								return this.isCollapsed(aTab);
-							}, this).map(function(aTab) {
-								return aTab._tPos;
-							}),
-			treeCollapsed : tabs.filter(function(aTab) {
-								return this.isSubtreeCollapsed(aTab);
-							}, this).map(function(aTab) {
-								return aTab._tPos;
-							})
-		};
-		this.SessionStore.setWindowValue(this.window, this.kSTRUCTURE, JSON.stringify(treeStructures))
-	},
- 
-	restoreTreeStructure : function TSTBrowser_restoreTreeStructure() 
-	{
-		if (!this.getTreePref('restoreTreeOnStartup'))
-			return;
-
-		this.restoreTreeStructure();
-
-		var treeStructures = JSON.parse(this.SessionStore.getWindowValue(this.window, this.kSTRUCTURE) || '{}');
-		var id = this.mTabBrowser.getAttribute('id');
-		var treeStructure = id in treeStructures ? treeStructures[id] : null ;
-		if (
-			!treeStructure ||
-			!treeStructure.tree ||
-			!treeStructure.tree.length
-			)
-			return;
-
-		this.applyTreeStructureToTabBrowser(this.mTabBrowser, treeStructure.tree);
-
-		this.getAllTabsArray(this.mTabBrowser)
-			.forEach(function(aTab, aIndex) {
-				if (treeStructure.treeCollapsed &&
-					treeStructure.treeCollapsed.indexOf(aIndex) > -1)
-					aTab.setAttribute(this.kSUBTREE_COLLAPSED, true);
-
-				if (treeStructure.collapsed &&
-					treeStructure.collapsed.indexOf(aIndex) > -1)
-					this.collapseExpandTab(aTab, true, true);
-
-				aTab.removeAttribute(this.kID);
-				aTab.removeAttribute(this.kPARENT);
-				aTab.removeAttribute(this.kCHILDREN);
-			}, this);
-	},
   
 /* DOM Event Handling */ 
 	
@@ -2356,10 +2388,10 @@ TreeStyleTabBrowser.prototype = {
 		switch (aEvent.type)
 		{
 			case 'TabOpen':
-				return this.onTabAdded(aEvent);
+				return this.onTabOpen(aEvent);
 
 			case 'TabClose':
-				return this.onTabRemoved(aEvent);
+				return this.onTabClose(aEvent);
 
 			case 'TabMove':
 				return this.onTabMove(aEvent);
@@ -2375,13 +2407,10 @@ TreeStyleTabBrowser.prototype = {
 				return this.onTabRestored(aEvent);
 
 			case 'TabPinned':
-				return this.onPinTab(aEvent.originalTarget);
+				return this.onTabPinned(aEvent.originalTarget);
 
 			case 'TabUnpinned':
-				return this.onUnpinTab(aEvent.originalTarget);
-
-			case 'DOMAttrModified':
-				return this.onDOMAttrModified(aEvent);
+				return this.onTabUnpinned(aEvent.originalTarget);
 
 			case 'select':
 				return this.onTabSelect(aEvent);
@@ -2398,14 +2427,23 @@ TreeStyleTabBrowser.prototype = {
 			case 'mousedown':
 				return this.onMouseDown(aEvent);
 
+			case 'DOMMouseScroll':
+				return this.onDOMMouseScroll(aEvent);
+
 			case 'scroll':
 				return this.onScroll(aEvent);
 
 			case 'popupshowing':
-				return this.onPopupShowing(aEvent)
+				return this.onPopupShowing(aEvent);
+
+			case 'popuphiding':
+				return this.onPopupHiding(aEvent);
 
 			case 'mouseover':
-				this._initDNDObservers();
+				if (!this.tooltipManager)
+					this._initTooltipManager();
+				if (!this._DNDObserversInitialized)
+					this._initDNDObservers();
 				let (tab = aEvent.target) {
 					if (tab.__treestyletab__twistyHoverTimer)
 						this.window.clearTimeout(tab.__treestyletab__twistyHoverTimer);
@@ -2419,7 +2457,11 @@ TreeStyleTabBrowser.prototype = {
 				return;
 
 			case 'dragover':
-				return this._initDNDObservers();
+				if (!this.tooltipManager)
+					this._initTooltipManager();
+				if (!this._DNDObserversInitialized)
+					this._initDNDObservers();
+				return;
 
 			case 'overflow':
 			case 'underflow':
@@ -2429,7 +2471,7 @@ TreeStyleTabBrowser.prototype = {
 				return this.onResize(aEvent);
 
 
-			// toolbar customizing on Firefox 4 or later
+			// toolbar customizing
 			case 'beforecustomization':
 				this.toolbarCustomizing = true;
 				return this.syncDestroyTabbar();
@@ -2444,12 +2486,8 @@ TreeStyleTabBrowser.prototype = {
 			case 'customizationchange':
 				return this.updateCustomizedTabsToolbar();
 
-			case 'tabviewhidden':
-				this.tabViewHiding = true;
-				this._addedCountClearTimer = this.window.setTimeout(function(aSelf) {
-					aSelf.tabViewHiding = false;
-				}, 0, this);
-				return;
+			case 'tabviewframeinitialized':
+				return this.lastTabViewGroup = this.getTabViewGroupId();
 
 
 			case this.kEVENT_TYPE_PRINT_PREVIEW_ENTERED:
@@ -2458,17 +2496,24 @@ TreeStyleTabBrowser.prototype = {
 				return this.onTreeStyleTabPrintPreviewExited(aEvent);
 
 
-			case 'nsDOMMultipleTabHandlerTabsClosing':
-				if (!this.onTabsRemoving(aEvent))
+			case this.kEVENT_TYPE_TAB_FOCUS_SWITCHING_END:
+				return this.cancelDelayedExpandOnTabSelect();
+
+
+			case 'SSWindowStateBusy':
+				return this.needRestoreTree = true;
+
+
+			case 'nsDOMMultipleTabHandlerTabsClosing':
+				if (!this.onTabsClosing(aEvent))
 					aEvent.preventDefault();
 				return;
 		}
 	},
 	lastScrollX : -1,
 	lastScrollY : -1,
-	tabViewHiding : false,
 	
-	restoreLastScrollPosition : function TSTBrowser_restoreLastScrollPosition()
+	restoreLastScrollPosition : function TSTBrowser_restoreLastScrollPosition() 
 	{
 		if (this.lastScrollX < 0 || this.lastScrollY < 0) return;
 		var lastX = this.lastScrollX;
@@ -2483,11 +2528,12 @@ TreeStyleTabBrowser.prototype = {
 				scrollBoxObject.scrollTo(lastX, lastY);
 		}
 	},
-	clearLastScrollPosition : function TSTBrowser_clearLastScrollPosition()
+ 
+	clearLastScrollPosition : function TSTBrowser_clearLastScrollPosition() 
 	{
-		this.lastScrollX = -1;
-		this.lastScrollY = -1;
+		this.lastScrollX = this.lastScrollY = -1;
 	},
+ 
 	updateLastScrollPosition : function TSTBrowser_updateLastScrollPosition() 
 	{
 		if (!this.isVertical) return;
@@ -2498,8 +2544,33 @@ TreeStyleTabBrowser.prototype = {
 		this.lastScrollX = x.value;
 		this.lastScrollY = y.value;
 	},
+ 
+	cancelPerformingAutoScroll : function TSTBrowser_cancelPerformingAutoScroll() 
+	{
+		if (this.smoothScrollTask) {
+			this.animationManager.removeTask(this.smoothScrollTask);
+			this.smoothScrollTask = null;
+		}
+		this.clearLastScrollPosition();
+
+		if (this.cancelingPerformingAutoScroll)
+			this.cancelingPerformingAutoScroll.cancel();
+
+		var self = this;
+		this.cancelingPerformingAutoScroll = this.Deferred.wait(0.3).next(function() {
+			self.cancelingPerformingAutoScroll = null;
+		}).error(this.defaultDeferredErrorHandler);
+	},
+ 
+	shouldCancelEnsureElementIsVisible : function TSTBRowser_shouldCancelEnsureElementIsVisible() 
+	{
+		return (
+			this.cancelingPerformingAutoScroll &&
+			(new Error()).stack.indexOf('onxblDOMMouseScroll') < 0
+		);
+	},
   
-	onTabAdded : function TSTBrowser_onTabAdded(aEvent, aTab) 
+	onTabOpen : function TSTBrowser_onTabOpen(aEvent, aTab) 
 	{
 		var tab = aTab || aEvent.originalTarget;
 		var b   = this.mTabBrowser;
@@ -2578,23 +2649,21 @@ TreeStyleTabBrowser.prototype = {
 
 		if (this.animationEnabled) {
 			this.updateTabCollapsed(tab, true, true);
-			this.updateTabCollapsed(tab, false, this.restoringTree);
-		}
-
-		var prev = this.getPreviousSiblingTab(tab);
-		if (prev) {
-			this.setTabValue(tab, this.kINSERT_AFTER, prev.getAttribute(this.kID));
-			this.setTabValue(prev, this.kINSERT_BEFORE, tab.getAttribute(this.kID));
+			let self = this;
+			this.updateTabCollapsed(tab, false, this.windowService.restoringTree, function() {
+				/**
+				 * When the system is too slow, the animation can start after
+				 * smooth scrolling is finished. The smooth scrolling should be
+				 * started together with the start of the animation effect.
+				 */
+				self.scrollToNewTab(tab);
+			});
 		}
-
-		var next = this.getNextSiblingTab(tab);
-		if (next) {
-			this.setTabValue(tab, this.kINSERT_BEFORE, next.getAttribute(this.kID));
-			this.setTabValue(next, this.kINSERT_AFTER, tab.getAttribute(this.kID));
+		else {
+			this.scrollToNewTab(tab);
 		}
 
-		if (this.scrollToNewTabMode > 0)
-			this.scrollToTab(tab, this.scrollToNewTabMode < 2);
+		this.updateInsertionPositionInfo(tab);
 
 		if (this.getPref('browser.tabs.autoHide'))
 			this.updateFloatingTabbar(this.kTABBAR_UPDATE_BY_SHOWHIDE_TABBAR);
@@ -2609,8 +2678,7 @@ TreeStyleTabBrowser.prototype = {
 			this.updateInvertedTabContentsOrder(tabs);
 
 		/**
-		 * gBrowser.adthis._changeTabbarPosition(position);
-		 dTab() resets gBrowser._lastRelatedTab.owner
+		 * gBrowser.addTab() resets gBrowser._lastRelatedTab.owner
 		 * when a new background tab is opened from the current tab,
 		 * but it will fail with TST because gBrowser.moveTab() (called
 		 * by TST) clears gBrowser._lastRelatedTab.
@@ -2623,8 +2691,29 @@ TreeStyleTabBrowser.prototype = {
 	_addedCountInThisLoop : 0,
 	_addedCountClearTimer : null,
 	_checkRestoringWindowTimerOnTabAdded : null,
+	
+	scrollToNewTab : function TSTBrowser_scrollToNewTab(aTab) 
+	{
+		if (this.scrollToNewTabMode > 0)
+			this.scrollToTab(aTab, this.scrollToNewTabMode < 2);
+	},
  
-	onTabRemoved : function TSTBrowser_onTabRemoved(aEvent) 
+	updateInsertionPositionInfo : function TSTBrowser_updateInsertionPositionInfo(aTab) 
+	{
+		var prev = this.getPreviousSiblingTab(aTab);
+		if (prev) {
+			this.setTabValue(aTab, this.kINSERT_AFTER, prev.getAttribute(this.kID));
+			this.setTabValue(prev, this.kINSERT_BEFORE, aTab.getAttribute(this.kID));
+		}
+
+		var next = this.getNextSiblingTab(aTab);
+		if (next) {
+			this.setTabValue(aTab, this.kINSERT_BEFORE, next.getAttribute(this.kID));
+			this.setTabValue(next, this.kINSERT_AFTER, aTab.getAttribute(this.kID));
+		}
+	},
+  
+	onTabClose : function TSTBrowser_onTabClose(aEvent) 
 	{
 		var tab = aEvent.originalTarget;
 		var d   = this.document;
@@ -2642,8 +2731,10 @@ TreeStyleTabBrowser.prototype = {
 			this.stopRendering();
 
 		var backupAttributes = {};
-		if (this.hasChildTabs(tab))
+		if (this.hasChildTabs(tab)) {
 			backupAttributes[this.kCHILDREN] = this.getTabValue(tab, this.kCHILDREN);
+			backupAttributes[this.kSUBTREE_COLLAPSED] = this.getTabValue(tab, this.kSUBTREE_COLLAPSED);
+		}
 
 		var subtreeCollapsed = this.isSubtreeCollapsed(tab);
 		if (
@@ -2657,9 +2748,11 @@ TreeStyleTabBrowser.prototype = {
 
 				this.markAsClosedSet([tab].concat(tabs));
 
-				tabs.reverse().forEach(function(aTab) {
-					b.removeTab(aTab, { animate : true });
-				}, this);
+				tabs.reverse();
+				for (let i = 0, maxi = tabs.length; i < maxi; i++)
+				{
+					b.removeTab(tabs[i], { animate : true });
+				}
 
 				this.fireTabSubtreeClosedEvent(b, tab, tabs);
 
@@ -2703,7 +2796,7 @@ TreeStyleTabBrowser.prototype = {
 						[children[0]] :
 						children
 				);
-			this.partAllChildren(tab, {
+			this.detachAllChildren(tab, {
 				behavior         : closeParentBehavior,
 				dontUpdateIndent : true
 			});
@@ -2741,7 +2834,7 @@ TreeStyleTabBrowser.prototype = {
 			if (shouldCloseParentTab && nextFocusedTab == parentTab)
 				nextFocusedTab = this.getNextFocusedTab(parentTab);
 
-			this.partTab(tab, { dontUpdateIndent : true });
+			this.detachTab(tab, { dontUpdateIndent : true });
 
 			if (shouldCloseParentTab) {
 				this.Deferred.next(function() {
@@ -2749,7 +2842,7 @@ TreeStyleTabBrowser.prototype = {
 						b.removeTab(parentTab, { animate : true });
 					parentTab = null;
 					b = null;
-				});
+				}).error(this.defaultDeferredErrorHandler);
 			}
 		}
 		else if (!nextFocusedTab) {
@@ -2804,16 +2897,15 @@ TreeStyleTabBrowser.prototype = {
 		if (collapsed)
 			this.startRendering();
 	},
-	_reserveCloseNeedlessGroupTabSibling : function TSTBrowser_reserveCloseNeedlessGroupTabSibling(aTab)
+	
+	_reserveCloseNeedlessGroupTabSibling : function TSTBrowser_reserveCloseNeedlessGroupTabSibling(aTab) 
 	{
 		if (!aTab)
 			return null;
 
 		var parent = this.getParentTab(aTab);
 		var siblings = this.getSiblingTabs(aTab);
-		var groupTabs = siblings.filter(function(aTab) {
-				return this.isGroupTab(aTab);
-			}, this);
+		var groupTabs = siblings.filter(this.isGroupTab, this);
 		var groupTab = (
 				groupTabs.length == 1 &&
 				siblings.length == 1 &&
@@ -2829,13 +2921,8 @@ TreeStyleTabBrowser.prototype = {
 
 		return null;
 	},
-	getNextFocusedTab : function TSTBrowser_getNextFocusedTab(aTab)
-	{
-		return this.getNextSiblingTab(aTab) ||
-				this.getPreviousVisibleTab(aTab);
-	},
- 
-	onTabsRemoving : function TSTBrowser_onTabsRemoving(aEvent) 
+  
+	onTabsClosing : function TSTBrowser_onTabsClosing(aEvent) 
 	{
 		var tabs = aEvent.tabs || aEvent.getData('tabs');
 		var b = this.getTabBrowserFromChild(tabs[0]);
@@ -2847,16 +2934,16 @@ TreeStyleTabBrowser.prototype = {
 			}, this))
 			return false;
 
-		trees.forEach(function(aTabs) {
-			this.markAsClosedSet(aTabs);
-		}, this);
+		trees.forEach(this.markAsClosedSet, this);
 
 		var self = this;
 		this.Deferred.next(function() {
-			trees.forEach(function(aTabs) {
-				self.fireTabSubtreeClosedEvent(b, aTabs[0], aTabs);
-			});
-		});
+			for (let i = 0, maxi = trees.length; i < maxi; i++)
+			{
+				let tabs = trees[i];
+				self.fireTabSubtreeClosedEvent(b, tabs[0], tabs);
+			}
+		}).error(this.defaultDeferredErrorHandler);
 
 		return true;
 	},
@@ -2868,7 +2955,7 @@ TreeStyleTabBrowser.prototype = {
 		tab.__treestyletab__previousPosition = aEvent.detail;
 
 		// When the tab was moved before TabOpen event is fired, we have to update manually.
-		var newlyOpened = !this.isTabInitialized(tab) && this.onTabAdded(null, tab);
+		var newlyOpened = !this.isTabInitialized(tab) && this.onTabOpen(null, tab);
 
 		// twisty vanished after the tab is moved!!
 		this.initTabContents(tab);
@@ -2968,11 +3055,9 @@ TreeStyleTabBrowser.prototype = {
 			nextTab = this.getNextTab(tabs[tabs.length-1]);
 		}
 
-
 		var prevParent = this.getParentTab(prevTab);
 		var nextParent = this.getParentTab(nextTab);
 
-
 		var prevLevel  = prevTab ? Number(prevTab.getAttribute(this.kNEST)) : -1 ;
 		var nextLevel  = nextTab ? Number(nextTab.getAttribute(this.kNEST)) : -1 ;
 
@@ -3006,7 +3091,7 @@ TreeStyleTabBrowser.prototype = {
 					this.attachTabTo(aTab, newParent, { insertBefore : nextTab });
 			}
 			else {
-				this.partTab(aTab);
+				this.detachTab(aTab);
 			}
 		}
 	},
@@ -3042,28 +3127,86 @@ TreeStyleTabBrowser.prototype = {
 	// for TabView (Panorama aka Tab Candy)
 	onTabVisibilityChanged : function TSTBrowser_onTabVisibilityChanged(aEvent) 
 	{
+		/**
+		 * Note: On this timing, we cannot know that which is the reason of this
+		 * event, by exitting from Panorama or the "Move to Group" command in the
+		 * context menu on tabs. So, we have to do operations with a delay to compare
+		 * last and current group which is updated in the next event loop.
+		 */
+
 		var tab = aEvent.originalTarget;
-		if (this.tabViewHiding) {
-			this.updateInvertedTabContentsOrder(aEvent.originalTarget);
+		this.updateInvertedTabContentsOrder(tab);
+		this.tabVisibilityChangedTabs.push({
+			tab  : tab,
+			type : aEvent.type
+		});
+
+		if (this.tabVisibilityChangedTimer) {
+			this.window.clearTimeout(this.tabVisibilityChangedTimer);
+			this.tabVisibilityChangedTimer = null;
+		}
+
+		this.tabVisibilityChangedTimer = this.window.setTimeout(function(aSelf) {
+			aSelf.tabVisibilityChangedTimer = null;
+
+			var tabs = aSelf.tabVisibilityChangedTabs;
+			if (!tabs.length)
+				return;
 
-			if (this.tabVisibilityChangedTimer) {
-				this.window.clearTimeout(this.tabVisibilityChangedTimer);
-				this.tabVisibilityChangedTimer = null;
+			// restore tree from bottom safely
+			var restoreTabs = tabs.filter(function(aChanged) {
+					return aChanged.type == 'TabShow' &&
+							aChanged.tab.__treestyletab__restoreState == aSelf.RESTORE_STATE_READY_TO_RESTORE;
+				})
+				.map(function(aChanged) {
+					return aChanged.tab;
+				})
+				.sort(function(aA, aB) {
+					return aB._tPos - aA._tPos;
+				})
+				.filter(aSelf.restoreOneTab, aSelf);
+			for (let i = 0, maxi = restoreTabs.length; i < maxi; i++)
+			{
+				let tab = restoreTabs[i];
+				aSelf.updateInsertionPositionInfo(tab);
+				delete tab.__treestyletab__restoreState;
 			}
-			this.tabVisibilityChangedTabs.push(tab);
-			this.tabVisibilityChangedTimer = this.window.setTimeout(function(aSelf) {
-				aSelf.tabVisibilityChangedTimer = null;
-				var tabs = aSelf.tabVisibilityChangedTabs;
+
+			var currentGroupId = aSelf.getTabViewGroupId();
+			if (aSelf.lastTabViewGroup && currentGroupId != aSelf.lastTabViewGroup) {
+				// We should clear it first, because updateTreeByTabVisibility() never change visibility of tabs.
 				aSelf.tabVisibilityChangedTabs = [];
-				aSelf.updateTreeByTabVisibility(tabs);
-			}, 0, this);
-		}
-		else if (aEvent.type == 'TabHide') {
-			this.subtreeFollowParentAcrossTabGroups(tab);
-		}
+				aSelf.updateTreeByTabVisibility(tabs.map(function(aChanged) { return aChanged.tab; }));
+			}
+			else {
+				// For tabs moved by "Move to Group" command in the context menu on tabs
+				var processedTabs = {};
+				/**
+				 * subtreeFollowParentAcrossTabGroups() can change visibility of child tabs, so,
+				 * we must not clear tabVisibilityChangedTabs here, and we have to use
+				 * simple "for" loop instead of Array.prototype.forEach.
+				 */
+				for (let i = 0; i < aSelf.tabVisibilityChangedTabs.length; i++)
+				{
+					let changed = aSelf.tabVisibilityChangedTabs[i];
+					let tab = changed.tab;
+					if (aSelf.getAncestorTabs(tab).some(function(aTab) {
+							return processedTabs[aTab.getAttribute(aSelf.kID)];
+						}))
+						continue;
+					aSelf.subtreeFollowParentAcrossTabGroups(tab);
+					processedTabs[tab.getAttribute(aSelf.kID)] = true;
+				}
+				// now we can clear it!
+				aSelf.tabVisibilityChangedTabs = [];
+			}
+			aSelf.lastTabViewGroup = currentGroupId;
+		}, 0, this);
 	},
 	tabVisibilityChangedTimer : null,
-	updateTreeByTabVisibility : function TSTBrowser_updateTreeByTabVisibility(aChangedTabs)
+	lastTabViewGroup : null,
+	
+	updateTreeByTabVisibility : function TSTBrowser_updateTreeByTabVisibility(aChangedTabs) 
 	{
 		this.internallyTabMovingCount++;
 
@@ -3083,8 +3226,9 @@ TreeStyleTabBrowser.prototype = {
 		var lastIndex = allTabs.length - 1;
 		var lastMovedTab;
 		normalTabs = normalTabs.slice(0).reverse();
-		for each (let tab in normalTabs)
+		for (let i = 0, maxi = normalTabs.length; i < maxi; i++)
 		{
+			let tab = normalTabs[i];
 			let parent = this.getParentTab(tab);
 			let attached = false;
 			if (parent && (tab.hidden != parent.hidden)) {
@@ -3104,7 +3248,7 @@ TreeStyleTabBrowser.prototype = {
 				}
 				if (!attached) {
 					this.collapseExpandTab(tab, false, true);
-					this.partTab(tab);
+					this.detachTab(tab);
 				}
 			}
 
@@ -3134,36 +3278,54 @@ TreeStyleTabBrowser.prototype = {
 		}
 		this.internallyTabMovingCount--;
 	},
-	tabViewTreeIsMoving : false,
-	subtreeFollowParentAcrossTabGroups : function TSTBrowser_subtreeFollowParentAcrossTabGroups(aParent)
+ 
+	subtreeFollowParentAcrossTabGroups : function TSTBrowser_subtreeFollowParentAcrossTabGroups(aParent) 
 	{
 		if (this.tabViewTreeIsMoving) return;
-		let item = aParent._tabViewTabItem;
-		if (!item) return;
-		let group = item.parent;
-		if (!group) return;
+
+		var id = this.getTabViewGroupId(aParent);
+		if (!id) return;
 
 		this.tabViewTreeIsMoving = true;
 		this.internallyTabMovingCount++;
-		let w = this.window;
-		let b = this.mTabBrowser;
-		let lastCount = this.getAllTabs(b).snapshotLength - 1;
-		w.setTimeout(function(aSelf) {
-			aSelf.partTab(aParent);
-			b.moveTabTo(aParent, lastCount);
-			let descendantTabs = aSelf.getDescendantTabs(aParent);
-			descendantTabs.forEach(function(aTab) {
-				w.TabView.moveTabTo(aTab, group.id);
-				b.moveTabTo(aTab, lastCount);
-			});
-			aSelf.internallyTabMovingCount--;
-			aSelf.tabViewTreeIsMoving = false;
-		}, 0, this);
+		var w = this.window;
+		var b = this.mTabBrowser;
+		var lastCount = this.getAllTabs(b).snapshotLength - 1;
+
+		this.detachTab(aParent);
+		b.moveTabTo(aParent, lastCount);
+		var descendantTabs = this.getDescendantTabs(aParent);
+		for (let i = 0, maxi = descendantTabs.length; i < maxi; i++)
+		{
+			let tab = descendantTabs[i];
+			w.TabView.moveTabTo(tab, id);
+			b.moveTabTo(tab, lastCount);
+		}
+		this.internallyTabMovingCount--;
+		this.tabViewTreeIsMoving = false;
 	},
+	tabViewTreeIsMoving : false,
  
+	getTabViewGroupId : function TSTBrowser_getTabViewGroupId(aTab) 
+	{
+		var tab = aTab || this.mTabBrowser.selectedTab;
+		var item = tab._tabViewTabItem;
+		if (!item) return null;
+
+		var group = item.parent;
+		if (!group) return null;
+
+		return group.id;
+	},
+  
 	onTabRestoring : function TSTBrowser_onTabRestoring(aEvent) 
 	{
-		this.restoreStructure(aEvent.originalTarget);
+		this.restoreTree();
+
+		var tab = aEvent.originalTarget;
+
+		tab.linkedBrowser.__treestyletab__toBeRestored = false;
+		this.handleRestoredTab(tab);
 
 		/**
 		 * Updating of the counter which is used to know how many tabs were
@@ -3187,10 +3349,10 @@ TreeStyleTabBrowser.prototype = {
 				 * Now we can decrement the counter.
 				 */
 				self.windowService.restoringCount--;
-			});
+			}).error(self.defaultDeferredErrorHandler);
 		}, 0);
 
-		if (!aEvent.originalTarget.selected &&
+		if (!tab.selected &&
 			this.mTabBrowser.currentURI.spec == 'about:sessionrestore') {
 			let frame = this.mTabBrowser.contentWindow;
 			frame = frame.wrappedJSObject || frame;
@@ -3201,7 +3363,7 @@ TreeStyleTabBrowser.prototype = {
 				this.window.setTimeout(function(aSelf, aTab, aTitle, aParent) {
 					if (aTab.label== aTitle)
 						aSelf.attachTabTo(aTab, aParent);
-				}, 0, this, aEvent.originalTarget, item.label, this.mTabBrowser.selectedTab);
+				}, 0, this, tab, item.label, this.mTabBrowser.selectedTab);
 			}
 		}
 	},
@@ -3209,45 +3371,81 @@ TreeStyleTabBrowser.prototype = {
 	RESTORED_TREE_COLLAPSED_STATE_LAST_STATE : -1,
 	RESTORED_TREE_COLLAPSED_STATE_COLLAPSED  : 0,
 	RESTORED_TREE_COLLAPSED_STATE_EXPANDED   : 1,
-	restoreStructure : function TSTBrowser_restoreStructure(aTab) 
-	{
-		var [id, mayBeDuplicated] = this._restoreTabId(aTab);
+	RESTORE_STATE_INITIAL             : 0,
+	RESTORE_STATE_READY_TO_RESTORE    : 1,
+	RESTORE_STATE_STRUCTURE_RESTORED  : 2,
+	handleRestoredTab : function TSTBrowser_handleRestoredTab(aTab) 
+	{
+		if (aTab.__treestyletab__restoreState == this.RESTORE_STATE_READY_TO_RESTORE) {
+			// this is a hidden tab in the background group, and
+			// have to be restored by restoreOneTab() on "TabShown" event.
+			this.deleteTabValue(aTab, this.kCLOSED_SET_ID);
+			return;
+		}
 
+		var [id, mayBeDuplicated] = this._restoreTabId(aTab);
+		var structureRestored = aTab.__treestyletab__restoreState == this.RESTORE_STATE_STRUCTURE_RESTORED;
 		var children = this.getTabValue(aTab, this.kCHILDREN);
-		if (!mayBeDuplicated || aTab.hasAttribute(this.kCHILDREN)) {
-			// for safety
-			this.partAllChildren(aTab, {
+		if (
+			!structureRestored &&
+			(
+				!mayBeDuplicated ||
+				aTab.getAttribute(this.kCHILDREN) != children
+			)
+			) {
+			// failsafe
+			this.detachAllChildren(aTab, {
 				dontUpdateIndent : true,
 				dontAnimate      : this.windowService.restoringTree
 			});
 		}
 
-		var closeSetId = this._restoreCloseSetId(aTab, mayBeDuplicated);
+		var closeSetId = !structureRestored && this._getCloseSetId(aTab, mayBeDuplicated);
+
+		var currentId = aTab.getAttribute(this.kID);
+		if (id != currentId && currentId)
+			delete this.tabsHash[currentId];
 
 		this.setTabValue(aTab, this.kID, id);
 		this.tabsHash[id] = aTab;
 
-		if (closeSetId)
-			this.restoreClosedSet(closeSetId, aTab);
+		if (structureRestored) {
+			this._fixMissingAttributesFromSessionData(aTab);
+		}
+		else {
 
-		var isSubtreeCollapsed = this._restoreSubtreeCollapsedState(aTab);
+			let isSubtreeCollapsed = this._restoreSubtreeCollapsedState(aTab);
 
-		var childTabs = this._restoreChildTabsRelation(aTab, children, mayBeDuplicated);
+			let restoringMultipleTabs = this.windowService.restoringTree;
+			let options = {
+					dontExpand       : restoringMultipleTabs,
+					dontUpdateIndent : true,
+					dontAnimate      : restoringMultipleTabs
+				};
+			let childTabs = this._restoreChildTabsRelation(aTab, children, mayBeDuplicated, options);
 
-		this._restoreTabPositionAndIndent(aTab, childTabs, mayBeDuplicated);
+			this._restoreTabPositionAndIndent(aTab, childTabs, mayBeDuplicated);
 
-		if (isSubtreeCollapsed)
-			this.collapseExpandSubtree(aTab, isSubtreeCollapsed);
+			if (closeSetId)
+				this.restoreClosedSet(closeSetId, aTab);
+
+			if (isSubtreeCollapsed)
+				this.collapseExpandSubtree(aTab, isSubtreeCollapsed);
+		}
 
 		if (mayBeDuplicated)
 			this.clearRedirectionTable();
+
+		delete aTab.__treestyletab__restoreState;
 	},
-	_restoreTabId : function TSTBrowser_restoreTabId(aTab)
+	
+	_restoreTabId : function TSTBrowser_restoreTabId(aTab) 
 	{
-		var id = this.getTabValue(aTab, this.kID);
+		var currentId  = aTab.getAttribute(this.kID);
+		var restoredId = this.getTabValue(aTab, this.kID);
 		var mayBeDuplicated = false;
 
-		aTab.setAttribute(this.kID_RESTORING, id);
+		aTab.setAttribute(this.kID_RESTORING, restoredId);
 		if (this.isTabDuplicated(aTab)) {
 			mayBeDuplicated = true;
 			/**
@@ -3255,13 +3453,14 @@ TreeStyleTabBrowser.prototype = {
 			 * instead of redirected ID, because the tab has been possibly
 			 * attached to another tab.
 			 */
-			id = aTab.getAttribute(this.kID) || this.redirectId(id);
+			restoredId = currentId || this.redirectId(restoredId);
 		}
 		aTab.removeAttribute(this.kID_RESTORING);
 
-		return [id, mayBeDuplicated];
+		return [restoredId || currentId, mayBeDuplicated];
 	},
-	_restoreCloseSetId : function TSTBrowser_restoreCloseSetId(aTab, aMayBeDuplicated)
+ 
+	_getCloseSetId : function TSTBrowser_getCloseSetId(aTab, aMayBeDuplicated) 
 	{
 		var closeSetId = null;
 		if (!aMayBeDuplicated) {
@@ -3271,7 +3470,7 @@ TreeStyleTabBrowser.prototype = {
 			 * it is wrongly attacched by tab moving on restoring.
 			 * Restoring the old ID (the next statement) breaks the children
 			 * list of the temporary parent and causes many problems.
-			 * So, to prevent these problems, I part the tab from the temporary
+			 * So, to prevent these problems, I detach the tab from the temporary
 			 * parent manually.
 			 * If the ID stored in the session equals to the value of the
 			 * attribute stored in the element itself, then don't reset the
@@ -3284,21 +3483,67 @@ TreeStyleTabBrowser.prototype = {
 		this.deleteTabValue(aTab, this.kCLOSED_SET_ID);
 		return closeSetId;
 	},
-	_restoreSubtreeCollapsedState : function TSTBrowser_restoreSubtreeCollapsedState(aTab)
+ 
+	_fixMissingAttributesFromSessionData : function TSTBrowser_fixMissingAttributesFromSessionData(aTab) 
+	{
+		/**
+		 * By some reasons (ex. persistTabAttribute()), actual state of
+		 * the tab (attributes) can be lost on SSTabRestoring.
+		 * For failsafe, we must override actual attributes by stored
+		 * values.
+		 */
+		var keys = [
+				this.kINSERT_BEFORE,
+				this.kINSERT_AFTER
+			];
+		for (let i = 0, maxi = keys.length; i < maxi; i++)
+		{
+			let key = keys[i];
+			let tab = this.getTabValue(aTab, key);
+			if (this.getTabById(tab))
+				this.setTabValue(aTab, key, tab);
+		}
+
+		let parentId = this.getTabValue(aTab, this.kPARENT);
+		let parentTab = this.getTabById(parentId);
+		if (parentTab && parentTab._tPos < aTab._tPos)
+			this.setTabValue(aTab, this.kPARENT, parentId);
+		else
+			this.deleteTabValue(aTab, this.kPARENT);
+
+		let ancestors = [aTab].concat(this.getAncestorTabs(aTab));
+		let children = this.getTabValue(aTab, this.kCHILDREN);
+		children = children.split('|').filter(function(aChild) {
+			let tab = this.getTabById(aChild);
+			return tab && ancestors.indexOf(tab) < 0;
+		}, this);
+		this.setTabValue(aTab, this.kCHILDREN, children.join('|'));
+
+		let subtreeCollapsed = this.getTabValue(aTab, this.kSUBTREE_COLLAPSED);
+		if (subtreeCollapsed != aTab.getAttribute(this.kSUBTREE_COLLAPSED))
+			this.collapseExpandSubtree(aTab, subtreeCollapsed == 'true', true);
+	},
+ 
+	_restoreSubtreeCollapsedState : function TSTBrowser_restoreSubtreeCollapsedState(aTab, aCollapsed) 
 	{
 		var shouldCollapse = this.getTreePref('collapseExpandSubtree.sessionRestore');
+
+		if (aCollapsed === void(0))
+			aCollapsed = this.getTabValue(aTab, this.kSUBTREE_COLLAPSED) == 'true';
+
 		var isSubtreeCollapsed = (
 				this.windowService.restoringTree &&
 				(
 					shouldCollapse == this.RESTORED_TREE_COLLAPSED_STATE_LAST_STATE ?
-						(this.getTabValue(aTab, this.kSUBTREE_COLLAPSED) == 'true') :
+						aCollapsed :
 						shouldCollapse == this.RESTORED_TREE_COLLAPSED_STATE_COLLAPSED
 				)
 			);
 		this.setTabValue(aTab, this.kSUBTREE_COLLAPSED, isSubtreeCollapsed);
 		return isSubtreeCollapsed;
 	},
-	_restoreChildTabsRelation : function TSTBrowser_restoreChildTabsRelation(aTab, aChildrenList, aMayBeDuplicated)
+ 
+	_restoreChildTabsRelation : function TSTBrowser_restoreChildTabsRelation(aTab, aChildrenList, aMayBeDuplicated, aOptions) 
 	{
 		var childTabs = [];
 		if (!aChildrenList)
@@ -3312,17 +3557,17 @@ TreeStyleTabBrowser.prototype = {
 				return this.redirectId(aChild);
 			}, this);
 
-		var restoringMultipleTabs = this.windowService.restoringTree;
-		aChildrenList.forEach(function(aChildTab) {
-			if (aChildTab && (aChildTab = this.getTabById(aChildTab))) {
-				this.attachTabTo(aChildTab, aTab, {
-					dontExpand       : restoringMultipleTabs,
-					dontUpdateIndent : true,
-					dontAnimate      : restoringMultipleTabs
-				});
-				childTabs.push(aChildTab);
+		for (let i = 0, maxi = aChildrenList.length; i < maxi; i++)
+		{
+			let childTab = aChildrenList[i];
+			if (childTab && (childTab = this.getTabById(childTab))) {
+				let options = aOptions;
+				if (options && typeof options == 'function')
+					options = options(childTab);
+				this.attachTabTo(childTab, aTab, options);
+				childTabs.push(childTab);
 			}
-		}, this);
+		}
 		aChildrenList = aChildrenList.join('|');
 		if (aTab.getAttribute(this.kCHILDREN) == aChildrenList)
 			aTab.removeAttribute(this.kCHILDREN_RESTORING);
@@ -3331,7 +3576,8 @@ TreeStyleTabBrowser.prototype = {
 
 		return childTabs;
 	},
-	_restoreTabPositionAndIndent : function TSTBrowser_restoreTabPositionAndIndent(aTab, aChildTabs, aMayBeDuplicated)
+ 
+	_restoreTabPositionAndIndent : function TSTBrowser_restoreTabPositionAndIndent(aTab, aChildTabs, aMayBeDuplicated) 
 	{
 		var restoringMultipleTabs = this.windowService.restoringTree;
 		var position = this._prepareInsertionPosition(aTab, aMayBeDuplicated);
@@ -3364,7 +3610,8 @@ TreeStyleTabBrowser.prototype = {
 			this._restoreTabPosition(aTab, position.next);
 		}
 	},
-	_prepareInsertionPosition : function TSTBrowser_prepareInsertionPosition(aTab, aMayBeDuplicated)
+	
+	_prepareInsertionPosition : function TSTBrowser_prepareInsertionPosition(aTab, aMayBeDuplicated) 
 	{
 		var next = this.getTabValue(aTab, this.kINSERT_BEFORE);
 		if (next && aMayBeDuplicated) next = this.redirectId(next);
@@ -3407,7 +3654,8 @@ TreeStyleTabBrowser.prototype = {
 			next   : next
 		};
 	},
-	_restoreTabPosition : function TSTBrowser_restoreTabPosition(aTab, aNextTab)
+  
+	_restoreTabPosition : function TSTBrowser_restoreTabPosition(aTab, aNextTab) 
 	{
 		if (!aNextTab) aNextTab = this.getNextTab(aTab);
 		var parentOfNext = this.getParentTab(aNextTab);
@@ -3423,7 +3671,7 @@ TreeStyleTabBrowser.prototype = {
 		if (newPos > -1)
 			this.mTabBrowser.moveTabTo(aTab, newPos);
 	},
- 
+  
 	correctChildTabsOrderWithDelay : function TSTBrowser_correctChildTabsOrderWithDelay(aTab) 
 	{
 		if (aTab.correctChildTabsOrderWithDelayTimer)
@@ -3441,24 +3689,25 @@ TreeStyleTabBrowser.prototype = {
 
 		var children = aTab.getAttribute(this.kCHILDREN);
 		if (restoringChildren != children) {
-			var restoringChildrenIDs = restoringChildren.split('|');
-			restoringChildrenIDs.reverse().forEach(function(aChild, aIndex) {
-				aChild = this.getTabById(aChild);
-				if (!aChild) return;
+			var restoringChildrenIDs = restoringChildren.split('|').reverse();
+			for (let i = 0, maxi = restoringChildrenIDs.length; i < maxi; i++)
+			{
+				let child = this.getTabById(restoringChildrenIDs[i]);
+				if (!child) continue;
 
-				let nextTab = aIndex > 0 ?
-							this.getTabById(restoringChildrenIDs[aIndex-1]) :
+				let nextTab = i > 0 ?
+							this.getTabById(restoringChildrenIDs[i-1]) :
 							this.getNextSiblingTab(aTab) ;
-				if (nextTab == this.getNextSiblingTab(aChild)) return;
+				if (nextTab == this.getNextSiblingTab(child)) continue;
 
 				let newPos = -1;
 				if (nextTab) {
 					newPos = nextTab._tPos;
-					if (newPos > aChild._tPos) newPos--;
+					if (newPos > child._tPos) newPos--;
 				}
 				if (newPos > -1)
-					this.moveTabSubtreeTo(aChild, newPos);
-			}, this);
+					this.moveTabSubtreeTo(child, newPos);
+			}
 			children = aTab.getAttribute(this.kCHILDREN);
 		}
 
@@ -3494,20 +3743,22 @@ TreeStyleTabBrowser.prototype = {
 		if (
 			aRestoredTab.__treestyletab__restoredByUndoCloseTab ||
 			!this.browser.__treestyletab__readyToUndoCloseTab ||
-			this.windowService.useTMPSessionAPI ||
+			this.useTMPSessionAPI ||
 			this._restoringClosedSet ||
 			!(behavior & this.kUNDO_CLOSE_SET || behavior & this.kUNDO_ASK)
 			)
 			return;
 
-		var items = this.evalInSandbox('('+this.SessionStore.getClosedTabData(this.window)+')');
 		var indexes = [];
-		items.forEach(function(aItem, aIndex) {
-			if (aItem.state.extData &&
-				aItem.state.extData[this.kCLOSED_SET_ID] &&
-				aItem.state.extData[this.kCLOSED_SET_ID] == aId)
-				indexes.push(aIndex);
-		}, this);
+		var items = this.evalInSandbox('('+this.SessionStore.getClosedTabData(this.window)+')');
+		for (let i = 0, maxi = items.length; i < maxi; i++)
+		{
+			let item = items[i];
+			if (item.state.extData &&
+				item.state.extData[this.kCLOSED_SET_ID] &&
+				item.state.extData[this.kCLOSED_SET_ID] == aId)
+				indexes.push(i);
+		}
 
 		var count = parseInt(aId.split('::')[1]);
 
@@ -3522,7 +3773,7 @@ TreeStyleTabBrowser.prototype = {
 
 		if (behavior & this.kUNDO_ASK) {
 			let self = this;
-			aRestoredTab.addEventListener('SSTabRestored', function(aEvent) {
+			aRestoredTab.addEventListener('SSTabRestoring', function(aEvent) {
 				aRestoredTab.removeEventListener(aEvent.type, arguments.callee, false);
 				self.askUndoCloseTabSetBehavior(aRestoredTab, indexes.length)
 					.next(function(aBehavior) {
@@ -3535,7 +3786,8 @@ TreeStyleTabBrowser.prototype = {
 			this.doRestoreClosedSet(aRestoredTab, indexes);
 		}
 	},
-	doRestoreClosedSet : function TSTBrowser_doRestoreClosedSet(aRestoredTab, aIndexes)
+	
+	doRestoreClosedSet : function TSTBrowser_doRestoreClosedSet(aRestoredTab, aIndexes) 
 	{
 		if (!this.window.PlacesUIUtils._confirmOpenInTabs(aIndexes.length))
 			return;
@@ -3546,11 +3798,13 @@ TreeStyleTabBrowser.prototype = {
 		this.windowService.restoringTree = true;
 
 		var offset = 0;
-		aIndexes.forEach(function(aIndex) {
-			undoCloseTab(aIndex - (offset++));
-		});
+		for (let i = 0, maxi = aIndexes.length; i < maxi; i++)
+		{
+			this.window.undoCloseTab(aIndexes[i] - (offset++));
+		}
 
 		this.window.setTimeout(function(aSelf, aNextFocused) {
+			aSelf.windowService.restoringTree = false;
 			aSelf.mTabBrowser.selectedTab = aNextFocused;
 		}, 0, this, aRestoredTab || aSelf.mTabBrowser.selectedTab);
 
@@ -3558,13 +3812,13 @@ TreeStyleTabBrowser.prototype = {
 		this._restoringClosedSet = false;
 	},
 	_restoringClosedSet : false,
-  
+   
 	onTabRestored : function TSTBrowser_onTabRestored(aEvent) 
 	{
 		delete aEvent.originalTarget.__treestyletab__restoredByUndoCloseTab;
 	},
  
-	onPinTab : function TSTBrowser_onPinTab(aTab) 
+	onTabPinned : function TSTBrowser_onTabPinned(aTab) 
 	{
 		var parentTab = this.getParentTab(aTab);
 
@@ -3581,10 +3835,13 @@ TreeStyleTabBrowser.prototype = {
 			 */
 			let b = this.browser;
 			this.internallyTabMovingCount++;
-			this.getDescendantTabs(aTab).reverse().forEach(function(aChildTab) {
-				if (aChildTab.__treestyletab__previousPosition > aChildTab._tPos)
-					b.moveTabTo(aChildTab, aChildTab.__treestyletab__previousPosition);
-			}, this);
+			let children = this.getDescendantTabs(aTab).reverse();
+			for (let i = 0, maxi = children.length; i < maxi; i++)
+			{
+				let childTab = children[i];
+				if (childTab.__treestyletab__previousPosition > childTab._tPos)
+					b.moveTabTo(childTab, childTab.__treestyletab__previousPosition);
+			}
 			this.internallyTabMovingCount--;
 		}
 		else {
@@ -3595,26 +3852,29 @@ TreeStyleTabBrowser.prototype = {
 			 */
 			let b = this.browser;
 			this.internallyTabMovingCount++;
-			this.getChildTabs(aTab).reverse().forEach(function(aChildTab) {
-				if (aChildTab._tPos < parentTab._tPos)
-					b.moveTabTo(aChildTab, parentTab._tPos);
-			}, this);
+			let children = this.getChildTabs(aTab).reverse();
+			for (let i = 0, maxi = children.length; i < maxi; i++)
+			{
+				let childTab = children[i];
+				if (childTab._tPos < parentTab._tPos)
+					b.moveTabTo(childTab, parentTab._tPos);
+			}
 			this.internallyTabMovingCount--;
 		}
 
-		this.partAllChildren(aTab, {
+		this.detachAllChildren(aTab, {
 			behavior : this.getCloseParentBehaviorForTab(
 				aTab,
 				this.kCLOSE_PARENT_BEHAVIOR_PROMOTE_FIRST_CHILD
 			)
 		});
-		this.partTab(aTab);
+		this.detachTab(aTab);
 
 		this.collapseExpandTab(aTab, false);
 		if (this.isVertical) this.positionPinnedTabsWithDelay();
 	},
  
-	onUnpinTab : function TSTBrowser_onUnpinTab(aTab) 
+	onTabUnpinned : function TSTBrowser_onTabUnpinned(aTab) 
 	{
 		var style = aTab.style;
 		style.marginLeft = style.marginRight = style.marginTop = '';
@@ -3623,32 +3883,13 @@ TreeStyleTabBrowser.prototype = {
 		if (this.isVertical) this.positionPinnedTabsWithDelay();
 	},
  
-	onDOMAttrModified : function TSTBrowser_onDOMAttrModified(aEvent) 
-	{
-		switch (aEvent.attrName)
-		{
-			case 'pinned':
-				let (tab = aEvent.originalTarget) {
-					if (tab.localName != 'tab')
-						return;
-
-					if (aEvent.newValue == 'true')
-						this.onPinTab(tab);
-					else
-						this.onUnpinTab(tab);
-				}
-				return;
-
-			default:
-				return;
-		}
-	},
- 
 	onTabSelect : function TSTBrowser_onTabSelect(aEvent) 
 	{
 		var b   = this.mTabBrowser;
 		var tab = b.selectedTab
 
+		this.cancelDelayedExpandOnTabSelect();
+
 		if (
 			/**
 			 * <tabbrowser>.previewTab() focuses to the tab internally,
@@ -3664,6 +3905,11 @@ TreeStyleTabBrowser.prototype = {
 			)
 			return;
 
+		var shouldCollapseExpandNow = this.getTreePref('autoCollapseExpandSubtreeOnSelect');
+		var newActiveTabOptions = {
+				canCollapseTree : shouldCollapseExpandNow,
+				canExpandTree   : shouldCollapseExpandNow
+			};
 		if (this.isCollapsed(tab)) {
 			if (this.getTreePref('autoExpandSubtreeOnCollapsedChildFocused')) {
 				let parentTab = tab;
@@ -3671,31 +3917,60 @@ TreeStyleTabBrowser.prototype = {
 				{
 					this.collapseExpandSubtree(parentTab, false);
 				}
-				this.collapseExpandTreesIntelligentlyWithDelayFor(tab);
+				this.handleNewActiveTab(tab, newActiveTabOptions);
 			}
 			else {
 				b.selectedTab = this.getRootTab(tab);
 			}
 		}
 		else if (
-				this.getTreePref('autoCollapseExpandSubtreeOnSelect') &&
 				(
-					!this._focusChangedByCurrentTabRemove ||
-					this.getTreePref('autoCollapseExpandSubtreeOnSelect.onCurrentTabRemove')
+					/**
+					 * Focus movings by arrow keys should not be handled on TabSelect,
+					 * because they are already handled by handleAdvanceSelectedTab().
+					 */
+					this.windowService.arrowKeyEventOnTab &&
+					this.windowService.arrowKeyEventOnTab.advanceFocus
+				) ||
+				(
+					/**
+					 * Focus movings by closing of the old current tab should be handled
+					 * only when it is activated by user preference expressly.
+					 */
+					this._focusChangedByCurrentTabRemove &&
+					!this.getTreePref('autoCollapseExpandSubtreeOnSelect.onCurrentTabRemove')
 				)
-				) {
-			if (!this.hasChildTabs(tab) || !this.isSubtreeCollapsed(tab))
-				tab = null;
-
+			) {
+			// do nothing!
+		}
+		else if (this.hasChildTabs(tab) && this.isSubtreeCollapsed(tab)) {
 			if (
 				this._focusChangedByShortcut &&
-				this.accelKeyPressed &&
-				!this.getTreePref('autoCollapseExpandSubtreeOnSelect.whileFocusMovingByShortcut')
+				this.windowService.accelKeyPressed
 				) {
-				this.windowService.expandTreeAfterKeyReleased(tab);
+				if (this.getTreePref('autoExpandSubtreeOnSelect.whileFocusMovingByShortcut')) {
+					newActiveTabOptions.canExpandTree = true;
+					newActiveTabOptions.canCollapseTree = (
+						newActiveTabOptions.canCollapseTree &&
+						this.getTreePref('autoExpandSubtreeOnSelect.whileFocusMovingByShortcut.collapseOthers')
+					);
+					let delay = this.getTreePref('autoExpandSubtreeOnSelect.whileFocusMovingByShortcut.delay');
+					if (delay > 0) {
+						this._autoExpandOnTabSelectTimer = this.window.setTimeout(function(aSelf) {
+							if (tab && tab.parentNode)
+								aSelf.handleNewActiveTab(tab, newActiveTabOptions);
+						}, delay, this);
+					}
+					else {
+						this.handleNewActiveTab(tab, newActiveTabOptions);
+					}
+				}
+				else if (newActiveTabOptions.canExpandTree) {
+					this.windowService.expandTreeAfterKeyReleased(tab);
+				}
 			}
 			else {
-				this.collapseExpandTreesIntelligentlyWithDelayFor(tab);
+				this.handleNewActiveTab(tab, newActiveTabOptions);
 			}
 		}
 
@@ -3709,31 +3984,146 @@ TreeStyleTabBrowser.prototype = {
 			aEvent.stopPropagation();
 		}
 	},
- 
-	handleAdvanceSelectedTab : function TSTBrowser_handleAdvanceSelectedTab(aDir, aWrap, aTabbar) 
+	cancelDelayedExpandOnTabSelect : function TSTBrowser_cancelDelayedExpandOnTabSelect() {
+		if (this._autoExpandOnTabSelectTimer) {
+			this.window.clearTimeout(this._autoExpandOnTabSelectTimer);
+			this._autoExpandOnTabSelectTimer = null;
+		}
+	},
+	handleNewActiveTab : function TSTBrowser_handleNewActiveTab(aTab, aOptions)
+	{
+		if (this.doingCollapseExpand || !aTab) return;
+
+		aOptions = aOptions || {};
+
+		if (this._handleNewActiveTabTimer)
+			this.window.clearTimeout(this._handleNewActiveTabTimer);
+
+		/**
+		 * First, we wait until all event listeners for the TabSelect
+		 * event were processed.
+		 */
+		this._handleNewActiveTabTimer = this.window.setTimeout(function(aSelf) {
+			aSelf.window.clearTimeout(aSelf._handleNewActiveTabTimer);
+			aSelf._handleNewActiveTabTimer = null;
+
+			if (aOptions.canExpandTree) {
+				if (aOptions.canCollapseTree)
+					aSelf.collapseExpandTreesIntelligentlyFor(aTab);
+				else
+					aSelf.collapseExpandSubtree(aTab, false);
+			}
+		}, 0, this);
+	},
+	_handleNewActiveTabTimer : null,
+	
+	handleAdvanceSelectedTab : function TSTBrowser_handleAdvanceSelectedTab(aDir, aWrap) 
 	{
 		this._focusChangedByShortcut = this.windowService.accelKeyPressed;
 
-		if (!this.canCollapseSubtree(aTabbar.selectedItem) ||
+		if (!this.canCollapseSubtree(this.mTabBrowser.selectedTab) ||
 			this.getTreePref('focusMode') != this.kFOCUS_VISIBLE)
 			return false;
 
-		var nextTab = (aDir < 0) ? this.getPreviousVisibleTab(aTabbar.selectedItem) : this.getNextVisibleTab(aTabbar.selectedItem) ;
+		if (this.processArrowKeyOnFocusAdvanced())
+			return true;
+
+		return this.advanceSelectedTab(aDir, aWrap);
+	},
+	
+	processArrowKeyOnFocusAdvanced : function TSTBrowser_processArrowKeyOnFocusAdvanced() 
+	{
+		var event = this.windowService.arrowKeyEventOnTab;
+		if (!event)
+			return false;
+
+		if (
+			event.altKey ||
+			event.ctrlKey ||
+			event.metaKey ||
+			event.shiftKey ||
+			(this.isVertical ? (event.up || event.down) : (event.left || event.right))
+			) {
+			event.advanceFocus = true;
+			return false;
+		}
+
+		var collapse, expand;
+		switch (this.position)
+		{
+			case 'top':
+				collapse = event.up;
+				expand = event.down;
+				break;
+
+			case 'bottom':
+				collapse = event.down;
+				expand = event.up;
+				break;
+
+			case 'left':
+				collapse = event.left;
+				expand = event.right;
+				break;
+
+			case 'right':
+				if (this.getTreePref('tabbar.invertTab')) {
+					collapse = event.right;
+					expand = event.left;
+				}
+				else {
+					collapse = event.left;
+					expand = event.right;
+				}
+				break;
+		}
+
+		var tab = this.mTabBrowser.selectedTab;
+
+		var collapsed = this.isSubtreeCollapsed(tab);
+		if (this.hasChildTabs(tab) && (collapsed ? expand : collapse )) {
+			event.collapse = collapse;
+			event.expand = expand;
+			this.collapseExpandSubtree(tab, !collapsed);
+			return true;
+		}
+
+		var nextSelected;
+		if (expand)
+			nextSelected = this.getFirstChildTab(tab);
+		else if (collapse)
+			nextSelected = this.getParentTab(tab);
+
+		if (nextSelected) {
+			event.advanceFocus = true;
+			this.mTabBrowser.selectedTab = nextSelected;
+			return true;
+		}
+
+		return true;
+	},
+ 
+	advanceSelectedTab : function TSTBrowser_advanceSelectedTab(aDir, aWrap) 
+	{
+		var tab = this.mTabBrowser.selectedTab;
+		var tabbar = this.mTabBrowser.mTabContainer;
+
+		var nextTab = (aDir < 0) ? this.getPreviousVisibleTab(tab) : this.getNextVisibleTab(tab) ;
 		if (!nextTab && aWrap) {
 			nextTab = this.evaluateXPath(
 					'child::xul:tab[not(@'+this.kCOLLAPSED+'="true")]['+
 					(aDir < 0 ? 'last()' : '1' )+
 					']',
-					aTabbar,
+					tabbar,
 					Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
 				).singleNodeValue;
 		}
-		if (nextTab && nextTab != aTabbar.selectedItem)
-			aTabbar._selectNewTab(nextTab, aDir, aWrap);
+		if (nextTab && nextTab != tab)
+			tabbar._selectNewTab(nextTab, aDir, aWrap);
 
 		return true;
 	},
- 
+   
 	onTabClick : function TSTBrowser_onTabClick(aEvent, aTab) 
 	{
 		aTab = aTab || this.getTabFromEvent(aEvent);
@@ -3751,7 +4141,7 @@ TreeStyleTabBrowser.prototype = {
 
 		if (this.isEventFiredOnTwisty(aEvent)) {
 			if (this.hasChildTabs(aTab) && this.canCollapseSubtree(aTab)) {
-				this.collapseExpandSubtree(aTab, aTab.getAttribute(this.kSUBTREE_COLLAPSED) != 'true');
+				this.manualCollapseExpandSubtree(aTab, aTab.getAttribute(this.kSUBTREE_COLLAPSED) != 'true');
 				aEvent.preventDefault();
 				aEvent.stopPropagation();
 			}
@@ -3766,29 +4156,6 @@ TreeStyleTabBrowser.prototype = {
 			return;
 		}
 	},
-	getTabFromTabbarEvent : function TSTBrowser_getTabFromTabbarEvent(aEvent)
-	{
-		if (
-			!this.shouldDetectClickOnIndentSpaces ||
-			!this.getAncestorTabbarFromEvent(aEvent) ||
-			this.isEventFiredOnClickable(aEvent) ||
-			this.getSplitterFromEvent(aEvent)
-			)
-			return null;
-
-		var tab = null;
-		var clickedPoint = aEvent[this.screenPositionProp];
-		this.getTabsArray(this.mTabBrowser).some(function(aTab) {
-			var box = aTab.boxObject;
-			if (box[this.screenPositionProp] > clickedPoint ||
-				box[this.screenPositionProp] + box[this.sizeProp] < clickedPoint) {
-				return false;
-			}
-			tab = aTab;
-			return true;
-		}, this);
-		return tab;
-	},
  
 	onClick : function TSTBrowser_onClick(aEvent) 
 	{
@@ -3816,7 +4183,7 @@ TreeStyleTabBrowser.prototype = {
 		if (tab &&
 			this.hasChildTabs(tab) &&
 			this.getTreePref('collapseExpandSubtree.dblclick')) {
-			this.collapseExpandSubtree(tab, tab.getAttribute(this.kSUBTREE_COLLAPSED) != 'true');
+			this.manualCollapseExpandSubtree(tab, tab.getAttribute(this.kSUBTREE_COLLAPSED) != 'true');
 			aEvent.preventDefault();
 			aEvent.stopPropagation();
 		}
@@ -3839,6 +4206,9 @@ TreeStyleTabBrowser.prototype = {
  
 	onMouseDown : function TSTBrowser_onMouseDown(aEvent) 
 	{
+		if (this.isEventFiredOnScrollbar(aEvent))
+			this.cancelPerformingAutoScroll();
+
 		if (
 			aEvent.button == 0 &&
 			this.isEventFiredOnTwisty(aEvent)
@@ -3853,6 +4223,11 @@ TreeStyleTabBrowser.prototype = {
 		}
 	},
  
+	onDOMMouseScroll : function TSTBrowser_onDOMMouseScroll(aEvent) 
+	{
+		this.cancelPerformingAutoScroll();
+	},
+ 
 	onScroll : function TSTBrowser_onScroll(aEvent) 
 	{
 		// restore scroll position when a tab is closed.
@@ -3866,13 +4241,22 @@ TreeStyleTabBrowser.prototype = {
 		if (horizontal) return;
 		aEvent.stopPropagation();
 		this.positionPinnedTabsWithDelay();
-		if (aEvent.detail == 1) return;
-		if (aEvent.type == 'overflow') {
-			tabs.setAttribute('overflow', 'true');
-			this.scrollBoxObject.ensureElementIsVisible(tabs.selectedItem);
+		if (aEvent.detail == 1) {
+			/**
+			 * By horizontal overflow/underflow, Firefox can wrongly
+			 * removes "overflow" attribute for vertical tab bar.
+			 * We have to override the result.
+			 */
+			this.updateTabbarOverflow();
 		}
 		else {
-			tabs.removeAttribute('overflow');
+			if (aEvent.type == 'overflow') {
+				tabs.setAttribute('overflow', 'true');
+				this.scrollBoxObject.ensureElementIsVisible(tabs.selectedItem);
+			}
+			else {
+				tabs.removeAttribute('overflow');
+			}
 		}
 	},
  
@@ -3884,100 +4268,53 @@ TreeStyleTabBrowser.prototype = {
 			)
 			return;
 
-		this.mTabBrowser.mTabContainer.adjustTabstrip();
-		this.updateInvertedTabContentsOrder(true);
-		this.updateFloatingTabbar(this.kTABBAR_UPDATE_BY_WINDOW_RESIZE);
+		var resizedTopFrame = aEvent.originalTarget.top;
+		if (resizedTopFrame == this.mTabBrowser.contentWindow ||
+			resizedTopFrame == this.window) {
+			this.mTabBrowser.mTabContainer.adjustTabstrip();
+			this.updateInvertedTabContentsOrder(true);
+			this.updateFloatingTabbar(this.kTABBAR_UPDATE_BY_WINDOW_RESIZE);
+		}
 	},
  
 	onPopupShowing : function TSTBrowser_onPopupShowing(aEvent) 
 	{
-		if (aEvent.target.localName == 'tooltip')
-			this.handleTooltip(aEvent);
-		else if (aEvent.target == aEvent.currentTarget)
+		if (aEvent.target == aEvent.currentTarget)
 			this.initTabContextMenu(aEvent);
 	},
 	
-	handleTooltip : function TSTBrowser_handleTooltip(aEvent) 
-	{
-		var tab = this.document.tooltipNode;
-		if (tab.localName != 'tab')
-			return;
-
-		var label;
-		var collapsed = this.isSubtreeCollapsed(tab);
-
-		var base = parseInt(tab.getAttribute(this.kNEST) || 0);
-		var descendant = this.getDescendantTabs(tab);
-		var indentPart = '  ';
-		var tree = (this.getTreePref('tooltip.includeChildren') && descendant.length) ?
-					[tab].concat(descendant)
-						.map(function(aTab) {
-							let label = aTab.getAttribute('label');
-							let indent = '';
-							let nest = parseInt(aTab.getAttribute(this.kNEST) || 0) - base;
-							for (let i = 0; i < nest; i++)
-							{
-								indent += indentPart;
-							}
-							return this.treeBundle.getFormattedString('tooltip.item.label', [label, indent]);
-						}, this)
-						.join('\n') :
-					null ;
-
-		if ('mOverCloseButton' in tab && tab.mOverCloseButton) {
-			if (descendant.length &&
-				(collapsed || this.getTreePref('closeParentBehavior') == this.kCLOSE_PARENT_BEHAVIOR_CLOSE_ALL_CHILDREN)) {
-				label = this.treeBundle.getString('tooltip.closeTree');
-			}
-		}
-		else if (tab.getAttribute(this.kTWISTY_HOVER) == 'true') {
-			let key = collapsed ?
-						'tooltip.expandSubtree' :
-						'tooltip.collapseSubtree' ;
-			label = tree || tab.getAttribute('label');
-			label = label ?
-					this.treeBundle.getFormattedString(key+'.labeled', [label]) :
-					this.treeBundle.getString(key) ;
-		}
-		else if (collapsed) {
-			label = tree;
-		}
-
-		if (label) {
-			aEvent.target.setAttribute('label', label);
-			aEvent.stopPropagation();
-		}
-	},
- 
 	initTabContextMenu : function TSTBrowser_initTabContextMenu(aEvent) 
 	{
 		var b = this.mTabBrowser;
 		var sep, items = {};
 
-		[
-			this.kMENUITEM_RELOADSUBTREE,
-			this.kMENUITEM_RELOADCHILDREN,
-			this.kMENUITEM_REMOVESUBTREE,
-			this.kMENUITEM_REMOVECHILDREN,
-			this.kMENUITEM_REMOVEALLTABSBUT,
-			this.kMENUITEM_COLLAPSE,
-			this.kMENUITEM_EXPAND,
-			this.kMENUITEM_AUTOHIDE,
-			this.kMENUITEM_FIXED,
-			this.kMENUITEM_BOOKMARKSUBTREE
-		].forEach(function(aID) {
+		var ids = [
+				this.kMENUITEM_RELOADSUBTREE,
+				this.kMENUITEM_RELOADCHILDREN,
+				this.kMENUITEM_REMOVESUBTREE,
+				this.kMENUITEM_REMOVECHILDREN,
+				this.kMENUITEM_REMOVEALLTABSBUT,
+				this.kMENUITEM_COLLAPSE,
+				this.kMENUITEM_EXPAND,
+				this.kMENUITEM_AUTOHIDE,
+				this.kMENUITEM_FIXED,
+				this.kMENUITEM_BOOKMARKSUBTREE
+			];
+		for (let i = 0, maxi = ids.length; i < maxi; i++)
+		{
+			let id = ids[i];
 			let item = this.evaluateXPath(
-				'descendant::xul:*[starts-with(@id, "'+aID+'")]',
+				'descendant::xul:*[starts-with(@id, "'+id+'")]',
 				aEvent.currentTarget,
 				Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
 			).singleNodeValue;
-			if (!item) return;
-			items[aID] = item;
-			if (this.getTreePref('show.'+aID))
+			if (!item) continue;
+			items[id] = item;
+			if (this.getTreePref('show.'+id))
 				item.removeAttribute('hidden');
 			else
 				item.setAttribute('hidden', true);
-			switch (aID)
+			switch (id)
 			{
 				case this.kMENUITEM_RELOADSUBTREE:
 				case this.kMENUITEM_RELOADCHILDREN:
@@ -3988,11 +4325,11 @@ TreeStyleTabBrowser.prototype = {
 				case this.kMENUITEM_EXPAND:
 				case this.kMENUITEM_BOOKMARKSUBTREE:
 					this.showHideSubtreeMenuItem(item, [b.mContextTab]);
-					break;
+					continue;
 				default:
-					break;
+					continue;
 			}
-		}, this);
+		}
 
 		// collapse/expand all
 		sep = this.evaluateXPath(
@@ -4101,7 +4438,8 @@ TreeStyleTabBrowser.prototype = {
 		if (
 			!aEnabled ||
 			this.position != 'top' ||
-			this.fixed
+			this.fixed ||
+			!this.windowService.isPopupWindow
 			)
 			return;
 		var self = this;
@@ -4112,7 +4450,8 @@ TreeStyleTabBrowser.prototype = {
 			.next(function() {
 				if (self.window.TabsOnTop.enabled != aEnabled)
 					self.window.TabsOnTop.enabled = aEnabled;
-			});
+			})
+			.error(this.defaultDeferredErrorHandler);
 	},
  
 	onTreeStyleTabPrintPreviewEntered : function TSTBrowser_onTreeStyleTabPrintPreviewEntered(aEvent) 
@@ -4129,35 +4468,44 @@ TreeStyleTabBrowser.prototype = {
 	
 /* reset */ 
 	
-	resetTab : function TSTBrowser_resetTab(aTab, aPartChildren) 
+	resetTab : function TSTBrowser_resetTab(aTab, aDetachAllChildren) 
 	{
-		if (aPartChildren)
-			this.partAllChildren(aTab, {
+		if (aDetachAllChildren)
+			this.detachAllChildren(aTab, {
 				dontUpdateIndent : true,
 				dontAnimate      : true
 			});
 
-		this.partTab(aTab, {
+		this.detachTab(aTab, {
 			dontUpdateIndent : true,
 			dontAnimate      : true
 		});
 
-		/* reset attributes before restoring */
+		this.resetTabState(aTab);
+		this.updateTabsIndent([aTab], undefined, true);
+	},
+	
+	resetTabState : function TSTBrowser_resetTabState(aTab) 
+	{
 		aTab.removeAttribute(this.kID);
+		aTab.removeAttribute(this.kID_RESTORING);
 		aTab.removeAttribute(this.kPARENT);
 		aTab.removeAttribute(this.kCHILDREN);
+		aTab.removeAttribute(this.kCHILDREN_RESTORING);
 		aTab.removeAttribute(this.kSUBTREE_COLLAPSED);
+		aTab.removeAttribute(this.kSUBTREE_EXPANDED_MANUALLY);
 		aTab.removeAttribute(this.kCOLLAPSED);
-		aTab.removeAttribute(this.kCOLLAPSED_DONE);
 		aTab.removeAttribute(this.kNEST);
-		this.updateTabsIndent([aTab], undefined, true);
+		this.updateTabCollapsed(aTab, false, true);
 	},
- 
-	resetAllTabs : function TSTBrowser_resetAllTabs(aPartChildren) 
+  
+	resetAllTabs : function TSTBrowser_resetAllTabs(aDetachAllChildren) 
 	{
-		this.getAllTabsArray(this.mTabBrowser).forEach(function(aTab) {
-			this.resetTab(aTab, aPartChildren);
-		}, this);
+		var tabs = this.getAllTabsArray(this.mTabBrowser);
+		for (let i = 0, maxi = tabs.length; i < maxi; i++)
+		{
+			this.resetTab(tabs[i], aDetachAllChildren);
+		}
 	},
  
 	resetTabbarSize : function TSTBrowser_resetTabbarSize() 
@@ -4168,11 +4516,9 @@ TreeStyleTabBrowser.prototype = {
 		}
 		else {
 			this.clearTreePref('tabbar.height');
-			if (this.isFloating) {
-				let tabContainerBox = this.getTabContainerBox(this.mTabBrowser);
-				tabContainerBox.removeAttribute('height');
-				this._tabStripPlaceHolder.height = tabContainerBox.boxObject.height;
-			}
+			let tabContainerBox = this.getTabContainerBox(this.mTabBrowser);
+			tabContainerBox.removeAttribute('height');
+			this._tabStripPlaceHolder.height = tabContainerBox.boxObject.height;
 		}
 		this.updateFloatingTabbar(this.kTABBAR_UPDATE_BY_RESET);
 	},
@@ -4193,20 +4539,30 @@ TreeStyleTabBrowser.prototype = {
 				this.allowSubtreeCollapseExpand = true;
 			delete this._lastAllowSubtreeCollapseExpand;
 
-			this.getAllTabsArray(this.browser).forEach(function(aTab) {
-				if (aTab._TSTLastSubtreeCollapsed)
-					this.collapseExpandSubtree(aTab, true, true);
-				delete aTab._TSTLastSubtreeCollapsed;
-				this.updateTabIndent(aTab, 0, true);
-			}, this);
+			let tabs = this.getAllTabsArray(this.browser);
+			for (let i = 0, maxi = tabs.length; i < maxi; i++)
+			{
+				let tab = tabs[i];
+				if (tab._TSTLastSubtreeCollapsed)
+					this.collapseExpandSubtree(tab, true, true);
+				if (tab._TSTLastSubtreeExpandedManually)
+					this.setTabValue(tab, this.kSUBTREE_EXPANDED_MANUALLY, true);
+				delete tab._TSTLastSubtreeCollapsed;
+				delete tab._TSTLastSubtreeExpandedManually;
+				this.updateTabIndent(tab, 0, true);
+			}
 			this.updateTabsIndent(this.rootTabs, undefined, true);
 		}
 		else {
-			this.getAllTabsArray(this.browser).forEach(function(aTab) {
-				this.updateTabIndent(aTab, 0, true);
-				aTab._TSTLastSubtreeCollapsed = this.isSubtreeCollapsed(aTab);
-				this.collapseExpandSubtree(aTab, false, true);
-			}, this);
+			let tabs = this.getAllTabsArray(this.browser);
+			for (let i = 0, maxi = tabs.length; i < maxi; i++)
+			{
+				let tab = tabs[i];
+				this.updateTabIndent(tab, 0, true);
+				tab._TSTLastSubtreeCollapsed = this.isSubtreeCollapsed(tab);
+				tab._TSTLastSubtreeExpandedManually = this.getTabValue(tab, this.kSUBTREE_EXPANDED_MANUALLY) == 'true';
+				this.collapseExpandSubtree(tab, false, true);
+			}
 
 			this._lastAllowSubtreeCollapseExpand = this.allowSubtreeCollapseExpand;
 			this.allowSubtreeCollapseExpand = false;
@@ -4215,7 +4571,7 @@ TreeStyleTabBrowser.prototype = {
 	},
 //	_treeViewEnabled : true,
   
-/* attach/part */ 
+/* attach/detach */ 
 	
 	attachTabTo : function TSTBrowser_attachTabTo(aChild, aParent, aInfo) /* PUBLIC API */ 
 	{
@@ -4243,18 +4599,16 @@ TreeStyleTabBrowser.prototype = {
 			return;
 		}
 
-		currentParent = aParent;
-		do {
-			if (currentParent != aChild) continue;
-			// this.fireAttachedEvent(aChild, aParent);
+		// avoid recursive tree
+		var ancestors = [aParent].concat(this.getAncestorTabs(aChild));
+		if (ancestors.indexOf(aChild) > -1)
 			return;
-		}
-		while (currentParent = this.getParentTab(currentParent));
 
-		shouldInheritIndent = (
-			!currentParent ||
-			(currentParent.getAttribute(this.kNEST) == aParent.getAttribute(this.kNEST))
-		);
+		currentParent = ancestors[ancestors.length-1];
+		var shouldInheritIndent = (
+				!currentParent ||
+				(currentParent.getAttribute(this.kNEST) == aParent.getAttribute(this.kNEST))
+			);
 
 		this.ensureTabInitialized(aChild);
 		this.ensureTabInitialized(aParent);
@@ -4263,7 +4617,7 @@ TreeStyleTabBrowser.prototype = {
 
 		var id = aChild.getAttribute(this.kID);
 
-		this.partTab(aChild, {
+		this.detachTab(aChild, {
 			dontUpdateIndent : true
 		});
 
@@ -4322,7 +4676,10 @@ TreeStyleTabBrowser.prototype = {
 			this.moveTabSubtreeTo(aChild, newIndex);
 		}
 
-		if (!aInfo.dontExpand) {
+		if (aInfo.forceExpand) {
+			this.collapseExpandSubtree(aParent, false, aInfo.dontAnimate);
+		}
+		else if (!aInfo.dontExpand) {
 			if (this.getTreePref('autoCollapseExpandSubtreeOnSelect')) {
 				if (this.shouldTabAutoExpanded(aParent))
 					this.collapseExpandTreesIntelligentlyFor(aParent);
@@ -4361,8 +4718,6 @@ TreeStyleTabBrowser.prototype = {
 
 		this.promoteTooDeepLevelTabs(aChild);
 
-		this.saveTreeStructureWithDelay();
-
 		this.fireAttachedEvent(aChild, aParent);
 	},
 	fireAttachedEvent : function TSTBrowser_fireAttachedEvent(aChild, aParent)
@@ -4383,7 +4738,7 @@ TreeStyleTabBrowser.prototype = {
 				this.isSubtreeCollapsed(aTab);
 	},
   
-	partTab : function TSTBrowser_partTab(aChild, aInfo) /* PUBLIC API */ 
+	detachTab : function TSTBrowser_detachTab(aChild, aInfo) /* PUBLIC API */ 
 	{
 		if (!aChild) return;
 		if (!aInfo) aInfo = {};
@@ -4414,8 +4769,6 @@ TreeStyleTabBrowser.prototype = {
 			this.checkTabsIndentOverflow();
 		}
 
-		this.saveTreeStructureWithDelay();
-
 		var data = {
 				parentTab : parentTab
 			};
@@ -4433,12 +4786,12 @@ TreeStyleTabBrowser.prototype = {
 			}, 0, this.getTabBrowserFromChild(parentTab));
 		}
 	},
-	detachTab : function TSTBrowser_detachTab(aChild, aInfo) // alias (unstable API!)
+	partTab : function TSTBrowser_partTab(aChild, aInfo) /* PUBLIC API, for backward compatibility */
 	{
-		return this.partTab(aChild, aInfo);
+		return this.detachTab(aChild, aInfo);
 	},
 	
-	partAllChildren : function TSTBrowser_partAllChildren(aTab, aInfo) 
+	detachAllChildren : function TSTBrowser_detachAllChildren(aTab, aInfo) 
 	{
 		aInfo = aInfo || {};
 		if (!('behavior' in aInfo))
@@ -4465,57 +4818,59 @@ TreeStyleTabBrowser.prototype = {
 			!this.getTreePref('closeParentBehavior.moveDetachedTabsToBottom')) {
 			insertBefore = this.getNextSiblingTab(this.getRootTab(aTab));
 		}
-		children.forEach((
-			aInfo.behavior == this.kCLOSE_PARENT_BEHAVIOR_DETACH_ALL_CHILDREN ?
-				function(aTab) {
-					this.partTab(aTab, aInfo);
-					this.moveTabSubtreeTo(aTab, insertBefore ? insertBefore._tPos - 1 : this.getLastTab(b)._tPos );
-				} :
-			aInfo.behavior == this.kCLOSE_PARENT_BEHAVIOR_PROMOTE_FIRST_CHILD ?
-				function(aTab, aIndex) {
-					this.partTab(aTab, aInfo);
-					if (aIndex == 0) {
-						if (parentTab) {
-							this.attachTabTo(aTab, parentTab, {
-								__proto__  : aInfo,
-								dontExpand : true,
-								dontMove   : true
-							});
-						}
-						this.collapseExpandSubtree(aTab, false);
-						this.deleteTabValue(aTab, this.kSUBTREE_COLLAPSED);
-					}
-					else {
-						this.attachTabTo(aTab, children[0], {
+		for (let i = 0, maxi = children.length; i < maxi; i++)
+		{
+			let tab = children[i];
+			if (aInfo.behavior == this.kCLOSE_PARENT_BEHAVIOR_DETACH_ALL_CHILDREN) {
+				this.detachTab(tab, aInfo);
+				this.moveTabSubtreeTo(tab, insertBefore ? insertBefore._tPos - 1 : this.getLastTab(b)._tPos );
+			}
+			else if (aInfo.behavior == this.kCLOSE_PARENT_BEHAVIOR_PROMOTE_FIRST_CHILD) {
+				this.detachTab(tab, aInfo);
+				if (i == 0) {
+					if (parentTab) {
+						this.attachTabTo(tab, parentTab, {
 							__proto__  : aInfo,
 							dontExpand : true,
 							dontMove   : true
 						});
 					}
-				} :
-			aInfo.behavior == this.kCLOSE_PARENT_BEHAVIOR_PROMOTE_ALL_CHILDREN && parentTab ?
-				function(aTab) {
-					this.attachTabTo(aTab, parentTab, {
+					this.collapseExpandSubtree(tab, false);
+					this.deleteTabValue(tab, this.kSUBTREE_COLLAPSED);
+				}
+				else {
+					this.attachTabTo(tab, children[0], {
 						__proto__  : aInfo,
 						dontExpand : true,
 						dontMove   : true
 					});
-				} :
-			// aInfo.behavior == this.kCLOSE_PARENT_BEHAVIOR_SIMPLY_DETACH_ALL_CHILDREN ?
-				function(aTab) {
-					this.partTab(aTab, aInfo);
 				}
-		), this);
+			}
+			else if (aInfo.behavior == this.kCLOSE_PARENT_BEHAVIOR_PROMOTE_ALL_CHILDREN && parentTab) {
+				this.attachTabTo(tab, parentTab, {
+					__proto__  : aInfo,
+					dontExpand : true,
+					dontMove   : true
+				});
+			}
+			else { // aInfo.behavior == this.kCLOSE_PARENT_BEHAVIOR_SIMPLY_DETACH_ALL_CHILDREN
+				this.detachTab(tab, aInfo);
+			}
+		}
+	},
+	partAllChildren : function TSTBrowser_partAllChildren(aTab, aInfo) /* for backward compatibility */
+	{
+		return this.detachAllChildren(aTab, aInfo);
 	},
  
-	partTabs : function TSTBrowser_partTabs(aTabs)
+	detachTabs : function TSTBrowser_detachTabs(aTabs) 
 	{
-		var aTabs = Array.slice(aTabs);
-		for each (let tab in aTabs)
+		for (let i = 0, maxi = aTabs.length; i < maxi; i++)
 		{
+			let tab = aTabs[i];
 			if (aTabs.indexOf(this.getParentTab(tab)) > -1)
 				continue;
-			this.partAllChildren(tab, {
+			this.detachAllChildren(tab, {
 				behavior : this.getCloseParentBehaviorForTab(
 					tab,
 					this.kCLOSE_PARENT_BEHAVIOR_PROMOTE_FIRST_CHILD
@@ -4523,6 +4878,10 @@ TreeStyleTabBrowser.prototype = {
 			});
 		}
 	},
+	partTabs : function TSTBrowser_partTabs(aTabs) /* for backward compatibility */
+	{
+		return this.detachTabs(aTabs);
+	},
  
 	getCloseParentBehaviorForTab : function TSTBrowser_getCloseParentBehaviorForTab(aTab, aDefaultBehavior) 
 	{
@@ -4560,13 +4919,15 @@ TreeStyleTabBrowser.prototype = {
 			indent = Math.min(aLevel * 3, maxIndent);
 		}
 
-		Array.slice(aTabs).forEach(function(aTab) {
-			if (!aTab.parentNode) return; // ignore removed tabs
-			this.updateTabIndent(aTab, indent, aJustNow);
-			aTab.setAttribute(this.kNEST, aLevel);
-			this.updateCanCollapseSubtree(aTab, aLevel);
-			this.updateTabsIndent(this.getChildTabs(aTab), aLevel+1, aJustNow);
-		}, this);
+		for (let i = 0, maxi = aTabs.length; i < maxi; i++)
+		{
+			let tab = aTabs[i];
+			if (!tab.parentNode) continue; // ignore removed tabs
+			this.updateTabIndent(tab, indent, aJustNow);
+			tab.setAttribute(this.kNEST, aLevel);
+			this.updateCanCollapseSubtree(tab, aLevel);
+			this.updateTabsIndent(this.getChildTabs(tab), aLevel+1, aJustNow);
+		}
 	},
 	updateTabsIndentWithDelay : function TSTBrowser_updateTabsIndentWithDelay(aTabs)
 	{
@@ -4576,9 +4937,11 @@ TreeStyleTabBrowser.prototype = {
 		this.updateTabsIndentWithDelayTabs = this.updateTabsIndentWithDelayTabs.concat(aTabs);
 		this.updateTabsIndentWithDelayTimer = this.window.setTimeout(function(aSelf) {
 			var tabs = [];
-			aSelf.updateTabsIndentWithDelayTabs.forEach(function(aTab) {
-				if (tabs.indexOf(aTab) < 0 && aTab.parentNode) tabs.push(aTab);
-			});
+			for (let i = 0, maxi = aSelf.updateTabsIndentWithDelayTabs.length; i < maxi; i++)
+			{
+				let tab = aSelf.updateTabsIndentWithDelayTabs[i];
+				if (tabs.indexOf(tab) < 0 && tab.parentNode) tabs.push(tab);
+			}
 			aSelf.updateTabsIndentWithDelayTabs = [];
 			aSelf.updateTabsIndent(tabs);
 			aSelf.window.clearTimeout(aSelf.updateTabsIndentWithDelayTimer);
@@ -4608,15 +4971,18 @@ TreeStyleTabBrowser.prototype = {
 				retVal.push('ThreeDShadow');
 				return retVal.length == 1 ? 'none' : retVal.join(' ') ;
 			})()+' !important;';
-			Array.slice(this.document.getAnonymousNodes(aTab)).forEach(function(aBox) {
-				if (aBox.nodeType != Node.ELEMENT_NODE) return;
-				aBox.setAttribute(
+			let boxes = this.document.getAnonymousNodes(aTab);
+			for (let i = 0, box = boxes.length; i < maxi; i++)
+			{
+				let box = boxes[i];
+				if (box.nodeType != Node.ELEMENT_NODE) continue;
+				box.setAttribute(
 					'style',
-					aBox.getAttribute('style').replace(/(-moz-)?border-(top|bottom)(-[^:]*)?.*:[^;]+;?/g, '') +
+					box.getAttribute('style')
+						.replace(/(-moz-)?border-(top|bottom)(-[^:]*)?.*:[^;]+;?/g, '') +
 					'; border-'+this.indentTarget+': solid transparent '+aIndent+'px !important;'+colors
 				);
-			}, this);
-
+			}
 			return;
 		}
 
@@ -4634,6 +5000,7 @@ TreeStyleTabBrowser.prototype = {
 		var CSSTransitionEnabled = ('Transition' in aTab.style || 'MozTransition' in aTab.style);
 		if (CSSTransitionEnabled) {
 			aTab.__treestyletab__updateTabIndentTask = function(aTime, aBeginning, aChange, aDuration) {
+				if (self.isDestroying) return true;
 				aTab.style.setProperty(self.indentCSSProp, aIndent+'px', 'important');
 				return true;
 			};
@@ -4648,6 +5015,7 @@ TreeStyleTabBrowser.prototype = {
 		var delta       = aIndent - startIndent;
 		var radian      = 90 * Math.PI / 180;
 		aTab.__treestyletab__updateTabIndentTask = function(aTime, aBeginning, aChange, aDuration) {
+			if (self.isDestroying) return true;
 			var indent, finished;
 			if (aTime >= aDuration) {
 				delete aTab.__treestyletab__updateTabIndentTask;
@@ -4778,7 +5146,10 @@ TreeStyleTabBrowser.prototype = {
 	{
 		var count = this.document.getAnonymousElementByAttribute(aTab, 'class', this.kCOUNTER);
 		if (count) {
-			count.setAttribute('value', this.getDescendantTabs(aTab).length);
+			let value = this.getDescendantTabs(aTab).length;
+			if (this.counterRole == this.kCOUNTER_ROLE_ALL_TABS)
+				value += 1;
+			count.setAttribute('value', value);
 		}
 		if (!aDontUpdateAncestor) {
 			let parent = this.getParentTab(aTab);
@@ -4787,30 +5158,41 @@ TreeStyleTabBrowser.prototype = {
 		}
 	},
  
+	updateAllTabsCount : function TSTBrowser_updateAllTabsCount() 
+	{
+		var tabs = this.rootTabs;
+		for (let i = 0, maxi = tabs.length; i < maxi; i++)
+		{
+			let tab = tabs[i];
+			this.updateTabsCount(tab, this);
+		}
+	},
+ 
 	promoteTooDeepLevelTabs : function TSTBrowser_promoteTooDeepLevelTabs(aParent) 
 	{
 		if (this.maxTreeLevel < 0 || !this.maxTreeLevelPhisical)
 			return;
 
 		var tabs = aParent ? this.getDescendantTabs(aParent) : this.getAllTabsArray(this.mTabBrowser) ;
-		tabs.forEach(function(aTab) {
-			var level = parseInt(aTab.getAttribute(this.kNEST) || 0);
+		for (let i = 0, maxi = tabs.length; i < maxi; i++)
+		{
+			let level = parseInt(tab.getAttribute(this.kNEST) || 0);
 			if (level <= this.maxTreeLevel)
-				return;
+				continue;
 
-			var parent = this.getParentTab(aTab);
-			var newParent = this.getParentTab(parent);
+			let parent = this.getParentTab(tab);
+			let newParent = this.getParentTab(parent);
 			if (this.maxTreeLevel == 0 || !newParent) {
-				this.partTab(aTab);
+				this.detachTab(aTab);
 			}
 			else {
-				let nextSibling = this.getNextTab(aTab);
-				this.attachTabTo(aTab, newParent, {
+				let nextSibling = this.getNextTab(tab);
+				this.attachTabTo(tab, newParent, {
 					dontMove     : true,
 					insertBefore : nextSibling
 				});
 			}
-		}, this);
+		}
 	},
   
 /* move */ 
@@ -4828,9 +5210,12 @@ TreeStyleTabBrowser.prototype = {
 
 		this.subTreeChildrenMovingCount++;
 		this.internallyTabMovingCount++;
-		this.getDescendantTabs(aTab).forEach(function(aDescendantTab, aIndex) {
-			b.moveTabTo(aDescendantTab, aTab._tPos + aIndex + (aTab._tPos < aDescendantTab._tPos ? 1 : 0 ));
-		}, this);
+		var descendantTabs = this.getDescendantTabs(aTab);
+		for (let i = 0, maxi = descendantTabs.length; i < maxi; i++)
+		{
+			let descendantTab = descendantTabs[i];
+			b.moveTabTo(descendantTab, aTab._tPos + i + (aTab._tPos < descendantTab._tPos ? 1 : 0 ));
+		}
 		this.internallyTabMovingCount--;
 		this.subTreeChildrenMovingCount--;
 
@@ -4862,7 +5247,7 @@ TreeStyleTabBrowser.prototype = {
 			}
 			else {
 				let nextTab = this.getNextSiblingTab(parentTab);
-				this.partTab(b.mCurrentTab);
+				this.detachTab(b.mCurrentTab);
 				this.internallyTabMovingCount++;
 				if (nextTab) {
 					b.moveTabTo(b.mCurrentTab, nextTab._tPos - 1);
@@ -4888,7 +5273,7 @@ TreeStyleTabBrowser.prototype = {
 	{
 		return this.moveTabsInternal(aTabs, { insertBefore : aInsertBefore });
 	},
-	duplicateTabs : function TSTBrowser_duplicateTabs(aTabs, aInsertBefore) /* PUBLIC API */ 
+	duplicateTabs : function TSTBrowser_duplicateTabs(aTabs, aInsertBefore) /* PUBLIC API */
 	{
 		return this.moveTabsInternal(aTabs, { insertBefore : aInsertBefore, duplicate : true });
 	},
@@ -4991,7 +5376,7 @@ TreeStyleTabBrowser.prototype = {
 		return newTabs;
 	},
  
-	importTab : function TSTBrowser_importTab(aTab)
+	importTab : function TSTBrowser_importTab(aTab) 
 	{
 		var newTab = this.mTabBrowser.addTab();
 		newTab.linkedBrowser.stop();
@@ -5001,7 +5386,7 @@ TreeStyleTabBrowser.prototype = {
 		return newTab;
 	},
  
-	duplicateTabAsOrphan : function TSTBrowser_duplicateTabAsOrphan(aTab)
+	duplicateTabAsOrphan : function TSTBrowser_duplicateTabAsOrphan(aTab) 
 	{
 		var newTab = this.mTabBrowser.duplicateTab(aTab);
 		this.deleteTabValue(newTab, this.kCHILDREN);
@@ -5039,24 +5424,39 @@ TreeStyleTabBrowser.prototype = {
 
 		this.setTabValue(aTab, this.kSUBTREE_COLLAPSED, aCollapse);
 
-		this.getChildTabs(aTab).forEach(function(aTab) {
-			this.collapseExpandTab(aTab, aCollapse, aJustNow);
-		}, this);
-
-		if (!aCollapse)
-			this.scrollToTabSubtree(aTab);
+		var expandedTabs = this.getChildTabs(aTab);
+		var lastExpandedTabIndex = expandedTabs.length - 1;
+		for (let i = 0, maxi = expandedTabs.length; i < maxi; i++)
+		{
+			let childTab = expandedTabs[i];
+			if (!aCollapse && !aJustNow && i == lastExpandedTabIndex) {
+				let self = this;
+				this.collapseExpandTab(childTab, aCollapse, aJustNow, function() {
+					self.scrollToTabSubtree(aTab);
+				});
+			}
+			else
+				this.collapseExpandTab(childTab, aCollapse, aJustNow);
+		}
 
-		this.saveTreeStructureWithDelay();
+		if (aCollapse)
+			this.deleteTabValue(aTab, this.kSUBTREE_EXPANDED_MANUALLY);
 
 		this.doingCollapseExpand = false;
 	},
+	manualCollapseExpandSubtree : function(aTab, aCollapse, aJustNow)
+	{
+		this.collapseExpandSubtree(aTab, aCollapse, aJustNow);
+		if (!aCollapse)
+			this.setTabValue(aTab, this.kSUBTREE_EXPANDED_MANUALLY, true);
+	},
  
-	collapseExpandTab : function TSTBrowser_collapseExpandTab(aTab, aCollapse, aJustNow) 
+	collapseExpandTab : function TSTBrowser_collapseExpandTab(aTab, aCollapse, aJustNow, aCallbackToRunOnStartAnimation) 
 	{
 		if (!aTab || !this.getParentTab(aTab)) return;
 
 		this.setTabValue(aTab, this.kCOLLAPSED, aCollapse);
-		this.updateTabCollapsed(aTab, aCollapse, aJustNow);
+		this.updateTabCollapsed(aTab, aCollapse, aJustNow, aCallbackToRunOnStartAnimation);
 
 		var data = {
 				collapsed : aCollapse
@@ -5081,12 +5481,14 @@ TreeStyleTabBrowser.prototype = {
 		}
 
 		if (!this.isSubtreeCollapsed(aTab)) {
-			this.getChildTabs(aTab).forEach(function(aTab) {
-				this.collapseExpandTab(aTab, aCollapse, aJustNow);
-			}, this);
+			let tabs = this.getChildTabs(aTab);
+			for (let i = 0, maxi = tabs.length; i < maxi; i++)
+			{
+				this.collapseExpandTab(tabs[i], aCollapse, aJustNow);
+			}
 		}
 	},
-	updateTabCollapsed : function TSTBrowser_updateTabCollapsed(aTab, aCollapsed, aJustNow)
+	updateTabCollapsed : function TSTBrowser_updateTabCollapsed(aTab, aCollapsed, aJustNow, aCallbackToRunOnStartAnimation)
 	{
 		this.stopTabCollapseAnimation(aTab);
 
@@ -5161,6 +5563,9 @@ TreeStyleTabBrowser.prototype = {
 				aTab.style.removeProperty(this.collapseCSSProp);
 				aTab.style.removeProperty('opacity');
 			}
+
+			if (aCallbackToRunOnStartAnimation)
+				aCallbackToRunOnStartAnimation();
 			return;
 		}
 
@@ -5179,9 +5584,15 @@ TreeStyleTabBrowser.prototype = {
 		var self   = this;
 		var firstFrame = true;
 		aTab.__treestyletab__updateTabCollapsedTask = function(aTime, aBeginning, aChange, aDuration) {
-			if (firstFrame && CSSTransitionEnabled) {
-				aTab.style.setProperty(self.collapseCSSProp, endMargin ? '-'+endMargin+'px' : '', 'important');
-				aTab.style.setProperty('opacity', endOpacity == 1 ? '' : endOpacity, 'important');
+			if (self.isDestroying) return true;
+			if (firstFrame) {
+				// The callback must be started before offsetAttr is changed!
+				if (aCallbackToRunOnStartAnimation)
+					aCallbackToRunOnStartAnimation();
+				if (CSSTransitionEnabled) {
+					aTab.style.setProperty(self.collapseCSSProp, endMargin ? '-'+endMargin+'px' : '', 'important');
+					aTab.style.setProperty('opacity', endOpacity == 1 ? '' : endOpacity, 'important');
+				}
 			}
 			firstFrame = false;
 			// If this is the last tab, negative scroll happens.
@@ -5268,17 +5679,15 @@ TreeStyleTabBrowser.prototype = {
 		expandedParentTabs = expandedParentTabs.join('|');
 
 		var xpathResult = this.evaluateXPath(
-				'child::xul:tab[@'+this.kCHILDREN+' and not(@'+this.kCOLLAPSED+'="true") and not(@'+this.kSUBTREE_COLLAPSED+'="true") and @'+this.kID+' and not(contains("'+expandedParentTabs+'", @'+this.kID+'))]',
+				'child::xul:tab[@'+this.kCHILDREN+' and not(@'+this.kCOLLAPSED+'="true") and not(@'+this.kSUBTREE_COLLAPSED+'="true") and @'+this.kID+' and not(contains("'+expandedParentTabs+'", @'+this.kID+')) and not(@hidden="true")]',
 				b.mTabContainer
 			);
-		var collapseTab;
-		var dontCollapse;
 		for (var i = 0, maxi = xpathResult.snapshotLength; i < maxi; i++)
 		{
-			dontCollapse = false;
-			collapseTab  = xpathResult.snapshotItem(i);
+			let dontCollapse = false;
+			let collapseTab  = xpathResult.snapshotItem(i);
 
-			parentTab = this.getParentTab(collapseTab);
+			let parentTab = this.getParentTab(collapseTab);
 			if (parentTab) {
 				dontCollapse = true;
 				if (!this.isSubtreeCollapsed(parentTab)) {
@@ -5292,24 +5701,13 @@ TreeStyleTabBrowser.prototype = {
 				}
 			}
 
-			if (!dontCollapse)
+			let manuallyExpanded = this.getTabValue(collapseTab, this.kSUBTREE_EXPANDED_MANUALLY) == 'true';
+			if (!dontCollapse && !manuallyExpanded)
 				this.collapseExpandSubtree(collapseTab, true, aJustNow);
 		}
 
 		this.collapseExpandSubtree(aTab, false, aJustNow);
 	},
-	collapseExpandTreesIntelligentlyWithDelayFor : function TSTBrowser_collapseExpandTreesIntelligentlyWithDelayFor(aTab)
-	{
-		if (this.doingCollapseExpand) return;
-		if (this._cETIWDFTimer)
-			this.window.clearTimeout(this._cETIWDFTimer);
-		this._cETIWDFTimer = this.window.setTimeout(function(aSelf) {
-			aSelf.window.clearTimeout(aSelf._cETIWDFTimer);
-			aSelf._cETIWDFTimer = null;
-			aSelf.collapseExpandTreesIntelligentlyFor(aTab);
-		}, 0, this);
-	},
-	_cETIWDFTimer : null,
  
 	collapseExpandAllSubtree : function TSTBrowser_collapseExpandAllSubtree(aCollapse, aJustNow) 
 	{
@@ -5333,16 +5731,14 @@ TreeStyleTabBrowser.prototype = {
 	
 	scrollTo : function TSTBrowser_scrollTo(aEndX, aEndY) 
 	{
-		// Prevent to restore scroll position for "TabClose".
-		// We override it.
-		this.lastScrollX = -1;
-		this.lastScrollY = -1;
+		if (this.cancelingPerformingAutoScroll) return;
 
 		if (this.animationEnabled || this.smoothScrollEnabled) {
 			this.smoothScrollTo(aEndX, aEndY);
 		}
 		else {
 			try {
+				this.cancelPerformingAutoScroll();
 				this.scrollBoxObject.scrollTo(aEndX, aEndY);
 			}
 			catch(e) {
@@ -5352,9 +5748,9 @@ TreeStyleTabBrowser.prototype = {
 	
 	smoothScrollTo : function TSTBrowser_smoothScrollTo(aEndX, aEndY, aDuration) 
 	{
-		var b = this.mTabBrowser;
-		this.animationManager.removeTask(this.smoothScrollTask);
+		this.cancelPerformingAutoScroll();
 
+		var b = this.mTabBrowser;
 		var scrollBoxObject = this.scrollBoxObject;
 		var x = {}, y = {};
 		scrollBoxObject.getPosition(x, y);
@@ -5376,33 +5772,36 @@ TreeStyleTabBrowser.prototype = {
 		var radian = 90 * Math.PI / 180;
 		var self = this;
 		this.smoothScrollTask = function(aTime, aBeginning, aChange, aDuration) {
+			if (self.isDestroying) return true;
 			var scrollBoxObject = self.scrollBoxObject;
-			if (aTime >= aDuration) {
-				scrollBoxObject.scrollTo(aEndX, aEndY);
-
-				/**
-				 * When there is any expanding tab, we have to retry to scroll.
-				 * if the scroll box was expanded.
-				 */
-				let oldSize = self._getMaxScrollSize(scrollBoxObject);
-				self.Deferred.next(function() {
-					let newSize = self._getMaxScrollSize(scrollBoxObject);
-					let lastTab = self.getLastVisibleTab(self.mTabBrowser);
-					if (
-						// scroll size can be expanded by expanding tabs.
-						oldSize[0] < newSize[0] || oldSize[1] < newSize[1] ||
-						// there are still animating tabs
-						self.getXOffsetOfTab(lastTab) || self.getYOffsetOfTab(lastTab) ||
-						self.evaluateXPath(
-							'child::xul:tab[@'+self.kCOLLAPSING_PHASE+'="'+self.kCOLLAPSING_PHASE_TO_BE_EXPANDED+'"]',
-							self.mTabBrowser.mTabContainer,
-							Ci.nsIDOMXPathResult.BOOLEAN_TYPE
-						).booleanValue
-						)
-						self.smoothScrollTo(aEndX, aEndY, parseInt(aDuration * 0.5));
-					self = null;
-					scrollBoxObject = null;
-				});
+			if (aTime >= aDuration || this.cancelingPerformingAutoScroll) {
+				if (!this.cancelingPerformingAutoScroll) {
+					scrollBoxObject.scrollTo(aEndX, aEndY);
+
+					/**
+					 * When there is any expanding tab, we have to retry to scroll.
+					 * if the scroll box was expanded.
+					 */
+					let oldSize = self._getMaxScrollSize(scrollBoxObject);
+					self.Deferred.next(function() {
+						let newSize = self._getMaxScrollSize(scrollBoxObject);
+						let lastTab = self.getLastVisibleTab(self.mTabBrowser);
+						if (
+							// scroll size can be expanded by expanding tabs.
+							oldSize[0] < newSize[0] || oldSize[1] < newSize[1] ||
+							// there are still animating tabs
+							self.getXOffsetOfTab(lastTab) || self.getYOffsetOfTab(lastTab) ||
+							self.evaluateXPath(
+								'child::xul:tab[@'+self.kCOLLAPSING_PHASE+'="'+self.kCOLLAPSING_PHASE_TO_BE_EXPANDED+'"]',
+								self.mTabBrowser.mTabContainer,
+								Ci.nsIDOMXPathResult.BOOLEAN_TYPE
+							).booleanValue
+							)
+							self.smoothScrollTo(aEndX, aEndY, parseInt(aDuration * 0.5));
+						self = null;
+						scrollBoxObject = null;
+					}).error(self.defaultDeferredErrorHandler);
+				}
 
 				b = null;
 				x = null;
@@ -5453,24 +5852,21 @@ TreeStyleTabBrowser.prototype = {
 			return;
 		}
 
-		var targetTabBox = aTab.boxObject;
+		var targetTabBox = this.getFutureBoxObject(aTab);
 		var baseTabBox = this.getFirstNormalTab(b).boxObject;
 
-		var xOffset = this.getXOffsetOfTab(aTab);
-		var yOffset = this.getYOffsetOfTab(aTab);
-
-		var targetX = (aTab.boxObject.screenX + xOffset < scrollBoxObject.screenX) ?
-			(targetTabBox.screenX + xOffset - baseTabBox.screenX) - (targetTabBox.width * 0.5) :
-			(targetTabBox.screenX + xOffset - baseTabBox.screenX) - scrollBoxObject.width + (targetTabBox.width * 1.5) ;
+		var targetX = (targetTabBox.screenX < scrollBoxObject.screenX) ?
+			(targetTabBox.screenX - baseTabBox.screenX) - (targetTabBox.width * 0.5) :
+			(targetTabBox.screenX - baseTabBox.screenX) - scrollBoxObject.width + (targetTabBox.width * 1.5) ;
 
-		var targetY = (aTab.boxObject.screenY + yOffset < scrollBoxObject.screenY) ?
-			(targetTabBox.screenY + yOffset - baseTabBox.screenY) - (targetTabBox.height * 0.5) :
-			(targetTabBox.screenY + yOffset - baseTabBox.screenY) - scrollBoxObject.height + (targetTabBox.height * 1.5) ;
+		var targetY = (targetTabBox.screenY < scrollBoxObject.screenY) ?
+			(targetTabBox.screenY - baseTabBox.screenY) - (targetTabBox.height * 0.5) :
+			(targetTabBox.screenY - baseTabBox.screenY) - scrollBoxObject.height + (targetTabBox.height * 1.5) ;
 
 		if (aOnlyWhenCurrentTabIsInViewport && b.selectedTab != aTab) {
 			let box = b.selectedTab.boxObject;
-			if (targetTabBox.screenX - box.screenX + baseTabBox.width + xOffset > scrollBoxObject.width ||
-				targetTabBox.screenY - box.screenY + baseTabBox.height + yOffset > scrollBoxObject.height)
+			if (targetTabBox.screenX - box.screenX + baseTabBox.width > scrollBoxObject.width ||
+				targetTabBox.screenY - box.screenY + baseTabBox.height > scrollBoxObject.height)
 				return;
 		}
 
@@ -5481,23 +5877,32 @@ TreeStyleTabBrowser.prototype = {
 	{
 		var b          = this.mTabBrowser;
 		var descendant = this.getDescendantTabs(aTab);
+		var parentTabBox = aTab.boxObject;
+
+		var containerPosition = this.tabStrip.boxObject[this.screenPositionProp];
+		var containerSize     = this.tabStrip.boxObject[this.sizeProp];
+		var parentPosition    = parentTabBox[this.screenPositionProp];
+
 		var lastVisible = aTab;
-		for (var i = descendant.length-1; i > -1; i--)
+		for (let i = descendant.length-1; i > -1; i--)
 		{
-			if (this.isCollapsed(descendant[i])) continue;
-			lastVisible = descendant[i];
+			let tab = descendant[i];
+			if (this.isCollapsed(tab))
+				continue;
+
+			let box = this.getFutureBoxObject(tab);
+			if (box[this.screenPositionProp] + box[this.sizeProp] - parentPosition > containerSize)
+				continue;
+
+			lastVisible = tab;
 			break;
 		}
 
-		if (this.isTabInViewport(aTab) && this.isTabInViewport(lastVisible)) {
+		if (this.isTabInViewport(aTab) && this.isTabInViewport(lastVisible))
 			return;
-		}
 
-		var containerPosition = this.tabStrip.boxObject[this.screenPositionProp];
-		var containerSize     = this.tabStrip.boxObject[this.sizeProp];
-		var parentPosition    = aTab.boxObject[this.screenPositionProp];
-		var lastPosition      = lastVisible.boxObject[this.screenPositionProp];
-		var tabSize           = lastVisible.boxObject[this.sizeProp];
+		var lastPosition = lastVisible.boxObject[this.screenPositionProp];
+		var tabSize      = lastVisible.boxObject[this.sizeProp];
 
 		if (lastPosition - parentPosition + tabSize > containerSize - tabSize) { // out of screen
 			var endPos = parentPosition - this.getFirstNormalTab(b).boxObject[this.screenPositionProp] - tabSize * 0.5;
@@ -5518,7 +5923,134 @@ TreeStyleTabBrowser.prototype = {
 			this.scrollToTab(lastVisible);
 		}
 	},
-   
+  
+	notifyBackgroundTab : function TSTBrowser_notifyBackgroundTab() 
+	{
+		var animateElement = this.mTabBrowser.mTabContainer._animateElement;
+		var attrName = this.kBG_NOTIFY_PHASE;
+		if (!animateElement)
+			return;
+
+		if (this.lastNotifyBackgroundTabAnimation)
+			this.lastNotifyBackgroundTabAnimation.cancel();
+
+		if (!animateElement.hasAttribute(attrName))
+			animateElement.setAttribute(attrName, 'ready');
+
+		var self = this;
+		this.lastNotifyBackgroundTabAnimation = this.Deferred
+			.next(function() {
+				animateElement.setAttribute(attrName, 'notifying');
+			})
+			.wait(0.15)
+			.next(function() {
+				animateElement.setAttribute(attrName, 'finish');
+			})
+			.wait(1)
+			.next(function() {
+				animateElement.removeAttribute(attrName);
+				self.lastNotifyBackgroundTabAnimation = null;
+			})
+			.error(this.defaultDeferredErrorHandler);
+	},
+ 
+	restoreTree : function TSTBrowser_restoreTree() 
+	{
+		if (!this.needRestoreTree || this.useTMPSessionAPI)
+			return;
+
+		this.needRestoreTree = false;
+
+		if (this.useTMPSessionAPI && this.getPref('extensions.tabmix.sessions.manager'))
+			return;
+
+		var level = this.getTreePref('restoreTree.level');
+		if (
+			level <= this.kRESTORE_TREE_LEVEL_NONE ||
+			!this.window.__SS_tabsToRestore ||
+			this.window.__SS_tabsToRestore <= 1
+			)
+			return;
+
+		var onlyVisible = level <= this.kRESTORE_TREE_ONLY_VISIBLE;
+		var tabs = this.getAllTabsArray(this.mTabBrowser);
+		tabs = tabs.filter(function(aTab) {
+			return (
+				aTab.linkedBrowser.__SS_restoreState &&
+				aTab.linkedBrowser.__treestyletab__toBeRestored &&
+				(!onlyVisible || !aTab.hidden)
+			);
+		});
+		if (tabs.length <= 1)
+			return;
+
+		for (let i = 0, maxi = tabs.length; i < maxi; i++)
+		{
+			let tab = tabs[i];
+			let currentId = tab.getAttribute(this.kID);
+			if (this.tabsHash[currentId] == tab)
+				delete this.tabsHash[currentId];
+
+			this.resetTabState(tab);
+
+			tab.setAttribute(this.kID, currentId); // to fallback to it
+			let [id, duplicated] = this._restoreTabId(tab);
+
+			this.setTabValue(tab, this.kID, id);
+			this.tabsHash[id] = tab;
+
+			tab.__treestyletab__restoreState = this.RESTORE_STATE_READY_TO_RESTORE;
+			tab.__treestyletab__duplicated = duplicated;
+		}
+
+		this.updateAllTabsIndent(true);
+
+		// restore tree from bottom safely
+		tabs.reverse()
+			.filter(this.restoreOneTab, this)
+			.forEach(this.updateInsertionPositionInfo, this);
+	},
+	restoreOneTab : function TSTBrowser_restoreOneTab(aTab)
+	{
+		if (aTab.__treestyletab__restoreState != this.RESTORE_STATE_READY_TO_RESTORE)
+			return false;
+
+		let duplicated = aTab.__treestyletab__duplicated;
+
+		let children = this.getTabValue(aTab, this.kCHILDREN);
+		if (children) {
+			this.deleteTabValue(aTab, this.kCHILDREN);
+			let manuallyExpanded = this.getTabValue(aTab, this.kSUBTREE_EXPANDED_MANUALLY) == 'true';
+			let subTreeCollapsed = this.getTabValue(aTab, this.kSUBTREE_COLLAPSED) == 'true';
+			subTreeCollapsed = this._restoreSubtreeCollapsedState(aTab, subTreeCollapsed);
+			let self = this;
+			this._restoreChildTabsRelation(aTab, children, duplicated, function(aChild) {
+				/**
+				 * When the child has the reference to the parent tab, attachTabTo()
+				 * does nothing. To ensure they are correctly related, we have to
+				 * clear the relation here.
+				 */
+				self.deleteTabValue(aChild, self.kPARENT);
+				let refId = self.getTabValue(aChild, self.kINSERT_BEFORE);
+				if (refId && duplicated) refId = self.redirectId(refId);
+				return {
+					forceExpand  : true, // to prevent to collapse the selected tab
+					dontAnimate  : true,
+					insertBefore : self.getTabById(refId)
+				};
+			});
+			this.collapseExpandSubtree(aTab, subTreeCollapsed, true);
+			if (manuallyExpanded && !subTreeCollapsed)
+				this.setTabValue(aTab, this.kSUBTREE_EXPANDED_MANUALLY, true);
+			else
+				this.deleteTabValue(aTab, this.kSUBTREE_EXPANDED_MANUALLY);
+		}
+
+		delete aTab.__treestyletab__duplicated;
+		aTab.__treestyletab__restoreState = this.RESTORE_STATE_STRUCTURE_RESTORED;
+		return true
+	},
+  
 /* sub modules */ 
 	
 	get tabbarDNDObserver() 
@@ -5617,5 +6149,4 @@ TreeStyleTabBrowser.prototype = {
 	cancelHideTabbarForFeedback : function TSTBrowser_cancelHideTabbarForFeedback() { this.autoHide.cancelHideForFeedback(); }
   
 }; 
-// rap('end of definition of browser');
  
diff --git a/modules/fullTooltip.js b/modules/fullTooltip.js
new file mode 100755
index 0000000..9a4bb23
--- /dev/null
+++ b/modules/fullTooltip.js
@@ -0,0 +1,439 @@
+/* ***** BEGIN LICENSE BLOCK ***** 
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Tree Style Tab.
+ *
+ * The Initial Developer of the Original Code is SHIMODA Hiroshi.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): SHIMODA Hiroshi <piro.outsider.reflex at gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ******/
+
+const EXPORTED_SYMBOLS = ['FullTooltipManager'];
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+Components.utils.import('resource://treestyletab-modules/utils.js');
+Components.utils.import('resource://treestyletab-modules/pseudoTreeBuilder.js');
+
+function FullTooltipManager(aOwner)
+{
+	this.init(aOwner);
+}
+FullTooltipManager.prototype = {
+	__proto__ : TreeStyleTabUtils,
+
+	kTOOLTIP_MODE_DEFAULT   : 0,
+	kTOOLTIP_MODE_COLLAPSED : 1,
+	kTOOLTIP_MODE_ALWAYS    : 2,
+
+	get window()
+	{
+		return this.owner.window;
+	},
+
+	get document()
+	{
+		return this.owner.document;
+	},
+ 
+	get tabTooltip() 
+	{
+		return this.document.getElementById('tabbrowser-tab-tooltip');
+	},
+ 
+	get tabFullTooltip() 
+	{
+		return this.document.getElementById('treestyletab-full-tree-tooltip');
+	},
+
+
+	init : function FTM_init(aOwner)
+	{
+		this.owner = aOwner;
+
+		this.tabTooltip.addEventListener('popupshowing', this, true);
+		this.tabTooltip.addEventListener('popuphiding', this, true);
+
+		this.tabFullTooltip.addEventListener('click', this, false);
+		this.tabFullTooltip.addEventListener(PseudoTreeBuilder.kTAB_LINK_CLICK, this, true);
+		this.tabFullTooltip.addEventListener('popupshown', this, true);
+		this.tabFullTooltip.addEventListener('popuphidden', this, true);
+	},
+
+	destroy : function FTM_destroy()
+	{
+		this.cancel();
+		this.stopListenTooltipEvents();
+
+		this.tabTooltip.removeEventListener('popupshowing', this, true);
+		this.tabTooltip.removeEventListener('popuphiding', this, true);
+
+		this.tabFullTooltip.removeEventListener('click', this, false);
+		this.tabFullTooltip.removeEventListener(PseudoTreeBuilder.kTAB_LINK_CLICK, this, true);
+		this.tabFullTooltip.removeEventListener('popupshown', this, true);
+		this.tabFullTooltip.removeEventListener('popuphidden', this, true);
+
+		delete this.owner;
+	},
+
+	handleEvent : function FTM_handleEvent(aEvent) 
+	{
+		switch (aEvent.type)
+		{
+			case 'click':
+				return this.onClick(aEvent);
+
+			case PseudoTreeBuilder.kTAB_LINK_CLICK:
+				return this.onItemClick(aEvent);
+
+			case 'popupshowing':
+				return this.onDefaultTooltipShowing(aEvent);
+
+			case 'popuphiding':
+				return this.onDefaultTooltipHiding(aEvent);
+
+			case 'popupshown':
+				return this.onShown(aEvent);
+
+			case 'popuphidden':
+				return this.onHidden(aEvent);
+
+			case 'mousemove':
+				return this.onTooltipMouseMove(aEvent);
+
+			case 'mouseover':
+				return this.cancelDelayedHide();
+
+			case 'mouseout':
+				return this.hideWithDelay();
+
+			default:
+				return this.onTooltipEvent(aEvent);
+		}
+	},
+
+	getFullTooltipFromEvent : function FTM_getFullTooltipFromEvent(aEvent)
+	{
+		return this.evaluateXPath(
+				'ancestor-or-self::xul:tooltip[@id="'+this.tabFullTooltip.id+'"]',
+				aEvent.target,
+				Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
+			).singleNodeValue;
+	},
+
+	onClick : function FTM_onClick(aEvent)
+	{
+		this.tabFullTooltip.hidePopup();
+	},
+
+	onItemClick : function FTM_onItemClick(aEvent)
+	{
+		var id = aEvent.getData('id');
+		if (id) {
+			let tab = this.getTabById(id, this.owner.browser);
+			if (tab) {
+				let event = aEvent.getData('sourceEvent');
+				if (event.button == 1 ||
+					(event.button == 0 && this.isAccelKeyPressed(event)))
+					this.owner.browser.removeTab(tab);
+				else if (event.button != 2)
+					this.owner.browser.selectedTab = tab;
+			}
+		}
+		this.tabFullTooltip.hidePopup();
+	},
+
+	onDefaultTooltipShowing : function FTM_onDefaultTooltipShowing(aEvent) 
+	{
+		this.cancel();
+		this.handleDefaultTooltip(aEvent);
+	},
+
+	onDefaultTooltipHiding : function FTM_onDefaultTooltipHiding(aEvent)
+	{
+		this.cancel();
+	},
+
+	onShown : function FTM_onShown(aEvent) 
+	{
+		this.startListenTooltipEvents();
+
+		var tooltip = this.tabFullTooltip;
+		tooltip.setAttribute('popup-shown', true);
+
+		var w = {},
+			h = {};
+		var box = tooltip.boxObject;
+		var scrollBoxObject = tooltip.firstChild.scrollBoxObject;
+		scrollBoxObject.getScrolledSize(w, h);
+		var currentW = box.width - scrollBoxObject.width + w.value;
+		var currentH = box.height - scrollBoxObject.height + h.value;
+		var currentX = box.screenX;
+		var currentY = box.screenY;
+
+		var currentScreen = Cc['@mozilla.org/gfx/screenmanager;1']
+							.getService(Ci.nsIScreenManager)
+							.screenForRect(box.screenX, box.screenY, box.width, box.height);
+		var screenLeft   = {},
+			screenTop    = {},
+			screenWidth  = {},
+			screenHeight = {};
+		currentScreen.GetRect(screenLeft, screenTop, screenWidth, screenHeight);
+
+		var style = tooltip.style;
+		style.maxWidth = screenWidth.value+'px';
+		style.maxHeight = screenHeight.value+'px';
+		style.minWidth = 0;
+		style.minHeight = 0;
+		if (currentX + currentW + screenLeft.value >= screenWidth.value)
+			style.marginLeft = (Math.max(screenLeft.value, screenWidth.value - currentW) - this.window.screenX)+'px';
+		if (currentY + currentH + screenTop.value >= screenHeight.value)
+			style.marginTop = (Math.max(screenTop.value, screenHeight.value - currentH) - this.window.screenY)+'px';
+	},
+
+	onHidden : function FTM_onHidden(aEvent) 
+	{
+		this.tabFullTooltip.removeAttribute('popup-shown');
+		this.stopListenTooltipEvents();
+		this.clear();
+	},
+
+	onTooltipMouseMove : function FTM_onTooltipMouseMove(aEvent)
+	{
+		if (this.getFullTooltipFromEvent(aEvent))
+			this.cancelDelayedHide();
+		else
+			this.hideWithDelay();
+	},
+
+	onTooltipEvent : function FTM_onTooltipEvent(aEvent)
+	{
+		if (!this.getFullTooltipFromEvent(aEvent))
+			this.hide();
+	},
+
+	startListenTooltipEvents : function FTM_startListenTooltipEvents()
+	{
+		if (this.listening)
+			return;
+		this.window.addEventListener('DOMMouseScroll', this, true);
+		this.window.addEventListener('keydown', this, true);
+		this.window.addEventListener('mousedown', this, true);
+		this.window.addEventListener('mouseup', this, true);
+		this.window.addEventListener('dragstart', this, true);
+		this.window.addEventListener('mousemove', this, true);
+		this.tabFullTooltip.addEventListener('mouseover', this, false);
+		this.tabFullTooltip.addEventListener('mouseout', this, false);
+		this.listening = true;
+	},
+
+	stopListenTooltipEvents : function FTM_stopListenTooltipEvents()
+	{
+		if (!this.listening)
+			return;
+		this.window.removeEventListener('DOMMouseScroll', this, true);
+		this.window.removeEventListener('keydown', this, true);
+		this.window.removeEventListener('mousedown', this, true);
+		this.window.removeEventListener('mouseup', this, true);
+		this.window.removeEventListener('dragstart', this, true);
+		this.window.removeEventListener('mousemove', this, true);
+		this.tabFullTooltip.removeEventListener('mouseover', this, false);
+		this.tabFullTooltip.removeEventListener('mouseout', this, false);
+		this.listening = false;
+	},
+
+
+	handleDefaultTooltip : function FTM_handleDefaultTooltip(aEvent) 
+	{
+		var tab = this.getTabFromChild(this.document.tooltipNode);
+		if (!tab || tab.localName != 'tab')
+			return;
+
+		var label;
+		var collapsed = this.isSubtreeCollapsed(tab);
+		var mode = this.getTreePref('tooltip.mode');
+
+		var base = parseInt(tab.getAttribute(this.kNEST) || 0);
+		var descendant = this.getDescendantTabs(tab);
+		var indentPart = '  ';
+		var tree = null;
+		var fullTooltipExtraLabel = '';
+		if (mode > this.kTOOLTIP_MODE_DEFAULT &&
+			descendant.length) {
+			let tabs = [tab].concat(descendant);
+			let tabsToBeListed = tabs.slice(0, Math.max(1, this.getTreePref('tooltip.maxCount')));
+			tree = tabsToBeListed
+					.map(function(aTab) {
+						let label = aTab.getAttribute('label');
+						let indent = '';
+						let nest = parseInt(aTab.getAttribute(this.kNEST) || 0) - base;
+						for (let i = 0; i < nest; i++)
+						{
+							indent += indentPart;
+						}
+						return this.treeBundle.getFormattedString('tooltip.item.label', [label, indent]);
+					}, this)
+					.join('\n');
+			if (tabs.length != tabsToBeListed.length) {
+				tree += '\n'+indentPart+this.treeBundle.getFormattedString('tooltip.more', [tabs.length-tabsToBeListed.length]);
+			}
+		}
+
+		if ('mOverCloseButton' in tab && tab.mOverCloseButton) {
+			if (descendant.length &&
+				(collapsed || this.getTreePref('closeParentBehavior') == this.kCLOSE_PARENT_BEHAVIOR_CLOSE_ALL_CHILDREN)) {
+				label = tree || tab.getAttribute('label');
+				label = label ?
+						this.treeBundle.getFormattedString('tooltip.closeTree.labeled', [label]) :
+						this.treeBundle.getString('tooltip.closeTree') ;
+				fullTooltipExtraLabel = this.treeBundle.getFormattedString('tooltip.closeTree.labeled', ['%TREE%']).split(/\s*%TREE%\s*/);
+			}
+		}
+		else if (tab.getAttribute(this.kTWISTY_HOVER) == 'true') {
+			let key = collapsed ?
+						'tooltip.expandSubtree' :
+						'tooltip.collapseSubtree' ;
+			label = tree || tab.getAttribute('label');
+			label = label ?
+					this.treeBundle.getFormattedString(key+'.labeled', [label]) :
+					this.treeBundle.getString(key) ;
+			fullTooltipExtraLabel = this.treeBundle.getFormattedString(key+'.labeled', ['%TREE%']).split(/\s*%TREE%\s*/);
+		}
+		else if (collapsed || mode == this.kTOOLTIP_MODE_ALWAYS) {
+			label = tree;
+		}
+
+		if (!label)
+			return;
+
+		aEvent.target.setAttribute('label', label);
+		aEvent.stopPropagation();
+
+		this.setup(aEvent.target, tab, fullTooltipExtraLabel);
+	},
+
+
+	setup : function FTM_setup(aBaseTooltip, aTab, aExtraLabels) 
+	{
+		this.cancel();
+
+		var delay = this.getTreePref('tooltip.fullTooltipDelay');
+		if (delay < 0)
+			return;
+
+		this._fullTooltipTimer = this.window.setTimeout(function(aSelf) {
+			var box = aBaseTooltip.boxObject;
+			var x = box.screenX - this.window.screenX;
+			var y = box.screenY - this.window.screenY;
+			var w = box.width;
+			var h = box.height;
+			aBaseTooltip.hidePopup();
+
+			aSelf.fill(aTab, aExtraLabels);
+
+			var tooltip = aSelf.tabFullTooltip;
+			let (style = tooltip.style) {
+				style.marginLeft = x+'px';
+				style.marginTop = y+'px';
+				style.maxWidth = style.minWidth = w+'px';
+				style.maxHeight = style.minHeight = h+'px';
+			}
+			tooltip.openPopupAtScreen(this.window.screenX, this.window.screenY, false);
+		}, Math.max(delay, 0), this);
+	},
+
+	cancel : function FTM_destroyFullTooltip()
+	{
+		if (this._fullTooltipTimer) {
+			this.window.clearTimeout(this._fullTooltipTimer);
+			this._fullTooltipTimer = null;
+		}
+		this.hide();
+	},
+
+	hide : function FTM_hide()
+	{
+		this.cancelDelayedHide();
+		this.tabFullTooltip.hidePopup();
+	},
+
+
+	hideWithDelay : function FTM_hideWithDelay()
+	{
+		this.cancelDelayedHide();
+		this._delayedHideTimer = this.window.setTimeout(function(aSelf) {
+			aSelf.hide();
+		}, 500, this);
+	},
+
+	cancelDelayedHide : function FTM_cancelDelayedHide()
+	{
+		if (this._delayedHideTimer) {
+			this.window.clearTimeout(this._delayedHideTimer);
+			this._delayedHideTimer = null;
+		}
+	},
+
+
+	fill : function FTM_fill(aTab, aExtraLabels)
+	{
+		this.clear();
+
+		var tree = PseudoTreeBuilder.build(aTab);
+		var root = this.document.createElement('arrowscrollbox');
+		root.setAttribute('orient', 'vertical');
+		root.setAttribute('flex', 1);
+
+		if (aExtraLabels) {
+			if (typeof aExtraLabels == 'string')
+				aExtraLabels = [aExtraLabels];
+			for (let i = 0, maxi = aExtraLabels.length; i < maxi; i++)
+			{
+				let label = aExtraLabels[i];
+				label = label.replace(/^\s+|\s+$/g, '');
+				if (!label)
+					continue;
+				root.appendChild(this.document.createElement('description'))
+					.appendChild(this.document.createTextNode(label));
+			}
+		}
+
+		root.insertBefore(tree, root.firstChild && root.firstChild.nextSibling);
+
+		this.tabFullTooltip.appendChild(root);
+	},
+
+	clear : function FTM_clear()
+	{
+		var range = this.document.createRange();
+		range.selectNodeContents(this.tabFullTooltip);
+		range.deleteContents();
+		range.detach();
+	}
+};
diff --git a/modules/groupTab.js b/modules/groupTab.js
new file mode 100755
index 0000000..3d344c5
--- /dev/null
+++ b/modules/groupTab.js
@@ -0,0 +1,388 @@
+/* ***** BEGIN LICENSE BLOCK ***** 
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Tree Style Tab.
+ *
+ * The Initial Developer of the Original Code is SHIMODA Hiroshi.
+ * Portions created by the Initial Developer are Copyright (C) 2010-2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): SHIMODA Hiroshi <piro.outsider.reflex at gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ******/
+
+const EXPORTED_SYMBOLS = ['GroupTab']; 
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+Components.utils.import('resource://treestyletab-modules/utils.js');
+Components.utils.import('resource://treestyletab-modules/pseudoTreeBuilder.js');
+
+function GroupTab(aWindow)
+{
+	this.window = aWindow;
+	this.init();
+}
+
+GroupTab.prototype = {
+	__proto__ : TreeStyleTabUtils,
+
+	initialized : false,
+	shouldUpdate : false,
+
+	window : null,
+	get document()
+	{
+		return this.window && this.window.document;
+	},
+	get location()
+	{
+		return this.window && this.window.location;
+	},
+
+	get label()
+	{
+		return this.document.getElementById('label');
+	},
+	get editor()
+	{
+		return this.document.getElementById('editor');
+	},
+	get deck()
+	{
+		return this.document.getElementById('deck');
+	},
+
+	get title()
+	{
+		if (this._title === null) {
+			let title = this.location.href.split('?')[1];
+			this._title = (this.location.href.indexOf('?') > -1 && title) ?
+							this.trim(decodeURIComponent(title)) :
+							'' ;
+		}
+		return this._title;
+	},
+	_title : null,
+
+	get browser()
+	{
+		var ownerWindow = this.window
+						.QueryInterface(Ci.nsIInterfaceRequestor)
+						.getInterface(Ci.nsIWebNavigation)
+						.QueryInterface(Ci.nsIDocShell)
+						.QueryInterface(Ci.nsIDocShellTreeItem)
+						.parent;
+		if (ownerWindow) {
+			ownerWindow = ownerWindow
+							.QueryInterface(Ci.nsIWebNavigation)
+							.document
+							.defaultView;
+			return ownerWindow.gBrowser;
+		}
+		return null;
+	},
+
+	getOwnerTab : function GT_getOwnerTab(aWindow)
+	{
+		var b = this.browser;
+		return b &&
+				b.treeStyleTab &&
+				b.treeStyleTab.getTabFromFrame(aWindow || this.window);
+	},
+
+
+	init : function GT_init()
+	{
+		var title = this.title;
+		if (title) {
+			this.document.title = title;
+			this.document.documentElement.setAttribute('title', title);
+			this.label.value = title;
+			this.label.setAttribute('tooltiptext', title);
+			this.editor.value = title;
+		}
+
+		this.window.addEventListener('load', this, false);
+
+		this.window.groupTab = this;
+	},
+
+
+	trim : function GT_trim(aString)
+	{
+		return aString.replace(/^\s+|\s+$/g, '');
+	},
+
+	getTabById : function GT_getTabById(aId)
+	{
+		var b = this.browser;
+		if (aId && b)
+			return b.treeStyleTab.getTabById(aId);
+		return null;
+	},
+
+
+	enterEdit : function GT_enterEdit()
+	{
+		if (this.deck.selectedIndex == 1) return;
+
+		this.editor.value = this.label.value;
+		this.deck.selectedIndex = 1;
+		this.editor.focus();
+		this.editor.select();
+	},
+
+	exitEdit : function GT_exitEdit()
+	{
+		if (this.deck.selectedIndex == 0) return;
+
+		var old = this.trim(this.label.value);
+		var value = this.trim(this.editor.value);
+		this.document.title = this.label.value = value;
+		this.label.setAttribute('tooltiptext', value);
+		this.document.documentElement.setAttribute('title', value);
+
+		if (value != old)
+			this.location.replace(this.location.href.split('?')[0]+'?'+encodeURIComponent(value));
+
+		this.editor.blur();
+		this.deck.selectedIndex = 0;
+	},
+
+
+	updateTree : function GT_updateTree()
+	{
+		if (!this.window || this.window.closed)
+			return;
+
+		var tree = this.document.getElementById('tree');
+
+		var range = this.document.createRange();
+		range.selectNodeContents(tree);
+		range.deleteContents();
+		range.detach();
+
+		var contents = PseudoTreeBuilder.build(this.getOwnerTab());
+		if (contents)
+			tree.appendChild(contents);
+	},
+
+	checkUpdateTreeNow : function GT_checkUpdateTreeNow()
+	{
+		if (this.getOwnerTab().selected)
+			this.window.setTimeout(function(aSelf) {
+				if (aSelf.window && !aSelf.window.closed)
+					aSelf.onTabSelect();
+			}, 0, this);
+	},
+
+
+	handleEvent : function GT_handleEvent(aEvent)
+	{
+		switch (aEvent.type)
+		{
+			case 'load':
+				if (aEvent.currentTarget == this.window)
+					this.onLoad(aEvent);
+				else
+					this.onDocumentModified(aEvent);
+				return;
+
+			case 'unload':
+			case 'TabClose':
+				return this.onUnload(aEvent);
+
+			case 'click':
+				return this.onClick(aEvent);
+			case 'dblclick':
+				return this.onDblClick(aEvent);
+			case 'keypress':
+				return this.onKeyPress(aEvent);
+
+			case PseudoTreeBuilder.kTAB_LINK_CLICK:
+				return this.onItemClick(aEvent);
+
+			case 'TabSelect':
+				return this.onTabSelect(aEvent);
+			case 'TabMove':
+			case this.kEVENT_TYPE_ATTACHED:
+				return this.onTabAttached(aEvent);
+			case this.kEVENT_TYPE_DETACHED:
+				return this.onTabDetached(aEvent);
+
+			case 'DOMTitleChanged':
+				return this.onDocumentModified(aEvent);
+		}
+	},
+
+	onLoad : function GT_onLoad(aEvent)
+	{
+		this.window.removeEventListener('load', this, false);
+
+		if (this.initialized)
+			return;
+
+		var tab = this.getOwnerTab();
+
+		this.updateTree();
+
+		this.window.addEventListener('unload', this, false);
+		this.window.addEventListener('click', this, false);
+		this.window.addEventListener('dblclick', this, false);
+
+		tab.addEventListener('TabSelect', this, false);
+		tab.addEventListener('TabClose', this, false);
+		tab.parentNode.addEventListener('TabMove', this, false);
+		tab.parentNode.addEventListener(this.kEVENT_TYPE_ATTACHED, this, false);
+		tab.parentNode.addEventListener(this.kEVENT_TYPE_DETACHED, this, false);
+
+		var b = this.browser;
+		b.addEventListener('load', this, true);
+		b.addEventListener('DOMTitleChanged', this, true);
+
+		this.editor.addEventListener('keypress', this, false);
+
+		this.document.getElementById('tree')
+			.addEventListener(PseudoTreeBuilder.kTAB_LINK_CLICK, this, false);
+
+		this.initialized = true;
+	},
+
+	onUnload : function GT_onUnload(aEvent)
+	{
+		var tab = this.getOwnerTab();
+		if (!this.initialized || !tab)
+			return;
+
+		this.window.removeEventListener('unload', this, false);
+		this.window.removeEventListener('click', this, false);
+		this.window.removeEventListener('dblclick', this, false);
+
+		tab.removeEventListener('TabSelect', this, false);
+		tab.removeEventListener('TabClose', this, false);
+		tab.parentNode.removeEventListener('TabMove', this, false);
+		tab.parentNode.removeEventListener(this.kEVENT_TYPE_ATTACHED, this, false);
+		tab.parentNode.removeEventListener(this.kEVENT_TYPE_DETACHED, this, false);
+
+		var b = this.browser;
+		b.removeEventListener('load', this, true);
+		b.removeEventListener('DOMTitleChanged', this, true);
+
+		this.editor.removeEventListener('keypress', this, false);
+
+		this.document.getElementById('tree')
+			.removeEventListener(PseudoTreeBuilder.kTAB_LINK_CLICK, this, false);
+
+		delete this.window.groupTab;
+		delete this.window;
+	},
+
+	onClick : function GT_onClick(aEvent)
+	{
+		if (aEvent.target == this.editor) return;
+		if (aEvent.target == this.label)
+			this.enterEdit();
+		else
+			this.exitEdit();
+	},
+
+	onDblClick : function GT_onDblClick(aEvent)
+	{
+		if (aEvent.target == this.editor) return;
+		if (this.deck.selectedIndex == 0)
+			this.enterEdit();
+		else
+			this.exitEdit();
+	},
+
+	onKeyPress : function GT_onKeyPress(aEvent)
+	{
+		if (aEvent.keyCode == aEvent.DOM_VK_ENTER ||
+			aEvent.keyCode == aEvent.DOM_VK_RETURN ||
+			aEvent.keyCode == aEvent.DOM_VK_ESCAPE)
+			this.exitEdit();
+	},
+
+	onItemClick : function GT_onItemClick(aEvent)
+	{
+		var b = this.browser;
+		if (!b)
+			return;
+
+		var tab = this.getTabById(aEvent.getData('id'));
+		if (!tab)
+			return;
+
+		var event = aEvent.getData('sourceEvent');
+		if (event.button == 1 ||
+			(event.button == 0 && this.isAccelKeyPressed(event)))
+			b.removeTab(tab);
+		else if (event.button != 2)
+			b.selectedTab = tab;
+	},
+
+	onTabSelect : function GT_onTabSelect(aEvent)
+	{
+		if (this.shouldUpdate)
+			this.updateTree();
+
+		this.shouldUpdate = false;
+	},
+
+	onTabAttached : function GT_onTabAttached(aEvent)
+	{
+		var tab = aEvent.getData('parentTab');
+		var id = tab.getAttribute(this.kID);
+		if (tab == this.getOwnerTab() ||
+			this.document.getElementsByAttribute('tab-id', id).length)
+			this.shouldUpdate = true;
+
+		this.checkUpdateTreeNow();
+	},
+
+	onTabDetached : function GT_onTabDetached(aEvent)
+	{
+		var tab = aEvent.originalTarget;
+		var id = tab.getAttribute(this.kID);
+		if (this.document.getElementsByAttribute('tab-id', id).length)
+			this.shouldUpdate = true;
+
+		this.checkUpdateTreeNow();
+	},
+
+	onDocumentModified : function GT_onDocumentModified(aEvent)
+	{
+		var tab = this.getOwnerTab(aEvent.target.defaultView.top);
+		if (tab) {
+			let id = tab.getAttribute(this.kID);
+			if (this.document.getElementsByAttribute('tab-id', id).length)
+				this.shouldUpdate = true;
+		}
+
+		this.checkUpdateTreeNow();
+	}
+};
diff --git a/modules/lib/animationManager.js b/modules/lib/animationManager.js
index 419512a..e060ed8 100755
--- a/modules/lib/animationManager.js
+++ b/modules/lib/animationManager.js
@@ -19,7 +19,7 @@
    // restart after doing something
    window['piro.sakura.ne.jp'].animationManager.start();
 
- license: The MIT License, Copyright (c) 2009-2011 SHIMODA "Piro" Hiroshi
+ license: The MIT License, Copyright (c) 2009-2012 SHIMODA "Piro" Hiroshi
    http://github.com/piroor/fxaddonlibs/blob/master/license.txt
  original:
    http://github.com/piroor/fxaddonlibs/blob/master/animationManager.js
@@ -46,7 +46,7 @@ if (typeof window == 'undefined' ||
 }
 
 (function() {
-	const currentRevision = 8;
+	const currentRevision = 10;
 
 	if (!('piro.sakura.ne.jp' in window)) window['piro.sakura.ne.jp'] = {};
 
@@ -129,14 +129,24 @@ if (typeof window == 'undefined' ||
 			}
 			if (this._windows.length) { // Firefox 4-
 				this._windows.forEach(function(aWindow) {
-					if (this._listeningWindows.indexOf(aWindow) < 0) {
-						aWindow.addEventListener('MozBeforePaint', this, false);
-						this._listeningWindows.push(aWindow);
-						this._listeningWindowSafetyTimers.push(window.setTimeout(function(aSelf) {
-							aSelf.handleEvent(aWindow);
+					var index = this._animatingWindows.indexOf(aWindow);
+					var callback;
+					if (index < 0) {
+						let self = this;
+						callback = function() {
+							self.processAnimationFrame(aWindow);
+						};
+						this._animatingWindowCallbacks.push(callback);
+						this._animatingWindows.push(aWindow);
+
+						this._animatingWindowSafetyTimers.push(window.setTimeout(function(aSelf) {
+							aSelf.processAnimationFrame(aWindow);
 						}, 1000, this));
 					}
-					aWindow.mozRequestAnimationFrame();
+					else {
+						callback = this._animatingWindowCallbacks[index];
+					}
+					aWindow.mozRequestAnimationFrame(callback);
 				}, this);
 			}
 		},
@@ -147,13 +157,13 @@ if (typeof window == 'undefined' ||
 				window.clearInterval(this.timer);
 				this.timer = null;
 			}
-			if (this._listeningWindows.length) { // Firefox 4-
-				this._listeningWindows.forEach(function(aWindow, aIndex) {
-					aWindow.removeEventListener('MozBeforePaint', this, false);
-					window.clearTimeout(this._listeningWindowSafetyTimers[aIndex]);
+			if (this._animatingWindows.length) { // Firefox 4-
+				this._animatingWindows.forEach(function(aWindow, aIndex) {
+					window.clearTimeout(this._animatingWindowSafetyTimers[aIndex]);
 				}, this);
-				this._listeningWindows = [];
-				this._listeningWindowSafetyTimers = [];
+				this._animatingWindows = [];
+				this._animatingWindowSafetyTimers = [];
+				this._animatingWindowCallbacks = [];
 			}
 		},
 
@@ -170,8 +180,9 @@ if (typeof window == 'undefined' ||
 
 		// Firefox 4 animation frame API
 		_windows : windows,
-		_listeningWindows : [],
-		_listeningWindowSafetyTimers : [],
+		_animatingWindows : [],
+		_animatingWindowSafetyTimers : [],
+		_animatingWindowCallbacks : [],
 
 		_isAnimationFrameAvailable : function(aWindow)
 		{
@@ -185,45 +196,43 @@ if (typeof window == 'undefined' ||
 						return aTask.window && this._windows.indexOf(aTask.window) > -1;
 					}, this))
 					return true;
-				let index = this._listeningWindows.indexOf(aWindow);
+				let index = this._animatingWindows.indexOf(aWindow);
 				if (index > -1) {
-					let timer = this._listeningWindowSafetyTimers[index];
+					let timer = this._animatingWindowSafetyTimers[index];
 					if (timer)
 						window.clearTimeout(timer);
-					this._listeningWindows.splice(index, 1);
-					this._listeningWindowSafetyTimers.splice(index, 1);
-					aWindow.removeEventListener('MozBeforePaint', this, false);
+					this._animatingWindows.splice(index, 1);
+					this._animatingWindowSafetyTimers.splice(index, 1);
+					this._animatingWindowCallbacks.splice(index, 1);
 				}
 				return false;
 			}, this);
 		},
 
-		handleEvent : function(aEvent)
+		processAnimationFrame : function(aWindow)
 		{
-			var w = aEvent && aEvent instanceof Ci.nsIDOMEvent ? aEvent.target.defaultView : aEvent ;
-			var index = this._listeningWindows.indexOf(w);
+			var index = this._animatingWindows.indexOf(aWindow);
 			if (index > -1) {
-				let timer = this._listeningWindowSafetyTimers[index];
+				let timer = this._animatingWindowSafetyTimers[index];
 				if (timer) window.clearTimeout(timer);
-				this._listeningWindowSafetyTimers[index] = null;
-				aEvent = null;
+				this._animatingWindowSafetyTimers[index] = null;
 			}
-			this.onAnimation(this, aEvent);
+			this.onAnimation(this, aWindow);
 			this._cleanUpWindows();
-			if (index > -1)
-				w.mozRequestAnimationFrame();
+			if (index > -1 && this._animatingWindowCallbacks[index])
+				aWindow.mozRequestAnimationFrame(this._animatingWindowCallbacks[index]);
 		},
 
-		onAnimation : function(aSelf, aEvent) 
+		onAnimation : function(aSelf, aWindow) 
 		{
 			// task should return true if it finishes.
-			var now = aEvent ? aEvent.timeStamp : (new Date()).getTime() ;
+			var now = (new Date()).getTime() ;
 			var tasks = aSelf.tasks;
 			aSelf.tasks = [null];
 			tasks = tasks.filter(function(aTask) {
 				if (!aTask)
 					return false;
-				if (aEvent && aTask.window != aEvent.target.defaultView)
+				if (aWindow && aTask.window != aWindow)
 					return true;
 				try {
 					var time = Math.min(aTask.duration, now - aTask.start);
@@ -236,6 +245,7 @@ if (typeof window == 'undefined' ||
 					return !finished && (time < aTask.duration);
 				}
 				catch(e) {
+					dump(e+'\n'+e.stack+'\n');
 				}
 				return false;
 			});
diff --git a/modules/lib/autoScroll.js b/modules/lib/autoScroll.js
index 920c3aa..bd4ceb4 100755
--- a/modules/lib/autoScroll.js
+++ b/modules/lib/autoScroll.js
@@ -6,7 +6,7 @@
                         .autoScroll
                         .processAutoScroll(mouseMoveOrDragOverEvent);
 
- license: The MIT License, Copyright (c) 2009-2011 SHIMODA "Piro" Hiroshi
+ license: The MIT License, Copyright (c) 2009-2012 SHIMODA "Piro" Hiroshi
    http://github.com/piroor/fxaddonlibs/blob/master/license.txt
  original:
    http://github.com/piroor/fxaddonlibs/blob/master/autoScroll.js
@@ -30,7 +30,7 @@ if (typeof window == 'undefined' ||
 }
 
 (function() {
-	const currentRevision = 5;
+	const currentRevision = 6;
 
 	if (!('piro.sakura.ne.jp' in window)) window['piro.sakura.ne.jp'] = {};
 
@@ -74,9 +74,24 @@ if (typeof window == 'undefined' ||
 			boxObject.getScrolledSize(maxX, maxY);
 			boxObject.getPosition(curX, curY);
 
+			var firstTab;
+			if (b.visibleTabs) {
+				let pinnedTabsCount = b.ownerDocument.evaluate(
+						'count(child::*[local-name()="tab" and @pinned="true"])',
+						tabs,
+						null,
+						Ci.nsIDOMXPathResult.NUMBER_TYPE,
+						null
+					).numberValue;
+				firstTab = b.visibleTabs[b.visibleTabs.length > pinnedTabsCount ? pinnedTabsCount : 0 ];
+			}
+			else {
+				firstTab = tabs.childNodes[0];
+			}
+
 			var pixels;
 			if (isVertical) {
-				pixels = tabs.childNodes[0].boxObject.height * 0.5;
+				pixels = firstTab.boxObject.height * 0.5;
 				if (isMultirow) pixels *= 0.5;
 				if (aEvent.screenY < boxObject.screenY + this.getUpButtonHeight(b)) {
 					if (curY.value == 0) return false;
@@ -98,7 +113,6 @@ if (typeof window == 'undefined' ||
 				}
 				else if (aEvent.screenX > boxObject.screenX + boxObject.width - this.getDownButtonWidth(b)) {
 					if (innerBoxObject.width + curX.value == maxX.value) return false;
-					return false;
 				}
 				else {
 					return false;
diff --git a/modules/lib/confirmWithPopup.js b/modules/lib/confirmWithPopup.js
new file mode 100755
index 0000000..3d36bef
--- /dev/null
+++ b/modules/lib/confirmWithPopup.js
@@ -0,0 +1,375 @@
+/**
+ * @fileOverview Popup Notification (Door Hanger) Based Confirmation Library for Firefox 4.0 or later
+ * @author       SHIMODA "Piro" Hiroshi
+ * @version      4
+ * Basic usage:
+ *
+ * @example
+ *   Usage:
+ *     Components.utils.import('resource://my-modules/confirmWithPopup.js');
+ *
+ *     confirmWithPopup({
+ *       browser : gBrowser.selectedBrowser,            // the related browser
+ *       label   : 'Ara you ready?',                    // the message
+ *       value   : 'treestyletab-undo-close-tree',      // the internal key (optional)
+ *       anchor  : '....',                              // the ID of the anchor element (optional)
+ *       image   : 'chrome://....png',                  // the icon (optional)
+ *       buttons : ['Yes', 'Yes forever', 'No forever], // button labels
+ *       // Native options for PopupNotifications.show() :
+ *       //   persistence (integer)
+ *       //   timeout (integer)
+ *       //   persistWhileVisible (boolean)
+ *       //   dismissed (boolean)
+ *       //   eventCallback (function)
+ *       //   neverShow (boolean)
+ *       //   popupIconURL (string) : will be used instead of "image" option.
+ *     });
+ *
+ *  JSDeferred style:
+ *    confirmWithPopup(...)
+ *     .next(function(aButtonIndex) {
+ *       // the next callback receives the index of the clicked button.
+ *       switch (aButtonIndex) {
+ *         case 0: return YesAction();
+ *         case 1: return YesForeverAction();
+ *         case 2: return NoForeverAction();
+ *       }
+ *     })
+ *     .error(function(aError) {
+ *       // dismissed or removed (not called if any button is chosen)
+ *       ...
+ *     });
+ *
+ *  without JSDeferred:
+ *    confirmWithPopup({ ...,
+ *      // Yes, Yes Forever, or No Forever
+ *      callback : function(aButtonIndex) { ... },
+ *      // dismissed or removed (not called if any button is chosen)
+ *      onerror  : function(aError) { ... }
+ *    });
+ *
+ * @license
+ *   The MIT License, Copyright (c) 2011-2012 SHIMODA "Piro" Hiroshi
+ *   http://github.com/piroor/fxaddonlibs/blob/master/license.txt
+ * @url http://github.com/piroor/fxaddonlibs/blob/master/confirmWithPopup.js
+ * @url http://github.com/piroor/fxaddonlibs
+ */
+
+if (typeof window == 'undefined')
+	this.EXPORTED_SYMBOLS = ['confirmWithPopup'];
+
+// var namespace;
+if (typeof namespace == 'undefined') {
+	// If namespace.jsm is available, export symbols to the shared namespace.
+	// See: http://github.com/piroor/fxaddonlibs/blob/master/namespace.jsm
+	try {
+		let ns = {};
+		Components.utils.import('resource://treestyletab-modules/lib/namespace.jsm', ns);
+		namespace = ns.getNamespaceFor('piro.sakura.ne.jp');
+	}
+	catch(e) {
+		namespace = (typeof window != 'undefined' ? window : null ) || {};
+	}
+}
+
+// This can be extended by JSDeferred.
+// See: https://github.com/cho45/jsdeferred
+try {
+	if (typeof namespace.Deferred == 'undefined')
+		Components.utils.import('resource://treestyletab-modules/lib/jsdeferred.js', namespace);
+}
+catch(e) {
+}
+
+var available = false;
+try {
+	Components.utils.import('resource://gre/modules/PopupNotifications.jsm');
+	available = true;
+}
+catch(e) {
+}
+
+var confirmWithPopup;
+(function() {
+	const currentRevision = 4;
+
+	var loadedRevision = 'confirmWithPopup' in namespace ?
+			namespace.confirmWithPopup.revision :
+			0 ;
+	if (loadedRevision && loadedRevision > currentRevision) {
+		confirmWithPopup = namespace.confirmWithPopup;
+		return;
+	}
+
+	if (!available)
+		return confirmWithPopup = undefined;
+
+	const Cc = Components.classes;
+	const Ci = Components.interfaces;
+
+	const DEFAULT_ANCHOR_ICON = 'default-notification-icon';
+	const NATIVE_OPTIONS = 'persistence,timeout,persistWhileVisible,dismissed,eventCallback,neverShow,popupIconURL'.split(',');
+	const OPTIONS = 'browser,tab,label,value,anchor,image,imageWidth,imageHeight,button,buttons,callback,onerror'.split(',');
+
+	function next(aCallback) {
+		Cc['@mozilla.org/timer;1']
+			.createInstance(Ci.nsITimer)
+			.init(aCallback, 0, Ci.nsITimer.TYPE_ONE_SHOT);
+	}
+
+	// We have to use a custom stylesheet to show the anchor element.
+	function addStyleSheet(aDocument, aOptions) {
+		var uri = 'data:text/css,'+encodeURIComponent(
+				(aOptions.image ?
+					'.popup-notification-icon[popupid="'+aOptions.id+'"] {'+
+					'	list-style-image: url("'+aOptions.image+'");'+
+					(aOptions.imageWidth ? 'width: '+aOptions.imageWidth+'px;' : '' )+
+					(aOptions.imageHeight ? 'height: '+aOptions.imageHeight+'px;' : '' )+
+					'}' :
+					''
+				)+
+				'#notification-popup-box[anchorid="'+aOptions.anchor+'"] > #'+aOptions.anchor+' {'+
+				'	display: -moz-box;'+
+				'}'
+			);
+
+		var styleSheets = aDocument.styleSheets;
+		for (var i = 0, maxi = styleSheets.length; i < maxi; i++) {
+			if (styleSheets[i].href == uri)
+				return styleSheets[i].ownerNode;
+		}
+
+		var style = aDocument.createProcessingInstruction('xml-stylesheet',
+				'type="text/css" href="'+uri+'"'
+			);
+		aDocument.insertBefore(style, aDocument.documentElement);
+		return style;
+	}
+
+	function normalizeOptions(aOptions) {
+		var options = collectNativeOptions(aOptions);
+		OPTIONS.forEach(function(aOption) {
+			options[aOption] = aOptions[aOption] ;
+		});
+
+		options.image = options.popupIconURL || options.image ;
+
+		// we should accept single button type popup
+		if (!options.buttons && options.button)
+			options.buttons = [options.button];
+
+		if (!options.browser && options.tab)
+			options.browser = options.tab.linkedBrowser;
+
+		if (!options.anchor)
+			options.anchor = DEFAULT_ANCHOR_ICON;
+
+		return options;
+	}
+
+	function collectNativeOptions(aOptions) {
+		var options = {};
+		NATIVE_OPTIONS.forEach(function(aOption) {
+			options[aOption] = aOptions.option && aOptions.option[aOption] || aOptions[aOption] ;
+		});
+		return options;
+	}
+
+	confirmWithPopup = function confirmWithPopup(aOptions) 
+	{
+		var options = normalizeOptions(aOptions);
+		var nativeOptions = collectNativeOptions(options);
+
+		var deferred = namespace.Deferred ?
+						new namespace.Deferred() :
+						{ // fake deferred
+							next : next,
+							call : function(aValue) { options.callback && options.callback.call(aOptions, aValue); },
+							fail : function(aError) { options.onerror && options.onerror.call(aOptions, aError); }
+						};
+
+		if (!options.buttons) {
+			return deferred
+					.next(function() {
+						throw new Error('confirmWithPopup requires any button!');
+					});
+		}
+
+		if (!options.browser)
+			return deferred
+					.next(function() {
+						throw new Error('confirmWithPopup requires a <xul:browser/>!');
+					});
+
+		var doc = options.browser.ownerDocument;
+		var style;
+		var done = false;
+		var postProcess = function() {
+				if (doc && style) {
+					doc.removeChild(style);
+					style = null;
+				}
+			};
+		var showPopup = function() {
+			var accessKeys = [];
+			var numericAccessKey = 0;
+			var buttons = options.buttons.map(function(aLabel, aIndex) {
+					// see resource://gre/modules/CommonDialog.jsm
+					var accessKey;
+					var match;
+					if (match = aLabel.match(/^\s*(.*?)\s*\(\&([^&])\)(:)?$/)) {
+						aLabel = (match[1] + (match[3] || '')).replace(/\&\&/g, '&');
+						accessKey = match[2];
+					}
+					else if (match = aLabel.match(/^\s*(.*[^&])?\&(([^&]).*$)/)) {
+						aLabel = ((match[1] || '') + match[2]).replace(/\&\&/g, '&');
+						accessKey = match[3];
+					}
+					else {
+						let lastUniqueKey;
+						let sanitizedLabel = [];
+						for (let i = 0, maxi = aLabel.length; i < maxi; i++)
+						{
+							let possibleAccessKey = aLabel.charAt(i);
+							if (!lastUniqueKey &&
+								accessKeys.indexOf(possibleAccessKey) < 0) {
+								lastUniqueKey = possibleAccessKey;
+							}
+							sanitizedLabel.push(possibleAccessKey);
+						}
+						if (!accessKey)
+							accessKey = lastUniqueKey;
+						if (!accessKey || !/[0-9a-z]/i.test(accessKey))
+							accessKey = ++numericAccessKey;
+
+						aLabel = sanitizedLabel.join('').replace(/\&\&/g, '&');
+					}
+
+					accessKeys.push(accessKey);
+
+					return {
+						label     : aLabel,
+						accessKey : accessKey,
+						callback  : function() {
+							done = true;
+							try {
+								deferred.call(aIndex);
+							}
+							finally {
+								postProcess();
+							}
+						}
+					};
+				});
+
+			var primaryAction = buttons[0];
+			var secondaryActions = buttons.length > 1 ? buttons.slice(1) : null ;
+
+			options.id = options.value || 'confirmWithPopup-'+encodeURIComponent(options.label);
+
+			style = addStyleSheet(doc, options);
+
+			try {
+				/**
+				 * 1st try: Prepare the anchor icon. If the icon isn't shown,
+				 *          the popup is wrongly positioned to the current tab
+				 *          by PopupNotifications.show().
+				 */
+				doc.defaultView.PopupNotifications.show(
+					options.browser,
+					options.id,
+					options.label,
+					options.anchor,
+					primaryAction,
+					secondaryActions,
+					{
+						__proto__ : nativeOptions,
+						dismissed : true
+					}
+				);
+				if (!options.dismissed) {
+					/**
+					 * 2nd try: Show the popup.
+					 */
+					let secondTry = function() {
+						doc.defaultView.PopupNotifications.show(
+							options.browser,
+							options.id,
+							options.label,
+							options.anchor,
+							primaryAction,
+							secondaryActions,
+							{
+								__proto__     : nativeOptions,
+								eventCallback : function(aEventType) {
+									try {
+										if (!done && (aEventType == 'removed' || aEventType == 'dismissed'))
+											deferred.fail(aEventType);
+										if (options.eventCallback)
+											options.eventCallback.call(aOptions.options || aOptions, aEventType);
+									}
+									finally {
+										if (aEventType == 'removed')
+											postProcess();
+									}
+								}
+							}
+						);
+					};
+					if (namespace.Deferred)
+						namespace.Deferred.next(secondTry);
+					else
+						next(secondTry);
+				}
+			}
+			catch(e) {
+				deferred.fail(e);
+			}
+		};
+
+		if (options.image && (!options.imageWidth || !options.imageHeight)) {
+			let loader = new doc.defaultView.Image();
+			loader.src = options.image;
+			loader.onload = function() {
+				options.imageWidth = loader.width;
+				options.imageHeight = loader.height;
+				showPopup();
+			};
+			loader.onerror = function() {
+				showPopup();
+			};
+		}
+		else if (namespace.Deferred) {
+			namespace.Deferred.next(showPopup);
+		}
+		else {
+			next(showPopup);
+		}
+
+		if (namespace.Deferred) {
+			return deferred;
+		}
+		else {
+			let originalCall = deferred.call;
+			deferred.call = function(aButtonIndex) {
+				try {
+					originalCall(aButtonIndex);
+				}
+				finally {
+					postProcess();
+				}
+			};
+			let originalFail = deferred.fail;
+			deferred.fail = function(aError) {
+				try {
+					originalFail(aError);
+				}
+				finally {
+					postProcess();
+				}
+			};
+		}
+	};
+
+	namespace.confirmWithPopup = confirmWithPopup;
+})();
diff --git a/modules/lib/confirmWithTab.js b/modules/lib/confirmWithTab.js
deleted file mode 100755
index a6f1f07..0000000
--- a/modules/lib/confirmWithTab.js
+++ /dev/null
@@ -1,226 +0,0 @@
-/**
- * @fileOverview Tab Related Confirmation Library for Firefox 3.5 or later
- * @author       SHIMODA "Piro" Hiroshi
- * @version      5
- * Basic usage:
- *
- * @example
- *   Components.utils.import('resource://my-modules/confirmWithTab.js');
- *
- *   var checkbox = {
- *         label   : 'Never ask me',
- *         checked : false
- *       };
- *   
- *   confirmWithTab({
- *     tab      : gBrowser.selectedTab,           // the related tab
- *     label    : 'Ara you ready?',               // the message
- *     value    : 'treestyletab-undo-close-tree', // the internal key (optional)
- *     buttons  : ['Yes', 'No'],                  // button labels
- *     checkbox : checkbox,                       // checkbox definition (optional)
- *     cancelEvents : ['SSTabRestoring']          // events to cancel this deferred (optional)
- *   })
- *   .next(function(aButtonIndex) {
- *     // the next callback receives the index of the clicked button.
- *     switch (aButtonIndex) {
- *       case 0: // Yes
- *         ...
- *         break;
- *       case 1: // No
- *         ...
- *         break;
- *     }
- *     // after the notification bar is closed, "checked" indicates
- *     // the state of the checkbox when the user clicks a button.
- *     var checked = checkbox.checked;
- *     ...
- *   })
- *   .error(function(aError) {
- *     // if the tab is closed, or any event in the cancelEvents array
- *     // is fired, then an exception is raised.
- *     ...
- *   });
- *
- * @license
- *   The MIT License, Copyright (c) 2010-2011 SHIMODA "Piro" Hiroshi
- *   http://github.com/piroor/fxaddonlibs/blob/master/license.txt
- * @url http://github.com/piroor/fxaddonlibs/blob/master/confirmWithTab.js
- * @url http://github.com/piroor/fxaddonlibs
- */
-
-if (typeof window == 'undefined')
-	this.EXPORTED_SYMBOLS = ['confirmWithTab'];
-
-// var namespace;
-if (typeof namespace == 'undefined') {
-	// If namespace.jsm is available, export symbols to the shared namespace.
-	// See: http://github.com/piroor/fxaddonlibs/blob/master/namespace.jsm
-	try {
-		let ns = {};
-		Components.utils.import('resource://treestyletab-modules/lib/namespace.jsm', ns);
-		namespace = ns.getNamespaceFor('piro.sakura.ne.jp');
-	}
-	catch(e) {
-		namespace = (typeof window != 'undefined' ? window : null ) || {};
-	}
-}
-
-// This depends on JSDeferred.
-// See: https://github.com/cho45/jsdeferred
-if (typeof namespace.Deferred == 'undefined')
-	Components.utils.import('resource://treestyletab-modules/lib/jsdeferred.js', namespace);
-
-var confirmWithTab;
-(function() {
-	const currentRevision = 6;
-
-	var loadedRevision = 'confirmWithTab' in namespace ?
-			namespace.confirmWithTab.revision :
-			0 ;
-	if (loadedRevision && loadedRevision > currentRevision) {
-		confirmWithTab = namespace.confirmWithTab;
-		return;
-	}
-
-	const Ci = Components.interfaces;
-
-	confirmWithTab = function confirmWithTab(aOptions) 
-	{
-		var deferred = new namespace.Deferred();
-		if (!aOptions.buttons) {
-			return deferred
-					.next(function() {
-						throw new Error('confirmWithTab requires one or more buttons!');
-					});
-		}
-
-		var buttonClicked = false;
-		var checkbox;
-		namespace.Deferred.next(function() {
-			aOptions.cancelEvents = (aOptions.cancelEvents || [])
-										.concat(['TabClose'])
-										.sort()
-										.join('\n')
-										.replace(/^(.+)$\n(\1\n)+/gm, '$1\n')
-										.split('\n');
-
-			var tab = aOptions.tab;
-			var b = getTabBrowserFromChild(tab);
-			var box = b.getNotificationBox(tab.linkedBrowser);
-			var accessKeys = [];
-			var numericAccessKey = 0;
-			var notification = box.appendNotification(
-					aOptions.label,
-					aOptions.value || 'confirmWithTab-'+encodeURIComponent(aOptions.label),
-					aOptions.image || null,
-					(aOptions.priority ?
-						(typeof aOptions.priority == 'number' ? aOptions.priority : box[aOptions.priority] ) :
-						box.PRIORITY_INFO_MEDIUM
-					),
-					aOptions.buttons.map(function(aLabel, aIndex) {
-						var accessKey;
-						var match = aLabel.match(/\s*\(&([0-9a-z])\)/i);
-						if (match) {
-							accessKey = match[1];
-							aLabel = aLabel.replace(match[0], '');
-						}
-						else {
-							let lastUniqueKey;
-							let sanitizedLabel = [];
-							for (let i = 0, maxi = aLabel.length; i < maxi; i++)
-							{
-								let possibleAccessKey = aLabel.charAt(i);
-								if (possibleAccessKey == '&' && i < maxi-1) {
-									possibleAccessKey = aLabel.charAt(i+1);
-									if (possibleAccessKey != '&') {
-										accessKey = possibleAccessKey;
-									}
-									i++;
-								}
-								else if (!lastUniqueKey &&
-										accessKeys.indexOf(possibleAccessKey) < 0) {
-									lastUniqueKey = possibleAccessKey;
-								}
-								sanitizedLabel.push(possibleAccessKey);
-							}
-							if (!accessKey)
-								accessKey = lastUniqueKey;
-							if (!accessKey || !/[0-9a-z]/i.test(accessKey))
-								accessKey = ++numericAccessKey;
-
-							aLabel = sanitizedLabel.join('');
-						}
-
-						accessKeys.push(accessKey);
-
-						return {
-							label     : aLabel,
-							accessKey : accessKey,
-							callback  : function() {
-								buttonClicked = true;
-								deferred.call(aIndex);
-							}
-						};
-					})
-				);
-
-			if (aOptions.checkbox) {
-				checkbox = notification.ownerDocument.createElement('checkbox');
-				checkbox.setAttribute('label', aOptions.checkbox.label);
-				if (aOptions.checkbox.checked)
-					checkbox.setAttribute('checked', 'true');
-
-				let container = notification.ownerDocument.createElement('hbox');
-				container.setAttribute('align', 'center');
-				container.appendChild(checkbox);
-
-				notification.appendChild(container);
-			}
-
-			var strip = b.tabContainer || b.mTabContainer;
-			var handleEvent = function handleEvent(aEvent) {
-					if (aEvent.type == 'DOMNodeRemoved' && aEvent.target != notification)
-						return;
-					if (aOptions.cancelEvents)
-						aOptions.cancelEvents.forEach(function(aEventType) {
-							strip.removeEventListener(aEventType, handleEvent, false);
-						});
-					if (notification.parentNode)
-						notification.parentNode.removeEventListener('DOMNodeRemoved', handleEvent, false);
-					if (aEvent.type != 'DOMNodeRemoved')
-						notification.close();
-					if (!buttonClicked)
-						deferred.fail(aEvent);
-				};
-			if (aOptions.cancelEvents)
-				aOptions.cancelEvents.forEach(function(aEventType) {
-					strip.addEventListener(aEventType, handleEvent, false);
-				});
-			notification.parentNode.addEventListener('DOMNodeRemoved', handleEvent, false);
-		});
-
-		return deferred
-				.next(function(aButtonIndex) {
-					buttonClicked = true;
-					if (aOptions.checkbox)
-						aOptions.checkbox.checked = checkbox.checked;
-					return aButtonIndex;
-				});
-	};
-
-	function getTabBrowserFromChild(aTabBrowserChild)
-	{
-		var b = aTabBrowserChild.ownerDocument.evaluate(
-				'ancestor::*[local-name()="tabbrowser"] | '+
-				'ancestor::*[local-name()="tabs"][@tabbrowser] |'+
-				'ancestor::*[local-name()="toolbar"]/descendant::*[local-name()="tabs"]',
-				aTabBrowserChild,
-				null,
-				Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE,
-				null
-			).singleNodeValue;
-		return (b && b.tabbrowser) || b;
-	}
-
-	namespace.confirmWithTab = confirmWithTab;
-})();
diff --git a/modules/pseudoTreeBuilder.js b/modules/pseudoTreeBuilder.js
new file mode 100755
index 0000000..bf08faf
--- /dev/null
+++ b/modules/pseudoTreeBuilder.js
@@ -0,0 +1,137 @@
+/* ***** BEGIN LICENSE BLOCK ***** 
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Tree Style Tab.
+ *
+ * The Initial Developer of the Original Code is SHIMODA Hiroshi.
+ * Portions created by the Initial Developer are Copyright (C) 2011
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s): SHIMODA Hiroshi <piro.outsider.reflex at gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ******/
+
+const EXPORTED_SYMBOLS = ['PseudoTreeBuilder'];
+
+const Cc = Components.classes;
+const Ci = Components.interfaces;
+
+Components.utils.import('resource://treestyletab-modules/utils.js');
+
+var PseudoTreeBuilder = {
+	__proto__ : TreeStyleTabUtils,
+
+	kFAVICON      : 'treestyletab-pseudo-tree-favicon',
+	kROOTITEM     : 'treestyletab-pseudo-tree-root-item',
+	kTREEITEM     : 'treestyletab-pseudo-tree-item',
+	kTREEROW      : 'treestyletab-pseudo-tree-row',
+	kTREECHILDREN : 'treestyletab-pseudo-tree-children',
+
+	kTAB_LINK_CLICK : 'nsDOMTSTPseudoTreeItemClick',
+
+	build : function TB_build(aTab) 
+	{
+		if (!aTab)
+			return null;
+
+		var tree = this.createTabItem(aTab);
+
+		var row = tree.querySelector("."+this.kTREEROW);
+		if (!row)
+			return;
+
+		row.className += " "+this.kROOTITEM;
+
+		tree.setAttribute('onclick', <![CDATA[
+			var doc = event.target.ownerDocument;
+			var label = doc.evaluate(
+					'ancestor-or-self::*[local-name()="label" and contains(@class, "text-link")][1]',
+					event.target,
+					null,
+					Components.interfaces.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE,
+					null
+				).singleNodeValue;
+			if (label) {
+				var customEvent = doc.createEvent('DataContainerEvent');
+				customEvent.initEvent(%EVENT_TYPE%, true, true);
+				customEvent.setData('id', label.getAttribute('tab-id'));
+				customEvent.setData('sourceEvent', event);
+				event.target.dispatchEvent(customEvent);
+			}
+		]]>.toString().replace('%EVENT_TYPE%', this.kTAB_LINK_CLICK.quote()));
+
+		return tree;
+	},
+
+	createTabItem : function TB_createTabItem(aTab)
+	{
+		var doc = aTab.ownerDocument;
+		var w = doc.defaultView;
+
+		var item = doc.createElement('hbox');
+		item.setAttribute('class', this.kTREEROW);
+
+		var favicon = item.appendChild(doc.createElement('image'));
+		favicon.setAttribute('src', aTab.getAttribute('image') || 'chrome://mozapps/skin/places/defaultFavicon.png');
+		favicon.setAttribute('class', this.kFAVICON);
+
+		var label = item.appendChild(doc.createElement('label'));
+		label.setAttribute('value', aTab.label);
+		var tooltip = aTab.label;
+		var uri = aTab.linkedBrowser.currentURI.spec;
+		if (w.isBlankPageURL ? !w.isBlankPageURL(uri) : (uri != 'about:blank')) tooltip += '\n' + uri;
+		label.setAttribute('tooltiptext', tooltip);
+		label.setAttribute('class', 'text-link '+this.kTREEITEM);
+		label.setAttribute('tab-id', this.getTabValue(aTab, this.kID));
+
+		var children = this.createTabChildren(aTab);
+		if (children) {
+			let container = doc.createElement('vbox');
+			container.appendChild(item);
+			container.appendChild(children);
+			return container;
+		}
+		else {
+			return item;
+		}
+	},
+
+	createTabChildren : function TB_createTabChildren(aTab)
+	{
+		var doc = aTab.ownerDocument;
+
+		var children = this.getChildTabs(aTab);
+		if (!children.length)
+			return null;
+
+		var container = doc.createElement('vbox');
+		for (let i = 0, maxi = children.length; i < maxi; i++)
+		{
+			container.appendChild(this.createTabItem(children[i]));
+		}
+		container.setAttribute('class', this.kTREECHILDREN);
+		return container;
+	}
+};
diff --git a/modules/rap.js b/modules/rap.js
deleted file mode 100755
index bd3e5ca..0000000
--- a/modules/rap.js
+++ /dev/null
@@ -1,11 +0,0 @@
-const EXPORTED_SYMBOLS = ['rap']; 
-
-var last = -1;
-var start = Date.now();
-
-function rap(aMessage) {
-	var now = Date.now();
-	var time = last < 0 ? 0 : (now - last);
-	dump(time+' (total '+(now - start)+') : '+(aMessage || Components.stack.caller)+'\n');
-	last = now;
-}
diff --git a/modules/tabbarDNDObserver.js b/modules/tabbarDNDObserver.js
index 2e7ff71..449a2ab 100755
--- a/modules/tabbarDNDObserver.js
+++ b/modules/tabbarDNDObserver.js
@@ -14,10 +14,10 @@
  * The Original Code is the Tree Style Tab.
  *
  * The Initial Developer of the Original Code is SHIMODA Hiroshi.
- * Portions created by the Initial Developer are Copyright (C) 2010-2011
+ * Portions created by the Initial Developer are Copyright (C) 2010-2012
  * the Initial Developer. All Rights Reserved.
  *
- * Contributor(s): SHIMODA Hiroshi <piro at p.club.ne.jp>
+ * Contributor(s): SHIMODA Hiroshi <piro.outsider.reflex at gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -160,7 +160,7 @@ try{
 			tab.parentNode != b.mTabContainer)
 			return true;
 
-		tab = sv.getTabFromEvent(aEvent);
+		tab = sv.getTabFromEvent(aEvent) || sv.getTabFromTabbarEvent(aEvent);
 		if (sv.isCollapsed(tab))
 			return false;
 
@@ -246,7 +246,7 @@ catch(e) {
 		var b  = this.browser;
 		var d  = this.document;
 
-		var tab        = aEvent.target;
+		var tab        = sv.getTabFromEvent(aEvent) || sv.getTabFromTabbarEvent(aEvent) || aEvent.target;
 		var tabs       = sv.getTabsArray(b);
 		var firstTab   = sv.getFirstNormalTab(b) || tabs[0];
 		var lastTabIndex = tabs.length - 1;
@@ -320,12 +320,12 @@ catch(e) {
 				info.parent       = tab;
 				info.insertBefore = sv.getTreePref('insertNewChildAt') == sv.kINSERT_FISRT ?
 						(sv.getFirstChildTab(tab) || visible) :
-						(sv.getNextSiblingTab(tab) || sv.getNextTab(sv.getLastDescendantTab(tab)) || visible);
+						(sv.getNextSiblingTab(tab) || sv.getNextTab(sv.getLastDescendantTab(tab)));
 				break;
 
 			case sv.kDROP_BEFORE:
 /*
-	[TARGET  ] ªpart from parent, and move
+	[TARGET  ] ªdetach from parent, and move
 
 	  [      ]
 	[TARGET  ] ªattach to the parent of the target, and move
@@ -414,11 +414,13 @@ catch(e) {
 		var tabs = sv.getTabsArray(targetBrowser);
 
 		var draggedWholeTree = [].concat(draggedRoots);
-		for each (let root in draggedRoots)
+		for (let i = 0, maxi = draggedRoots.length; i < maxi; i++)
 		{
+			let root = draggedRoots[i];
 			let tabs = sourceService.getDescendantTabs(root);
-			for each (let tab in tabs)
+			for (let i = 0, maxi = tabs.length; i < maxi; i++)
 			{
+				let tab = tabs[i];
 				if (draggedWholeTree.indexOf(tab) < 0)
 					draggedWholeTree.push(tab);
 			}
@@ -431,7 +433,7 @@ catch(e) {
 			selectedTabs.length) {
 			draggedTabs = draggedRoots = selectedTabs;
 			if (aInfo.action & sv.kACTIONS_FOR_SOURCE)
-				sourceService.partTabs(selectedTabs);
+				sourceService.detachTabs(selectedTabs);
 		}
 
 		while (aInfo.insertBefore && draggedWholeTree.indexOf(aInfo.insertBefore) > -1)
@@ -441,7 +443,7 @@ catch(e) {
 
 		if (aInfo.action & sv.kACTIONS_FOR_SOURCE) {
 			if (aInfo.action & sv.kACTION_PART) {
-				this.partTabsOnDrop(draggedRoots);
+				this.detachTabsOnDrop(draggedRoots);
 			}
 			else if (aInfo.action & sv.kACTION_ATTACH) {
 				this.attachTabsOnDrop(draggedRoots, aInfo.parent);
@@ -515,28 +517,32 @@ catch(e) {
 		var sv = b.treeStyleTab;
 
 		b.movingSelectedTabs = true; // Multiple Tab Handler
-		aTabs.forEach(function(aTab) {
-			if (!aTab.parentNode) return; // ignore removed tabs
+		for (let i = 0, maxi = aTabs.length; i < maxi; i++)
+		{
+			let tab = aTabs[i];
+			if (!tab.parentNode) continue; // ignore removed tabs
 			if (aParent)
-				sv.attachTabTo(aTab, aParent);
+				sv.attachTabTo(tab, aParent);
 			else
-				sv.partTab(aTab);
-			sv.collapseExpandTab(aTab, false);
-		}, sv);
+				sv.detachTab(tab);
+			sv.collapseExpandTab(tab, false);
+		}
 		b.movingSelectedTabs = false; // Multiple Tab Handler
 	},
  
-	partTabsOnDrop : function TabbarDND_partTabsOnDrop(aTabs) 
+	detachTabsOnDrop : function TabbarDND_detachTabsOnDrop(aTabs) 
 	{
 		var b  = aTabs[0].ownerDocument.defaultView.TreeStyleTabService.getTabBrowserFromChild(aTabs[0]);
 		var sv = b.treeStyleTab;
 
 		b.movingSelectedTabs = true; // Multiple Tab Handler
-		aTabs.forEach(function(aTab) {
-			if (!aTab.parentNode) return; // ignore removed tabs
-			sv.partTab(aTab);
-			sv.collapseExpandTab(aTab, false);
-		}, sv);
+		for (let i = 0, maxi = aTabs.length; i < maxi; i++)
+		{
+			let tab = aTabs[i];
+			if (!tab.parentNode) continue; // ignore removed tabs
+			sv.detachTab(tab);
+			sv.collapseExpandTab(tab, false);
+		}
 		b.movingSelectedTabs = false; // Multiple Tab Handler
 	},
   
@@ -573,7 +579,7 @@ catch(e) {
  
 	handleEvent : function TabbarDND_handleEvent(aEvent) 
 	{
-		// ignore drag and drop while toolbar customization (for Firefox 3.6)
+		// ignore drag and drop while toolbar customization
 		if (this.treeStyleTab.isToolbarCustomizing)
 			return;
 
@@ -754,6 +760,9 @@ catch(e) {
 		if (this.isDraggingAllCurrentTabs(draggedTab))
 			return;
 
+		if (aEvent.ctrlKey || aEvent.metaKey)
+			draggedTab.__treestyletab__toBeDuplicated = true;
+
 		b.replaceTabWithWindow(draggedTab);
 	},
  
@@ -791,18 +800,15 @@ try{
 		var info = this.getDropAction(aEvent, session);
 
 		var observer = b;
-		if (b.tabContainer && b.tabContainer._setEffectAllowedForDataTransfer) // for Firefox 4.0
+		if (b.tabContainer && b.tabContainer._setEffectAllowedForDataTransfer)
 			observer = b.tabContainer;
 
-		// auto-switch for staying on tabs (Firefox 3.5 or later)
+		// auto-switch for staying on tabs
 		if (
 			info.position == sv.kDROP_ON &&
 			info.target &&
 			!info.target.selected &&
-			(
-				('mDragTime' in observer && 'mDragOverDelay' in observer) || // Firefox 3.6
-				('_dragTime' in observer && '_dragOverDelay' in observer) // Firefox 4.0 or later
-			)
+			'_dragTime' in observer && '_dragOverDelay' in observer
 			) {
 			let time = observer.mDragTime || observer._dragTime || 0;
 			let delay = observer.mDragOverDelay || observer._dragOverDelay || 0;
@@ -864,9 +870,10 @@ catch(e) {
 		var sv = this.treeStyleTab;
 		if (this.mAutoExpandedTabs.length) {
 			if (sv.getTreePref('autoExpand.collapseFinally')) {
-				this.mAutoExpandedTabs.forEach(function(aTarget) {
-					this.collapseExpandSubtree(this.getTabById(aTarget), true, true);
-				}, sv);
+				for (let i = 0, maxi = this.mAutoExpandedTabs.length; i < maxi; i++)
+				{
+					sv.collapseExpandSubtree(sv.getTabById(this.mAutoExpandedTabs[i]), true, true);
+				}
 			}
 			this.mAutoExpandedTabs = [];
 		}
@@ -883,7 +890,7 @@ catch(e) {
 
 		this.clearDropPosition();
 
-		if (tabbar._tabDropIndicator) // for Firefox 4 or later
+		if (tabbar._tabDropIndicator)
 			tabbar._tabDropIndicator.collapsed = true;
 
 		var session = sv.currentDragSession;
diff --git a/modules/tabpanelDNDObserver.js b/modules/tabpanelDNDObserver.js
index 75e2e02..b541a21 100755
--- a/modules/tabpanelDNDObserver.js
+++ b/modules/tabpanelDNDObserver.js
@@ -14,10 +14,10 @@
  * The Original Code is the Tree Style Tab.
  *
  * The Initial Developer of the Original Code is SHIMODA Hiroshi.
- * Portions created by the Initial Developer are Copyright (C) 2010-2011
+ * Portions created by the Initial Developer are Copyright (C) 2010-2012
  * the Initial Developer. All Rights Reserved.
  *
- * Contributor(s): SHIMODA Hiroshi <piro at p.club.ne.jp>
+ * Contributor(s): SHIMODA Hiroshi <piro.outsider.reflex at gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -82,7 +82,7 @@ TabpanelDNDObserver.prototype = {
  
 	handleEvent : function TabpanelDND_handleEvent(aEvent) 
 	{
-		// ignore drag and drop while toolbar customization (for Firefox 3.6)
+		// ignore drag and drop while toolbar customization
 		if (this.treeStyleTab.isToolbarCustomizing)
 			return;
 
diff --git a/modules/themeManager.js b/modules/themeManager.js
index e06badc..fb0a596 100755
--- a/modules/themeManager.js
+++ b/modules/themeManager.js
@@ -14,10 +14,10 @@
  * The Original Code is the Tree Style Tab.
  *
  * The Initial Developer of the Original Code is SHIMODA Hiroshi.
- * Portions created by the Initial Developer are Copyright (C) 2011
+ * Portions created by the Initial Developer are Copyright (C) 2011-2012
  * the Initial Developer. All Rights Reserved.
  *
- * Contributor(s): SHIMODA Hiroshi <piro at p.club.ne.jp>
+ * Contributor(s): SHIMODA Hiroshi <piro.outsider.reflex at gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -53,10 +53,13 @@ TreeStyleTabThemeManager.prototype = {
 
 	set : function(aStyle, aPosition)
 	{
-		if (this._lastStyles)
-			this._lastStyles.forEach(function(aStyle) {
-				aStyle.parentNode.removeChild(aStyle);
-			});
+		if (this._lastStyles) {
+			for (let i = 0, maxi = this._lastStyles.length; i < maxi; i++)
+			{
+				let style = this._lastStyles[i];
+				style.parentNode.removeChild(style);
+			}
+		}
 		this._lastStyles = null;
 
 		var styles = [];
@@ -88,7 +91,6 @@ TreeStyleTabThemeManager.prototype = {
 
 			case 'metal':
 				styles.push(BASE+'metal/base.css');
-				styles.push(BASE+'metal/base-inactive.css');
 				styles.push(BASE+'metal/tab.css');
 				styles.push(BASE+'metal/aero.css');
 				styles.push(BASE+'platform-styled.css');
@@ -96,8 +98,7 @@ TreeStyleTabThemeManager.prototype = {
 				break;
 
 			case 'sidebar':
-				styles.push(BASE+'sidebar/base.css');
-				styles.push(BASE+'sidebar/inactive.css');
+				styles.push(BASE+'sidebar/sidebar.css');
 				styles.push(BASE+'sidebar/aero.css');
 				styles.push(BASE+'platform-styled.css');
 				break;
@@ -130,13 +131,15 @@ TreeStyleTabThemeManager.prototype = {
 				null ;
 		if (!images) return;
 
-		images.forEach(function(aImage) {
-			if (this._preLoadImagesForStyleDoneImages.indexOf(aImage) > -1)
-				return;
+		for (let i = 0, maxi = images.length; i < maxi; i++)
+		{
+			let image = images[i];
+			if (this._preLoadImagesForStyleDoneImages.indexOf(image) > -1)
+				continue;
 
-			(new this.window.Image()).src = aImage;
-			this._preLoadImagesForStyleDoneImages.push(aImage);
-		}, this);
+			(new this.window.Image()).src = image;
+			this._preLoadImagesForStyleDoneImages.push(image);
+		}
 	},
 
 	_preLoadImages : {
diff --git a/modules/utils.js b/modules/utils.js
index 58321ce..d8615bb 100755
--- a/modules/utils.js
+++ b/modules/utils.js
@@ -14,10 +14,10 @@
  * The Original Code is the Tree Style Tab.
  *
  * The Initial Developer of the Original Code is SHIMODA Hiroshi.
- * Portions created by the Initial Developer are Copyright (C) 2010-2011
+ * Portions created by the Initial Developer are Copyright (C) 2010-2012
  * the Initial Developer. All Rights Reserved.
  *
- * Contributor(s): SHIMODA Hiroshi <piro at p.club.ne.jp>
+ * Contributor(s): SHIMODA Hiroshi <piro.outsider.reflex at gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -40,8 +40,6 @@ const Ci = Components.interfaces;
  
 Components.utils.import('resource://gre/modules/XPCOMUtils.jsm'); 
 
-// Components.utils.import('resource://treestyletab-modules/rap.js');
-// rap();
 Components.utils.import('resource://treestyletab-modules/lib/prefs.js');
 Components.utils.import('resource://treestyletab-modules/lib/namespace.jsm');
 var window = getNamespaceFor('piro.sakura.ne.jp');
@@ -76,12 +74,11 @@ XPCOMUtils.defineLazyGetter(this, 'autoScroll', function() {
 	Components.utils.import('resource://treestyletab-modules/lib/autoScroll.js', {});
 	return window['piro.sakura.ne.jp'].autoScroll;
 });
-XPCOMUtils.defineLazyGetter(this, 'confirmWithTab', function() {
+XPCOMUtils.defineLazyGetter(this, 'confirmWithPopup', function() {
 	var ns = {};
-	Components.utils.import('resource://treestyletab-modules/lib/confirmWithTab.js', ns);
-	return ns.confirmWithTab;
+	Components.utils.import('resource://treestyletab-modules/lib/confirmWithPopup.js', ns);
+	return ns.confirmWithPopup;
 });
-// rap('end of definition of lazy getters');
  
 var TreeStyleTabUtils = { 
 	__proto__ : window['piro.sakura.ne.jp'].prefs,
@@ -97,12 +94,12 @@ var TreeStyleTabUtils = {
 	kINSERT_BEFORE      : 'treestyletab-insert-before',
 	kINSERT_AFTER       : 'treestyletab-insert-after',
 	kCLOSED_SET_ID      : 'treestyletab-closed-set-id',
-	kSTRUCTURE          : 'treestyletab-tree-structure',
 
 	kID_RESTORING       : 'treestyletab-id-restoring',
 	kCHILDREN_RESTORING : 'treestyletab-children-restoring',
 
 	kSUBTREE_COLLAPSED  : 'treestyletab-subtree-collapsed',
+	kSUBTREE_EXPANDED_MANUALLY : 'treestyletab-subtree-expanded-manually',
 	kCOLLAPSED          : 'treestyletab-collapsed',
 	kCOLLAPSED_DONE     : 'treestyletab-collapsed-done',
 	kCOLLAPSING_PHASE   : 'treestyletab-collapsing-phase',
@@ -119,7 +116,6 @@ var TreeStyleTabUtils = {
 	kMODE               : 'treestyletab-mode',
 
 	kHIDE_NEWTAB        : 'treestyletab-hide-newtab-button',
-	kHIDE_ALLTABS       : 'treestyletab-hide-alltabs-button', /* legacy feature for Firefox 3.6 or olders */
 	kSTYLE              : 'treestyletab-style',
 	kFIRSTTAB_BORDER    : 'treestyletab-firsttab-border',
 	kFIXED              : 'treestyletab-tabbar-fixed',
@@ -131,6 +127,7 @@ var TreeStyleTabUtils = {
 	kINVERT_SCROLLBAR   : 'treestyletab-invert-scrollbar',
 	kNARROW_SCROLLBAR   : 'treestyletab-narrow-scrollbar',
 	kFAVICONIZED        : 'treestyletab-faviconized',
+	kBG_NOTIFY_PHASE    : 'treestyletab-notifybgtab-phase',
 
 	kTAB_INVERTED          : 'treestyletab-tab-inverted',
 	kTAB_CONTENTS_INVERTED : 'treestyletab-tab-contents-inverted',
@@ -147,9 +144,6 @@ var TreeStyleTabUtils = {
  
 /* classes */ 
 	kTWISTY                     : 'treestyletab-twisty',
-	kTWISTY_CONTAINER           : 'treestyletab-twisty-container',
-	kDROP_MARKER                : 'treestyletab-drop-marker',
-	kDROP_MARKER_CONTAINER      : 'treestyletab-drop-marker-container',
 	kCOUNTER                    : 'treestyletab-counter',
 	kCOUNTER_CONTAINER          : 'treestyletab-counter-container',
 	kCOUNTER_PAREN              : 'treestyletab-counter-paren',
@@ -244,6 +238,13 @@ var TreeStyleTabUtils = {
 	kCLOSE_PARENT_BEHAVIOR_SIMPLY_DETACH_ALL_CHILDREN : 4,
 	kCLOSE_PARENT_BEHAVIOR_CLOSE_ALL_CHILDREN         : 2, // onTabRemoved only
 
+	kRESTORE_TREE_LEVEL_NONE   : 0,
+	kRESTORE_TREE_ONLY_VISIBLE : 1,
+	kRESTORE_TREE_ALL          : 2,
+
+	kCOUNTER_ROLE_ALL_TABS       : 1,
+	kCOUNTER_ROLE_CONTAINED_TABS : 2,
+
 	MAX_TABBAR_SIZE_RATIO        : 0.8,
 	DEFAULT_SHRUNKEN_WIDTH_RATIO : 0.67,
  
@@ -261,6 +262,9 @@ var TreeStyleTabUtils = {
 	shouldExpandTwistyArea : true,
 
 	scrollToNewTabMode : false,
+
+	counterRoleHorizontal : -1,
+	counterRoleVertical : -1,
  
 	get SessionStore() { 
 		if (!this._SessionStore) {
@@ -303,6 +307,15 @@ var TreeStyleTabUtils = {
 	},
 	_PromptService : null,
 
+	get FocusManager()
+	{
+		if (!this._FocusManager) {
+			this._FocusManager = Cc['@mozilla.org/focus-manager;1'].getService(Ci.nsIFocusManager);
+		}
+		return this._FocusManager;
+	},
+	 _FocusManager : null,
+
 	get XULAppInfo() {
 		if (!this._XULAppInfo) {
 			this._XULAppInfo = Cc['@mozilla.org/xre/app-info;1'].getService(Ci.nsIXULAppInfo).QueryInterface(Ci.nsIXULRuntime);
@@ -323,15 +336,6 @@ var TreeStyleTabUtils = {
 		return this.Comparator.compare(this.XULAppInfo.version, '10.0a') > 0;
 	},
  
-	get isGecko2OrLater() 
-	{
-		return this.Comparator.compare(this.XULAppInfo.version, '4.0b5') > 0;
-	},
-	get isGecko2() // for backward compatibility
-	{
-		return this.isGecko2OrLater
-	},
- 
 	get treeBundle() { 
 		return stringBundle.get('chrome://treestyletab/locale/treestyletab.properties');
 	},
@@ -346,12 +350,12 @@ var TreeStyleTabUtils = {
  
 	init : function TSTUtils_init() 
 	{
-// rap('utils/init start');
 		if (this._initialized) return;
 
 		this.isMac = this.XULAppInfo.OS == 'Darwin';
 
 		this.applyPlatformDefaultPrefs();
+		this.migratePrefs();
 
 		this.addPrefListener(this);
 
@@ -368,6 +372,8 @@ var TreeStyleTabUtils = {
 		this.onPrefChange('extensions.treestyletab.animation.indent.duration');
 		this.onPrefChange('extensions.treestyletab.animation.collapse.duration');
 		this.onPrefChange('extensions.treestyletab.twisty.expandSensitiveArea');
+		this.onPrefChange('extensions.treestyletab.counter.role.horizontal');
+		this.onPrefChange('extensions.treestyletab.counter.role.vertical');
 
 		try {
 			if (this.XULAppInfo.OS == 'WINNT')
@@ -383,23 +389,146 @@ var TreeStyleTabUtils = {
 		catch(e) {
 			dump(e+'\n');
 		}
-// rap('utils/init end');
 	},
 	_initialized : false,
 	applyPlatformDefaultPrefs : function TSTUtils_applyPlatformDefaultPrefs()
 	{
 		var OS = this.XULAppInfo.OS;
 		var processed = {};
-		this.getDescendant('extensions.treestyletab.platform.'+OS).forEach(function(aKey) {
-			var key = aKey.replace('platform.'+OS+'.', '');
-			this.setDefaultPref(key, this.getPref(aKey));
+		var originalKeys = this.getDescendant('extensions.treestyletab.platform.'+OS);
+		for (let i = 0, maxi = originalKeys.length; i < maxi; i++)
+		{
+			let originalKey = originalKeys[i];
+			let key = originalKey.replace('platform.'+OS+'.', '');
+			this.setDefaultPref(key, this.getPref(originalKey));
 			processed[key] = true;
-		}, this);
-		this.getDescendant('extensions.treestyletab.platform.default').forEach(function(aKey) {
-			var key = aKey.replace('platform.default.', '');
+		}
+		originalKeys = this.getDescendant('extensions.treestyletab.platform.default');
+		for (let i = 0, maxi = originalKeys.length; i < maxi; i++)
+		{
+			let originalKey = originalKeys[i];
+			let key = originalKey.replace('platform.default.', '');
 			if (!(key in processed))
-				this.setDefaultPref(key, this.getPref(aKey));
-		}, this);
+				this.setDefaultPref(key, this.getPref(originalKey));
+		}
+	},
+	kPREF_VERSION : 8,
+	migratePrefs : function TSTUtils_migratePrefs() 
+	{
+		// migrate old prefs
+		var orientalPrefs = [];
+		switch (this.getTreePref('prefsVersion'))
+		{
+			case 0:
+				orientalPrefs = orientalPrefs.concat([
+					'extensions.treestyletab.tabbar.fixed',
+					'extensions.treestyletab.enableSubtreeIndent',
+					'extensions.treestyletab.allowSubtreeCollapseExpand'
+				]);
+			case 1:
+			case 2:
+				if (this.getTreePref('urlbar.loadSameDomainToNewChildTab') !== null) {
+					let value = this.getTreePref('urlbar.loadSameDomainToNewChildTab');
+					this.setTreePref('urlbar.loadSameDomainToNewTab', value);
+					this.setTreePref('urlbar.loadSameDomainToNewTab.asChild', value);
+					if (value) this.setTreePref('urlbar.loadDifferentDomainToNewTab', value);
+					this.clearTreePref('urlbar.loadSameDomainToNewChildTab');
+				}
+			case 3:
+				if (this.getTreePref('loadDroppedLinkToNewChildTab') !== null) {
+					this.setTreePref('dropLinksOnTab.behavior',
+						this.getTreePref('loadDroppedLinkToNewChildTab.confirm') ?
+							this.kDROPLINK_ASK :
+						this.getTreePref('loadDroppedLinkToNewChildTab') ?
+							this.kDROPLINK_NEWTAB :
+							this.kDROPLINK_LOAD
+					);
+					this.clearTreePref('loadDroppedLinkToNewChildTab.confirm');
+					this.clearTreePref('loadDroppedLinkToNewChildTab');
+				}
+				if (this.getTreePref('openGroupBookmarkAsTabSubTree') !== null) {
+					let behavior = 0;
+					if (this.getTreePref('openGroupBookmarkAsTabSubTree.underParent'))
+						behavior += this.kGROUP_BOOKMARK_USE_DUMMY;
+					if (!this.getTreePref('openGroupBookmarkBehavior.confirm')) {
+						behavior += (
+							this.getTreePref('openGroupBookmarkAsTabSubTree') ?
+								this.kGROUP_BOOKMARK_SUBTREE :
+							this.getTreePref('browser.tabs.loadFolderAndReplace') ?
+								this.kGROUP_BOOKMARK_REPLACE :
+								this.kGROUP_BOOKMARK_SEPARATE
+						);
+					}
+					this.setTreePref('openGroupBookmark.behavior', behavior);
+					this.clearTreePref('openGroupBookmarkBehavior.confirm');
+					this.clearTreePref('openGroupBookmarkAsTabSubTree');
+					this.clearTreePref('openGroupBookmarkAsTabSubTree.underParent');
+					this.setPref('browser.tabs.loadFolderAndReplace', !!(behavior & this.kGROUP_BOOKMARK_REPLACE));
+				}
+			case 4:
+				let (prefs = [
+						'extensions.treestyletab.autoCollapseExpandSubTreeOnSelect',
+						'extensions.treestyletab.autoCollapseExpandSubTreeOnSelect.onCurrentTabRemove',
+						'extensions.treestyletab.autoCollapseExpandSubTreeOnSelect.whileFocusMovingByShortcut',
+						'extensions.treestyletab.autoExpandSubTreeOnAppendChild',
+						'extensions.treestyletab.autoExpandSubTreeOnCollapsedChildFocused',
+						'extensions.treestyletab.collapseExpandSubTree.dblclick',
+						'extensions.treestyletab.createSubTree.underParent',
+						'extensions.treestyletab.show.context-item-reloadTabSubTree',
+						'extensions.treestyletab.show.context-item-removeTabSubTree',
+						'extensions.treestyletab.show.context-item-bookmarkTabSubTree',
+						'extensions.multipletab.show.multipletab-selection-item-removeTabSubTree',
+						'extensions.multipletab.show.multipletab-selection-item-createSubTree'
+					]) {
+					for (let i = 0, maxi = prefs.length; i < maxi; i++)
+					{
+						let pref = prefs[i];
+						let value = this.getPref(pref);
+						if (value === null) continue;
+						this.setPref(pref.replace('SubTree', 'Subtree'), value);
+						this.clearPref(pref);
+					}
+				}
+			case 5:
+				let (behavior = this.getTreePref('openGroupBookmark.behavior')) {
+					behavior = behavior | 2048;
+					this.setTreePref('openGroupBookmark.behavior', behavior);
+				}
+			case 6:
+				let (
+					general = this.getTreePref('autoAttachNewTabsAsChildren'),
+					search = this.getTreePref('autoAttachSearchResultAsChildren')
+					) {
+					if (general !== null)
+						this.setTreePref('autoAttach', general);
+					if (search !== null)
+						this.setTreePref('autoAttach.searchResult', search);
+				}
+			case 7:
+				let (
+					enabled = this.getTreePref('autoCollapseExpandSubtreeOnSelect.whileFocusMovingByShortcut'),
+					delay = this.getTreePref('autoCollapseExpandSubtreeOnSelect.whileFocusMovingByShortcut.delay')
+					) {
+					if (enabled !== null) {
+						this.setTreePref('autoExpandSubtreeOnSelect.whileFocusMovingByShortcut', enabled);
+						this.setTreePref('autoExpandSubtreeOnSelect.whileFocusMovingByShortcut.collapseOthers', enabled);
+					}
+					if (delay !== null)
+						this.setTreePref('autoExpandSubtreeOnSelect.whileFocusMovingByShortcut.delay', delay);
+				}
+			default:
+				for (let i = 0, maxi = orientalPrefs.length; i < maxi; i++)
+				{
+					let pref = orientalPrefs[i];
+					let value = this.getPref(pref);
+					if (value === null) continue;
+					this.setPref(pref+'.horizontal', value);
+					this.setPref(pref+'.vertical', value);
+					this.clearPref(pref);
+				}
+				break;
+		}
+		this.setTreePref('prefsVersion', this.kPREF_VERSION);
 	},
 	
 	updateAeroPeek : function TSTUtils_updateAeroPeek() 
@@ -454,7 +583,12 @@ var TreeStyleTabUtils = {
 					margin-left: 0;
 					margin-right: 0;
 				}
+
+				%FORCE_NARROW_SCROLLBAR%
 			]]>.toString()
+				.replace(/%FORCE_NARROW_SCROLLBAR%/g,
+					this.getTreePref('tabbar.narrowScrollbar.overrideSystemAppearance') ?
+						this.kOVERRIDE_SYSTEM_SCROLLBAR_APPEARANCE : '' )
 				.replace(/%MODE%/g, this.kMODE)
 				.replace(/%NARROW%/g, this.kNARROW_SCROLLBAR)
 				.replace(/%SIZE%/g, this.getTreePref('tabbar.narrowScrollbar.size'))
@@ -462,6 +596,16 @@ var TreeStyleTabUtils = {
 		this.lastAgentSheet = this.makeURIFromSpec(style);
 		SSS.loadAndRegisterSheet(this.lastAgentSheet, SSS.AGENT_SHEET);
 	},
+	kOVERRIDE_SYSTEM_SCROLLBAR_APPEARANCE : <![CDATA[
+		tabs.tabbrowser-tabs[%MODE%="vertical"][%NARROW%="true"]
+		  .tabbrowser-arrowscrollbox
+		  > scrollbox
+		  > scrollbar[orient="vertical"] {
+			-moz-appearance: none;
+			background: ThreeDFace;
+			border: 1px solid ThreeDShadow;
+		}
+	]]>.toString(),
 	lastAgentSheet : null,
   
 	observe : function TSTUtils_observe(aSubject, aTopic, aData) 
@@ -658,27 +802,23 @@ var TreeStyleTabUtils = {
 		if (behavior & this.kUNDO_CLOSE_SET) behavior ^= this.kUNDO_CLOSE_SET;
 
 		var self = this;
-		var neverAskState = !(behavior & this.kUNDO_ASK);
-		var checkbox = {
-				label : this.treeBundle.getString('undoCloseTabSetBehavior.never'),
-				checked : neverAskState
-			};
-		return confirmWithTab({
-				tab      : aRestoredTab,
+		return confirmWithPopup({
+				browser  : aRestoredTab.linkedBrowser,
 				label    : this.treeBundle.getFormattedString('undoCloseTabSetBehavior.label', [aCount]),
 				value    : 'treestyletab-undo-close-tree',
+				image    : 'chrome://treestyletab/content/res/icon.png',
 				buttons  : [
-					this.treeBundle.getString('undoCloseTabSetBehavior.set'),
-					this.treeBundle.getString('undoCloseTabSetBehavior.separate')
+					this.treeBundle.getString('undoCloseTabSetBehavior.restoreOnce'),
+					this.treeBundle.getString('undoCloseTabSetBehavior.restoreForever'),
+					this.treeBundle.getString('undoCloseTabSetBehavior.ignoreForever')
 				],
-				checkbox : checkbox,
-				cancelEvents : ['TabClose', 'SSTabRestoring']
+				persistence : -1 // don't hide even if the tab is restored after the panel is shown.
 			})
 			.next(function(aButtonIndex) {
-				if (aButtonIndex == 0) {
+				if (aButtonIndex < 2) {
 					behavior |= self.kUNDO_CLOSE_SET;
 				}
-				if (checkbox.checked != neverAskState) {
+				if (aButtonIndex > 0) {
 					behavior ^= self.kUNDO_ASK;
 					self.setTreePref('undoCloseTabSet.behavior', behavior);
 				}
@@ -696,26 +836,28 @@ var TreeStyleTabUtils = {
 	doAndWaitDOMEvent : function TSTUtils_doAndWaitDOMEvent() 
 	{
 		var type, target, delay, task;
-		Array.slice(arguments).forEach(function(aArg) {
-			switch(typeof aArg)
+		for (let i = 0, maxi = arguments.length; i < maxi; i++)
+		{
+			let arg = arguments[i];
+			switch(typeof arg)
 			{
 				case 'string':
-					type = aArg;
-					break;
+					type = arg;
+					continue;
 
 				case 'number':
-					delay = aArg;
-					break;
+					delay = arg;
+					continue;
 
 				case 'function':
-					task = aArg;
-					break;
+					task = arg;
+					continue;
 
 				default:
-					target = aArg;
-					break;
+					target = arg;
+					continue;
 			}
-		});
+		}
 
 		if (!target || !type) {
 			if (task) task();
@@ -740,7 +882,7 @@ var TreeStyleTabUtils = {
 					target.removeEventListener(type, listener, false);
 					done = true;
 				}
-			});
+			}).error(this.defaultDeferredErrorHandler);
 
 		target.addEventListener(type, listener, false);
 
@@ -770,6 +912,25 @@ var TreeStyleTabUtils = {
 		return doc.documentElement;
 	},
  
+	assertBeforeDestruction : function TSTUtils_assertBeforeDestruction(aNotDestructed) 
+	{
+		if (aNotDestructed)
+			return;
+
+		var message = 'ERROR: accessed after destruction!';
+		var error = new Error(message);
+		dump(message+'\n'+error.stack+'\n');
+		throw error;
+	},
+ 
+	defaultDeferredErrorHandler : function TSTUtils_defaultDeferredErrorHandler(aError) 
+	{
+		if (aError.stack)
+			Components.utils.reportError(aError.message+'\n'+aError.stack);
+		else
+			Components.utils.reportError(aError);
+	},
+ 
 // event 
 	
 	isNewTabAction : function TSTUtils_isNewTabAction(aEvent) 
@@ -808,7 +969,16 @@ var TreeStyleTabUtils = {
 	isEventFiredOnClickable : function TSTUtils_isEventFiredOnClickable(aEvent) 
 	{
 		return this.evaluateXPath(
-				'ancestor-or-self::*[contains(" button toolbarbutton scrollbar popup menupopup panel tooltip splitter textbox ", concat(" ", local-name(), " "))]',
+				'ancestor-or-self::*[contains(" button toolbarbutton scrollbar nativescrollbar popup menupopup panel tooltip splitter textbox ", concat(" ", local-name(), " "))]',
+				aEvent.originalTarget,
+				Ci.nsIDOMXPathResult.BOOLEAN_TYPE
+			).booleanValue;
+	},
+ 
+	isEventFiredOnScrollbar : function TSTUtils_isEventFiredOnScrollbar(aEvent) 
+	{
+		return this.evaluateXPath(
+				'ancestor-or-self::*[local-name()="scrollbar" or local-name()="nativescrollbar"]',
 				aEvent.originalTarget,
 				Ci.nsIDOMXPathResult.BOOLEAN_TYPE
 			).booleanValue;
@@ -827,54 +997,87 @@ var TreeStyleTabUtils = {
 			return false;
 
 		var box = twisty.boxObject;
-		var minX = box.screenX;
-		var minY = box.screenY;
-		var maxX = minX + box.width;
-		var maxY = minY + box.height;
-		var icon  = tab.ownerDocument.getAnonymousElementByAttribute(tab, 'class', 'tab-icon');
-		var iconBox = icon.boxObject;
+		var left = box.screenX;
+		var top = box.screenY;
+		var right = left + box.width;
+		var bottom = top + box.height;
+		var favicon = this.getFaviconRect(tab);
 		if (!box.width || !box.height) {
-			minX = iconBox.screenX;
-			minY = iconBox.screenY;
-			maxX = minX + iconBox.width;
-			maxY = minY + iconBox.height;
+			left = favicon.left;
+			top = favicon.top;
+			right = favicon.right;
+			bottom = favicon.bottom;
 		}
-		if (
-			box.width && box.height &&
+		else if (
 			this.shouldExpandTwistyArea &&
 			!this._expandTwistyAreaBlockers.length
 			) {
-			minX = Math.min(minX, iconBox.screenX);
-			minY = Math.min(minY, iconBox.screenY);
-			maxX = Math.max(maxX, iconBox.screenX + iconBox.width);
-			maxY = Math.max(maxY, iconBox.screenY + iconBox.height);
+			left = Math.min(left, favicon.left);
+			top = Math.min(top, favicon.top);
+			right = Math.max(right, favicon.right);
+			bottom = Math.max(bottom, favicon.bottom);
 		}
 
 		var x = aEvent.screenX;
 		var y = aEvent.screenY;
-		return (x >= minX && x <= maxX && y >= minY && y <= maxY);
+		return (x >= left && x <= right && y >= top && y <= bottom);
+	},
+	getFaviconRect : function TSTUtils_getFaviconRect(aTab)
+	{
+		var icon  = aTab.ownerDocument.getAnonymousElementByAttribute(aTab, 'class', 'tab-icon-image');
+		var iconBox = icon.boxObject;
+		var iconRect = {
+				left   : iconBox.screenX,
+				top    : iconBox.screenY,
+				right  : iconBox.screenX + iconBox.width,
+				bottom : iconBox.screenY + iconBox.height
+			};
+
+		var throbber  = aTab.ownerDocument.getAnonymousElementByAttribute(aTab, 'class', 'tab-throbber');
+		var throbberBox = throbber.boxObject;
+		var throbberRect = {
+				left   : throbberBox.screenX,
+				top    : throbberBox.screenY,
+				right  : throbberBox.screenX + throbberBox.width,
+				bottom : throbberBox.screenY + throbberBox.height
+			};
+
+		if (!iconBox.width && !iconBox.height)
+			return throbberRect;
+
+		if (!throbberBox.width && !throbberBox.height)
+			return iconRect;
+
+		return {
+			left   : Math.min(throbberRect.left, iconRect.left),
+			right  : Math.max(throbberRect.right, iconRect.right),
+			top    : Math.min(throbberRect.top, iconRect.top),
+			bottom : Math.max(throbberRect.bottom, iconRect.bottom)
+		};
 	},
 	
 	// called with target(nsIDOMEventTarget), document(nsIDOMDocument), type(string) and data(object) 
-	fireDataContainerEvent : function()
+	fireDataContainerEvent : function TSTUtils_fireDataContainerEvent()
 	{
 		var target, document, type, data, canBubble, cancellable;
-		Array.slice(arguments).forEach(function(aArg) {
-			if (typeof aArg == 'boolean') {
+		for (let i = 0, maxi = arguments.length; i < maxi; i++)
+		{
+			let arg = arguments[i];
+			if (typeof arg == 'boolean') {
 				if (canBubble === void(0))
-					canBubble = aArg;
+					canBubble = arg;
 				else
-					cancellable = aArg;
+					cancellable = arg;
 			}
-			else if (typeof aArg == 'string')
-				type = aArg;
-			else if (aArg instanceof Ci.nsIDOMDocument)
-				document = aArg;
-			else if (aArg instanceof Ci.nsIDOMEventTarget)
-				target = aArg;
+			else if (typeof arg == 'string')
+				type = arg;
+			else if (arg instanceof Ci.nsIDOMDocument)
+				document = arg;
+			else if (arg instanceof Ci.nsIDOMEventTarget)
+				target = arg;
 			else
-				data = aArg;
-		});
+				data = arg;
+		}
 		if (!target)
 			target = document;
 		if (!document)
@@ -882,12 +1085,13 @@ var TreeStyleTabUtils = {
 
 		var event = document.createEvent('DataContainerEvent');
 		event.initEvent(type, canBubble, cancellable);
-		for (var i in data)
+		var properties = Object.keys(data);
+		for (let i = 0, maxi = properties.length; i < maxi; i++)
 		{
-			if (!data.hasOwnProperty(i))
-				continue;
-			event.setData(i, data[i]);
-			event[i] = data[i]; // for backward compatibility
+			let property = properties[i];
+			let value = data[property];
+			event.setData(property, value);
+			event[property] = value; // for backward compatibility
 		}
 
 		return target.dispatchEvent(event);
@@ -1051,8 +1255,7 @@ var TreeStyleTabUtils = {
 	// workaround for http://piro.sakura.ne.jp/latest/blosxom/mozilla/extension/treestyletab/2009-09-29_debug.htm
 	checkCachedSessionDataExpiration : function TSTUtils_checkCachedSessionDataExpiration(aTab) 
 	{
-		var data = aTab.linkedBrowser.__SS_data || // Firefox 3.6-
-					aTab.linkedBrowser.parentNode.__SS_data; // -Frefox 3.5
+		var data = aTab.linkedBrowser.__SS_data;
 		if (data &&
 			data._tabStillLoading &&
 			aTab.getAttribute('busy') != 'true' &&
@@ -1064,17 +1267,19 @@ var TreeStyleTabUtils = {
 	{
 		if (!aTabs || aTabs.length <= 1) return;
 		var id = this.makeNewClosedSetId() + '::' + aTabs.length;
-		aTabs.forEach(function(aTab) {
-			this.setTabValue(aTab, this.kCLOSED_SET_ID, id);
-		}, this);
+		for (let i = 0, maxi = aTabs.length; i < maxi; i++)
+		{
+			this.setTabValue(aTabs[i], this.kCLOSED_SET_ID, id);
+		}
 	},
  
 	unmarkAsClosedSet : function TSTUtils_unmarkAsClosedSet(aTabs) /* PUBLIC API */ 
 	{
 		if (!aTabs || !aTabs.length) return;
-		aTabs.forEach(function(aTab) {
-			this.deleteTabValue(aTab, this.kCLOSED_SET_ID);
-		}, this);
+		for (let i = 0, maxi = aTabs.length; i < maxi; i++)
+		{
+			this.deleteTabValue(aTabs[i], this.kCLOSED_SET_ID);
+		}
 	},
  
 	useTMPSessionAPI : false, 
@@ -1212,8 +1417,9 @@ var TreeStyleTabUtils = {
 		var b = aTabBrowser || this.browser;
 		var top = aFrame.top;
 		var tabs = this.getAllTabsArray(b);
-		for each (var tab in tabs)
+		for (let i = 0, maxi = tabs.length; i < maxi; i++)
 		{
+			let tab = tabs[i];
 			if (tab.linkedBrowser.contentWindow == top)
 				return tab;
 		}
@@ -1252,10 +1458,12 @@ var TreeStyleTabUtils = {
 	cleanUpTabsArray : function TSTUtils_cleanUpTabsArray(aTabs) 
 	{
 		var newTabs = [];
-		aTabs.forEach(function(aTab) {
-			if (!aTab.parentNode) return; // ignore removed tabs
-			if (newTabs.indexOf(aTab) < 0) newTabs.push(aTab);
-		});
+		for (let i = 0, maxi = aTabs.length; i < maxi; i++)
+		{
+			let tab = aTabs[i];
+			if (!tab || !tab.parentNode) continue; // ignore removed tabs
+			if (newTabs.indexOf(tab) < 0) newTabs.push(tab);
+		}
 		newTabs.sort(this.sortTabsByOrder);
 		return newTabs;
 	},
@@ -1287,17 +1495,19 @@ var TreeStyleTabUtils = {
 		var groups = [];
 
 		var group = [];
-		this.cleanUpTabsArray(aTabs)
-			.forEach(function(aTab) {
-				var parent = this.getParentTab(aTab);
-				if (!parent || group.indexOf(parent) < 0) {
-					if (group.length) groups.push(group);
-					group = [aTab];
-				}
-				else {
-					group.push(aTab);
-				}
-			}, this);
+		aTabs = this.cleanUpTabsArray(aTabs);
+		for (let i = 0, maxi = aTabs.length; i < maxi; i++)
+		{
+			let tab = aTabs[i];
+			let parent = this.getParentTab(tab);
+			if (!parent || group.indexOf(parent) < 0) {
+				if (group.length) groups.push(group);
+				group = [tab];
+			}
+			else {
+				group.push(tab);
+			}
+		}
 		if (group.length) groups.push(group);
 		return groups;
 	},
@@ -1315,13 +1525,13 @@ var TreeStyleTabUtils = {
 		if (aTabBrowserChild.localName == 'tabbrowser') // itself
 			return aTabBrowserChild;
 
-		if (aTabBrowserChild.tabbrowser) // tabs, Firefox 4.0 or later
+		if (aTabBrowserChild.tabbrowser) // tabs
 			return aTabBrowserChild.tabbrowser;
 
-		if (aTabBrowserChild.localName == 'toolbar') // tabs toolbar, Firefox 4.0 or later
+		if (aTabBrowserChild.localName == 'toolbar') // tabs toolbar
 			return aTabBrowserChild.getElementsByTagName('tabs')[0].tabbrowser;
 
-		// tab context menu on Firefox 4.0
+		// tab context menu
 		var popup = this.evaluateXPath(
 				'ancestor-or-self::xul:menupopup[@id="tabContextMenu"]',
 				aTabBrowserChild,
@@ -1410,6 +1620,7 @@ var TreeStyleTabUtils = {
 	getAllTabs : function TSTUtils_getTabs(aTabBrowserChild) /* OBSOLETE */ 
 	{
 		var b = this.getTabBrowserFromChild(aTabBrowserChild);
+		this.assertBeforeDestruction(b && b.mTabContainer);
 		return this.evaluateXPath(
 			'descendant::xul:tab',
 			b.mTabContainer
@@ -1423,6 +1634,7 @@ var TreeStyleTabUtils = {
 	getTabs : function TSTUtils_getTabs(aTabBrowserChild) /* OBSOLETE */ 
 	{
 		var b = this.getTabBrowserFromChild(aTabBrowserChild);
+		this.assertBeforeDestruction(b && b.mTabContainer);
 		return this.evaluateXPath(
 			'descendant::xul:tab[not(@hidden="true")]',
 			b.mTabContainer
@@ -1436,6 +1648,7 @@ var TreeStyleTabUtils = {
 	getAllTabsArray : function TSTUtils_getAllTabsArray(aTabBrowserChild) 
 	{
 		var b = this.getTabBrowserFromChild(aTabBrowserChild);
+		this.assertBeforeDestruction(b && b.mTabContainer);
 		return Array.slice(b.mTabContainer.childNodes) ;
 	},
  
@@ -1446,6 +1659,7 @@ var TreeStyleTabUtils = {
 	getTabsArray : function TSTUtils_getTabsArray(aTabBrowserChild) 
 	{
 		var b = this.getTabBrowserFromChild(aTabBrowserChild);
+		this.assertBeforeDestruction(b && b.mTabContainer);
 		return b.visibleTabs || Array.slice(b.mTabContainer.childNodes) ;
 	},
  
@@ -1455,6 +1669,7 @@ var TreeStyleTabUtils = {
 	getFirstTab : function TSTUtils_getFirstTab(aTabBrowserChild) 
 	{
 		var b = this.getTabBrowserFromChild(aTabBrowserChild);
+		this.assertBeforeDestruction(b && b.mTabContainer);
 		var tabs = b.visibleTabs;
 		return tabs ? tabs[0] : b.mTabContainer.firstChild;
 	},
@@ -1465,9 +1680,11 @@ var TreeStyleTabUtils = {
 	getFirstNormalTab : function TSTUtils_getFirstNormalTab(aTabBrowserChild) 
 	{
 		var b = this.getTabBrowserFromChild(aTabBrowserChild);
+		this.assertBeforeDestruction(b && b.mTabContainer);
 		return this.evaluateXPath(
 			'descendant::xul:tab[not(@pinned="true") and not(@hidden="true")]',
 			b.mTabContainer,
+
 			Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
 		).singleNodeValue;
 	},
@@ -1478,6 +1695,7 @@ var TreeStyleTabUtils = {
 	getLastTab : function TSTUtils_getLastTab(aTabBrowserChild) 
 	{
 		var b = this.getTabBrowserFromChild(aTabBrowserChild);
+		this.assertBeforeDestruction(b && b.mTabContainer);
 		var tabs = b.visibleTabs;
 		return tabs ? tabs[tabs.length-1] : b.mTabContainer.lastChild ;
 	},
@@ -1489,6 +1707,7 @@ var TreeStyleTabUtils = {
 	{
 		if (!aTab) return null;
 		var b = this.getTabBrowserFromChild(aTab);
+		this.assertBeforeDestruction(b && b.mTabContainer);
 		var tabs = b.visibleTabs;
 		if (tabs) {
 			let index = tabs.indexOf(aTab);
@@ -1506,6 +1725,7 @@ var TreeStyleTabUtils = {
 	{
 		if (!aTab) return null;
 		var b = this.getTabBrowserFromChild(aTab);
+		this.assertBeforeDestruction(b && b.mTabContainer);
 		var tabs = b.visibleTabs;
 		if (tabs) {
 			let index = tabs.indexOf(aTab);
@@ -1660,7 +1880,7 @@ var TreeStyleTabUtils = {
 			let self = this;
 			this.Deferred.next(function() {
 				self.stopToOpenChildTab(aFrameOrTabBrowser);
-			});
+			}).error(this.defaultDeferredErrorHandler);
 			return true;
 		}
 		return false;
@@ -1711,7 +1931,7 @@ var TreeStyleTabUtils = {
 			let self = this;
 			this.Deferred.next(function() {
 				self.stopToOpenChildTab(aFrameOrTabBrowser);
-			});
+			}).error(this.defaultDeferredErrorHandler);
 			return true;
 		}
 		return false;
@@ -1742,11 +1962,12 @@ var TreeStyleTabUtils = {
 	 */
 	readyToOpenNewTabGroupNow : function TSTUtils_readyToOpenNewTabGroupNow(aFrameOrTabBrowser) /* PUBLIC API */
 	{
+
 		if (this.readyToOpenNewTabGroup.apply(this, arguments)) {
 			let self = this;
 			this.Deferred.next(function() {
 				self.stopToOpenChildTab(aFrameOrTabBrowser);
-			});
+			}).error(this.defaultDeferredErrorHandler);
 			return true;
 		}
 		return false;
@@ -1874,27 +2095,53 @@ var TreeStyleTabUtils = {
 	{
 		if (!aTab) return null;
 
+		var parent;
 		if (this.tabsHash) { // XPath-less implementation
-			let parent = this.getTabById(aTab.getAttribute(this.kPARENT));
-			return (parent && parent != aTab) ? parent : null ;
+			parent = this.getTabById(aTab.getAttribute(this.kPARENT));
 		}
-
-		return this.evaluateXPath(
-			'preceding-sibling::xul:tab[@'+this.kID+'="'+aTab.getAttribute(this.kPARENT)+'"][1]',
-			aTab,
-			Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
-		).singleNodeValue;
+		else {
+			parent =  this.evaluateXPath(
+				'preceding-sibling::xul:tab[@'+this.kID+'="'+aTab.getAttribute(this.kPARENT)+'"][1]',
+				aTab,
+				Ci.nsIDOMXPathResult.FIRST_ORDERED_NODE_TYPE
+			).singleNodeValue;
+		}
+		return (parent && parent != aTab) ? parent : null ;
 	},
  
 	getAncestorTabs : function TSTUtils_getAncestorTabs(aTab) /* PUBLIC API */ 
 	{
-		var tabs = [];
+		var tabs = [aTab];
 		var parentTab = aTab;
 		while (parentTab = this.getParentTab(parentTab))
 		{
+			if (tabs.indexOf(parentTab) > -1) {
+				let message = 'recursive tree detected!\n'+
+					tabs.concat([parentTab])
+					.reverse().map(function(aTab) {
+						return '  '+aTab._tPos+' : '+
+								aTab.label+'\n     '+
+								aTab.getAttribute(this.kID);
+					}, this).join('\n');
+				dump(message+'\n');
+				break;
+			}
+
+			if (aTab._tPos < parentTab._tPos) {
+				let message = 'broken tree detected!\n'+
+					tabs.concat([parentTab])
+					.reverse().map(function(aTab) {
+						return '  '+aTab._tPos+' : '+
+								aTab.label+'\n     '+
+								aTab.getAttribute(this.kID);
+					}, this).join('\n');
+				dump(message+'\n');
+			}
+
 			tabs.push(parentTab);
+			aTab = parentTab;
 		}
-		return tabs;
+		return tabs.slice(1);
 	},
  
 	getRootTab : function TSTUtils_getRootTab(aTab) /* PUBLIC API */ 
@@ -1902,13 +2149,8 @@ var TreeStyleTabUtils = {
 		if (!aTab) return null;
 
 		if (this.tabsHash) { // XPath-less implementation
-			let parent = aTab;
-			let root   = aTab;
-			while (parent = this.getParentTab(parent))
-			{
-				root = parent;
-			}
-			return root;
+			let ancestors = this.getAncestorTabs(aTab);
+			return ancestors.length ? ancestors[ancestors.length-1] : aTab ;
 		}
 
 		return this.evaluateXPath(
@@ -1938,7 +2180,8 @@ var TreeStyleTabUtils = {
 
 			let children = parentTab.getAttribute(this.kCHILDREN);
 			if (children) {
-				let list = ('|'+children).split('|'+aTab.getAttribute(this.kID))[1].split('|');
+				let list = ('|'+children).split('|'+aTab.getAttribute(this.kID));
+				list = list.length > 1 ? list[1].split('|') : [] ;
 				for (let i = 0, maxi = list.length; i < maxi; i++)
 				{
 					let firstChild = this.getTabById(list[i], aTab);
@@ -1998,7 +2241,7 @@ var TreeStyleTabUtils = {
 		).singleNodeValue;
 	},
  
-	getSiblingTabs : function TSTUtils_getSiblingTabs(aTab) /* PUBLIC API */
+	getSiblingTabs : function TSTUtils_getSiblingTabs(aTab) /* PUBLIC API */ 
 	{
 		var parent = this.getParentTab(aTab);
 
@@ -2124,47 +2367,38 @@ var TreeStyleTabUtils = {
  
 	getChildIndex : function TSTUtils_getChildIndex(aTab, aParent) /* PUBLIC API */ 
 	{
-		if (this.tabsHash) { // XPath-less implementation
-			let parent = this.getParentTab(aTab);
-			if (!aParent || !parent || aParent != parent) {
-				parent = aTab;
-				while (parent && parent != aParent)
-				{
-					aTab = parent;
-					parent = this.getParentTab(parent);
-				}
-				if (parent != aParent)
-					return -1;
-				aParent = parent;
+		var parent = this.getParentTab(aTab);
+		if (!aParent || !parent || aParent != parent) {
+			let tabs = [aTab].concat(this.getAncestorTabs(aTab));
+			parent = aTab;
+			for (let i = 0, maxi = tabs.length; i < maxi && parent != aParent; i++)
+			{
+				aTab = parent;
+				parent = i < maxi ? tabs[i+1] : null ;
 			}
-
-			if (aParent) {
-				let children = aParent.getAttribute(this.kCHILDREN);
-				let list = children.split('|');
-				let id = aTab.getAttribute(this.kID);
-				for (let i = 0, maxi = list.length; i < maxi; i++)
-				{
-					if (list[i] == id) return i;
-				}
+			if (parent != aParent)
 				return -1;
-			}
-			else {
-				let tabs = this.rootTabs;
-				for (let i = 0, maxi = tabs.length; i < maxi; i++)
-				{
-					if (tabs[i] == aTab) return i;
-				}
+			aParent = parent;
+		}
+
+		if (aParent) {
+			let children = aParent.getAttribute(this.kCHILDREN);
+			let list = children.split('|');
+			let id = aTab.getAttribute(this.kID);
+			for (let i = 0, maxi = list.length; i < maxi; i++)
+			{
+				if (list[i] == id) return i;
 			}
 			return -1;
 		}
-
-		var parent = aTab.getAttribute(this.kPARENT);
-		if (!parent) return -1;
-		return this.evaluateXPath(
-			'count(preceding-sibling::xul:tab[@'+this.kPARENT+' and @'+this.kPARENT+'="'+parent+'"])',
-			aTab,
-			Ci.nsIDOMXPathResult.NUMBER_TYPE
-		).numberValue;
+		else {
+			let tabs = this.rootTabs;
+			for (let i = 0, maxi = tabs.length; i < maxi; i++)
+			{
+				if (tabs[i] == aTab) return i;
+			}
+		}
+		return -1;
 	},
  
 	getXOffsetOfTab : function TSTUtils_getXOffsetOfTab(aTab) 
@@ -2193,6 +2427,20 @@ var TreeStyleTabUtils = {
 			Ci.nsIDOMXPathResult.NUMBER_TYPE
 		).numberValue;
 	},
+	getFutureBoxObject : function TSTUtils_getFutureBoxObject(aTab)
+	{
+		var tabBox = aTab.boxObject;
+		var xOffset = this.getXOffsetOfTab(aTab);
+		var yOffset = this.getYOffsetOfTab(aTab);
+		return {
+			width     : tabBox.width,
+			height    : tabBox.height,
+			x         : tabBox.x + xOffset,
+			y         : tabBox.y + yOffset,
+			screenX   : tabBox.screenX + xOffset,
+			screenY   : tabBox.screenY + yOffset
+		};
+	},
  
 	isGroupTab : function TSTUtils_isGroupTab(aTab, aLazyCheck) 
 	{
@@ -2211,15 +2459,17 @@ var TreeStyleTabUtils = {
 				).numberValue;
 	},
  
-	forceExpandTabs : function TSTUtils_forceExpandTabs(aTabs)
+	forceExpandTabs : function TSTUtils_forceExpandTabs(aTabs) 
 	{
 		var collapsedStates = aTabs.map(function(aTab) {
 				return this.getTabValue(aTab, this.kSUBTREE_COLLAPSED) == 'true';
 			}, this);
-		aTabs.forEach(function(aTab) {
-			this.collapseExpandSubtree(aTab, false, true);
-			this.collapseExpandTab(aTab, false, true);
-		}, this);
+		for (let i = 0, maxi = aTabs.length; i < maxi; i++)
+		{
+			let tab = aTabs[i];
+			this.collapseExpandSubtree(tab, false, true);
+			this.collapseExpandTab(tab, false, true);
+		}
 		return collapsedStates;
 	},
  
@@ -2283,30 +2533,32 @@ var TreeStyleTabUtils = {
 		while (aExpandStates.length < aTabs.length) aExpandStates.push(-1);
 
 		var parentTab = null;
-		aTabs.forEach(function(aTab, aIndex) {
-			if (sv.isCollapsed(aTab)) sv.collapseExpandTab(aTab, false, true);
-			sv.partTab(aTab);
+		for (let i = 0, maxi = aTabs.length; i < maxi; i++)
+		{
+			let tab = aTabs[i];
+			if (sv.isCollapsed(tab)) sv.collapseExpandTab(tab, false, true);
+			sv.detachTab(tab);
 
-			var parentIndexInTree = aTreeStructure[aIndex];
+			let parentIndexInTree = aTreeStructure[i];
 			if (parentIndexInTree < 0) // there is no parent, so this is a new parent!
-				parentTab = aTab.getAttribute(sv.kID);
+				parentTab = tab.getAttribute(sv.kID);
 
-			var parent = sv.getTabById(parentTab);
+			let parent = sv.getTabById(parentTab);
 			if (parent) {
 				let tabs = [parent].concat(sv.getDescendantTabs(parent));
 				parent = parentIndexInTree < tabs.length ? tabs[parentIndexInTree] : parent ;
 			}
 			if (parent) {
-				sv.attachTabTo(aTab, parent, {
-					dontExpand : true,
-					dontMove   : true
+				sv.attachTabTo(tab, parent, {
+					forceExpand : true,
+					dontMove    : true
 				});
 			}
-		});
+		}
 
 		for (let i = aTabs.length-1; i > -1; i--)
 		{
-			sv.collapseExpandSubtree(aTabs[i], !aExpandStates[i], true);
+			sv.collapseExpandSubtree(aTabs[i], !sv.hasChildTabs(aTabs[i]) || !aExpandStates[i], true);
 		}
 	},
  
@@ -2429,6 +2681,12 @@ var TreeStyleTabUtils = {
 			case 'extensions.treestyletab.twisty.expandSensitiveArea':
 				return this.shouldExpandTwistyArea = value;
 
+			case 'extensions.treestyletab.counter.role.horizontal':
+				return this.counterRoleHorizontal = value;
+
+			case 'extensions.treestyletab.counter.role.vertical':
+				return this.counterRoleVertical = value;
+
 			default:
 				return;
 		}
@@ -2500,7 +2758,5 @@ var TreeStyleTabUtils = {
   
 }; 
  
-// rap('end of definition of utils');
 TreeStyleTabUtils.init(); 
-// rap('end of initialization of utils');
   
diff --git a/modules/window.js b/modules/window.js
index 85a3cf1..e58f885 100755
--- a/modules/window.js
+++ b/modules/window.js
@@ -14,10 +14,10 @@
  * The Original Code is the Tree Style Tab.
  *
  * The Initial Developer of the Original Code is SHIMODA Hiroshi.
- * Portions created by the Initial Developer are Copyright (C) 2011
+ * Portions created by the Initial Developer are Copyright (C) 2012
  * the Initial Developer. All Rights Reserved.
  *
- * Contributor(s): SHIMODA Hiroshi <piro at p.club.ne.jp>
+ * Contributor(s): SHIMODA Hiroshi <piro.outsider.reflex at gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either the GNU General Public License Version 2 or later (the "GPL"), or
@@ -40,8 +40,6 @@ const Ci = Components.interfaces;
 
 Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
 
-// Components.utils.import('resource://treestyletab-modules/rap.js');
-// rap();
 Components.utils.import('resource://treestyletab-modules/utils.js');
 XPCOMUtils.defineLazyGetter(this, 'TreeStyleTabBrowser', function() {
 	var ns = {};
@@ -146,9 +144,15 @@ TreeStyleTabWindow.prototype = {
 	get browser() 
 	{
 		var w = this.window;
+		this.assertBeforeDestruction(w);
 		return 'SplitBrowser' in w ? w.SplitBrowser.activeBrowser :
 			w.gBrowser ;
 	},
+ 
+	get isPopupWindow() 
+	{
+		return this.document && this.document.documentElement.getAttribute('chromehidden') != '';
+	},
   
 /* backward compatibility */ 
 	getTempTreeStyleTab : function TSTWindow_getTempTreeStyleTab(aTabBrowser)
@@ -205,10 +209,22 @@ TreeStyleTabWindow.prototype = {
 		return toolbox && toolbox.customizing;
 	},
  
+	get maximized() 
+	{
+		var sizemode = this.document.documentElement.getAttribute('sizemode');
+		return (
+			this.window.fullScreen ||
+			this.window.windowState == this.window.STATE_MAXIMIZED ||
+			sizemode == 'maximized' ||
+			sizemode == 'fullscreen'
+		);
+	},
+ 
 	maxTabbarWidth : function TSTWindow_maxTabbarWidth(aWidth, aTabBrowser) 
 	{
 		aTabBrowser = aTabBrowser || this.browser;
-		var windowWidth = this.window.outerWidth;
+		var safePadding = 20; // for window border, etc.
+		var windowWidth = this.maximized ? this.window.screen.availWidth - safePadding : this.window.outerWidth ;
 		var rootWidth = parseInt(this.document.documentElement.getAttribute('width') || 0);
 		var max = Math.max(windowWidth, rootWidth);
 		return Math.max(0, Math.min(aWidth, max * this.MAX_TABBAR_SIZE_RATIO));
@@ -217,7 +233,8 @@ TreeStyleTabWindow.prototype = {
 	maxTabbarHeight : function TSTWindow_maxTabbarHeight(aHeight, aTabBrowser) 
 	{
 		aTabBrowser = aTabBrowser || this.browser;
-		var windowHeight = this.window.outerHeight;
+		var safePadding = 20; // for window border, etc.
+		var windowHeight = this.maximized ? this.window.screen.availHeight - safePadding : this.window.outerHeight ;
 		var rootHeight = parseInt(this.document.documentElement.getAttribute('height') || 0);
 		var max = Math.max(windowHeight, rootHeight);
 		return Math.max(0, Math.min(aHeight, max * this.MAX_TABBAR_SIZE_RATIO));
@@ -286,7 +303,6 @@ TreeStyleTabWindow.prototype = {
 	
 	preInit : function TSTWindow_preInit() 
 	{
-// rap('window/preInit start');
 		if (this.preInitialized) return;
 		this.preInitialized = true;
 
@@ -299,121 +315,13 @@ TreeStyleTabWindow.prototype = {
 
 		w.TreeStyleTabWindowHelper.preInit();
 
-		this.migratePrefs();
-
 		// initialize theme
 		this.onPrefChange('extensions.treestyletab.tabbar.style');
-// rap('window/preInit end');
 	},
 	preInitialized : false,
-	
-	kPREF_VERSION : 7,
-	migratePrefs : function TSTWindow_migratePrefs() 
-	{
-		// migrate old prefs
-		var orientalPrefs = [];
-		switch (this.getTreePref('prefsVersion'))
-		{
-			case 0:
-				orientalPrefs = orientalPrefs.concat([
-					'extensions.treestyletab.tabbar.fixed',
-					'extensions.treestyletab.enableSubtreeIndent',
-					'extensions.treestyletab.allowSubtreeCollapseExpand'
-				]);
-			case 1:
-				orientalPrefs = orientalPrefs.concat([
-					'extensions.treestyletab.tabbar.hideAlltabsButton'
-				]);
-			case 2:
-				if (this.getTreePref('urlbar.loadSameDomainToNewChildTab') !== null) {
-					let value = this.getTreePref('urlbar.loadSameDomainToNewChildTab');
-					this.setTreePref('urlbar.loadSameDomainToNewTab', value);
-					this.setTreePref('urlbar.loadSameDomainToNewTab.asChild', value);
-					if (value) this.setTreePref('urlbar.loadDifferentDomainToNewTab', value);
-					this.clearTreePref('urlbar.loadSameDomainToNewChildTab');
-				}
-			case 3:
-				if (this.getTreePref('loadDroppedLinkToNewChildTab') !== null) {
-					this.setTreePref('dropLinksOnTab.behavior',
-						this.getTreePref('loadDroppedLinkToNewChildTab.confirm') ?
-							this.kDROPLINK_ASK :
-						this.getTreePref('loadDroppedLinkToNewChildTab') ?
-							this.kDROPLINK_NEWTAB :
-							this.kDROPLINK_LOAD
-					);
-					this.clearTreePref('loadDroppedLinkToNewChildTab.confirm');
-					this.clearTreePref('loadDroppedLinkToNewChildTab');
-				}
-				if (this.getTreePref('openGroupBookmarkAsTabSubTree') !== null) {
-					let behavior = 0;
-					if (this.getTreePref('openGroupBookmarkAsTabSubTree.underParent'))
-						behavior += this.kGROUP_BOOKMARK_USE_DUMMY;
-					if (!this.getTreePref('openGroupBookmarkBehavior.confirm')) {
-						behavior += (
-							this.getTreePref('openGroupBookmarkAsTabSubTree') ?
-								this.kGROUP_BOOKMARK_SUBTREE :
-							this.getTreePref('browser.tabs.loadFolderAndReplace') ?
-								this.kGROUP_BOOKMARK_REPLACE :
-								this.kGROUP_BOOKMARK_SEPARATE
-						);
-					}
-					this.setTreePref('openGroupBookmark.behavior', behavior);
-					this.clearTreePref('openGroupBookmarkBehavior.confirm');
-					this.clearTreePref('openGroupBookmarkAsTabSubTree');
-					this.clearTreePref('openGroupBookmarkAsTabSubTree.underParent');
-					this.setPref('browser.tabs.loadFolderAndReplace', !!(behavior & this.kGROUP_BOOKMARK_REPLACE));
-				}
-			case 4:
-				[
-					'extensions.treestyletab.autoCollapseExpandSubTreeOnSelect',
-					'extensions.treestyletab.autoCollapseExpandSubTreeOnSelect.onCurrentTabRemove',
-					'extensions.treestyletab.autoCollapseExpandSubTreeOnSelect.whileFocusMovingByShortcut',
-					'extensions.treestyletab.autoExpandSubTreeOnAppendChild',
-					'extensions.treestyletab.autoExpandSubTreeOnCollapsedChildFocused',
-					'extensions.treestyletab.collapseExpandSubTree.dblclick',
-					'extensions.treestyletab.createSubTree.underParent',
-					'extensions.treestyletab.show.context-item-reloadTabSubTree',
-					'extensions.treestyletab.show.context-item-removeTabSubTree',
-					'extensions.treestyletab.show.context-item-bookmarkTabSubTree',
-					'extensions.multipletab.show.multipletab-selection-item-removeTabSubTree',
-					'extensions.multipletab.show.multipletab-selection-item-createSubTree'
-				].forEach(function(aPref) {
-					var value = this.getPref(aPref);
-					if (value === null) return;
-					this.setPref(aPref.replace('SubTree', 'Subtree'), value);
-					this.clearPref(aPref);
-				}, this);
-			case 5:
-				let (behavior = this.getTreePref('openGroupBookmark.behavior')) {
-					behavior = behavior | 2048;
-					this.setTreePref('openGroupBookmark.behavior', behavior);
-				}
-			case 6:
-				let (
-					general = this.getTreePref('autoAttachNewTabsAsChildren'),
-					search = this.getTreePref('autoAttachSearchResultAsChildren')
-					) {
-					if (general !== null)
-						this.setTreePref('autoAttach', general);
-					if (search !== null)
-						this.setTreePref('autoAttach.searchResult', search);
-				}
-			default:
-				orientalPrefs.forEach(function(aPref) {
-					let value = this.getPref(aPref);
-					if (value === null) return;
-					this.setPref(aPref+'.horizontal', value);
-					this.setPref(aPref+'.vertical', value);
-					this.clearPref(aPref);
-				}, this);
-				break;
-		}
-		this.setTreePref('prefsVersion', this.kPREF_VERSION);
-	},
-  
+ 
 	init : function TSTWindow_init() 
 	{
-// rap('window/init start');
 		var w = this.window;
 		w.removeEventListener('load', this, false);
 
@@ -464,8 +372,6 @@ TreeStyleTabWindow.prototype = {
 			this.onPrefChange('extensions.treestyletab.tabbar.autoHide.mode');
 
 		this.onPrefChange('extensions.treestyletab.autoCollapseExpandSubtreeOnSelect.whileFocusMovingByShortcut');
-		this.onPrefChange('extensions.treestyletab.pinnedTab.width');
-// rap('window/init end');
 	},
 	initialized : false,
 	
@@ -491,16 +397,20 @@ TreeStyleTabWindow.prototype = {
 				}
 
 				if (!prefs) return;
-				[
-					'browser.tabs.loadFolderAndReplace',
-					'browser.tabs.insertRelatedAfterCurrent',
-					'extensions.stm.tabBarMultiRows' // Super Tab Mode
-				].forEach(function(aPref) {
-					var backup = prefs.getPref(aPref+'.backup');
-					if (backup === null) return;
-					prefs.setPref(aPref+'.override', backup); // we have to set to ".override" pref, to avoid unexpectedly reset by the preference listener.
-					prefs.clearPref(aPref+'.backup');
-				});
+
+				let restorePrefs = [
+						'browser.tabs.loadFolderAndReplace',
+						'browser.tabs.insertRelatedAfterCurrent',
+						'extensions.stm.tabBarMultiRows' // Super Tab Mode
+					];
+				for (let i = 0, maxi = pref.length; i < maxi; i++)
+				{
+					let pref = restorePrefs[i];
+					let backup = prefs.getPref(pref+'.backup');
+					if (backup === null) continue;
+					prefs.setPref(pref+'.override', backup); // we have to set to ".override" pref, to avoid unexpectedly reset by the preference listener.
+					prefs.clearPref(pref+'.backup');
+				}
 			};
 		new this.window['piro.sakura.ne.jp'].UninstallationListener({
 			id : 'treestyletab at piro.sakura.ne.jp',
@@ -524,8 +434,7 @@ TreeStyleTabWindow.prototype = {
 	{
 		var d = this.document;
 		aTabBrowser = aTabBrowser || this.browser;
-		var allTabsButton = d.getElementById('alltabs-button') || // Firefox 4.0 or later
-				d.getAnonymousElementByAttribute(aTabBrowser.mTabContainer, 'class', 'tabs-alltabs-button') || // Firefox 3.6 or older
+		var allTabsButton = d.getElementById('alltabs-button') ||
 				( // Tab Mix Plus
 					this.getTreePref('compatibility.TMP') &&
 					d.getAnonymousElementByAttribute(aTabBrowser.mTabContainer, 'anonid', 'alltabs-button')
@@ -542,21 +451,25 @@ TreeStyleTabWindow.prototype = {
 		var items = Array.slice(aEvent.originalTarget.childNodes);
 		var firstItemIndex = 0;
 		// ignore menu items inserted by Weave (Firefox Sync), Tab Utilities, and others.
-		items.forEach(function(aItem, aIndex) {
+		for (let i = 0, maxi = items.length; i < maxi; i++)
+		{
+			let item = items[i];
 			if (
-				aItem.getAttribute('anonid') ||
-				aItem.id ||
-				aItem.hidden ||
-				aItem.localName != 'menuitem'
+				item.getAttribute('anonid') ||
+				item.id ||
+				item.hidden ||
+				item.localName != 'menuitem'
 				)
-				firstItemIndex = aIndex + 1;
-		});
+				firstItemIndex = i + 1;
+		}
 		items = items.slice(firstItemIndex);
 
 		var b = this.getTabBrowserFromChild(aEvent.originalTarget) || this.browser;
-		this.getTabsArray(b).forEach(function(aTab, aIndex) {
-			items[aIndex].style.paddingLeft = aTab.getAttribute(this.kNEST)+'em';
-		}, this);
+		var tabs = this.getTabsArray(b);
+		for (let i = 0, maxi = tabs.length; i < maxi; i++)
+		{
+			items[i].style.marginLeft = tabs[i].getAttribute(this.kNEST)+'em';
+		}
 	},
   
 	destroy : function TSTWindow_destroy() 
@@ -587,9 +500,10 @@ TreeStyleTabWindow.prototype = {
 				d.removeEventListener(this.kEVENT_TYPE_TABBAR_STATE_CHANGED,        this, false);
 				d.removeEventListener(this.kEVENT_TYPE_FOCUS_NEXT_TAB,              this, false);
 
-				this._tabFocusAllowance.forEach(function(aListener) {
-					w.removeEventListener(this.kEVENT_TYPE_FOCUS_NEXT_TAB, aListener, false);
-				}, this);
+				for (let i = 0, maxi = this._tabFocusAllowance.length; i < maxi; i++)
+				{
+					w.removeEventListener(this.kEVENT_TYPE_FOCUS_NEXT_TAB, this._tabFocusAllowance[i], false);
+				}
 
 				var appcontent = d.getElementById('appcontent');
 				appcontent.removeEventListener('SubBrowserAdded', this, false);
@@ -753,6 +667,27 @@ TreeStyleTabWindow.prototype = {
 		// this.accelKeyPressed = this.isAccelKeyPressed(aEvent);
 		this.accelKeyPressed = aEvent.ctrlKey || aEvent.keyCode == Ci.nsIDOMKeyEvent.DOM_VK_CONTROL;
 
+		var left  = aEvent.keyCode == Ci.nsIDOMKeyEvent.DOM_VK_LEFT;
+		var right = aEvent.keyCode == Ci.nsIDOMKeyEvent.DOM_VK_RIGHT;
+		var up    = aEvent.keyCode == Ci.nsIDOMKeyEvent.DOM_VK_UP;
+		var down  = aEvent.keyCode == Ci.nsIDOMKeyEvent.DOM_VK_DOWN;
+		if (
+			this.FocusManager &&
+			this.FocusManager.focusedElement == this.browser.selectedTab &&
+			(up || down || left || right)
+			)
+			this.arrowKeyEventOnTab = {
+				keyCode  : aEvent.keyCode,
+				left     : left,
+				right    : right,
+				up       : up,
+				down     : down,
+				altKey   : aEvent.altKey,
+				ctrlKey  : aEvent.ctrlKey,
+				metaKey  : aEvent.metaKey,
+				shiftKey : aEvent.shiftKey
+			};
+
 		var b = this.browser;
 		var data = {
 				sourceEvent : aEvent
@@ -764,6 +699,7 @@ TreeStyleTabWindow.prototype = {
 		this.fireDataContainerEvent(this.kEVENT_TYPE_TAB_FOCUS_SWITCHING_KEY_DOWN.replace(/^nsDOM/, ''), b, true, false, data);
 	},
 	accelKeyPressed : false,
+	arrowKeyEventOnTab : null,
  
 	onKeyRelease : function TSTWindow_onKeyRelease(aEvent) 
 	{
@@ -776,6 +712,9 @@ TreeStyleTabWindow.prototype = {
 
 		// this.accelKeyPressed = this.isAccelKeyPressed(aEvent);
 		this.accelKeyPressed = aEvent.ctrlKey || aEvent.keyCode == Ci.nsIDOMKeyEvent.DOM_VK_CONTROL;
+		this.window.setTimeout(function(aSelf) {
+			aSelf.arrowKeyEventOnTab = null;
+		}, 10, this);
 
 		var standBy = scrollDown = scrollUp = (!aEvent.altKey && this.accelKeyPressed);
 
@@ -839,8 +778,10 @@ TreeStyleTabWindow.prototype = {
 	get shouldListenKeyEventsForAutoExpandByFocusChange() 
 	{
 		return !this.ctrlTabPreviewsEnabled &&
-				!this.getTreePref('autoCollapseExpandSubtreeOnSelect.whileFocusMovingByShortcut') &&
-				this.getTreePref('autoCollapseExpandSubtreeOnSelect');
+				(
+					this.getTreePref('autoExpandSubtreeOnSelect.whileFocusMovingByShortcut') ||
+					this.getTreePref('autoCollapseExpandSubtreeOnSelect')
+				);
 	},
  
 	get ctrlTabPreviewsEnabled() 
@@ -892,7 +833,7 @@ TreeStyleTabWindow.prototype = {
 
 		this.Deferred.next(function() {
 			b.treeStyleTab.fixTooNarrowTabbar();
-		});
+		}).error(this.defaultDeferredErrorHandler);
 	},
 	onTabbarResizing : function TSTWindow_onTabbarResizing(aEvent)
 	{
@@ -1020,11 +961,14 @@ TreeStyleTabWindow.prototype = {
 
 		this.AeroPeek.windows.some(function(aTabWindow) {
 			if (aTabWindow.win == this.window) {
-				aTabWindow.previews.forEach(function(aPreview) {
-					if (!aPreview) return;
-					var tab = aPreview.controller.wrappedJSObject.tab;
-					aPreview.visible = !this.isCollapsed(tab);
-				}, this);
+				let previews = aTabWindow.previews;
+				for (let i = 0, maxi = previews.length; i < maxi; i++)
+				{
+					let preview = previews[i];
+					if (!preview) continue;
+					let tab = preview.controller.wrappedJSObject.tab;
+					preview.visible = !this.isCollapsed(tab);
+				}
 				this.AeroPeek.checkPreviewCount();
 				return true;
 			}
@@ -1035,7 +979,7 @@ TreeStyleTabWindow.prototype = {
 	updateTabsOnTop : function TSTWindow_updateTabsOnTop() 
 	{
 		var w = this.window;
-		if (!('TabsOnTop' in w) || !('enabled' in w.TabsOnTop))
+		if (this.isPopupWindow || !('TabsOnTop' in w) || !('enabled' in w.TabsOnTop))
 			return;
 
 		var TabsOnTop = w.TabsOnTop;
@@ -1170,14 +1114,16 @@ TreeStyleTabWindow.prototype = {
  
 	processRestoredTabs : function TSTWindow_processRestoredTabs() 
 	{
-		this._restoringTabs.forEach(function(aTab) {
+		for (let i = 0, maxi = this._restoringTabs.length; i < maxi; i++)
+		{
+			let tab = this._restoringTabs[i];
 			try {
-				var b = this.getTabBrowserFromChild(aTab);
-				if (b) b.treeStyleTab.restoreStructure(aTab, true);
+				let b = this.getTabBrowserFromChild(aTab);
+				if (b) b.treeStyleTab.handleRestoredTab(aTab);
 			}
 			catch(e) {
 			}
-		}, this);
+		}
 		this._restoringTabs = [];
 	},
   
@@ -1238,23 +1184,26 @@ TreeStyleTabWindow.prototype = {
 		if (aOnlyChildren)
 			tabs = this.gatherSubtreeMemberTabs(aTabOrTabs);
 
-		this.splitTabsToSubtrees(tabs).forEach(function(aTabs) {
-			if (!this.fireTabSubtreeClosingEvent(aTabs[0], aTabs))
-				return;
-			var b = this.getTabBrowserFromChild(aTabs[0]);
+		var allSubtrees = this.splitTabsToSubtrees(tabs);
+		for (let i = 0, maxi = allSubtrees.length; i < maxi; i++)
+		{
+			let subtreeTabs = allSubtrees[i];
+			if (!this.fireTabSubtreeClosingEvent(subtreeTabs[0], subtreeTabs))
+				continue;
+			let b = this.getTabBrowserFromChild(subtreeTabs[0]);
 			if (aOnlyChildren)
-				aTabs = aTabs.slice(1);
-			if (!aTabs.length)
-				return;
+				subtreeTabs = subtreeTabs.slice(1);
+			if (!subtreeTabs.length)
+				continue;
 			this.stopRendering();
-			this.markAsClosedSet(aTabs);
-			for (let i = aTabs.length-1; i > -1; i--)
+			this.markAsClosedSet(subtreeTabs);
+			for (let i = subtreeTabs.length-1; i > -1; i--)
 			{
-				b.removeTab(aTabs[i], { animate : true });
+				b.removeTab(subtreeTabs[i], { animate : true });
 			}
 			this.startRendering();
-			this.fireTabSubtreeClosedEvent(b, aTabs[0], aTabs)
-		}, this);
+			this.fireTabSubtreeClosedEvent(b, subtreeTabs[0], subtreeTabs)
+		}
 	},
 	removeTabSubTree : function() { return this.removeTabSubtree.apply(this, arguments); }, // obsolete, for backward compatibility
 	
@@ -1354,10 +1303,12 @@ TreeStyleTabWindow.prototype = {
 					aTabs.shift() ;
 		var self = this;
 		this.Deferred.next(function(self) {
-			aTabs.forEach(function(aTab) {
-				b.treeStyleTab.attachTabTo(aTab, root);
-				b.treeStyleTab.collapseExpandTab(aTab, false);
-			}, self);
+			for (let i = 0, maxi = aTabs.length; i < maxi; i++)
+			{
+				let tab = aTabs[i];
+				b.treeStyleTab.attachTabTo(tab, root);
+				b.treeStyleTab.collapseExpandTab(tab, false);
+			}
 			if (parent) {
 				b.treeStyleTab.attachTabTo(root, parent, {
 					insertBefore : next
@@ -1366,7 +1317,7 @@ TreeStyleTabWindow.prototype = {
 			else if (next) {
 				b.treeStyleTab.moveTabSubtreeTo(root, next._tPos);
 			}
-		});
+		}).error(this.defaultDeferredErrorHandler);
 	},
 	createSubTree : function() { return this.createSubtree.apply(this, arguments); }, // obsolete, for backward compatibility
 	
@@ -1391,11 +1342,13 @@ TreeStyleTabWindow.prototype = {
 		var roots = [];
 		if (!aTabs || !aTabs.length) return roots;
 		aTabs = this.cleanUpTabsArray(aTabs);
-		aTabs.forEach(function(aTab) {
-			var parent = this.getParentTab(aTab);
-			if (parent && aTabs.indexOf(parent) > -1) return;
-			roots.push(aTab);
-		}, this);
+		for (let i = 0, maxi = aTabs.length; i < maxi; i++)
+		{
+			let tab = aTabs[i];
+			let parent = this.getParentTab(tab);
+			if (parent && aTabs.indexOf(parent) > -1) continue;
+			roots.push(tab);
+		}
 		return roots;
 	},
   
@@ -1425,7 +1378,7 @@ TreeStyleTabWindow.prototype = {
 			});
 		}
 		else {
-			sv.partTab(aTab);
+			sv.detachTab(aTab);
 			let index = nextSibling ? nextSibling._tPos : b.mTabContainer.childNodes.length ;
 			if (index > aTab._tPos) index--;
 			b.moveTabTo(aTab, index);
@@ -1473,9 +1426,11 @@ TreeStyleTabWindow.prototype = {
 
 		this.stopRendering();
 		this.markAsClosedSet(closeTabs);
-		closeTabs.reverse().forEach(function(aTab) {
-			b.removeTab(aTab);
-		});
+		var tabs = closeTabs.reverse();
+		for (let i = 0, maxi = tabs.length; i < maxi; i++)
+		{
+			b.removeTab(tabs[i]);
+		}
 		this.startRendering();
 	},
  
@@ -1511,8 +1466,9 @@ TreeStyleTabWindow.prototype = {
 			}
 			else {
 				let actionInfo = {
-						action : this.kACTIONS_FOR_DESTINATION | this.kACTION_IMPORT
+						action : remoteTab.__treestyletab__toBeDuplicated ? this.kACTION_DUPLICATE : this.kACTION_IMPORT
 					};
+
 				let b = this.browser;
 				let blankTab;
 				this.Deferred
@@ -1528,7 +1484,8 @@ TreeStyleTabWindow.prototype = {
 						remoteWindow = null
 						remoteService = null;
 						remoteMultipleTabService = null;
-					});
+					})
+					.error(this.defaultDeferredErrorHandler);
 			}
 			return true;
 		}
@@ -1561,31 +1518,6 @@ TreeStyleTabWindow.prototype = {
 		event.initEvent(this.kEVENT_TYPE_PRINT_PREVIEW_EXITED.replace(/^nsDOM/, ''), true, false);
 		d.documentElement.dispatchEvent(event);
 	},
- 
-	updatePinnedTabsSize : function TSTWindow_updatePinnedTabsSize()
-	{
-		if (this.pinnedTabsSizeStyle) {
-			this.pinnedTabsSizeStyle.parentNode.removeChild(this.pinnedTabsSizeStyle);
-			this.pinnedTabsSizeStyle = null;
-		}
-
-		var style = ['.tabbrowser-tabs[treestyletab-mode="vertical"] .tabbrowser-tab[pinned="true"] {'];
-		style.push('height: '+Math.max(this.MIN_PINNED_TAB_HEIGHT, this.pinnedTabHeight)+'px;');
-		style.push('}');
-
-		var d = this.document;
-		var pi = d.createProcessingInstruction(
-					'xml-stylesheet',
-					'type="text/css" href="data:text/css,'+encodeURIComponent(style.join(''))+'"'
-				);
-		d.insertBefore(pi, d.documentElement);
-		this.pinnedTabsSizeStyle = pi;
-	},
-	MIN_PINNED_TAB_WIDTH : 24,
-	MIN_PINNED_TAB_HEIGHT : 24,
-	pinnedTabWidth : 24,
-	pinnedTabHeight : 24,
-	pinnedTabsSizeStyle : null,
   
 	observe : function TSTWindow_observe(aSubject, aTopic, aData) 
 	{
@@ -1597,8 +1529,21 @@ TreeStyleTabWindow.prototype = {
 		}
 	},
 	get restoringTree() {
-		return this.restoringCount > 0;
+		if (this._restoringTree || !!this.restoringCount)
+			return true;
+
+		var count = 0;
+		this.browser.visibleTabs.some(function(aTab) {
+			if (aTab.linkedBrowser.__treestyletab__toBeRestored)
+				count++;
+			return count > 1;
+		});
+		return count > 1;
 	},
+	set restoringTree(aValue) {
+		return this._restoringTree = !!aValue;
+	},
+	_restoringTree : false,
  
 /* Pref Listener */ 
 	
@@ -1636,21 +1581,10 @@ TreeStyleTabWindow.prototype = {
 					this.endListenKeyEventsFor(this.LISTEN_FOR_AUTOEXPAND_BY_FOCUSCHANGE);
 				break;
 
-			case 'extensions.treestyletab.pinnedTab.width':
-				this.pinnedTabWidth = value;
-				this.updatePinnedTabsSize();
-				return;
-
-			case 'extensions.treestyletab.pinnedTab.height':
-				this.pinnedTabHeight = value;
-				this.updatePinnedTabsSize();
-				return;
-
 			default:
 				break;
 		}
 	}
   
 }; 
-// rap('end of definition of window');
   

-- 
Show tabs like a tree



More information about the Pkg-mozext-commits mailing list