Report errors if TST fails to apply patch to Firefox's functions

This commit is contained in:
Piro / YUKI Hiroshi 2014-11-13 02:13:23 +09:00
parent 1e8bad6e2e
commit 3de030ce48
4 changed files with 445 additions and 442 deletions

View File

@ -236,8 +236,8 @@ var TreeStyleTabBookmarksService = inherit(TreeStyleTabService, {
let (method = (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && PlacesUIUtils.TU__openTabset) ? let (method = (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && PlacesUIUtils.TU__openTabset) ?
'TU__openTabset' : 'TU__openTabset' :
'_openTabset') { '_openTabset') {
eval('PlacesUIUtils.'+method+' = '+ TreeStyleTabUtils.doPatching(PlacesUIUtils[method], 'PlacesUIUtils.'+method, function(aName, aSource) {
PlacesUIUtils[method].toSource().replace( var patched = eval(aName+' = '+aSource.replace(
/(function[^\(]*\([^\)]+)(\))/, /(function[^\(]*\([^\)]+)(\))/,
'$1, aFolderTitle$2' '$1, aFolderTitle$2'
).replace( ).replace(
@ -268,17 +268,18 @@ var TreeStyleTabBookmarksService = inherit(TreeStyleTabService, {
' browserWindow.TreeStyleTabService.applyTreeStructureToTabs(tabs, TSTTreeStructure, TSTOpenGroupBookmarkBehavior & browserWindow.TreeStyleTabBookmarksService.kGROUP_BOOKMARK_EXPAND_ALL_TREE);\n' + ' browserWindow.TreeStyleTabService.applyTreeStructureToTabs(tabs, TSTTreeStructure, TSTOpenGroupBookmarkBehavior & browserWindow.TreeStyleTabBookmarksService.kGROUP_BOOKMARK_EXPAND_ALL_TREE);\n' +
' }\n' + ' }\n' +
'$1' '$1'
) ));
); if (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && method.indexOf('TU_') > -1)
if (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && method.indexOf('TU_') > -1) window[method] = patched;
window[method] = PlacesUIUtils[method]; return patched;
}, 'TreeStyleTab');
} }
let (method = (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && PlacesUIUtils.TU_openContainerNodeInTabs) ? let (method = (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && PlacesUIUtils.TU_openContainerNodeInTabs) ?
'TU_openContainerNodeInTabs' : 'TU_openContainerNodeInTabs' :
'openContainerNodeInTabs') { 'openContainerNodeInTabs') {
eval('PlacesUIUtils.'+method+' = '+ TreeStyleTabUtils.doPatching(PlacesUIUtils[method], 'PlacesUIUtils.'+method, function(aName, aSource) {
PlacesUIUtils[method].toSource().replace( var patched = eval(aName+' = '+aSource.replace(
/(this\._openTabset\([^\)]+)(\))/, /(this\._openTabset\([^\)]+)(\))/,
'let (w = "_getTopBrowserWin" in this ?\n' + 'let (w = "_getTopBrowserWin" in this ?\n' +
' this._getTopBrowserWin() :\n' + ' this._getTopBrowserWin() :\n' +
@ -291,17 +292,18 @@ var TreeStyleTabBookmarksService = inherit(TreeStyleTabService, {
' }\n' + ' }\n' +
'}\n' + '}\n' +
'$1, aNode.title$2' '$1, aNode.title$2'
) ));
); if (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && method.indexOf('TU_') > -1)
if (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && method.indexOf('TU_') > -1) window[method] = patched;
window[method] = PlacesUIUtils[method]; return patched;
}, 'TreeStyleTab');
} }
let (method = (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && PlacesUIUtils.TU_openURINodesInTabs) ? let (method = (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && PlacesUIUtils.TU_openURINodesInTabs) ?
'TU_openURINodesInTabs' : 'TU_openURINodesInTabs' :
'openURINodesInTabs') { 'openURINodesInTabs') {
eval('PlacesUIUtils.'+method+' = '+ TreeStyleTabUtils.doPatching(PlacesUIUtils[method], 'PlacesUIUtils.'+method, function(aName, aSource) {
PlacesUIUtils[method].toSource().replace( var patched = eval(aName+' = '+aSource.replace(
'{', '{',
'{\n' + '{\n' +
' var TSTBS, TSTUtils;\n' + ' var TSTBS, TSTUtils;\n' +
@ -328,10 +330,11 @@ var TreeStyleTabBookmarksService = inherit(TreeStyleTabService, {
' [aNodes[0].title, aNodes.length]\n' + ' [aNodes[0].title, aNodes.length]\n' +
' )\n' + ' )\n' +
'$2' '$2'
) ));
); if (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && method.indexOf('TU_') > -1)
if (TreeStyleTabUtils.getTreePref('compatibility.TabUtilities') && method.indexOf('TU_') > -1) window[method] = patched;
window[method] = PlacesUIUtils[method]; return patched;
}, 'TreeStyleTab');
} }
PlacesUIUtils.__treestyletab__done = true; PlacesUIUtils.__treestyletab__done = true;
@ -341,8 +344,8 @@ var TreeStyleTabBookmarksService = inherit(TreeStyleTabService, {
if ('PlacesCommandHook' in window && 'bookmarkCurrentPages' in PlacesCommandHook) { if ('PlacesCommandHook' in window && 'bookmarkCurrentPages' in PlacesCommandHook) {
// Bookmark All Tabs // Bookmark All Tabs
eval('PlacesCommandHook.bookmarkCurrentPages = '+ TreeStyleTabUtils.doPatching(PlacesCommandHook.bookmarkCurrentPages, 'PlacesCommandHook.bookmarkCurrentPages', function(aName, aSource) {
PlacesCommandHook.bookmarkCurrentPages.toSource().replace( return eval(aName+' = '+aSource.replace(
'{', '{',
'{\n' + '{\n' +
' TreeStyleTabBookmarksService.beginAddBookmarksFromTabs((function() {\n' + ' TreeStyleTabBookmarksService.beginAddBookmarksFromTabs((function() {\n' +
@ -367,8 +370,8 @@ var TreeStyleTabBookmarksService = inherit(TreeStyleTabService, {
' }\n' + ' }\n' +
' TreeStyleTabBookmarksService.endAddBookmarksFromTabs();\n' + ' TreeStyleTabBookmarksService.endAddBookmarksFromTabs();\n' +
'$1' '$1'
) ));
); }, 'TreeStyleTab');
} }
}, },
handleTabsOpenProcess : function TSTBMService_handleTabsOpenProcess(aWhere, aEvent, aBrowserWindow, aIDs, aURLs, aFolderTitle) handleTabsOpenProcess : function TSTBMService_handleTabsOpenProcess(aWhere, aEvent, aBrowserWindow, aIDs, aURLs, aFolderTitle)

View File

@ -47,32 +47,36 @@ var TreeStyleTabBookmarksServiceEditable = inherit(TreeStyleTabBookmarksService,
// main browser window // main browser window
if ('StarUI' in window) { if ('StarUI' in window) {
if ('_doShowEditBookmarkPanel' in StarUI) { TreeStyleTabUtils.doPatching(StarUI._doShowEditBookmarkPanel, 'StarUI._doShowEditBookmarkPanel', function(aName, aSource) {
eval('StarUI._doShowEditBookmarkPanel = '+StarUI._doShowEditBookmarkPanel.toSource().replace( return eval(aName+' = '+aSource.replace(
'{', '{',
'{ TreeStyleTabBookmarksServiceEditable.initEditUI();' '{ TreeStyleTabBookmarksServiceEditable.initEditUI();'
)); ));
} }, 'TreeStyleTab');
if ('quitEditMode' in StarUI) {
eval('StarUI.quitEditMode = '+StarUI.quitEditMode.toSource().replace( TreeStyleTabUtils.doPatching(StarUI.quitEditMode, 'StarUI.quitEditMode', function(aName, aSource) {
return eval(aName+' = '+aSource.replace(
'{', '{',
'{ TreeStyleTabBookmarksServiceEditable.saveParentFor(this._itemId);' '{ TreeStyleTabBookmarksServiceEditable.saveParentFor(this._itemId);'
)); ));
} }, 'TreeStyleTab');
if ('cancelButtonOnCommand' in StarUI) {
eval('StarUI.cancelButtonOnCommand = '+StarUI.cancelButtonOnCommand.toSource().replace( TreeStyleTabUtils.doPatching(StarUI.cancelButtonOnCommand, 'StarUI.cancelButtonOnCommand', function(aName, aSource) {
return eval(aName+' = '+aSource.replace(
'{', '{',
'{ TreeStyleTabBookmarksServiceEditable.canceled = true;' '{ TreeStyleTabBookmarksServiceEditable.canceled = true;'
)); ));
} }, 'TreeStyleTab');
} }
// Bookmarks Property dialog // Bookmarks Property dialog
if ('BookmarkPropertiesPanel' in window) { if ('BookmarkPropertiesPanel' in window) {
eval('BookmarkPropertiesPanel._endBatch = '+BookmarkPropertiesPanel._endBatch.toSource().replace( TreeStyleTabUtils.doPatching(BookmarkPropertiesPanel._endBatch, 'BookmarkPropertiesPanel._endBatch', function(aName, aSource) {
/(PlacesUIUtils\.transactionManager\.endBatch\([^\)]+\);)/, return eval(aName+' = '+aSource.replace(
'$1 TreeStyleTabBookmarksServiceEditable.saveParentFor(this._itemId);' /(PlacesUtils\.transactionManager\.endBatch\([^)]*\);)/,
)); '$1 TreeStyleTabBookmarksServiceEditable.saveParentFor(this._itemId);'
));
}, 'TreeStyleTab');
} }
// Places Organizer (Library) // Places Organizer (Library)
@ -118,21 +122,27 @@ var TreeStyleTabBookmarksServiceEditable = inherit(TreeStyleTabBookmarksService,
this.blankItem.setAttribute('label', TreeStyleTabUtils.treeBundle.getString('bookmarkProperty.parent.blank.label')); this.blankItem.setAttribute('label', TreeStyleTabUtils.treeBundle.getString('bookmarkProperty.parent.blank.label'));
eval('gEditItemOverlay._showHideRows = '+gEditItemOverlay._showHideRows.toSource().replace( TreeStyleTabUtils.doPatching(gEditItemOverlay._showHideRows, 'gEditItemOverlay._showHideRows', function(aName, aSource) {
/(\}\)?)$/, return eval(aName+' = '+aSource.replace(
' TreeStyleTabBookmarksServiceEditable.parentRow.collapsed = this._element("keywordRow").collapsed && this._element("folderRow").collapsed;\n' + /(\}\)?)$/,
'$1' ' TreeStyleTabBookmarksServiceEditable.parentRow.collapsed = this._element("keywordRow").collapsed && this._element("folderRow").collapsed;\n' +
)); '$1'
));
}, 'TreeStyleTab');
eval('gEditItemOverlay.initPanel = '+gEditItemOverlay.initPanel.toSource().replace( TreeStyleTabUtils.doPatching(gEditItemOverlay.initPanel, 'gEditItemOverlay.initPanel', function(aName, aSource) {
'if (this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK) {', return eval(aName+' = '+aSource.replace(
'$& TreeStyleTabBookmarksServiceEditable.initParentMenuList();' 'if (this._itemType == Ci.nsINavBookmarksService.TYPE_BOOKMARK) {',
)); '$& TreeStyleTabBookmarksServiceEditable.initParentMenuList();'
));
}, 'TreeStyleTab');
eval('gEditItemOverlay.onItemMoved = '+gEditItemOverlay.onItemMoved.toSource().replace( TreeStyleTabUtils.doPatching(gEditItemOverlay.onItemMoved, 'gEditItemOverlay.onItemMoved', function(aName, aSource) {
'{', return eval(aName+' = '+aSource.replace(
'$& if (aNewParent == this._getFolderIdFromMenuList()) TreeStyleTabBookmarksServiceEditable.initParentMenuList();' '{',
)); '$& if (aNewParent == this._getFolderIdFromMenuList()) TreeStyleTabBookmarksServiceEditable.initParentMenuList();'
));
}, 'TreeStyleTab');
this.editUIInitialized = true; this.editUIInitialized = true;
}, },

View File

@ -1,3 +1,7 @@
Components.utils.import('resource://gre/modules/XPCOMUtils.jsm');
XPCOMUtils.defineLazyModuleGetter(this,
'TreeStyleTabUtils', 'resource://treestyletab-modules/utils.js');
var TreeStyleTabWindowHelper = { var TreeStyleTabWindowHelper = {
get service() get service()
@ -7,116 +11,94 @@ var TreeStyleTabWindowHelper = {
preInit : function TSTWH_preInit() preInit : function TSTWH_preInit()
{ {
var source; TreeStyleTabUtils.doPatching(gBrowserInit._delayedStartup, 'gBrowserInit._delayedStartup', function(aName, aSource) {
var target; if (aSource.indexOf('!MultipleTabService.tearOffSelectedTabsFromRemote()') > -1) {
if ('gBrowserInit' in window) { return eval(aName+' = '+aSource.replace(
if ( '!MultipleTabService.tearOffSelectedTabsFromRemote()',
'_delayedStartup' in gBrowserInit && '!TreeStyleTabService.tearOffSubtreeFromRemote() && $&'
(source = gBrowserInit._delayedStartup.toSource()) && ));
source.indexOf('swapBrowsersAndCloseOther') > -1
) {
target = 'gBrowserInit._delayedStartup';
} }
} else if (aSource.indexOf('gBrowser.swapBrowsersAndCloseOther') > -1) {
if (!target) return eval(aName+' = '+aSource.replace(
dump('Tree Style Tab: failed to initialize startup function!'); 'gBrowser.swapBrowsersAndCloseOther(gBrowser.selectedTab, uriToLoad);',
if (source.indexOf('!MultipleTabService.tearOffSelectedTabsFromRemote()') > -1) { 'if (!TreeStyleTabService.tearOffSubtreeFromRemote()) { $& }'
eval(target+' = '+source.replace( ).replace(
'!MultipleTabService.tearOffSelectedTabsFromRemote()', // Workaround for https://github.com/piroor/treestyletab/issues/741
'!TreeStyleTabService.tearOffSubtreeFromRemote() && $&' // After the function is updated by TST, reassignment of a global variable raises an error like:
)); // > System JS : ERROR chrome://treestyletab/content/windowHelper.js line 30 > eval:130 - TypeError: can't redefine non-configurable property 'gBidiUI'
} // If I access it as a property of the global object, the error doesn't appear.
else if (source.indexOf('gBrowser.swapBrowsersAndCloseOther') > -1) { /([^\.])\bgBidiUI =/,
eval(target+' = '+source.replace( '$1window.gBidiUI ='
'gBrowser.swapBrowsersAndCloseOther(gBrowser.selectedTab, uriToLoad);', ));
'if (!TreeStyleTabService.tearOffSubtreeFromRemote()) { $& }' }
).replace( }, 'TreeStyleTab');
// Workaround for https://github.com/piroor/treestyletab/issues/741
// After the function is updated by TST, reassignment of a global variable raises an error like:
// > System JS : ERROR chrome://treestyletab/content/windowHelper.js line 30 > eval:130 - TypeError: can't redefine non-configurable property 'gBidiUI'
// If I access it as a property of the global object, the error doesn't appear.
/([^\.])\bgBidiUI =/,
'$1window.gBidiUI ='
));
}
eval('nsBrowserAccess.prototype.openURI = '+ TreeStyleTabUtils.doPatching(nsBrowserAccess.prototype.openURI, 'nsBrowserAccess.prototype.openURI', function(aName, aSource) {
nsBrowserAccess.prototype.openURI.toSource().replace( return eval(aName+' = '+aSource.replace(
/(switch\s*\(aWhere\))/, /(switch\s*\(aWhere\))/,
'TreeStyleTabService.onBeforeBrowserAccessOpenURI(aOpener, aWhere, aContext); $1' 'TreeStyleTabService.onBeforeBrowserAccessOpenURI(aOpener, aWhere, aContext); $1'
) ));
); }, 'TreeStyleTab');
if (nsBrowserAccess.prototype.openURIInFrame) {
eval('nsBrowserAccess.prototype.openURIInFrame = '+
nsBrowserAccess.prototype.openURIInFrame.toSource().replace(
'let browser = ',
'TreeStyleTabService.onBeforeBrowserAccessOpenURI(aOpener, aWhere, aContext); $&'
)
);
}
if ('TabsInTitlebar' in window && TreeStyleTabUtils.doPatching(nsBrowserAccess.prototype.openURIInFrame, 'nsBrowserAccess.prototype.openURIInFrame', function(aName, aSource) {
TabsInTitlebar._update) { return eval(aName+' = '+aSource.replace(
eval('window.TabsInTitlebar._update = '+ 'let browser = ',
window.TabsInTitlebar._update.toSource().replace( 'TreeStyleTabService.onBeforeBrowserAccessOpenURI(aOpener, aWhere, aContext); $&'
));
}, 'TreeStyleTab');
if ('TabsInTitlebar' in window) {
TreeStyleTabUtils.doPatching(TabsInTitlebar._update, 'TabsInTitlebar._update', function(aName, aSource) {
return eval(aName+' = '+aSource.replace(
/let fullTabsHeight = /, /let fullTabsHeight = /,
'$& gBrowser.treeStyleTab.position != "top" ? 0 : ' '$& gBrowser.treeStyleTab.position != "top" ? 0 : '
) ));
); }, 'treeStyleTab');
} }
if ('BrowserOpenTab' in window) { TreeStyleTabUtils.doPatching(window.BrowserOpenTab, 'window.BrowserOpenTab', function(aName, aSource) {
eval('window.BrowserOpenTab = '+ return eval(aName+' = '+aSource.replace(
window.BrowserOpenTab.toSource().replace( 'openUILinkIn(',
'openUILinkIn(', 'gBrowser.treeStyleTab.onBeforeNewTabCommand(); $&'
'gBrowser.treeStyleTab.onBeforeNewTabCommand(); $&' ));
) }, 'treeStyleTab');
);
}
if ('undoCloseTab' in window) { TreeStyleTabUtils.doPatching(window.undoCloseTab, 'window.undoCloseTab', function(aName, aSource) {
eval('window.undoCloseTab = '+ return eval(aName+' = '+aSource.replace(
window.undoCloseTab.toSource().replace( /(\btab\s*=\s*[^\.]+\.undoCloseTab\([^;]+\);)/,
/(\btab\s*=\s*[^\.]+\.undoCloseTab\([^;]+\);)/, 'gBrowser.__treestyletab__doingUndoCloseTab = true;\n' +
'gBrowser.__treestyletab__doingUndoCloseTab = true;\n' + '$1\n' +
'$1\n' + 'tab.__treestyletab__restoredByUndoCloseTab = true;\n' +
'tab.__treestyletab__restoredByUndoCloseTab = true;\n' + 'setTimeout(function() { delete gBrowser.__treestyletab__doingUndoCloseTab; }, 0);'
'setTimeout(function() { delete gBrowser.__treestyletab__doingUndoCloseTab; }, 0);' ));
) }, 'treestyletab');
);
}
if ('XULBrowserWindow' in window && TreeStyleTabUtils.doPatching(window.XULBrowserWindow.hideChromeForLocation, 'XULBrowserWindow.hideChromeForLocation', function(aName, aSource) {
'hideChromeForLocation' in window.XULBrowserWindow) { return eval(aName+' = '+aSource.replace(
eval('XULBrowserWindow.hideChromeForLocation = '+ '{',
XULBrowserWindow.hideChromeForLocation.toSource().replace( '{ if (gBrowser.treeStyleTab.isVertical) return false;\n'
'{', ));
'{ if (gBrowser.treeStyleTab.isVertical) return false;\n' }, 'treeStyleTab');
)
);
}
let (functions = [ [
'window.duplicateTab.handleLinkClick', 'window.duplicateTab.handleLinkClick',
'window.duplicatethistab.handleLinkClick', 'window.duplicatethistab.handleLinkClick',
'window.__treestyletab__highlander__origHandleLinkClick', 'window.__treestyletab__highlander__origHandleLinkClick',
'window.__splitbrowser__handleLinkClick', 'window.__splitbrowser__handleLinkClick',
'window.__ctxextensions__handleLinkClick', 'window.__ctxextensions__handleLinkClick',
'window.handleLinkClick' 'window.handleLinkClick'
]) { ].some(function(aName) {
for (let i = 0, maxi = functions.length; i < maxi; i++) let func = this._getFunction(aName);
{ if (!func || !/^\(?function handleLinkClick/.test(func.toString()))
let func = functions[i]; return false;
let source = this._getFunctionSource(func); TreeStyleTabUtils.doPatching(func, aName, function(aName, aSource) {
if (!source || !/^\(?function handleLinkClick/.test(source)) return eval(aName+' = '+aSource.replace(
continue;
eval(func+' = '+source.replace(
/(charset\s*:\s*doc\.characterSet\s*)/, /(charset\s*:\s*doc\.characterSet\s*)/,
'$1, event : event, linkNode : linkNode' '$1, event : event, linkNode : linkNode'
)); ));
break; }, 'event : event, linkNode : linkNode');
} return true;
} }, this);
this.overrideExtensionsPreInit(); // windowHelperHacks.js this.overrideExtensionsPreInit(); // windowHelperHacks.js
}, },
@ -143,182 +125,179 @@ var TreeStyleTabWindowHelper = {
) )
aObserver = aObserver.tabContainer; aObserver = aObserver.tabContainer;
if ('_setEffectAllowedForDataTransfer' in aObserver) { TreeStyleTabUtils.doPatching(aObserver._setEffectAllowedForDataTransfer, aObserver+'._setEffectAllowedForDataTransfer', function(aName, aSource) {
eval('aObserver._setEffectAllowedForDataTransfer = '+ return eval('aObserver._setEffectAllowedForDataTransfer = '+aSource.replace(
aObserver._setEffectAllowedForDataTransfer.toSource().replace( '{',
'{', '{ var TSTTabBrowser = this instanceof Element ? (this.tabbrowser || this) : gBrowser ; var TST = TSTTabBrowser.treeStyleTab;'
'{ var TSTTabBrowser = this instanceof Element ? (this.tabbrowser || this) : gBrowser ; var TST = TSTTabBrowser.treeStyleTab;' ).replace(
).replace( /\.screenX/g, '[TST.screenPositionProp]'
/\.screenX/g, '[TST.screenPositionProp]' ).replace(
).replace( /\.width/g, '[TST.sizeProp]'
/\.width/g, '[TST.sizeProp]' ).replace(
).replace( /(return (?:true|dt.effectAllowed = "copyMove");)/,
/(return (?:true|dt.effectAllowed = "copyMove");)/, 'if (!TST.tabbarDNDObserver.canDropTab(arguments[0])) {\n' +
'if (!TST.tabbarDNDObserver.canDropTab(arguments[0])) {\n' + ' return dt.effectAllowed = "none";\n' +
' return dt.effectAllowed = "none";\n' + '}\n' +
'}\n' + '$1'
'$1' ).replace(
).replace( 'sourceNode.parentNode == this &&',
'sourceNode.parentNode == this &&', '$& TST.getTabFromEvent(event) == sourceNode &&'
'$& TST.getTabFromEvent(event) == sourceNode &&' ));
) }, 'TST');
);
}
}, },
overrideGlobalFunctions : function TSTWH_overrideGlobalFunctions() overrideGlobalFunctions : function TSTWH_overrideGlobalFunctions()
{ {
this.initToolbarItems(); this.initToolbarItems();
eval('nsContextMenu.prototype.openLinkInTab = '+ TreeStyleTabUtils.doPatching(nsContextMenu.prototype.openLinkInTab, 'nsContextMenu.prototype.openLinkInTab', function(aName, aSource) {
nsContextMenu.prototype.openLinkInTab.toSource().replace( return eval(aName+' = '+aSource.replace(
'{', '{',
'{\n' + '{\n' +
' TreeStyleTabService.handleNewTabFromCurrent(this.target.ownerDocument.defaultView);' ' TreeStyleTabService.handleNewTabFromCurrent(this.target.ownerDocument.defaultView);'
) ));
); }, 'TreeStyleTab');
eval('nsContextMenu.prototype.openFrameInTab = '+
nsContextMenu.prototype.openFrameInTab.toSource().replace( TreeStyleTabUtils.doPatching(nsContextMenu.prototype.openFrameInTab, 'nsContextMenu.prototype.openFrameInTab', function(aName, aSource) {
return eval(aName+' = '+aSource.replace(
'{', '{',
'{\n' + '{\n' +
' TreeStyleTabService.handleNewTabFromCurrent(this.target.ownerDocument.defaultView);' ' TreeStyleTabService.handleNewTabFromCurrent(this.target.ownerDocument.defaultView);'
) ));
); }, 'TreeStyleTab');
var viewImageMethod = ('viewImage' in nsContextMenu.prototype) ? 'viewImage' : 'viewMedia' ; var viewImageMethod = ('viewImage' in nsContextMenu.prototype) ? 'viewImage' : 'viewMedia' ;
eval('nsContextMenu.prototype.'+viewImageMethod+' = '+ TreeStyleTabUtils.doPatching(nsContextMenu.prototype[viewImageMethod], 'nsContextMenu.prototype.'+viewImageMethod, function(aName, aSource) {
nsContextMenu.prototype[viewImageMethod].toSource().replace( return eval(aName+' = '+aSource.replace(
'openUILink(', 'openUILink(',
'TreeStyleTabService.onBeforeViewMedia(e, this.target.ownerDocument.defaultView); $&' 'TreeStyleTabService.onBeforeViewMedia(e, this.target.ownerDocument.defaultView); $&'
) ));
); }, 'TreeStyleTab');
eval('nsContextMenu.prototype.viewBGImage = '+
nsContextMenu.prototype.viewBGImage.toSource().replace( TreeStyleTabUtils.doPatching(nsContextMenu.prototype.viewBGImage, 'nsContextMenu.prototype.viewBGImage', function(aName, aSource) {
return eval(aName+' = '+aSource.replace(
'openUILink(', 'openUILink(',
'TreeStyleTabService.onBeforeViewMedia(e, this.target.ownerDocument.defaultView); $&' 'TreeStyleTabService.onBeforeViewMedia(e, this.target.ownerDocument.defaultView); $&'
) ));
); }, 'TreeStyleTab');
eval('nsContextMenu.prototype.addDictionaries = '+
nsContextMenu.prototype.addDictionaries.toSource().replace( TreeStyleTabUtils.doPatching(nsContextMenu.prototype.addDictionaries, 'nsContextMenu.prototype.addDictionaries', function(aName, aSource) {
return eval(aName+' = '+aSource.replace(
'openUILinkIn(', 'openUILinkIn(',
'TreeStyleTabService.onBeforeOpenLink(where, this.target.ownerDocument.defaultView); $&' 'TreeStyleTabService.onBeforeOpenLink(where, this.target.ownerDocument.defaultView); $&'
) ));
); }, 'TreeStyleTab');
if ('BrowserSearch' in window && TreeStyleTabUtils.doPatching(BrowserSearch._loadSearch, 'BrowserSearch._loadSearch', function(aName, aSource) {
'_loadSearch' in BrowserSearch) { return eval(aName+' = '+aSource.replace(
eval('BrowserSearch._loadSearch = '+ 'openLinkIn(',
BrowserSearch._loadSearch.toSource().replace( 'TreeStyleTabService.onBeforeBrowserSearch(arguments[0], useNewTab); $&'
'openLinkIn(', ));
'TreeStyleTabService.onBeforeBrowserSearch(arguments[0], useNewTab); $&' }, 'TreeStyleTab');
)
);
}
if ('openLinkIn' in window) { TreeStyleTabUtils.doPatching(window.openLinkIn, 'window.openLinkIn', function(aName, aSource) {
// Bug 1050447 changed this line in Fx 34 to // Bug 1050447 changed this line in Fx 34 to
// newTab = w.gBrowser.loadOneTab( // newTab = w.gBrowser.loadOneTab(
eval('window.openLinkIn = '+ return eval(aName+' = '+aSource.replace(
window.openLinkIn.toSource().replace( /((b|newTab = w\.gB)rowser.loadOneTab\()/g,
/((b|newTab = w\.gB)rowser.loadOneTab\()/g, 'TreeStyleTabService.onBeforeOpenLinkWithTab(gBrowser.selectedTab, aFromChrome); $1'
'TreeStyleTabService.onBeforeOpenLinkWithTab(gBrowser.selectedTab, aFromChrome); $1' ));
) }, 'TreeStyleTab');
);
}
let (functions = [ [
'window.permaTabs.utils.wrappedFunctions["window.contentAreaClick"]', 'window.permaTabs.utils.wrappedFunctions["window.contentAreaClick"]',
'window.__contentAreaClick', 'window.__contentAreaClick',
'window.__ctxextensions__contentAreaClick', 'window.__ctxextensions__contentAreaClick',
'window.contentAreaClick' 'window.contentAreaClick'
]) { ].forEach(function(aName) {
for (let i = 0, maxi = functions.length; i < maxi; i++) var func = this._getFunction(aName);
{ var source = func && func.toString();
let func = functions[i]; if (!func ||
let source = this._getFunctionSource(func); !/^\(?function contentAreaClick/.test(source) ||
if (!source || !/^\(?function contentAreaClick/.test(source)) // for Tab Utilities, etc. Some addons insert openNewTabWith() to the function.
continue; // (calls for the function is not included by Firefox default.)
eval(func+' = '+source.replace( !/(openNewTabWith\()/.test(source))
// for Tab Utilities, etc. Some addons insert openNewTabWith() to the function. return;
// (calls for the function is not included by Firefox default.) TreeStyleTabUtils.doPatching(func, aName, function(aName, aSource) {
return eval(aName+' = '+aSource.replace(
/(openNewTabWith\()/g, /(openNewTabWith\()/g,
'TreeStyleTabService.onBeforeOpenNewTabByThirdParty(event.target.ownerDocument.defaultView); $1' 'TreeStyleTabService.onBeforeOpenNewTabByThirdParty(event.target.ownerDocument.defaultView); $1'
)); ));
} }, 'TreeStyleTab');
} }, this);
if (window.duplicateTabIn) { TreeStyleTabUtils.doPatching(window.duplicateTabIn, 'window.duplicateTabIn', function(aName, aSource) {
eval('window.duplicateTabIn = '+ return eval(aName+' = '+aSource.replace(
window.duplicateTabIn.toSource().replace( '{',
'{', '{ gBrowser.treeStyleTab.onBeforeTabDuplicate(aTab, where, delta); '
'{ gBrowser.treeStyleTab.onBeforeTabDuplicate(aTab, where, delta); ' ));
) }, 'treeStyleTab');
);
}
let (functions = [ [
'permaTabs.utils.wrappedFunctions["window.BrowserHomeClick"]', 'permaTabs.utils.wrappedFunctions["window.BrowserHomeClick"]',
'window.BrowserHomeClick', 'window.BrowserHomeClick',
'window.BrowserGoHome' 'window.BrowserGoHome'
]) { ].forEach(function(aName) {
for (let i = 0, maxi = functions.length; i < maxi; i++) let func = this._getFunction(aName);
{ if (!func || !/^\(?function (BrowserHomeClick|BrowserGoHome)/.test(func.toString()))
let func = functions[i]; return;
let source = this._getFunctionSource(func); TreeStyleTabUtils.doPatching(func, aName, function(aName, aSource) {
if (!source || !/^\(?function (BrowserHomeClick|BrowserGoHome)/.test(source)) return eval(aName+' = '+aSource.replace(
continue;
eval(func+' = '+source.replace(
'gBrowser.loadTabs(', 'gBrowser.loadTabs(',
'TreeStyleTabService.readyToOpenNewTabGroup(gBrowser); $&' 'TreeStyleTabService.readyToOpenNewTabGroup(gBrowser); $&'
)); ));
} }, 'TreeStyleTab');
} }, this);
eval('FeedHandler.loadFeed = '+ TreeStyleTabUtils.doPatching(FeedHandler.loadFeed, 'FeedHandler.loadFeed', function(aName, aSource) {
FeedHandler.loadFeed.toSource().replace( return eval(aName+' = '+aSource.replace(
'openUILink(', 'openUILink(',
'TreeStyleTabService.onBeforeViewMedia(event, gBrowser); $&' 'TreeStyleTabService.onBeforeViewMedia(event, gBrowser); $&'
) ));
); }, 'TreeStyleTab');
eval('FullScreen.mouseoverToggle = '+ TreeStyleTabUtils.doPatching(FullScreen.mouseoverToggle, 'FullScreen.mouseoverToggle', function(aName, aSource) {
FullScreen.mouseoverToggle.toSource().replace( return eval(aName+' = '+aSource.replace(
'this._isChromeCollapsed = !aShow;', 'this._isChromeCollapsed = !aShow;',
'gBrowser.treeStyleTab.updateFloatingTabbar(gBrowser.treeStyleTab.kTABBAR_UPDATE_BY_FULLSCREEN); $&' 'gBrowser.treeStyleTab.updateFloatingTabbar(gBrowser.treeStyleTab.kTABBAR_UPDATE_BY_FULLSCREEN); $&'
) ));
); }, 'treeStyleTab');
eval('FullScreen.toggle = '+
FullScreen.toggle.toSource().replace( TreeStyleTabUtils.doPatching(FullScreen.toggle, 'FullScreen.toggle', function(aName, aSource) {
return eval(aName+' = '+aSource.replace(
'{', '{',
'{ gBrowser.treeStyleTab.onBeforeFullScreenToggle(); ' '{ gBrowser.treeStyleTab.onBeforeFullScreenToggle(); '
) ));
); }, 'treeStyleTab');
if ('PrintUtils' in window) { TreeStyleTabUtils.doPatching(PrintUtils.printPreview, 'PrintUtils.printPreview', function(aName, aSource) {
eval('PrintUtils.printPreview = '+PrintUtils.printPreview.toSource().replace( return eval(aName+' = '+aSource.replace(
'{', '{',
'{ TreeStyleTabService.onPrintPreviewEnter();' '{ TreeStyleTabService.onPrintPreviewEnter();'
)); ));
eval('PrintUtils.exitPrintPreview = '+PrintUtils.exitPrintPreview.toSource().replace( }, 'TreeStyleTab');
TreeStyleTabUtils.doPatching(PrintUtils.exitPrintPreview, 'PrintUtils.exitPrintPreview', function(aName, aSource) {
return eval(aName+' = '+aSource.replace(
'{', '{',
'{ TreeStyleTabService.onPrintPreviewExit();' '{ TreeStyleTabService.onPrintPreviewExit();'
)); ));
}, 'TreeStyleTab');
if ('TabsOnTop' in window) {
TreeStyleTabUtils.doPatching(TabsOnTop.syncUI, 'TabsOnTop.syncUI', function(aName, aSource) {
return eval(aName+' = '+aSource.replace(
/(\}\)?)$/,
'gBrowser.treeStyleTab.onTabsOnTopSyncCommand(enabled); $&'
));
}, 'treeStyleTab');
} }
if ('TabsOnTop' in window && TabsOnTop.syncUI) { TreeStyleTabUtils.doPatching(window.toggleSidebar, 'window.toggleSidebar', function(aName, aSource) {
eval('TabsOnTop.syncUI = '+TabsOnTop.syncUI.toSource().replace( return eval(aName+' = '+aSource.replace(
/(\}\)?)$/, '{',
'gBrowser.treeStyleTab.onTabsOnTopSyncCommand(enabled); $&' '{ gBrowser.treeStyleTab.updateFloatingTabbar(gBrowser.treeStyleTab.kTABBAR_UPDATE_BY_TOGGLE_SIDEBAR);'
)); ));
} }, 'treeStyleTab');
if ('toggleSidebar' in window) {
eval('window.toggleSidebar = '+
window.toggleSidebar.toSource().replace(
'{',
'{ gBrowser.treeStyleTab.updateFloatingTabbar(gBrowser.treeStyleTab.kTABBAR_UPDATE_BY_TOGGLE_SIDEBAR);'
)
);
}
}, },
_splitFunctionNames : function TSTWH__splitFunctionNames(aString) _splitFunctionNames : function TSTWH__splitFunctionNames(aString)
{ {
@ -331,7 +310,7 @@ var TreeStyleTabWindowHelper = {
.trim(); .trim();
}); });
}, },
_getFunctionSource : function TSTWH__getFunctionSource(aFunc) _getFunction : function TSTWH__getFunction(aFunc)
{ {
var func; var func;
try { try {
@ -340,7 +319,7 @@ var TreeStyleTabWindowHelper = {
catch(e) { catch(e) {
return null; return null;
} }
return func ? func.toSource() : null ; return func;
}, },
initToolbarItems : function TSTWH_initToolbarItems() initToolbarItems : function TSTWH_initToolbarItems()
@ -349,12 +328,14 @@ var TreeStyleTabWindowHelper = {
if (searchbar && if (searchbar &&
searchbar.doSearch && searchbar.doSearch &&
searchbar.doSearch.toSource().toSource().indexOf('TreeStyleTabService') < 0) { searchbar.doSearch.toSource().toSource().indexOf('TreeStyleTabService') < 0) {
eval('searchbar.doSearch = '+searchbar.doSearch.toSource().replace( TreeStyleTabUtils.doPatching(searchbar.doSearch, 'searchbar.doSearch', function(aName, aSource) {
/(openUILinkIn\(.+?\);)/, return eval(aName+' = '+aSource.replace(
'TreeStyleTabService.onBeforeBrowserSearch(arguments[0]);\n' + /(openUILinkIn\(.+?\);)/,
'$1\n' + 'TreeStyleTabService.onBeforeBrowserSearch(arguments[0]);\n' +
'TreeStyleTabService.stopToOpenChildTab();' '$1\n' +
)); 'TreeStyleTabService.stopToOpenChildTab();'
));
}, 'TreeStyleTab');
} }
var goButton = document.getElementById('urlbar-go-button'); var goButton = document.getElementById('urlbar-go-button');
@ -397,67 +378,63 @@ var TreeStyleTabWindowHelper = {
{ {
var b = aTabBrowser; var b = aTabBrowser;
let (source = b.moveTabForward.toSource()) { TreeStyleTabUtils.doPatching(b.moveTabForward, 'b.moveTabForward', function(aName, aSource) {
eval('b.moveTabForward = '+ return eval(aName+' = '+aSource.replace(
source.replace( 'if (nextTab)',
'if (nextTab)', '(function() {\n' +
'(function() {\n' + ' if (this.treeStyleTab.hasChildTabs(this.mCurrentTab)) {\n' +
' if (this.treeStyleTab.hasChildTabs(this.mCurrentTab)) {\n' + ' let descendant = this.treeStyleTab.getDescendantTabs(this.mCurrentTab);\n' +
' let descendant = this.treeStyleTab.getDescendantTabs(this.mCurrentTab);\n' + ' if (descendant.length)\n' +
' if (descendant.length)\n' + ' nextTab = this.treeStyleTab.getNextTab(descendant[descendant.length-1]);\n' +
' nextTab = this.treeStyleTab.getNextTab(descendant[descendant.length-1]);\n' + ' }\n' +
' }\n' + '}).call(this);' +
'}).call(this);' + '$&'
'$&' ).replace(
).replace( /(this.moveTabTo\([^;]+\);)/,
/(this.moveTabTo\([^;]+\);)/, '(function() {\n' +
'(function() {\n' + ' let descendant = this.treeStyleTab.getDescendantTabs(nextTab);\n' +
' let descendant = this.treeStyleTab.getDescendantTabs(nextTab);\n' + ' if (descendant.length) {\n' +
' if (descendant.length) {\n' + ' nextTab = descendant[descendant.length-1];\n' +
' nextTab = descendant[descendant.length-1];\n' + ' }\n' +
' }\n' + ' $1\n' +
' $1\n' + '}).call(this);'
'}).call(this);' ).replace(
).replace( 'this.moveTabToStart();',
'this.moveTabToStart();', '(function() {\n' +
'(function() {\n' + ' this.treeStyleTab.internallyTabMovingCount++;\n' +
' this.treeStyleTab.internallyTabMovingCount++;\n' + ' let parentTab = this.treeStyleTab.getParentTab(this.mCurrentTab);\n' +
' let parentTab = this.treeStyleTab.getParentTab(this.mCurrentTab);\n' + ' if (parentTab) {\n' +
' if (parentTab) {\n' + ' this.moveTabTo(this.mCurrentTab, this.treeStyleTab.getFirstChildTab(parentTab)._tPos);\n' +
' this.moveTabTo(this.mCurrentTab, this.treeStyleTab.getFirstChildTab(parentTab)._tPos);\n' + ' this.mCurrentTab.focus();\n' +
' this.mCurrentTab.focus();\n' + ' }\n' +
' }\n' + ' else {\n' +
' else {\n' + ' $&\n' +
' $&\n' + ' }\n' +
' }\n' + ' this.treeStyleTab.internallyTabMovingCount--;\n' +
' this.treeStyleTab.internallyTabMovingCount--;\n' + '}).call(this);'
'}).call(this);' ));
) }, 'treeStyleTab');
);
}
let (source = b.moveTabBackward.toSource()) { TreeStyleTabUtils.doPatching(b.moveTabBackward, 'b.moveTabBackward', function(aName, aSource) {
eval('b.moveTabBackward = '+ return eval(aName+' = '+aSource.replace(
source.replace( 'this.moveTabToEnd();',
'this.moveTabToEnd();', '(function() {\n' +
'(function() {\n' + ' this.treeStyleTab.internallyTabMovingCount++;\n' +
' this.treeStyleTab.internallyTabMovingCount++;\n' + ' let parentTab = this.treeStyleTab.getParentTab(this.mCurrentTab);\n' +
' let parentTab = this.treeStyleTab.getParentTab(this.mCurrentTab);\n' + ' if (parentTab) {\n' +
' if (parentTab) {\n' + ' this.moveTabTo(this.mCurrentTab, this.treeStyleTab.getLastChildTab(parentTab)._tPos);\n' +
' this.moveTabTo(this.mCurrentTab, this.treeStyleTab.getLastChildTab(parentTab)._tPos);\n' + ' this.mCurrentTab.focus();\n' +
' this.mCurrentTab.focus();\n' + ' }\n' +
' }\n' + ' else {\n' +
' else {\n' + ' $&\n' +
' $&\n' + ' }\n' +
' }\n' + ' this.treeStyleTab.internallyTabMovingCount--;\n' +
' this.treeStyleTab.internallyTabMovingCount--;\n' + '}).call(this);'
'}).call(this);' ));
) }, 'treeStyleTab');
);
}
eval('b.loadTabs = '+ TreeStyleTabUtils.doPatching(b.loadTabs, 'b.loadTabs', function(aName, aSource) {
b.loadTabs.toSource().replace( return eval(aName+' = '+aSource.replace(
'var tabNum = ', 'var tabNum = ',
'if (this.treeStyleTab.readiedToAttachNewTabGroup)\n' + 'if (this.treeStyleTab.readiedToAttachNewTabGroup)\n' +
' TreeStyleTabService.readyToOpenChildTab(firstTabAdded || this.selectedTab, true);\n' + ' TreeStyleTabService.readyToOpenChildTab(firstTabAdded || this.selectedTab, true);\n' +
@ -472,133 +449,117 @@ var TreeStyleTabWindowHelper = {
'this.selectedTab = aURIs[0].indexOf("about:treestyletab-group") < 0 ? \n' + 'this.selectedTab = aURIs[0].indexOf("about:treestyletab-group") < 0 ? \n' +
' firstTabAdded :\n' + ' firstTabAdded :\n' +
' TreeStyleTabService.getNextTab(firstTabAdded) ;' ' TreeStyleTabService.getNextTab(firstTabAdded) ;'
) ));
); }, 'TreeStyleTab');
if ('_beginRemoveTab' in b) { TreeStyleTabUtils.doPatching(b._beginRemoveTab, 'b._beginRemoveTab', function(aName, aSource) {
eval('b._beginRemoveTab = '+ return eval(aName+' = '+aSource.replace(
b._beginRemoveTab.toSource().replace( 'if (this.tabs.length - this._removingTabs.length == 1) {',
'if (this.tabs.length - this._removingTabs.length == 1) {', 'if (this.tabs.length - this._removingTabs.length == 1 || this.treeStyleTab.shouldCloseLastTabSubtreeOf(aTab)) {'
'if (this.tabs.length - this._removingTabs.length == 1 || this.treeStyleTab.shouldCloseLastTabSubtreeOf(aTab)) {' ).replace(
).replace( 'this._removingTabs.length == 0',
'this._removingTabs.length == 0', '(this.treeStyleTab.shouldCloseLastTabSubtreeOf(aTab) || $&)'
'(this.treeStyleTab.shouldCloseLastTabSubtreeOf(aTab) || $&)' ));
) }, 'treeStyleTab');
);
}
eval('b.removeCurrentTab = '+b.removeCurrentTab.toSource().replace( TreeStyleTabUtils.doPatching(b.removeCurrentTab, 'b.removeCurrentTab', function(aName, aSource) {
'{', return eval(aName+' = '+aSource.replace(
'{ if (!this.treeStyleTab.warnAboutClosingTabSubtreeOf(this.selectedTab)) return;' '{',
)); '{ if (!this.treeStyleTab.warnAboutClosingTabSubtreeOf(this.selectedTab)) return;'
));
}, 'treeStyleTab');
}, },
initTabbarMethods : function TSTWH_initTabbarMethods(aTabBrowser) initTabbarMethods : function TSTWH_initTabbarMethods(aTabBrowser)
{ {
var b = aTabBrowser; var b = aTabBrowser;
var source = b.mTabContainer.advanceSelectedTab.toSource(); TreeStyleTabUtils.doPatching(b.mTabContainer.advanceSelectedTab, 'b.mTabContainer.advanceSelectedTab', function(aName, aSource) {
if (source.indexOf('treeStyleTab.handleAdvanceSelectedTab') < 0) { return eval(aName+' = '+aSource.replace(
eval('b.mTabContainer.advanceSelectedTab = '+ '{',
source.replace( '{\n' +
'{', ' var treeStyleTab = TreeStyleTabService.getTabBrowserFromChild(this).treeStyleTab;\n' +
'{\n' + ' if (treeStyleTab.handleAdvanceSelectedTab(arguments[0], arguments[1]))\n' +
' var treeStyleTab = TreeStyleTabService.getTabBrowserFromChild(this).treeStyleTab;\n' + ' return;'
' if (treeStyleTab.handleAdvanceSelectedTab(arguments[0], arguments[1]))\n' + ));
' return;' }, 'treeStyleTab.handleAdvanceSelectedTab');
)
);
}
source = b.mTabContainer._notifyBackgroundTab.toSource(); TreeStyleTabUtils.doPatching(b.mTabContainer._notifyBackgroundTab, 'b.mTabContainer._notifyBackgroundTab', function(aName, aSource) {
if (source.indexOf('TreeStyleTabService.getTabBrowserFromChild') < 0) { return eval(aName+' = '+aSource.replace(
eval('b.mTabContainer._notifyBackgroundTab = '+ '{',
source.replace( '{\n' +
'{', ' var treeStyleTab = TreeStyleTabService.getTabBrowserFromChild(this).treeStyleTab;\n' +
'{\n' + ' if (treeStyleTab.scrollToNewTabMode == 0 ||\n' +
' var treeStyleTab = TreeStyleTabService.getTabBrowserFromChild(this).treeStyleTab;\n' + ' treeStyleTab.shouldCancelEnsureElementIsVisible())\n' +
' if (treeStyleTab.scrollToNewTabMode == 0 ||\n' + ' return;'
' treeStyleTab.shouldCancelEnsureElementIsVisible())\n' + ).replace(
' return;' /\.screenX/g, '[treeStyleTab.screenPositionProp]'
).replace( ).replace(
/\.screenX/g, '[treeStyleTab.screenPositionProp]' /\.width/g, '[treeStyleTab.sizeProp]'
).replace( ).replace(
/\.width/g, '[treeStyleTab.sizeProp]' /\.left/g, '[treeStyleTab.startProp]'
).replace( ).replace(
/\.left/g, '[treeStyleTab.startProp]' /\.right/g, '[treeStyleTab.endProp]'
).replace(
/\.right/g, '[treeStyleTab.endProp]'
// replace such codes: // replace such codes:
// tab = {left: tab.left, right: tab.right}; // tab = {left: tab.left, right: tab.right};
).replace( ).replace(
/left\s*:/g, 'start:' /left\s*:/g, 'start:'
).replace( ).replace(
/right\s*:/g, 'end:' /right\s*:/g, 'end:'
).replace( ).replace(
/((tab|selected)\s*=\s*\{\s*start:[^\}]+\})/g, /((tab|selected)\s*=\s*\{\s*start:[^\}]+\})/g,
'$1; $2[treeStyleTab.startProp] = $2.start; $2[treeStyleTab.endProp] = $2.end;' '$1; $2[treeStyleTab.startProp] = $2.start; $2[treeStyleTab.endProp] = $2.end;'
).replace( ).replace(
'!selected ||', '!selected ||',
'$& treeStyleTab.scrollToNewTabMode == 1 && ' '$& treeStyleTab.scrollToNewTabMode == 1 && '
).replace( ).replace(
/(\}\)?)$/, /(\}\)?)$/,
'treeStyleTab.notifyBackgroundTab(); $1' 'treeStyleTab.notifyBackgroundTab(); $1'
) ));
); }, 'TreeStyleTabService.getTabBrowserFromChild');
}
if (b.tabContainer && '_getDropIndex' in b.tabContainer) { TreeStyleTabUtils.doPatching(b.tabContainer._getDropIndex, 'b.tabContainer._getDropIndex', function(aName, aSource) {
eval('b.tabContainer._getDropIndex = '+ return eval(aName+' = '+aSource.replace(
b.tabContainer._getDropIndex.toSource().replace( /\.screenX/g, '[this.treeStyleTab.screenPositionProp]'
/\.screenX/g, '[this.treeStyleTab.screenPositionProp]' ).replace(
).replace( /\.width/g, '[this.treeStyleTab.sizeProp]'
/\.width/g, '[this.treeStyleTab.sizeProp]' ));
) }, 'treeStyleTab');
);
}
/** /**
* The default implementation fails to scroll to tab if it is expanding. * The default implementation fails to scroll to tab if it is expanding.
* So we have to inject codes to override its effect. * So we have to inject codes to override its effect.
*/ */
let (scrollbox = aTabBrowser.treeStyleTab.scrollBox) { let (scrollbox = aTabBrowser.treeStyleTab.scrollBox) {
let source = scrollbox.ensureElementIsVisible.toSource(); TreeStyleTabUtils.doPatching(scrollbox.ensureElementIsVisible, 'scrollbox.ensureElementIsVisible', function(aName, aSource) {
if ( return eval(aName+' = '+aSource.replace(
source.indexOf('treeStyleTab') < 0 && // not updated yet '{',
source.indexOf('ensureTabIsVisible') < 0 // not replaced by Tab Mix Plus '{\n' +
) { ' var treeStyleTab = TreeStyleTabService.getTabBrowserFromChild(this).treeStyleTab;\n' +
eval('scrollbox.ensureElementIsVisible = '+ ' if (treeStyleTab && treeStyleTab.shouldCancelEnsureElementIsVisible())\n' +
source.replace( ' return;\n' +
'{', ' if (\n' +
'{\n' + ' treeStyleTab &&\n' +
' var treeStyleTab = TreeStyleTabService.getTabBrowserFromChild(this).treeStyleTab;\n' + ' (arguments.length == 1 || arguments[1])\n' +
' if (treeStyleTab && treeStyleTab.shouldCancelEnsureElementIsVisible())\n' + ' )\n' +
' return;\n' + ' return treeStyleTab.scrollToTab(arguments[0]);'
' if (\n' + ));
' treeStyleTab &&\n' + }, /treeStyleTab|ensureTabIsVisible/); // if there is a string "ensureTabIsVisible", it is replaced by Tab Mix Plus!
' (arguments.length == 1 || arguments[1])\n' +
' )\n' +
' return treeStyleTab.scrollToTab(arguments[0]);'
)
);
}
} }
let (popup = document.getElementById('alltabs-popup')) { let (popup = document.getElementById('alltabs-popup')) {
if (popup && '_updateTabsVisibilityStatus' in popup) { TreeStyleTabUtils.doPatching(popup._updateTabsVisibilityStatus, 'popup._updateTabsVisibilityStatus', function(aName, aSource) {
eval('popup._updateTabsVisibilityStatus = '+ return eval(aName+' = '+aSource.replace(
popup._updateTabsVisibilityStatus.toSource().replace( '{',
'{', '{ var treeStyleTab = gBrowser.treeStyleTab;'
'{ var treeStyleTab = gBrowser.treeStyleTab;' ).replace(
).replace( /\.screenX/g, '[treeStyleTab.screenPositionProp]'
/\.screenX/g, '[treeStyleTab.screenPositionProp]' ).replace(
).replace( /\.width/g, '[treeStyleTab.sizeProp]'
/\.width/g, '[treeStyleTab.sizeProp]' ));
) }, 'treeStyleTab');
);
}
} }
} }

View File

@ -302,5 +302,34 @@ let TreeStyleTabUtils = {
} }
return aURI; return aURI;
},
doPatching : function utils_assertFunctionExists(aFunction, aName, aPatchingTask, aMatcher)
{
if (typeof aFunction == 'function') {
if (aMatcher && this.functionIsMatched(aFunction, aMatcher)) // already patched
return;
let patched = aPatchingTask(aName, aFunction.toSource());
if (patched && aMatcher)
this.assertFunctionIsPatched(patched, aName, aMatcher);
}
else
Components.utils.reportError(new Error('treestyletab: doPatching: ' + aName + ' is missing!'));
},
assertFunctionIsPatched : function utils_assertFunctionIsPatched(aFunction, aName, aMatcher)
{
if (!this.functionIsMatched(aFunction, aMatcher))
Components.utils.reportError(new Error('treestyletab: Failed to patch to ' + aName + ': ' + aFunction.toString()));
},
functionIsMatched : function utils_functionIsMatched(aFunction, aMatcher)
{
var source = aFunction.toString();
if (typeof aMatcher == 'string')
return source.indexOf(aMatcher) > -1;
else
return aMatcher.test(source);
} }
}; };