diff --git a/bootstrap.js b/bootstrap.js index 6bbba4b..699880a 100644 --- a/bootstrap.js +++ b/bootstrap.js @@ -1,4 +1,4 @@ -// VERSION 1.8.8 +// VERSION 1.8.9 // This looks for file defaults.js in resource folder, expects: // objName - (string) main object name for the add-on, to be added to window element @@ -85,6 +85,28 @@ function LOG(str) { if(!str) { str = typeof(str)+': '+str; } console.log(objName+' :: CHROME :: '+str); } +function STEPLOGGER(name) { + this.name = name; + this.steps = []; + this.initTime = new Date().getTime(); + this.lastTime = this.initTime; +} +STEPLOGGER.prototype = { + step: function(name) { + let time = new Date().getTime(); + this.steps.push({ name, time: time - this.lastTime}); + this.lastTime = time; + }, + end: function() { + this.step('end'); + let endTime = new Date().getTime(); + let report = { name: this.name, total: endTime - this.initTime }; + for(let x of this.steps) { + report[x.name] = x.time; + } + console.log(report); + } +}; XPCOMUtils.defineLazyServiceGetter(Services, "xulStore", "@mozilla.org/xul/xulstore;1", "nsIXULStore"); XPCOMUtils.defineLazyServiceGetter(Services, "navigator", "@mozilla.org/network/protocol;1?name=http", "nsIHttpProtocolHandler"); diff --git a/install.rdf b/install.rdf index 23526ae..e1317d1 100644 --- a/install.rdf +++ b/install.rdf @@ -19,8 +19,8 @@ {ec8030f7-c20a-464f-9b0e-13a3a9e97384} - 44.0 - 47.0a1 + 45.0 + 48.0a1 diff --git a/resource/modules/content/mFinder.jsm b/resource/modules/content/mFinder.jsm index d605442..82c73d4 100644 --- a/resource/modules/content/mFinder.jsm +++ b/resource/modules/content/mFinder.jsm @@ -1,4 +1,4 @@ -// VERSION 1.0.22 +// VERSION 1.0.23 this.__defineGetter__('isPDFJS', function() { return Finder.isPDFJS; }); @@ -1079,11 +1079,7 @@ this.Finder = { } else { let body = (document instanceof Ci.nsIDOMHTMLDocument && document.body) ? document.body : document.documentElement; - if(Services.vc.compare(Services.appinfo.version, "45.0a1") >= 0) { - text = body.innerText; - } else { - text = innerText(body); - } + text = body.innerText; } resolve(text); }); @@ -1115,11 +1111,7 @@ this.Finder = { let doc = (aWindow.frames[i]) ? aWindow.frames[i].document : null; if(!doc) { continue; } let body = (doc instanceof Ci.nsIDOMHTMLDocument && doc.body) ? doc.body : doc.documentElement; - if(Services.vc.compare(Services.appinfo.version, "45.0a1") >= 0) { - text += body.innerText; - } else { - text += innerText(body); - } + text += body.innerText; text += this.getInnerTextFrames(aWindow.frames[i]); } return text; diff --git a/resource/modules/content/utils/ChildProcess.jsm b/resource/modules/content/utils/ChildProcess.jsm index 8cdbfac..5a201db 100644 --- a/resource/modules/content/utils/ChildProcess.jsm +++ b/resource/modules/content/utils/ChildProcess.jsm @@ -1,4 +1,4 @@ -// VERSION 1.0.1 +// VERSION 1.0.3 // This script should be loaded by defaultsContent.js, which is in turn loaded directly by the Messenger module. // defaultsContent.js call its .init(objPathString, frame) method, where frame is the enviroment of the frame script. @@ -80,6 +80,28 @@ function LOG(str) { if(!str) { str = typeof(str)+': '+str; } console.log(objName+' :: CONTENT :: '+str); } +function STEPLOGGER(name) { + this.name = name; + this.steps = []; + this.initTime = new Date().getTime(); + this.lastTime = this.initTime; +} +STEPLOGGER.prototype = { + step: function(name) { + let time = new Date().getTime(); + this.steps.push({ name, time: time - this.lastTime}); + this.lastTime = time; + }, + end: function() { + this.step('end'); + let endTime = new Date().getTime(); + let report = { name: this.name, total: endTime - this.initTime }; + for(let x of this.steps) { + report[x.name] = x.time; + } + console.log(report); + } +}; function handleDeadObject(ex) { if(ex.message == "can't access dead object") { @@ -455,6 +477,9 @@ var ChildProcess = { 'disable' ], + // modules that are found in modules/utils/ and not in modules/content/utils/ + nonContentModules: new Set([ 'utils/PrefPanes' ]), + receiveMessage: function(m) { let name = messageName(m); @@ -534,11 +559,17 @@ var ChildProcess = { }, loadModule: function(name) { - Modules.load('content/'+name); + if(!this.nonContentModules.has(name)) { + name = 'content/'+name; + } + Modules.load(name); }, unloadModule: function(name) { - Modules.unload('content/'+name); + if(!this.nonContentModules.has(name)) { + name = 'content/'+name; + } + Modules.unload(name); }, // clean up this object diff --git a/resource/modules/findInTabs.jsm b/resource/modules/findInTabs.jsm index bb059f2..fbbb4fa 100644 --- a/resource/modules/findInTabs.jsm +++ b/resource/modules/findInTabs.jsm @@ -1,4 +1,4 @@ -// VERSION 2.3.18 +// VERSION 2.3.19 this.__defineGetter__('FITdeferred', function() { return window.FITdeferred; }); this.__defineGetter__('FITinitialized', function() { return FITdeferred.promise; }); @@ -776,28 +776,7 @@ this.FIT = { getTabGroupName: function(aGroup) { if(aGroup.linkedWindow.TabView) { // Tab Groups add-on provides an easy way to get the group title - if(aGroup.linkedWindow.TabView.getGroupTitle) { - return aGroup.linkedWindow.TabView.getGroupTitle(aGroup); - } - - // This is a copy of what happens in TabView._createGroupMenuItem() - // can be removed in FF45 - let name = aGroup.getTitle(); - if(!name.trim()) { - let topChildLabel = aGroup.getTopChild().tab.label; - let childNum = aGroup.getChildren().length; - - if(childNum > 1) { - Windows.callOnMostRecent(function(win) { - let num = childNum -1; - name = win.gNavigatorBundle.getString("tabview.moveToUnnamedGroup.label"); - name = win.PluralForm.get(num, name).replace("#1", topChildLabel).replace("#2", num); - }, 'navigator:browser'); - } else { - name = topChildLabel; - } - } - return name; + return aGroup.linkedWindow.TabView.getGroupTitle(aGroup); } // Tab Groups are gone, so we make up our own "group" name, which represents the full window diff --git a/resource/modules/gFindBar.jsm b/resource/modules/gFindBar.jsm index a7f9564..0eedd1e 100644 --- a/resource/modules/gFindBar.jsm +++ b/resource/modules/gFindBar.jsm @@ -1,4 +1,4 @@ -// VERSION 1.2.6 +// VERSION 1.2.7 this.__defineGetter__('gFindBar', function() { return window.gFindBar || $('FindToolbar'); }); this.__defineGetter__('gFindBarInitialized', function() { return FITFull || viewSource || window.gFindBarInitialized; }); @@ -205,64 +205,6 @@ this.baseInit = function(bar) { Piggyback.add('gFindBar', bar, '_updateMatchesCount', function() {}); bar._foundMatches.value = ''; bar._foundMatches.hidden = true; - - // opening the findbar is a somewhat asynchronous process, it needs to fetch the value to prefill from content, - // if the user types in the findbar after it's opened, but before the prefill value is fetched, it can lead to some weirdness with the search query - // see https://github.com/Quicksaver/FindBar-Tweak/issues/198 and https://bugzilla.mozilla.org/show_bug.cgi?id=1198465 - if(Services.vc.compare(Services.appinfo.version, "45.0a1") < 0) { - Piggyback.add('gFindBar', bar, 'onCurrentSelection', function(aSelectionString, aIsInitialSelection) { - // no-op in case something resolved and nulled startFindDeferred in the meantime - return !aIsInitialSelection || this._startFindDeferred; - }, Piggyback.MODE_BEFORE); - - // keypresses are communicated through a message sent from content - Piggyback.add('gFindBar', bar, '_onBrowserKeypress', function(aFakeEvent) { - // in theory, fast keypresses could stack up when the process is slow/hanging, especially in e10s-code which has a high degree of asynchronicity here. - // we should make sure the findbar isn't "opened" several times, otherwise it could lead to erroneous find queries - // see https://github.com/Quicksaver/FindBar-Tweak/issues/198 and https://bugzilla.mozilla.org/show_bug.cgi?id=1198465 - if(!this.hidden && document.activeElement == this._findField.inputField) { - this._dispatchKeypressEvent(this._findField.inputField, aFakeEvent); - return false; - } - - let FAYT_LINKS_KEY = "'"; - let FAYT_TEXT_KEY = "/"; - - if(this._findMode != this.FIND_NORMAL && this._quickFindTimeout) { - if(!aFakeEvent.charCode) { - return true; - } - - this._findField.select(); - this._findField.focus(); - this._dispatchKeypressEvent(this._findField.inputField, aFakeEvent); - return false; - } - - let key = aFakeEvent.charCode ? String.fromCharCode(aFakeEvent.charCode) : null; - let manualstartFAYT = (key == FAYT_LINKS_KEY || key == FAYT_TEXT_KEY); - let autostartFAYT = !manualstartFAYT && Prefs.FAYTenabled && key && key != " "; - if(manualstartFAYT || autostartFAYT) { - let mode = (key == FAYT_LINKS_KEY || (autostartFAYT && this._typeAheadLinksOnly)) ? this.FIND_LINKS : this.FIND_TYPEAHEAD; - - // Clear bar first, so that when open() calls setCaseSensitivity() it doesn't get confused by a lingering value - this._findField.value = ""; - - this.open(mode); - this._setFindCloseTimeout(); - this._findField.select(); - this._findField.focus(); - - if(autostartFAYT) { - this._dispatchKeypressEvent(this._findField.inputField, aFakeEvent); - } else { - this._updateStatusUI(this.nsITypeAheadFind.FIND_FOUND); - } - - return false; - } - }); - } }; this.baseDeinit = function(bar) { @@ -291,10 +233,6 @@ this.baseDeinit = function(bar) { Piggyback.revert('gFindBar', bar, '_findAgain'); Piggyback.revert('gFindBar', bar, 'onFindAgainCommand'); Piggyback.revert('gFindBar', bar, '_updateMatchesCount'); - if(Services.vc.compare(Services.appinfo.version, "45.0a1") < 0) { - Piggyback.revert('gFindBar', bar, 'onCurrentSelection'); - Piggyback.revert('gFindBar', bar, '_onBrowserKeypress'); - } // this should always be resolved just after opening the sidebar, // but in case any of our initialization listeners hangs around for some reason, better ret rid of it diff --git a/resource/modules/utils/HTMLElements.jsm b/resource/modules/utils/HTMLElements.jsm deleted file mode 100644 index 18b8aa3..0000000 --- a/resource/modules/utils/HTMLElements.jsm +++ /dev/null @@ -1,42 +0,0 @@ -// VERSION 1.2.1 -Modules.UTILS = true; -Modules.BASEUTILS = true; - -// innerText(node) - returns the equivalent of IE's .innerText property of node; essentially returns .textContent stripped of all the script tags -// node - (xul element) to retrieve text content from -// This process is almost immediate (0-5ms) in normal smaller pages. -// https://bugzilla.mozilla.org/attachment.cgi?id=815787&action=diff, which is already a larger page, takes about 40-50ms. -// Isohunt results, which have a lot of frames, can be a little more than as above. -// Note: an alternative to this would be to crawl through all the childNodes of node and retrive text individually, -// but I found from my tests that this would be almost 50x slower, probably more if taking into account node visibility, which I didn't test for. -// Firefox 45 implements innerText at least, making this obsolete. -this.innerText = function(node) { - try { - if(!node || !node.ownerDocument || !(node instanceof node.ownerDocument.defaultView.HTMLElement)) { - return ''; - } - - // Cloning directly on the same document often triggers new onStateChange events in the browser, which could create endless loops of processing. - var clone = node.ownerDocument.implementation.createHTMLDocument('').importNode(node, true); - if(clone.getElementsByTagName) { - var heads = clone.getElementsByTagName('head'); - while(heads.length > 0) { - heads[0].remove(); - } - var scripts = clone.getElementsByTagName('script'); - while(scripts.length > 0) { - scripts[0].remove(); - } - var styles = clone.getElementsByTagName('style'); - while(styles.length > 0) { - styles[0].remove(); - } - } - - return clone.textContent; - } - catch(ex) { - Cu.reportError(ex); - return ''; - } -}; diff --git a/resource/modules/utils/PrefPanes.jsm b/resource/modules/utils/PrefPanes.jsm index b3a61e9..8303e46 100644 --- a/resource/modules/utils/PrefPanes.jsm +++ b/resource/modules/utils/PrefPanes.jsm @@ -1,4 +1,4 @@ -// VERSION 1.0.14 +// VERSION 1.0.15 Modules.UTILS = true; // PrefPanes - handles the preferences tab and all its contents for the add-on @@ -57,15 +57,6 @@ this.PrefPanes = { }, init: function() { - // we set the add-on status in the API webpage from within the add-on itself - Messenger.loadInAll('utils/api'); - - // always add the about pane to the preferences dialog, it should be the last category in the list - this.register('utils/about', { paneAbout: 'utils/about' }); - - Browsers.callOnAll(aWindow => { this.initWindow(aWindow); }, this.chromeUri); - Browsers.register(this, 'pageshow', this.chromeUri); - // if defaults.js supplies an addonUUID, use it to register the about: uri linking to the add-on's preferences if(addonUUID) { this.aboutUri = { @@ -86,12 +77,20 @@ this.PrefPanes = { getURIFlags: function(aURI) { return 0; } }, + loaded: function() { + return this.manager.isContractIDRegistered(this.handler.contractID); + }, + load: function() { - this.manager.registerFactory(this.handler.classID, this.handler.classDescription, this.handler.contractID, this); + if(!this.loaded()) { + this.manager.registerFactory(this.handler.classID, this.handler.classDescription, this.handler.contractID, this); + } }, unload: function() { - this.manager.unregisterFactory(this.handler.classID, this); + if(this.loaded()) { + this.manager.unregisterFactory(this.handler.classID, this); + } }, createInstance: function(outer, iid) { @@ -103,10 +102,27 @@ this.PrefPanes = { }; this.aboutUri.load(); - Browsers.callOnAll(aWindow => { this.initWindow(aWindow); }, this.aboutUri.spec); - Browsers.register(this, 'pageshow', this.aboutUri.spec); + if(isChrome) { + // We still need to register the about: handler in the content process, so that web navigation works; + // see https://bugzilla.mozilla.org/show_bug.cgi?id=1215793#c7 + Messenger.loadInAll('utils/PrefPanes'); + Browsers.callOnAll(aWindow => { this.initWindow(aWindow); }, this.aboutUri.spec); + Browsers.register(this, 'pageshow', this.aboutUri.spec); + } } + // In the content process we really only need to register the about: handler. + if(isContent) { return; } + + // we set the add-on status in the API webpage from within the add-on itself + Messenger.loadInAll('utils/api'); + + // always add the about pane to the preferences dialog, it should be the last category in the list + this.register('utils/about', { paneAbout: 'utils/about' }); + + Browsers.callOnAll(aWindow => { this.initWindow(aWindow); }, this.chromeUri); + Browsers.register(this, 'pageshow', this.chromeUri); + // if we're in a dev version, ignore all this if(AddonData.version.includes('a') || AddonData.version.includes('b')) { return; } @@ -128,6 +144,16 @@ this.PrefPanes = { }, uninit: function() { + if(this.aboutUri) { + if(isChrome) { + Messenger.unloadFromAll('utils/PrefPanes'); + Browsers.unregister(this, 'pageshow', this.aboutUri.spec); + } + this.aboutUri.unload(); + } + + if(isContent) { return; } + Messenger.unloadFromAll('utils/api'); this.closeAll(); @@ -136,11 +162,6 @@ this.PrefPanes = { Styles.unload('PrefPanesXulFix'); Browsers.unregister(this, 'pageshow', this.chromeUri); - - if(this.aboutUri) { - Browsers.unregister(this, 'pageshow', this.aboutUri.spec); - this.aboutUri.unload(); - } }, // we have to wait for Session Store to finish, otherwise our tab will be overriden by a session-restored tab @@ -298,12 +319,15 @@ this.PrefPanes = { }; Modules.LOADMODULE = function() { - Prefs.setDefaults({ - lastPrefPane: '', - lastVersionNotify: '0', - showTabOnUpdates: true, - userNoticedTabOnUpdates: false - }); + if(isChrome) { + // Initialize some pref dependencies. + Prefs.setDefaults({ + lastPrefPane: '', + lastVersionNotify: '0', + showTabOnUpdates: true, + userNoticedTabOnUpdates: false + }); + } PrefPanes.init(); }; diff --git a/resource/modules/utils/sandboxUtilsPreload.jsm b/resource/modules/utils/sandboxUtilsPreload.jsm index d70d715..3e420bc 100644 --- a/resource/modules/utils/sandboxUtilsPreload.jsm +++ b/resource/modules/utils/sandboxUtilsPreload.jsm @@ -1,4 +1,4 @@ -// VERSION 1.0.7 +// VERSION 1.0.8 // Prefs - Object to contain and manage all preferences related to the add-on (and others if necessary) this.__defineGetter__('Prefs', function() { delete this.Prefs; Modules.load('utils/Prefs'); return Prefs; }); @@ -42,9 +42,6 @@ this.toggleAttribute = function(obj, attr, condition, trueval, falseval) { loadA // trueAttribute() - checks if attr on obj has value 'true'; once again, I'm uber lazy this.trueAttribute = function(obj, attr) { loadAttributesTools(); return trueAttribute(obj, attr); }; -// innerText() - returns the equivalent of IE's .innerText property of node; essentially returns .textContent without the script tags -this.innerText = function(node) { loadHTMLElementsTools(); return innerText(node); }; - // Piggyback - This module allows me to Piggyback methods of any object. It also gives me access to the CustomizableUI module backstage pass, so I can do the same to it. if(this.isChrome) { this.__defineGetter__('Piggyback', function() { delete this.Piggyback; delete this.CustomizableUI; delete this.CUIBackstage; Modules.load('utils/Piggyback'); return Piggyback; }); @@ -75,9 +72,3 @@ this.loadAttributesTools = function() { delete this.loadAttributesTools; Modules.load('utils/attributes'); }; - -this.loadHTMLElementsTools = function() { - delete this.innerText; - delete this.loadHTMLElementsTools; - Modules.load('utils/HTMLElements'); -};