diff --git a/README.md b/README.md index e69de29..f24fb2a 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,27 @@ +[![Mozilla Add-on](https://img.shields.io/amo/v/tab-utilities-fixed.svg)](https://addons.mozilla.org/firefox/addon/tab-utilities-fixed/) +[![Mozilla Add-on](https://img.shields.io/amo/d/tab-utilities-fixed.svg)]() +[![Mozilla Add-on](https://img.shields.io/amo/users/tab-utilities-fixed.svg)]() +[![GitHub release](https://img.shields.io/github/release/yfdyh000/tabutils/all.svg)]() + +# Tab Utilities Fixed (Deprecated) + +[Tab Utilities](https://addons.mozilla.org/firefox/addon/tab-utilities/)'s compatibility fixes release. + +The project's focused goal: Compatibility fixes for Firefox 28 (with orange 'Firefox' button or Pale Moon) to the latest Firefox Beta (tested for Windows). + +Issue reports and patches are welcome. + +## Deprecated +This project has been deprecated due to the new browser extension standard ([WebExtensions](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions); [W3C](https://browserext.github.io/browserext/); [Terminology](https://wiki.mozilla.org/Add-ons/Terminology)) to Firefox 57 and difficult to maintain, it still has some bugs in the final version, such as full screen support, as well as other quirks. + +If you would, you can continue to report problems (but no guaranteed for repair) or recommend alternatives on the issues. + +### My collections on AMO site +* [WebExtensions for tabs](https://addons.mozilla.org/firefox/collections/yfdyh000/webextensions-for-tabs/) +* [WebExtensions](https://addons.mozilla.org/firefox/collections/yfdyh000/webextensions/) + +## Resources +[newer TODO board](https://github.com/yfdyh000/tabutils/projects); +[older TODO and notes](https://github.com/yfdyh000/tabutils/wiki/TODO). + +[Release versions and notes](https://github.com/yfdyh000/tabutils/releases) < may include the latest unsigned version. diff --git a/chrome.manifest b/chrome.manifest index a5afe7d..c42efd4 100644 --- a/chrome.manifest +++ b/chrome.manifest @@ -1,5 +1,6 @@ content tabutils chrome/content/ skin tabutils classic/1.0 chrome/skin/ +resource tabmixplus modules/ overlay chrome://browser/content/browser.xul chrome://tabutils/content/tabutils.xul overlay chrome://browser/content/places/placesOverlay.xul chrome://tabutils/content/placesOverlay.xul diff --git a/chrome/content/bookmarkProperties.xul b/chrome/content/bookmarkProperties.xul index b0be7f0..9dc75fb 100644 --- a/chrome/content/bookmarkProperties.xul +++ b/chrome/content/bookmarkProperties.xul @@ -3,13 +3,16 @@ diff --git a/chrome/content/content.js b/chrome/content/content.js new file mode 100644 index 0000000..9b305dc --- /dev/null +++ b/chrome/content/content.js @@ -0,0 +1,20 @@ +// This frame script is used to assist Tab Utilities Fixed, to avoid performance degradation in e10s. + +var getLinksSelected = function() { + let links = content.document.links; + let selection = content.getSelection(); + if (!links || !selection) return []; + + let linkURLs = []; + //console.time('checkLinkSelected'); + for (let link of links) { + if (selection.containsNode(link, true) && (link.offsetHeight > 0) && linkURLs.indexOf(link.href) == -1) + linkURLs.push(link.href); + } + //console.timeEnd('checkLinkSelected'); + return linkURLs; +}; + +sendAsyncMessage("tabutils-fixed:LinksSelected", { + links : getLinksSelected() +}); diff --git a/chrome/content/preferences.xul b/chrome/content/preferences.xul index 66476c8..0e8ae78 100644 --- a/chrome/content/preferences.xul +++ b/chrome/content/preferences.xul @@ -5,8 +5,6 @@ %browserDTD; - -%tabBrowserDTD; %tabsDTD; @@ -21,8 +19,8 @@ - + @@ -575,16 +573,14 @@ - + + - - - - @@ -1052,9 +1048,9 @@ var preferences = document.getElementsByTagName("preference"); for (let preference of preferences) { str += 'pref('; - str += preference.name.quote(); + str += JSON.stringify(preference.name); str += ', '; - str += preference.type == typeof preference.value ? preference.value.quote() : + str += preference.type == typeof preference.value ? JSON.stringify(preference.value) : preference.inverted ? !preference.value : preference.value; str += ');\n'; } @@ -1155,7 +1151,9 @@ } function closeButtons() { - $("tabClipWidth").disabled = ($("closeButtons").value & 0x0f) != 1; + var value = $("closeButtons").value; + $("tabClipWidth").disabled = (value != 1) && (value != 10); + $("c.closeButtons").disabled = value == 2; } function hideLoadInBackground() { @@ -1313,8 +1311,10 @@ if(!aPane._inited) return; - aPane.setAttribute('lastSelected', [tabbox.selectedIndex for (tabbox of aPane.getElementsByTagName('tabbox'))].join()); + let tabbox = aPane.getElementsByTagName('tabbox')[0]; + if (tabbox) + aPane.setAttribute('lastSelected', tabbox.selectedIndex); } ]]> - \ No newline at end of file + diff --git a/chrome/content/tabutils-mt.js b/chrome/content/tabutils-mt.js index a13988d..92d92f7 100644 --- a/chrome/content/tabutils-mt.js +++ b/chrome/content/tabutils-mt.js @@ -42,8 +42,8 @@ tabutils._multirowTabs = function() { }, false); TU_hookCode("gBrowser.mTabContainer._getDropIndex", - [/event.screenX.*width \/ 2/g, function(s) s + " && " + s.replace("screenX", "screenY", "g").replace("width / 2", "height") - + " || " + s.replace("screenX", "screenY", "g").replace("width / 2", "height * 0")] + [/event.screenX.*width \/ 2/g, function(s) s + " && " + s.replace(/screenX/g, "screenY").replace("width / 2", "height") + + " || " + s.replace(/screenX/g, "screenY").replace("width / 2", "height * 0")] ); tabutils.addEventListener(gBrowser.mTabContainer, "dragover", function(event) { @@ -75,7 +75,7 @@ tabutils._multirowTabs = function() { if (TU_getPref("extensions.tabutils.disableTabMoveAnimation", true)) { TU_hookFunc(arguments.callee.caller.toString().match(/^.*{|var (ind|tabStrip|ltr).*|var pixelsToScroll[\s\S]*$/g).join("\n"), [/.*scrollByPixels.*/, ";"], - [/.*effects == "move"[\s\S]*?(?=var (newIndex|scrollRect|rect))/, ""] + [/.*effects == "move"[\s\S]*?(?=var (newIndex|scrollRect|rect))/, ""] // needs fix ).apply(this, arguments); return; } @@ -95,7 +95,7 @@ tabutils._multirowTabs = function() { }, true); TU_hookCode("gBrowser.moveTabTo", "{", function() { - if (["onxbldrop", "ondrop"].indexOf(arguments.callee.caller.name) > -1) { + if (TMP_console.isCallerInList(["onxbldrop", "ondrop"])) { if (aTab.pinned) { if (aIndex >= this._numPinnedTabs) this.pinTab(aTab, false); diff --git a/chrome/content/tabutils-st.js b/chrome/content/tabutils-st.js index 8c66600..8d45274 100644 --- a/chrome/content/tabutils-st.js +++ b/chrome/content/tabutils-st.js @@ -113,6 +113,11 @@ tabutils._stackTabs = function() { if (bTab.getAttribute("group-counter") == 1) { bTab.setAttribute("group-collapsed", !options.expand && TU_getPref("extensions.tabutils.autoCollapseNewStack", true)); this.mTabContainer.mTabstrip.ensureElementIsVisible(bTab); + if (bTab.image && TU_getPref('extensions.tabutils.colorStackFromFavicon', false)) + Services.mozIColorAnalyzer.findRepresentativeColor(makeURI(bTab.image), function(success, color) { + if (success) + this.updateStack(bTab, {color: "#" + ("000000" + color.toString(16)).slice(-6)}); + }.bind(this)); } //must happen after "group" is set to avoid bypassing stack, and @@ -221,6 +226,10 @@ tabutils._stackTabs = function() { let tabs = this.siblingTabsOf(aTab); if (tabs.length == 0) return; + if (tabs.length == 1 && TU_getPref("extensions.tabutils.autoCleanupStack", false)) { + gBrowser.detachTab(aTab); + return; + } if (typeof aTab == "string") { aTab = tabs[0]; @@ -471,7 +480,7 @@ tabutils._stackTabs = function() { } } - let lastTab = this.getLastSelectedTab(); + lastTab = this.getLastSelectedTab(); if (lastTab && lastTab.hasAttribute("group") && lastTab.getAttribute("group") != aTab.getAttribute("group") && TU_getPref("extensions.tabutils.autoCollapseStackOnBlur", false)) @@ -495,8 +504,8 @@ tabutils._stackTabs = function() { }); TU_hookCode("gBrowser.loadTabs", - [/(?=var tabNum)/, "var tabs = [firstTabAdded || this.mCurrentTab];"], - [/(?=.*aReplace.*\n.*moveTabTo.*)/, "tabs.push(tab);"], + [/(?=(?:var|let) tabNum)/, "var tabs = [firstTabAdded || this.mCurrentTab];"], + [/(?=if\s*\(.*\n.*moveTabTo.*tab.*)/, "tabs.push(tab);"], [/(?=.*!aLoadInBackground.*)/, function() { if (tabs.length > 1 && TU_getPref("extensions.tabutils.autoStack", false)) this.stackTabs(tabs); @@ -505,16 +514,16 @@ tabutils._stackTabs = function() { TU_hookCode("gBrowser.mTabContainer._selectNewTab", "aNewTab.hidden", "$& || aNewTab.collapsed"); - TU_hookCode("gBrowser.createTooltip", /(tab|tn).getAttribute\("label"\)/, function(s, s1) (function() { - $1.mOverTwisty ? $1.hasAttribute("group-collapsed") ? + TU_hookCode("gBrowser.createTooltip", /(?:tab\._.+)(tab|tn).getAttribute\("label"\)/, function(s, s1) (function() { + a1.mOverTwisty ? a1.hasAttribute("group-collapsed") ? document.getElementById("context_collapseStack").getAttribute("label_expand") : document.getElementById("context_collapseStack").getAttribute("label_collapse") - : this.isCollapsedStack($1) ? + : this.isCollapsedStack(a1) ? TU_getPref("extensions.tabutils.mouseHoverPopup", true) ? event.preventDefault() : - this.siblingTabsOf($1).map(function($1) ($1.hasAttribute("group-selected") ? "> " : "# ") + $0).join("\n") : - $0 - }).toString().replace(/^.*{|}$/g, "").replace("$0", s, "g").replace("$1", s1, "g")); + this.siblingTabsOf(a1).map(function(a1) (a1.hasAttribute("group-selected") ? "> " : "# ") + a0).join("\n") : + a0 + }).toString().replace(/^.*{|}$/g, "").replace(/a0/g, s).replace(/a1/g, s1)); gBrowser._setMenuitemAttributes = function _setMenuitemAttributes(aItem, aTab) { ["label", "crop", "image"].forEach(function(aProp) { diff --git a/chrome/content/tabutils-vt.js b/chrome/content/tabutils-vt.js index 6e370bb..e174dab 100644 --- a/chrome/content/tabutils-vt.js +++ b/chrome/content/tabutils-vt.js @@ -6,6 +6,8 @@ tabutils._verticalTabs = function() { var [start, end, size] = vertical ? ["top", "bottom", "height"] : ["left", "right", "width"]; }], + ["left:", "[start]:", "g"], // Bug 971630 [Fx29] + ["right:", "[end]:", "g"], [".left", "[start]", "g"], [".right", "[end]", "g"], [".width", "[size]", "g"] @@ -31,34 +33,48 @@ tabutils._verticalTabs = function() { gBrowser.mTabContainer.visible = aShow; }); - TU_hookCode("FullScreen.toggle", /.*_expandCallback.*\n.*_expandCallback.*/, function() { - for (let fullScrToggler of this._fullScrTogglers) { - fullScrToggler.addEventListener("mouseover", this._expandCallback, false); - fullScrToggler.addEventListener("dragenter", this._expandCallback, false); - } - }); - - TU_hookCode("FullScreen.enterDomFullscreen", /.*_expandCallback.*\n.*_expandCallback.*/, function() { - for (let fullScrToggler of this._fullScrTogglers) { - fullScrToggler.removeEventListener("mouseover", this._expandCallback, false); - fullScrToggler.removeEventListener("dragenter", this._expandCallback, false); - } - }); + if (tabutils.fxVersion >= 35.0) { // Bug 1071821 [Fx35] + // I did not find a compatible approach + TU_hookCode("FullScreen.toggle", /.*if.*\(\!this\._fullScrToggler\).*\n.*\n.*\n.*\n.*\}/, function() { + if (!this._eventLoaded) { // the equivalent to "if (!this._fullScrToggler)" + for (let fullScrToggler of this._fullScrTogglers) { + fullScrToggler.addEventListener("mouseover", this._expandCallback, false); + fullScrToggler.addEventListener("dragenter", this._expandCallback, false); + fullScrToggler.collapsed = false; + } + this._eventLoaded = true; + } + }); - TU_hookCode("FullScreen.cleanup", /.*_expandCallback.*\n.*_expandCallback.*/, function() { - for (let fullScrToggler of this._fullScrTogglers) { - fullScrToggler.removeEventListener("mouseover", this._expandCallback, false); - fullScrToggler.removeEventListener("dragenter", this._expandCallback, false); - } - }); + } else { // Earlier than Fx35 + TU_hookCode("FullScreen.toggle", /.*_expandCallback.*\n.*_expandCallback.*/, function() { + for (let fullScrToggler of this._fullScrTogglers) { + fullScrToggler.addEventListener("mouseover", this._expandCallback, false); + fullScrToggler.addEventListener("dragenter", this._expandCallback, false); + fullScrToggler.hidden = false; + } + }); + TU_hookCode("FullScreen.enterDomFullscreen", /.*_expandCallback.*\n.*_expandCallback.*/, function() { + for (let fullScrToggler of this._fullScrTogglers) { + fullScrToggler.removeEventListener("mouseover", this._expandCallback, false); + fullScrToggler.removeEventListener("dragenter", this._expandCallback, false); + } + }); - TU_hookCode("FullScreen.mouseoverToggle", /.*collapsed = aShow.*/, function() { + TU_hookCode("FullScreen.cleanup", /.*_expandCallback.*\n.*_expandCallback.*/, function() { + for (let fullScrToggler of this._fullScrTogglers) { + fullScrToggler.removeEventListener("mouseover", this._expandCallback, false); + fullScrToggler.removeEventListener("dragenter", this._expandCallback, false); + } + }); + } + TU_hookCode("FullScreen.mouseoverToggle", /.*(collapsed|hidden) = aShow.*/, function() { let tabBarPosition = TU_getPref("extensions.tabutils.tabBarPosition"); - this._fullScrTogglers[0].collapsed = aShow; - this._fullScrTogglers[1].collapsed = aShow || tabBarPosition != 1; - this._fullScrTogglers[2].collapsed = aShow || tabBarPosition != 2; - this._fullScrTogglers[3].collapsed = aShow || tabBarPosition != 3; - }); + this._fullScrTogglers[0].$1 = aShow; + this._fullScrTogglers[1].$1 = aShow || tabBarPosition != 1; + this._fullScrTogglers[2].$1 = aShow || tabBarPosition != 2; + this._fullScrTogglers[3].$1 = aShow || tabBarPosition != 3; + }); // Note: mozFullScreen is Fx9+. I did not add " || document.mozFullScreen" because it seems always return to false, unknown reason. TU_hookCode("FullScreen.showXULChrome", ['fullscreenctls.parentNode == navbar', 'document.getElementById("TabsToolbar").parentNode == gNavToolbox'], diff --git a/chrome/content/tabutils.js b/chrome/content/tabutils.js index 679af62..142927c 100644 --- a/chrome/content/tabutils.js +++ b/chrome/content/tabutils.js @@ -29,13 +29,23 @@ var tabutils = { window.addEventListener("load", this, false); window.addEventListener("unload", this, false); - if (gBrowser.mTabListeners.length > 0) { // Bug 463384 [Fx5] + if (typeof gBrowser._tabListeners === "object") { // Bug 1238685 [Fx46] + let tabFilters = gBrowser._tabFilters.values().next().value; + let tabListener = gBrowser._tabListeners.values().next().value; + gBrowser.browsers[0].webProgress.removeProgressListener(tabFilters); + tabFilters.removeProgressListener(tabListener); + tabListener = gBrowser.mTabProgressListener(tabListener.mTab, tabListener.mBrowser, tabListener.mBlank); + tabFilters.addProgressListener(tabListener, Ci.nsIWebProgress.NOTIFY_ALL); + gBrowser.browsers[0].webProgress.addProgressListener(tabFilters, Ci.nsIWebProgress.NOTIFY_ALL); + } + else if (gBrowser.mTabListeners.length > 0) { // Bug 463384 [Fx5] + let tabFilters = gBrowser.mTabFilters[0]; let tabListener = gBrowser.mTabListeners[0]; - gBrowser.browsers[0].webProgress.removeProgressListener(gBrowser.mTabFilters[0]); - gBrowser.mTabFilters[0].removeProgressListener(gBrowser.mTabListeners[0]); - gBrowser.mTabListeners[0] = gBrowser.mTabProgressListener(tabListener.mTab, tabListener.mBrowser, tabListener.mBlank); - gBrowser.mTabFilters[0].addProgressListener(gBrowser.mTabListeners[0], Ci.nsIWebProgress.NOTIFY_ALL); - gBrowser.browsers[0].webProgress.addProgressListener(gBrowser.mTabFilters[0], Ci.nsIWebProgress.NOTIFY_ALL); + gBrowser.browsers[0].webProgress.removeProgressListener(tabFilters); + tabFilters.removeProgressListener(tabListener); + tabListener = gBrowser.mTabProgressListener(tabListener.mTab, tabListener.mBrowser, tabListener.mBlank); + tabFilters.addProgressListener(tabListener, Ci.nsIWebProgress.NOTIFY_ALL); + gBrowser.browsers[0].webProgress.addProgressListener(tabFilters, Ci.nsIWebProgress.NOTIFY_ALL); } if (!("privateBrowsingEnabled" in gPrivateBrowsingUI)) { // Bug 799001 [Fx20] @@ -44,14 +54,21 @@ var tabutils = { }); } - let os = Services.appinfo.OS; //WINNT, Linux or Darwin - let version = parseFloat(Services.appinfo.version); - document.documentElement.setAttribute("OS", os); + this.fxOnOS = Services.appinfo.OS; //WINNT, Linux or Darwin + this.fxVersion = parseFloat(Services.appinfo.version); + document.documentElement.setAttribute("OS", this.FxOnOS); document.documentElement.setAttribute("v4", true); document.documentElement.setAttribute("v6", true); document.documentElement.setAttribute("v14", true); document.documentElement.setAttribute("v17", true); - document.documentElement.setAttribute("v29", version >= 29.0); + document.documentElement.setAttribute("v29", this.fxVersion >= 29.0); + document.documentElement.setAttribute("v31", this.fxVersion >= 31.0); + document.documentElement.setAttribute("v45", this.fxVersion >= 45.0); + + gBrowser.mTabContainer._originalAdjustTabstripFunc = gBrowser.mTabContainer.adjustTabstrip; + gBrowser.mTabContainer.adjustTabstrip = function adjustTabstrip() { + this._originalAdjustTabstripFunc(); + } // Function.prototype.__defineGetter__("stack", function() { // var stack = []; @@ -91,7 +108,7 @@ var tabutils = { return this.removeAttribute(aTab, aAttr); aTab.setAttribute(aAttr, aVal); - this._ss.setTabValue(aTab, aAttr, aVal); + this._ss.setTabValue(aTab, aAttr, String(aVal)); }, removeAttribute: function(aTab, aAttr) { @@ -147,7 +164,7 @@ var tabutils = { _eventListeners: [], addEventListener: function() { - document.addEventListener.apply(arguments[0], Array.slice(arguments, 1)); + arguments[0].addEventListener.apply(arguments[0], Array.slice(arguments, 1)); this._eventListeners.push(arguments); }, @@ -170,6 +187,7 @@ window.addEventListener("DOMContentLoaded", tabutils, false); [ ["@mozilla.org/browser/sessionstore;1", "nsISessionStore", "_ss", tabutils], // Bug 898732 [Fx26] ["@mozilla.org/docshell/urifixup;1", "nsIURIFixup"], // Bug 802026 [Fx20] + ["@mozilla.org/places/colorAnalyzer;1", "mozIColorAnalyzer"], ["@mozilla.org/widget/clipboardhelper;1", "nsIClipboardHelper"], ["@mozilla.org/uuid-generator;1", "nsIUUIDGenerator"] ].forEach(function([aContract, aInterface, aName, aObject]) @@ -304,13 +322,17 @@ tabutils._PlacesUtilsExt = function() { tabutils._openUILinkInTab = function() { - //主页 + //涓婚〉 TU_hookCode("BrowserGoHome", "browser.tabs.loadBookmarksInBackground", "extensions.tabutils.loadHomepageInBackground"); - //地址栏回车键 + //鍦板潃鏍忓洖杞﹂敭 TU_hookCode("gURLBar.handleCommand", - [/((aTriggeringEvent)\s*&&\s*(aTriggeringEvent.altKey))(?![\s\S]*\1)/, "let (newTabPref = TU_getPref('extensions.tabutils.openUrlInTab', true)) ($1 || newTabPref) && !(($2 ? $3 : false) && newTabPref && TU_getPref('extensions.tabutils.invertAlt', true))"], - [/(?=.*openUILinkIn.*)/, function() { + [/(let altEnter\s*=.+)\s*((aTriggeringEvent|event)\s*&&\s*(aTriggeringEvent\.altKey|event\.altKey))\s*&&\s*.*isTabEmpty.*;/, function() { + let newTabPref = TU_getPref('extensions.tabutils.openUrlInTab', true); + let TU_altEnter = ($2 || newTabPref) && !(($3 ? $4 : false) && newTabPref && TU_getPref('extensions.tabutils.invertAlt', true)); + $1TU_altEnter; + }], + [/(?=.*openUILinkIn\(url\, where\, params.*)/, function() { params.inBackground = TU_getPref('extensions.tabutils.loadUrlInBackground', false); params.disallowInheritPrincipal = !mayInheritPrincipal; params.event = aTriggeringEvent || {}; @@ -319,16 +341,16 @@ tabutils._openUILinkInTab = function() { ["aTriggeringEvent.preventDefault();", ""], ["aTriggeringEvent.stopPropagation();", ""] ); - TU_hookCode("openLinkIn", /(?=let uriObj)/, "w.gURLBar.handleRevert();"); + // TU_hookCode("openLinkIn", /(?=let uriObj)/, "w.gURLBar.handleRevert();"); - //搜索栏回车键 + //鎼滅储鏍忓洖杞﹂敭 if (BrowserSearch.searchBar) TU_hookCode("BrowserSearch.searchBar.handleSearchCommand", [/(\(aEvent && aEvent.altKey\)) \^ (newTabPref)/, "($1 || $2) && !($1 && $2 && TU_getPref('extensions.tabutils.invertAlt', true)) && !isTabEmpty(gBrowser.selectedTab)"], [/"tab"/, "TU_getPref('extensions.tabutils.loadSearchInBackground', false) ? 'background' : 'foreground'"] ); - //右键点击书签 + //鍙抽敭鐐瑰嚮涔︾ TU_hookCode("BookmarksEventHandler.onClick", ["aEvent.button == 2", "$& && (aEvent.ctrlKey || aEvent.altKey || aEvent.metaKey || !TU_getPref('extensions.tabutils.rightClickBookmarks', 0))"], ["aEvent.button == 1", "aEvent.button > 0"], @@ -340,7 +362,7 @@ tabutils._openUILinkInTab = function() { ); TU_hookCode("whereToOpenLink", "e.button == 1", "e.button > 0"); - //保持菜单打开 + //淇濇寔鑿滃崟鎵撳紑 TU_hookCode("BookmarksEventHandler.onClick", /.*hidePopup.*/, "if (!(TU_getPref('extensions.tabutils.middleClickBookmarks', 0) & 4)) $&"); TU_hookCode("checkForMiddleClick", /.*closeMenus.*/, "if (!(TU_getPref('extensions.tabutils.middleClickBookmarks', 0) & 4)) $&"); @@ -364,7 +386,7 @@ tabutils._openUILinkInTab = function() { tabutils._openLinkInTab = function() { - //强制在新标签页打开所有链接 + //寮哄埗鍦ㄦ柊鏍囩椤垫墦寮鎵鏈夐摼鎺 TU_hookCode("contentAreaClick", /if[^{}]*event.button == 0[^{}]*{([^{}]|{[^{}]*}|{([^{}]|{[^{}]*})*})*(?=})/, "$&" + (function() { if (tabutils.gOpenLinkInTab && !href.startsWith("javascript:")) { openNewTabWith(href, linkNode.ownerDocument, null, event, false); @@ -378,11 +400,11 @@ tabutils._openLinkInTab = function() { aWhere = Ci.nsIBrowserDOMWindow.OPEN_NEWTAB; }); - //强制在后台打开所有新标签页 + //寮哄埗鍦ㄥ悗鍙版墦寮鎵鏈夋柊鏍囩椤 TU_hookCode("gBrowser.loadOneTab", /(?=var owner)/, "bgLoad = bgLoad && !tabutils.gLoadAllInForeground || tabutils.gLoadAllInBackground;"); TU_hookCode("gBrowser.loadTabs", /(?=var owner)/, "aLoadInBackground = aLoadInBackground && !tabutils.gLoadAllInForeground || tabutils.gLoadAllInBackground;"); - //强制在新标签页打开外部链接 + //寮哄埗鍦ㄦ柊鏍囩椤垫墦寮澶栭儴閾炬帴 TU_hookCode("contentAreaClick", /if[^{}]*event.button == 0[^{}]*{([^{}]|{[^{}]*}|{([^{}]|{[^{}]*})*})*(?=})/, "$&" + (function() { if (/^(https?|ftp)/.test(href) && TU_getPref("extensions.tabutils.openExternalInTab", false)) { let ourDomain = tabutils.getDomainFromURI(linkNode.ownerDocument.documentURIObject); @@ -395,7 +417,7 @@ tabutils._openLinkInTab = function() { } }).toString().replace(/^.*{|}$/g, "")); - //外来链接 + //澶栨潵閾炬帴 TU_hookCode("nsBrowserAccess.prototype.openURI", '"browser.link.open_newwindow"', 'isExternal ? "browser.link.open_external" : $&'); // L-click @@ -415,7 +437,7 @@ tabutils._openLinkInTab = function() { ); TU_hookCode("openNewTabWith", "aEvent.button == 1", "aEvent.button > 0"); - //拖曳链接 + //鎷栨洺閾炬帴 TU_hookCode("handleDroppedLink", /.*loadURI.*/, function(s) (function() { { switch (true) { @@ -429,12 +451,28 @@ tabutils._openLinkInTab = function() { } } }).toString().replace(/^.*{|}$/g, "").replace("$0", s)); + // For Fx51 and earlier + + // The following edition applies to bug 92737 [Fx52] changes and later. + TU_hookCode("handleDroppedLink", /.*urls\.push\([\s\S]*?postData.*/g, function(s) (function() { + { + switch (true) { + case /\.(xpi|user\.js)$/.test(data.url): // Bug 846635 [Fx25] + case !TU_getPref("extensions.tabutils.dragAndGo", true): + $0;break; + case event.ctrlKey != TU_getPref("extensions.tabutils.invertDrag", false): + BrowserSearch.loadSearch(name || link.url, true);break; + default: + openNewTabWith(data.url, null, data.postData, event, true);break; // ", event.target.ownerDocument.documentURIObject" will break for example drop an local file (file:///) to about:newtab page, blocked for security reasons. + } + } + }).toString().replace(/^.*{|}$/g, "").replace("$0", s)); for (let b of gBrowser.browsers) { b.droppedLinkHandler = handleDroppedLink; } - //在新标签页打开链接时继承历史 + //鍦ㄦ柊鏍囩椤垫墦寮閾炬帴鏃剁户鎵垮巻鍙 TU_hookCode("gBrowser.loadOneTab", ["{", function() { var currentTab = this.mCurrentTab; @@ -451,7 +489,7 @@ tabutils._openLinkInTab = function() { ); }; -//单窗口模式 +//鍗曠獥鍙fā寮 tabutils._singleWindowMode = function() { if (TU_getPref("extensions.tabutils.singleWindowMode", false)) { var win = (function() { @@ -465,7 +503,7 @@ tabutils._singleWindowMode = function() { if (win) { TU_hookFunc((gBrowserInit.onLoad + gBrowserInit._delayedStartup).toString().match(/^.*{|if \(uriToLoad.*{([^{}]|{[^{}]*}|{([^{}]|{[^{}]*})*})*}|}$/g).join("\n"), // Bug 756313 [Fx19] - ["{", "var uriToLoad = window.arguments && window.arguments[0];"], + ["{", "var uriToLoad = {window.arguments && window.arguments[0]};"], ["gBrowser.loadTabs(specs, false, true);", "this.gBrowser.loadTabs(specs, false, false);"], ["loadOneOrMoreURIs(uriToLoad);", "this.gBrowser.loadTabs(uriToLoad.split('|'), false, false);"], [/.*loadURI.*\n.*/, "this.gBrowser.loadOneTab(uriToLoad, window.arguments[2], window.arguments[1] && window.arguments[1].split('=')[1], window.arguments[3] || null, false, window.arguments[4] || false);"], @@ -489,7 +527,8 @@ tabutils._singleWindowMode = function() { }; TU_hookCode("OpenBrowserWindow", "{", function() { - if (TU_getPref("extensions.tabutils.singleWindowMode", false)) + if (TU_getPref("extensions.tabutils.singleWindowMode", false) + && typeof options != "object") // .remote for non-e10s; .private (window) return BrowserOpenTab() || gBrowser.getLastOpenedTab(); }); @@ -514,7 +553,7 @@ tabutils._singleWindowMode = function() { }); TU_hookCode("gBrowser.replaceTabWithWindow", "{", function() { - if (["_onDragEnd", "onxbldragend"].indexOf(arguments.callee.caller.name) > -1 && TU_getPref("extensions.tabutils.singleWindowMode", false)) + if (TMP_console.isCallerInList(["_onDragEnd", "onxbldragend"]) && TU_getPref("extensions.tabutils.singleWindowMode", false)) return null; }); @@ -541,7 +580,7 @@ tabutils._singleWindowMode = function() { tabutils._tabOpeningOptions = function() { - //新建标签页时利用已有空白标签页 + //鏂板缓鏍囩椤垫椂鍒╃敤宸叉湁绌虹櫧鏍囩椤 TU_hookCode("gBrowser.addTab", [/if \(arguments.length == 2[^{}]*\) {[^{}]*}/, "$&" + (function() { if (!isBlankPageURL(aURI)) { @@ -552,9 +591,10 @@ tabutils._tabOpeningOptions = function() { } } }).toString().replace(/^.*{|}$/g, "")], - [/(?=return t;)/, gBrowser.addTab.toString().match(/var (uriIsBlankPage|uriIsNotAboutBlank|uriIsAboutBlank).*|let docShellsSwapped[\s\S]*(?=\n.*docShellsSwapped.*)|if \((uriIsNotAboutBlank|.*uriIsAboutBlank)\) {([^{}]|{[^{}]*})*}/g).join("\n")] // Bug 716108 [Fx16] - ); - + [/(?=return t;)/, gBrowser.addTab.toString().match( + /var (?:uriIsBlankPage|uriIsNotAboutBlank|uriIsAboutBlank).*|let (?:options|browserParams) = \{[\s\S]*?dispatchEvent.+;|if.+!usingPreloadedContent[\s\S]*catch[^}]+?\}[^}]+?\}|let (docShellsSwapped|usingPreloadedContent)[\s\S]*(?=\n.*(docShellsSwapped|usingPreloadedContent).*)|if \((uriIsNotAboutBlank|.*uriIsAboutBlank)\) {([^{}]|{[^{}]*})*}/g + ).join("\n").replace(/(?:var|let) b\s*=/, "b =")] + ); // Bug 716108 [Fx16], Bug 1077652 [Fx37], Bug 1243707 [Fx48], etc. Grab all about preload tab, open tab, barring select tab. gBrowser.getBlankTab = function getBlankTab() { var reuseBlank = TU_getPref("extensions.tabutils.reuseBlank", 1); return reuseBlank & 1 && this.isBlankTab(this.mCurrentTab) ? this.mCurrentTab : @@ -581,7 +621,7 @@ tabutils._tabOpeningOptions = function() { }; TU_hookCode("isBlankPageURL", 'aURL == "about:blank"', "gInitialPages.indexOf(aURL) > -1"); - //自动关闭非主动打开的空白标签页 + //鑷姩鍏抽棴闈炰富鍔ㄦ墦寮鐨勭┖鐧芥爣绛鹃〉 TU_hookCode("gBrowser.mTabProgressListener", /(?=var location)/, function() { if (aWebProgress.DOMWindow.document.documentURI == "about:blank" && aRequest.QueryInterface(nsIChannel).URI.spec != "about:blank" @@ -594,6 +634,10 @@ tabutils._tabOpeningOptions = function() { } }); + // Not understand the purpose of the module, + // and it has been broken since Firefox 38. + // https://hg.mozilla.org/releases/mozilla-aurora/diff/120b108aa176/toolkit/mozapps/downloads/DownloadLastDir.jsm [Bug 1115248] + /* let tmp = {}; Cu.import("resource://gre/modules/DownloadLastDir.jsm", tmp); @@ -621,14 +665,15 @@ tabutils._tabOpeningOptions = function() { getFileAsync.apply(this, arguments); }; })(); + */ - //在当前标签页的右侧打开新标签页 - //连续打开后台标签时保持原有顺序 + //鍦ㄥ綋鍓嶆爣绛鹃〉鐨勫彸渚ф墦寮鏂版爣绛鹃〉 + //杩炵画鎵撳紑鍚庡彴鏍囩鏃朵繚鎸佸師鏈夐『搴 TU_hookCode("gBrowser.addTab", - [/\S*insertRelatedAfterCurrent\S*(?=\))/, "false"], + [/\S*insertRelatedAfterCurrent\S*(?=\))/, "false"], // replace "getBoolPref("browser.tabs.insertRelatedAfterCurrent")" [/(?=(return t;)(?![\s\S]*\1))/, function() { if (t.hasAttribute("opener")) { - function shouldStack(tab) let (args = tab.arguments) (args.aReferrerURI || args.aRelatedToCurrent && args.aURI != "about:blank"); + function shouldStack(tab) { let args = tab.arguments; return args.aReferrerURI || args.aRelatedToCurrent && args.aURI != "about:blank"; } let lastRelatedTab = this.mCurrentTab; let isStack = this.isStackedTab(lastRelatedTab); @@ -655,7 +700,7 @@ tabutils._tabOpeningOptions = function() { if ((function() { switch (TU_getPref("extensions.tabutils.openTabNext", 1)) { case 1: //All - case 2: return aRelatedToCurrent || aReferrerURI || aURI != "about:blank"; //All but New Tab + case 2: return aRelatedToCurrent || aReferrerURI || (aURI != "about:blank" && aURI != "about:newtab"); //All but New Tab case 3: return aRelatedToCurrent == null ? aReferrerURI : aRelatedToCurrent; //None but Links default: return false; //None } @@ -674,14 +719,15 @@ tabutils._tabOpeningOptions = function() { this.updateCurrentBrowser(true); }); - //新建标签页 + //鏂板缓鏍囩椤 if (BrowserOpenTab.name == "BrowserOpenTab") { //Compatibility with Speed Dial TU_hookCode("BrowserOpenTab", [/.*openUILinkIn\((.*)\)/, function(s, s1) s.replace(s1, ( + s1 = s1.replace(/,\s*\{\s*relatedToCurrent\s*\}/, ""), s1 = s1.split(","), s1.push("{inBackground: TU_getPref('extensions.tabutils.loadNewInBackground', false)}"), s1.push("{relatedToCurrent: TU_getPref('extensions.tabutils.openTabNext', 1) == 1}"), - s1.join().replace("},{", ",") + s1.join().replace(/\}\s*,\s*\{/, ",") ))] // Bug 490225 [Fx11] ); } @@ -694,12 +740,12 @@ tabutils._tabOpeningOptions = function() { return this.mTabContainer.getElementsByAttribute("linkedpanel", this.mPanelContainer.lastChild.id)[0]; }; - //复制标签页 + //澶嶅埗鏍囩椤 TU_hookCode("gBrowser.duplicateTab", [/return/g, "var tab ="], ["}", function() { this.detachTab(tab, true); - if (["_onDrop", "onxbldrop", "duplicateTabIn"].indexOf(arguments.callee.caller.name) == -1) { + if (TMP_console.isCallerInList(["_onDrop", "onxbldrop", "duplicateTabIn"])) { if (TU_getPref("extensions.tabutils.openDuplicateNext", true)) { if (this.isStackedTab(aTab)) aTab = this.lastSiblingTabOf(aTab); @@ -712,9 +758,9 @@ tabutils._tabOpeningOptions = function() { }] ); - //撤销关闭标签页 - TU_hookCode("gBrowser.moveTabTo", "{", function() { - if (arguments.callee.caller.name == "ssi_undoCloseTab" + //鎾ら攢鍏抽棴鏍囩椤 + TU_hookCode("gBrowser.moveTabTo", "}", function() { + if (TMP_console.callerName() == "ssi_undoCloseTab" && !TU_getPref("extensions.tabutils.restoreOriginalPosition", true)) return; }); @@ -722,7 +768,7 @@ tabutils._tabOpeningOptions = function() { tabutils._tabClosingOptions = function() { - //关闭标签页时选择左侧/右侧/第一个/最后一个标签 + //鍏抽棴鏍囩椤垫椂閫夋嫨宸︿晶/鍙充晶/绗竴涓/鏈鍚庝竴涓爣绛 gBrowser._tabsToSelect = function _tabsToSelect(aTabs) { if (!aTabs) aTabs = this.visibleTabs; @@ -800,7 +846,7 @@ tabutils._tabClosingOptions = function() { } }; - //关闭标签页时选择亲属标签 + //鍏抽棴鏍囩椤垫椂閫夋嫨浜插睘鏍囩 TU_hookCode("gBrowser.onTabSelect", "}", function() { var panelId = aTab.linkedPanel + "#"; Array.forEach(this.visibleTabs, function(aTab) { @@ -834,27 +880,27 @@ tabutils._tabClosingOptions = function() { || bTab.getAttribute("opener").startsWith(aTab.linkedPanel + "#"); }; - //关闭标签页时选择上次浏览的标签 + //鍏抽棴鏍囩椤垫椂閫夋嫨涓婃娴忚鐨勬爣绛 gBrowser.mTabContainer._tabHistory = Array.slice(gBrowser.mTabs); TU_hookCode("gBrowser.onTabOpen", "}", function() { var tabHistory = this.mTabContainer._tabHistory; tabHistory.splice(1, 0, aTab); aTab._lastAccessed = Date.now(); - tabutils._ss.setTabValue(aTab, "lastAccessed", aTab._lastAccessed); + tabutils._ss.setTabValue(aTab, "lastAccessed", String(aTab._lastAccessed)); }); TU_hookCode("gBrowser.onTabSelect", "}", function() { var tabHistory = this.mTabContainer._tabHistory; - var lastTab = tabHistory[0]; + lastTab = tabHistory[0]; lastTab._lastAccessed = Date.now(); - tabutils._ss.setTabValue(lastTab, "lastAccessed", lastTab._lastAccessed); + tabutils._ss.setTabValue(lastTab, "lastAccessed", String(lastTab._lastAccessed)); var index = tabHistory.indexOf(aTab); if (index > -1) tabHistory.splice(index, 1); tabHistory.unshift(aTab); aTab._lastAccessed = Infinity; - tabutils._ss.setTabValue(aTab, "lastAccessed", aTab._lastAccessed); + tabutils._ss.setTabValue(aTab, "lastAccessed", String(aTab._lastAccessed)); }); TU_hookCode("gBrowser.onTabClose", "}", function() { @@ -871,7 +917,7 @@ tabutils._tabClosingOptions = function() { tabHistory.splice(index, 1); if (aTab._lastAccessed == Infinity) - tabutils._ss.setTabValue(aTab, "lastAccessed", aTab._lastAccessed); + tabutils._ss.setTabValue(aTab, "lastAccessed", String(aTab._lastAccessed)); else aTab._lastAccessed = tabutils._ss.getTabValue(aTab, "lastAccessed"); @@ -889,8 +935,8 @@ tabutils._tabClosingOptions = function() { || tabHistory[aDir < 0 ? tabHistory.length - 1 : 0]; }; - //Ctrl+Tab切换到上次浏览的标签 - //Ctrl+左右方向键切换到前一个/后一个标签 + //Ctrl+Tab鍒囨崲鍒颁笂娆℃祻瑙堢殑鏍囩 + //Ctrl+宸﹀彸鏂瑰悜閿垏鎹㈠埌鍓嶄竴涓/鍚庝竴涓爣绛 tabutils.addEventListener(window, "keydown", function(event) { if (!event.ctrlKey || event.altKey || event.metaKey) return; @@ -980,7 +1026,9 @@ tabutils._tabClosingOptions = function() { TU_hookCode("gBrowser.updateCurrentBrowser", /.*dispatchEvent[\s\S]*_tabAttrModified.*/, "$&};if (window.windowState != window.STATE_MINIMIZED) {"); //Don't close the last primary window with the las tab - TU_hookCode("gBrowser._beginRemoveTab", "_closeWindowWithLastTab", "$& && " + (function() { //Bug 607893 + TU_hookCode("gBrowser._beginRemoveTab", + /_closeWindowWithLastTab|Services\.prefs\.getBoolPref\("browser\.tabs\.closeWindowWithLastTab"\)/, // Bug 997681 [Fx31] + "$& && " + (function() { //Implement to Bug 607893 (TU_getPref("extensions.tabutils.closeLastWindowWithLastTab", false) || function() { var winEnum = Services.wm.getEnumerator("navigator:browser"); while (winEnum.hasMoreElements()) { @@ -1104,7 +1152,7 @@ tabutils._tabClosingOptions = function() { }, false); }; -//标记未读标签页 +//鏍囪鏈鏍囩椤 tabutils._unreadTab = function() { gBrowser.unreadTab = function unreadTab(aTab, aForce) { if (aForce == null) @@ -1143,7 +1191,7 @@ tabutils._unreadTab = function() { }); } -//保护标签页、锁定标签页、冻结标签页 +//淇濇姢鏍囩椤点侀攣瀹氭爣绛鹃〉銆佸喕缁撴爣绛鹃〉 tabutils._protectAndLockTab = function() { /* aRestoring = null: setAttribute + setTabValue + tagURI * aRestoring = false: setAttribute + setTabValue @@ -1168,7 +1216,7 @@ tabutils._protectAndLockTab = function() { else { aTab.setAttribute("protected", true); if (!aRestoring) - tabutils._ss.setTabValue(aTab, "protected", true); + tabutils._ss.setTabValue(aTab, "protected", String(true)); if (aRestoring == null && !gPrivateBrowsingUI.privateBrowsingEnabled && TU_getPref("extensions.tabutils.autoProtect", true)) { PlacesUtils.tagging.tagURI(aTab.linkedBrowser.currentURI, ["protected"]); } @@ -1194,7 +1242,7 @@ tabutils._protectAndLockTab = function() { else { aTab.setAttribute("locked", true); if (!aRestoring) - tabutils._ss.setTabValue(aTab, "locked", true); + tabutils._ss.setTabValue(aTab, "locked", String(true)); if (aRestoring == null && !gPrivateBrowsingUI.privateBrowsingEnabled && TU_getPref("extensions.tabutils.autoLock", true)) { PlacesUtils.tagging.tagURI(aTab.linkedBrowser.currentURI, ["locked"]); } @@ -1272,7 +1320,7 @@ tabutils._protectAndLockTab = function() { }).toString().replace(/^.*{|}$/g, "")); }; -//图标化标签页 +//鍥炬爣鍖栨爣绛鹃〉 tabutils._faviconizeTab = function() { gBrowser.faviconizeTab = function faviconizeTab(aTab, aForce, aRestoring) { if (aForce == aTab.hasAttribute("faviconized")) @@ -1293,7 +1341,7 @@ tabutils._faviconizeTab = function() { else { aTab.setAttribute("faviconized", true); if (!aRestoring) - tabutils._ss.setTabValue(aTab, "faviconized", true); + tabutils._ss.setTabValue(aTab, "faviconized", String(true)); if (aRestoring == null && !gPrivateBrowsingUI.privateBrowsingEnabled && TU_getPref("extensions.tabutils.autoFaviconize", true)) { PlacesUtils.tagging.tagURI(aTab.linkedBrowser.currentURI, ["faviconized"]); } @@ -1316,11 +1364,11 @@ tabutils._faviconizeTab = function() { TU_hookCode("gBrowser.onLocationChange", "}", "this.autoFaviconizeTab(aTab, uri, tags);"); }; -//固定标签页 +//鍥哄畾鏍囩椤 tabutils._pinTab = function() { }; -//重命名标签页 +//閲嶅懡鍚嶆爣绛鹃〉 tabutils._renameTab = function() { gBrowser.renameTab = function renameTab(aTab, aTitle, aRestoring) { if (aTab.getAttribute("title") == aTitle) @@ -1373,11 +1421,11 @@ tabutils._renameTab = function() { TU_hookCode("gBrowser.loadTabs", ["{", "var lastArg = Object(arguments[arguments.length - 1]), aTitles = TU_getPref('extensions.tabutils.titleAsBookmark', false) ? lastArg.titles : null;"], - [/(\w+) = .*addTab.*\[(.*)\].*/g, function(s, s1, s2) (function() { + [/(\w+) = .*addTab.*\[(.*)\][\s\S]*?\}\);/g, function(s, s1, s2) (function() { $0 if (aTitles && aTitles[$2]) $1.setAttribute("title", aTitles[$2]); - }).toString().replace(/^.*{|}$/g, "").replace("$0", s).replace("$1", s1, "g").replace("$2", s2, "g")] + }).toString().replace(/^.*{|}$/g, "").replace("$0", s).replace(/\$1/g, s1).replace(/\$2/g, s2)] ); }; @@ -1422,7 +1470,7 @@ tabutils._restartTab = function() { aTab._restartTimer = null; } - let lastTab = this.getLastSelectedTab(); + lastTab = this.getLastSelectedTab(); if (lastTab) this.autoRestartTab(lastTab); }); @@ -1436,7 +1484,7 @@ tabutils._restartTab = function() { }); }; -//自动刷新标签页 +//鑷姩鍒锋柊鏍囩椤 tabutils._reloadEvery = function() { gBrowser.autoReloadTab = function autoReloadTab(aTab, aForce, aRestoring, aInterval) { if (aForce == aTab.hasAttribute("autoReload") && (!aForce || aInterval == aTab._reloadInterval)) @@ -1463,8 +1511,8 @@ tabutils._reloadEvery = function() { aTab._reloadInterval = aInterval || aTab._reloadInterval || TU_getPref("extensions.tabutils.reloadInterval", 10); TU_setPref("extensions.tabutils.reloadInterval", aTab._reloadInterval); if (!aRestoring) { - tabutils._ss.setTabValue(aTab, "autoReload", true); - tabutils._ss.setTabValue(aTab, "reloadInterval", aTab._reloadInterval); + tabutils._ss.setTabValue(aTab, "autoReload", String(true)); + tabutils._ss.setTabValue(aTab, "reloadInterval", String(aTab._reloadInterval)); } if (aRestoring == null && !gPrivateBrowsingUI.privateBrowsingEnabled && TU_getPref("extensions.tabutils.autoEnableAutoReload", true)) { @@ -1583,6 +1631,7 @@ tabutils._bookmarkTabs = function() { PlacesCommandHook.bookmarkPage(aTabs[0].linkedBrowser, PlacesUtils.bookmarksMenuFolderId, true); }; + if (tabutils.fxVersion < 40) { // https://hg.mozilla.org/mozilla-central/diff/d84b62b367b4/browser/base/content/browser-places.js TU_hookCode("PlacesCommandHook.bookmarkPage", [/(?=.*(createItem|PlacesCreateBookmarkTransaction).*)/, function() { var annos = [descAnno]; @@ -1594,7 +1643,9 @@ tabutils._bookmarkTabs = function() { }], [/.*(createItem|PlacesCreateBookmarkTransaction).*/, function(s) s.replace("[descAnno]", "annos")] // Bug 575955 [Fx13] ); + } + if (!("abHere2" in window)) { // Compatibility with Add Bookmark Here 虏 TU_hookCode("PlacesCommandHook.bookmarkCurrentPages", ["this.uniqueCurrentPages", (function() { !gPrivateBrowsingUI.privateBrowsingEnabled && TU_getPref("extensions.tabutils.bookmarkAllWithHistory", true) ? @@ -1603,6 +1654,7 @@ tabutils._bookmarkTabs = function() { }).toString().replace(/^.*{|}$/g, "")], ["pages.length > 1", "true"] ); + } //Highlight bookmarks with history TU_hookCode("PlacesViewBase.prototype._createMenuItemForPlacesNode", /(?=return element;)/, function() { @@ -1628,13 +1680,13 @@ tabutils._bookmarkTabs = function() { TU_hookCode("gBrowser.loadTabs", ["{", "var lastArg = Object(arguments[arguments.length - 1]), aItemIds = lastArg.itemIds;"], - [/(\w+) = .*addTab.*\[(.*)\].*/g, function(s, s1, s2) (function() { + [/(\w+) = .*addTab.*\[(.*)\][\s\S]*?\}\);/g, function(s, s1, s2) (function() { $0 if (aItemIds && aItemIds[$2] && PlacesUtils.annotations.itemHasAnnotation(aItemIds[$2], "bookmarkProperties/tabState")) { $1.linkedBrowser.stop(); tabutils._ss.setTabState($1, PlacesUtils.annotations.getItemAnnotation(aItemIds[$2], "bookmarkProperties/tabState")); } - }).toString().replace(/^.*{|}$/g, "").replace("$0", s).replace("$1", s1, "g").replace("$2", s2, "g")] + }).toString().replace(/^.*{|}$/g, "").replace("$0", s).replace(/\$1/g, s1).replace(/\$2/g, s2)] ); }; @@ -1781,7 +1833,7 @@ tabutils._multiTabHandler = function() { }, []); }; - //关闭多个标签页 + //鍏抽棴澶氫釜鏍囩椤 TU_hookCode("gBrowser.warnAboutClosingTabs", /\w+(?= <= 1)/, "($& = arguments[1] && 'length' in arguments[1] ? arguments[1].length : $&)"); // Bug 866880 [Fx24] gBrowser.removeTabsBut = function removeTabsBut(aTabs, bTabs) { aTabs = aTabs ? "length" in aTabs ? aTabs : [aTabs] : []; @@ -1822,7 +1874,7 @@ tabutils._multiTabHandler = function() { gBrowser.closeAllTabs = function() this.removeTabsBut(this.allTabs); gBrowser.closeAllDuplicateTabs = function() this.removeTabsBut(this.allTabs, this.uniqueTabsOf(this.allTabs)); - //拖曳多个标签页 + //鎷栨洺澶氫釜鏍囩椤 gBrowser.gatherTabs = function gatherTabs(aTabs, aTab, aSuppressTabMove) { let index = 0; if (aTab) { @@ -1874,7 +1926,9 @@ tabutils._multiTabHandler = function() { } }, true); - TU_hookCode("gBrowser.mTabContainer._setEffectAllowedForDataTransfer", + TU_hookCode(typeof gBrowser.mTabContainer._setEffectAllowedForDataTransfer === 'function' ? + "gBrowser.mTabContainer._setEffectAllowedForDataTransfer" : // Firefox 43 and older + "gBrowser.mTabContainer._getDropEffectForTabDrag", // Firefox 44 and later ["dt.mozItemCount > 1", "false"] ); @@ -1901,7 +1955,7 @@ tabutils._multiTabHandler = function() { }); TU_hookCode("gBrowser.moveTabTo", // Bug 822068 [Fx20] - ["this.mCurrentTab._selected = false;", "let wasFocused = (document.activeElement == this.mCurrentTab);$&"], + ["this.mCurrentTab._selected = false;", "wasFocused = (document.activeElement == this.mCurrentTab);$&"], ["this.mCurrentTab._selected = true;", "$&;if (wasFocused) this.mCurrentTab.focus();"] ); @@ -1980,7 +2034,7 @@ tabutils._multiTabHandler = function() { TU_hookCode("gBrowser.swapBrowsersAndCloseOther", /(?=.*_beginRemoveTab.*)/, function() { if ([gBrowserInit.onLoad, gBrowserInit._delayedStartup].indexOf(arguments.callee.caller) > -1 || // Bug 756313 [Fx19] - ["onxbldrop", "_handleTabDrop"].indexOf(arguments.callee.caller.name) > -1) { + TMP_console.isCallerInList(["onxbldrop", "_handleTabDrop"])) { let selectedTabs = aOtherTab._selectedTabs || remoteBrowser.contextTabsOf(aOtherTab); if (selectedTabs.length > 1) { this.swapBrowsersAndCloseOther(aOurTab, selectedTabs.shift()); @@ -2023,7 +2077,7 @@ tabutils._multiTabHandler = function() { tabutils._tabClickingOptions = function() { - //载入剪贴板URL + //杞藉叆鍓创鏉縐RL gBrowser.loadURLFromClipboard = function loadURLFromClipboard(aTab) { var url = readFromClipboard(); if (!url) @@ -2038,16 +2092,17 @@ tabutils._tabClickingOptions = function() { } }; - //浏览历史菜单 - TU_hookCode("FillHistoryMenu", - ["count <= 1", "count == 0"], - [/(?=var webNav)/, function() { + //娴忚鍘嗗彶鑿滃崟 + TU_hookCode("FillHistoryMenu", // Fillin the history menu + ["count <= 1", "count == 0"], // Always show the menu + ["gBrowser.selectedTab", "tab", "g"], // since Bug 1148505 [Fx43]. + [FillHistoryMenu.toString().indexOf("var webNav")>0 ? /(?=var webNav)/ : /(?=let sessionHistory)/, function() { // Bug 1148505 [Fx43]. var tab = document.popupNode; if (!tab || tab.localName != 'tab') tab = gBrowser.selectedTab; aParent.value = tab._tPos; }], - ["gBrowser.webNavigation", "tab.linkedBrowser.webNavigation"] + ["gBrowser.webNavigation", "tab.linkedBrowser.webNavigation"] // Is no longer valid since Bug 1148505 [Fx43]. ); TU_hookCode("gotoHistoryIndex", ["gBrowser.selectedTab", "tab", "g"], @@ -2057,7 +2112,7 @@ tabutils._tabClickingOptions = function() { TU_hookCode("TabContextMenu.updateContextMenu", "aPopupMenu.triggerNode", "document.popupNode", "g"); TU_hookCode("gBrowser.mTabContainer._selectNewTab", "{", function() { - if (["onxblmousedown"].indexOf(arguments.callee.caller.name) > -1 && + if (TMP_console.isCallerInList(["onxblmousedown"]) && !aNewTab.selected) aNewTab.setAttribute("firstclick", true); }); @@ -2285,7 +2340,7 @@ tabutils._tabClickingOptions = function() { //Mouse release to select TU_hookCode("gBrowser.mTabContainer._selectNewTab", "{", function() { - if (["onxblmousedown"].indexOf(arguments.callee.caller.name) > -1 && + if (TMP_console.isCallerInList(["onxblmousedown"]) && TU_getPref("extensions.tabutils.mouseReleaseSelect", true)) return; }); @@ -2318,9 +2373,13 @@ tabutils._tabClickingOptions = function() { }, false); //Mouse scroll to select - tabutils.addEventListener(gBrowser.mTabContainer, 'DOMMouseScroll', function(event) { + tabutils.addEventListener(gBrowser.mTabContainer, 'wheel', function(event) { + let isVertical = Math.abs(event.deltaY) > Math.abs(event.deltaX); + let delta = isVertical ? event.deltaY : event.deltaX; + let scrollByDelta = isVertical && this._isRTLScrollbox ? -delta : delta; if (event.ctrlKey) { - document.getElementById(event.detail < 0 ? "cmd_prevGroup" : "cmd_nextGroup").doCommand(); + document.getElementById(scrollByDelta < 0 ? "cmd_prevGroup" : "cmd_nextGroup").doCommand(); + event.preventDefault(); event.stopPropagation(); return; } @@ -2328,8 +2387,9 @@ tabutils._tabClickingOptions = function() { if (event.originalTarget != this.mTabstrip._scrollButtonUp && event.originalTarget != this.mTabstrip._scrollButtonDown && TU_getPref("extensions.tabutils.mouseScrollSelect", false)) { - let scrollDir = event.detail < 0 ^ TU_getPref("extensions.tabutils.mouseScrollSelectDir", false) ? -1 : 1; + let scrollDir = scrollByDelta < 0 ^ TU_getPref("extensions.tabutils.mouseScrollSelectDir", false) ? -1 : 1; this.advanceSelectedTab(scrollDir, TU_getPref("extensions.tabutils.mouseScrollSelectWrap", false)); + event.preventDefault(); event.stopPropagation(); } }, true); @@ -2373,10 +2433,14 @@ tabutils._miscFeatures = function() { TU_hookCode("openGMarkLabelInTabs", [/.*openUILinkIn.*/, ""], [/(?=.*(labelArray)(?![\s\S]*\1))/, function() { - var urls = [label.url for (label of labelArray)]; + var urls = $1; var loadInBackground = TU_getPref("browser.tabs.loadBookmarksInBackground"); gBrowser.loadTabs(urls, loadInBackground, false); - }] + }.toString().replace("$1", + tabutils.fxVersion >= 30.0 ? + "[for (label of labelArray) label.url]" : // Bug 979865 [Fx30] support + "[label.url for (label of labelArray)]" // Bug 1220564 [Fx46] removed + )] ); TU_hookCode("BookmarkingUI" in window ? "BookmarkingUI._updateStar" : "PlacesStarButton._updateStateInternal", /(?=.*this._itemIds.*)/, function() { //Bug 650527 @@ -2435,37 +2499,36 @@ tabutils._miscFeatures = function() { } }; -//浏览区右键菜单 +//娴忚鍖哄彸閿彍鍗 tabutils._mainContextMenu = function() { - nsContextMenu.prototype.isLinkSelected = function() { - var focusedWindow = document.commandDispatcher.focusedWindow; - if (!focusedWindow || focusedWindow == window) - focusedWindow = window.content; - - var links = focusedWindow.document.links; - var selection = focusedWindow.getSelection(); - if (!links || !selection) - return false; - - this.linkURLs = []; - for (let link of links) { - if (selection.containsNode(link, true) && this.linkURLs.indexOf(link.href) == -1) - this.linkURLs.push(link.href); - } - - var item = document.getElementById("context-openselectedlinksintab"); - item.setAttribute("label", item.getAttribute("label").replace(/\d*(?=])/, this.linkURLs.length)); - - return this.linkURLs.length > 1; + var TUF_LinksSelected = []; // due to an call in that "listener". + nsContextMenu.prototype.checkLinkSelected = function() { + //console.time('getLinkSelected'); + messageManager.addMessageListener("tabutils-fixed:LinksSelected", listener); + function listener(message) { + //console.dir(message); + let linkURLs = message.data.links; + TUF_LinksSelected = linkURLs; + let item = document.getElementById("context-openselectedlinksintab"); + item.setAttribute("label", item.getAttribute("label").replace(/\d*(?=])/, linkURLs.length)); + item.setAttribute("hidden", linkURLs.length > 1 ? "" : "true"); + //console.timeEnd('getLinkSelected'); + } + let browserMM = gBrowser.selectedBrowser.messageManager; + browserMM.loadFrameScript('chrome://tabutils/content/content.js', true); }; nsContextMenu.prototype.openSelectedLinksInTab = function() { - this.linkURLs.forEach(function(aURL) openNewTabWith(aURL, this.target.ownerDocument, null, null, false), this); + gBrowser.loadTabs(TUF_LinksSelected); }; //TU_hookCode("nsContextMenu.prototype.initOpenItems", /.*openlinkincurrent.*/, function(s) s.replace("onPlainTextLink", "shouldShow")); TU_hookCode("nsContextMenu.prototype.initOpenItems", "}", function() { - this.showItem("context-openselectedlinksintab", this.isLinkSelected()); + this.checkLinkSelected(); + }); + TU_hookCode("nsContextMenu.prototype.hiding", "}", function() { + let item = document.getElementById("context-openselectedlinksintab"); + item.setAttribute("hidden", true); }); }; @@ -2759,7 +2822,7 @@ tabutils._hideTabBar = function() { TU_hookCode("gBrowser.mTabContainer.updateVisibility", "{", 'if (!TU_getPref("browser.tabs.autoHide")) return;'); }; -//撤销关闭标签页按钮 +//鎾ら攢鍏抽棴鏍囩椤垫寜閽 tabutils._undoCloseTabButton = function() { TU_hookCode("RecentlyClosedTabsAndWindowsMenuUtils" in window ? "RecentlyClosedTabsAndWindowsMenuUtils._undoCloseMiddleClick" : // Bug 928640 [Fx27] @@ -2812,6 +2875,7 @@ tabutils._undoCloseTabButton = function() { tabutils._undoCloseMiddleClick = HistoryMenu.prototype._undoCloseMiddleClick; tabutils.populateUndoSubmenu = HistoryMenu.prototype.populateUndoSubmenu; + tabutils._getClosedTabCount = HistoryMenu.prototype._getClosedTabCount; // Bug 1064217 [Fx35] TU_hookCode("tabutils.populateUndoSubmenu", [/var undoPopup.*/, "var undoPopup = arguments[0];"], [/.*undoMenu.*/g, ""], @@ -2852,22 +2916,31 @@ tabutils._tabPrefObserver = { //Close buttons TU_hookCode("gBrowser.mTabContainer.adjustTabstrip", - [/let tab.*/, function() { - let tab; - Array.some(this.tabbrowser.visibleTabs, function(aTab) { - return !aTab.collapsed && getComputedStyle(aTab).MozBoxFlex > 0 && (tab = aTab); - }); - }], - ["this.mCloseButtons", "($& & 0x0f)"], - ["this.mCloseButtons != 3", "(this.mCloseButtons & 0x0f) != 3 && !(this.mCloseButtons & 0x20)"], - ["this._closeWindowWithLastTab", "false", "g"], - ["}", function() { - this.setAttribute("closeButtonOnPointedTab", (this.mCloseButtons & 0x0f) == 1 || !!(this.mCloseButtons & 0x10)); + ["this._originalAdjustTabstripFunc();", "if (this.TU_mCloseButtons == 10) {this.mCloseButtons = this.legacy_mCloseButtons; $&}"], + ["}", function() { + if (this.TU_mCloseButtons != 10) { + var def = "alltabs"; + var map = { + 0: "activetab", + 1: "alltabs", + 2: "hidden", + 16: "activepointedtab", + 18: "pointedtab" + }; + var value = map[this.TU_mCloseButtons] || def; + if (value == "alltabs") { + let tab = this.tabbrowser.visibleTabs[this.tabbrowser._numPinnedTabs]; + if (tab && tab.getBoundingClientRect().width <= this.mTabClipWidth) { + value = "hidden"; + } + } + this.setAttribute("closebuttons", value); + } }] ); //Tab counter - TU_hookCode("gBrowser.mTabContainer.adjustTabstrip", "}", function() { + TU_hookCode("gBrowser.mTabContainer.adjustTabstrip", "{", function() { if (this.mAllTabsPopup) { let n = gBrowser.mTabs.length - gBrowser._removingTabs.length; let m = gBrowser.allTabs.length; @@ -2907,7 +2980,7 @@ tabutils._tabPrefObserver = { '.alltabs-item#Selector#' ].join(), textSelector: [ - '.tabbrowser-tab#Selector# > * > .tab-content > .tab-text', + '.tabbrowser-tab#Selector# > * > .tab-content .tab-text', '.alltabs-item#Selector#' ].join(), bgSelector: [ @@ -2933,7 +3006,7 @@ tabutils._tabPrefObserver = { if (!aData.startsWith("extensions.tabutils.")) return; - let name = aData.slice(20).replace(".", "_", "g"); + let name = aData.slice(20).replace(/\./g, "_"); if (name in this) { this[name](); return; @@ -2954,9 +3027,9 @@ tabutils._tabPrefObserver = { return; this.cssRules[prefName] = { - tab: tabutils.insertRule(this.tabSelector.replace('#Selector#', selector, 'g') + '{}'), - text: tabutils.insertRule(this.textSelector.replace('#Selector#', selector, 'g') + '{}'), - bg: tabutils.insertRule(this.bgSelector.replace('#Selector#', selector, 'g') + '{}') + tab: tabutils.insertRule(this.tabSelector.replace(/#Selector#/g, selector) + '{}'), + text: tabutils.insertRule(this.textSelector.replace(/#Selector#/g, selector) + '{}'), + bg: tabutils.insertRule(this.bgSelector.replace(/#Selector#/g, selector) + '{}') }; } @@ -3053,7 +3126,8 @@ tabutils._tabPrefObserver = { if (!button) { button = document.getElementById("nav-bar").appendChild(document.createElement("toolbarbutton")); button.id = RegExp.$1; - button.image = gBrowser.mFaviconService.defaultFavicon.spec; + const FaviconService = Cc["@mozilla.org/browser/favicon-service;1"]. getService(Ci.nsIFaviconService); + button.image = FaviconService.defaultFavicon.spec; button.className = "toolbarbutton-1 chromeclass-toolbar-additional"; button.collapsed = !TU_getPref("extensions.tabutils.button." + RegExp.$1); } @@ -3187,7 +3261,8 @@ tabutils._tabPrefObserver = { }, closeButtons: function() { - gBrowser.mTabContainer.mCloseButtons = TU_getPref("extensions.tabutils.closeButtons"); + gBrowser.mTabContainer.legacy_mCloseButtons = TU_getPref("browser.tabs.closeButtons"); + gBrowser.mTabContainer.TU_mCloseButtons = TU_getPref("extensions.tabutils.closeButtons"); gBrowser.mTabContainer.adjustTabstrip(); }, @@ -3220,40 +3295,64 @@ tabutils._tabPrefObserver = { hideOpenInTab: function() { var hideOpenInTab = TU_getPref("extensions.tabutils.hideOpenInTab"); - document.getElementById("statusbar-openintab").collapsed = hideOpenInTab; + var toolbarItem = document.getElementById("statusbar-openintab"); + //Check if toolbar item is not removed by user + if (toolbarItem) { + toolbarItem.collapsed = hideOpenInTab; + } }, hideLoadInBackground: function() { var hideLoadInBackground = TU_getPref("extensions.tabutils.hideLoadInBackground"); if (hideLoadInBackground) TU_setPref("extensions.tabutils.loadAllInBackground", false); - document.getElementById("statusbar-loadinbackground").collapsed = hideLoadInBackground; + var toolbarItem = document.getElementById("statusbar-loadinbackground"); + //Check if toolbar item is not removed by user + if (toolbarItem) { + toolbarItem.collapsed = hideLoadInBackground; + } }, hideLoadInForeground: function() { var hideLoadInForeground = TU_getPref("extensions.tabutils.hideLoadInForeground"); if (hideLoadInForeground) TU_setPref("extensions.tabutils.loadAllInForeground", false); - document.getElementById("statusbar-loadinforeground").collapsed = hideLoadInForeground; + var toolbarItem = document.getElementById("statusbar-loadinforeground"); + //Check if toolbar item is not removed by user + if (toolbarItem) { + toolbarItem.collapsed = hideLoadInForeground; + } }, openLinkInTab: function() { tabutils.gOpenLinkInTab = TU_getPref("extensions.tabutils.openLinkInTab"); - document.getElementById("statusbar-openintab").setAttribute("checked", tabutils.gOpenLinkInTab); + var toolbarItem = document.getElementById("statusbar-openintab"); + //Check if toolbar item is not removed by user + if (toolbarItem) { + toolbarItem.setAttribute("checked", tabutils.gOpenLinkInTab); + } }, loadAllInBackground: function() { tabutils.gLoadAllInBackground = TU_getPref("extensions.tabutils.loadAllInBackground"); if (tabutils.gLoadAllInBackground) TU_setPref("extensions.tabutils.loadAllInForeground", false); - document.getElementById("statusbar-loadinbackground").setAttribute("checked", tabutils.gLoadAllInBackground); + var toolbarItem = document.getElementById("statusbar-loadinbackground"); + //Check if toolbar item is not removed by user + if (toolbarItem) { + toolbarItem.setAttribute("checked", tabutils.gLoadAllInBackground); + } }, loadAllInForeground: function() { tabutils.gLoadAllInForeground = TU_getPref("extensions.tabutils.loadAllInForeground"); if (tabutils.gLoadAllInForeground) TU_setPref("extensions.tabutils.loadAllInBackground", false); - document.getElementById("statusbar-loadinforeground").setAttribute("checked", tabutils.gLoadAllInForeground); + var toolbarItem = document.getElementById("statusbar-loadinforeground"); + //Check if toolbar item is not removed by user + if (toolbarItem) { + toolbarItem.setAttribute("checked", tabutils.gLoadAllInForeground); + } }, loadInNewTab: function() { diff --git a/chrome/content/tabutils.xml b/chrome/content/tabutils.xml index 09b61a4..809e69c 100644 --- a/chrome/content/tabutils.xml +++ b/chrome/content/tabutils.xml @@ -5,8 +5,6 @@ %globalDTD; %browserDTD; - -%tabBrowserDTD; ]> - + - + - - @@ -214,7 +217,7 @@ + + %browserDTD; - -%tabBrowserDTD; %tabutilsDTD; ]> @@ -100,22 +100,12 @@ onpopupshowing="try {BookmarksEventHandler.onPopupShowing(event);} catch (e) {this.parentNode._placesView || new PlacesMenu(event, this.getAttribute('place'));}" tooltip="bhTooltip" popupsinherittooltip="true"/> - - - - - - - - - - -