 Issue 8433028:
  added hook function to appIntegration to handle function-overwrites from other extensions  (Closed)
    
  
    Issue 8433028:
  added hook function to appIntegration to handle function-overwrites from other extensions  (Closed) 
  | Index: lib/appIntegration.js | 
| =================================================================== | 
| --- a/lib/appIntegration.js | 
| +++ b/lib/appIntegration.js | 
| @@ -2,17 +2,8 @@ | 
| * License, v. 2.0. If a copy of the MPL was not distributed with this file, | 
| * You can obtain one at http://mozilla.org/MPL/2.0/. */ | 
| -// Extensions like Tab Mix Plus will try to recompile our handlers and fail | 
| -// badly - they manage to replace our handler but the recompiled version | 
| -// won't work because the closure is missing its variables. We replace | 
| -// toString() function to prevent this kind of recompiling on earlier stages | 
| -// (produce a syntax error but still leave the source code viewable). | 
| -function doNotRecompile() | 
| -{ | 
| - let result = Function.prototype.toString.apply(this); | 
| - return result + "\n$%&!/DO_NOT_RECOMPILE" | 
| -} | 
| - | 
| +let functionHooks = new WeakMap(); | 
| +let {hook} = require("hooks"); | 
| let {application} = require("info"); | 
| switch (application) | 
| { | 
| @@ -28,50 +19,39 @@ | 
| exports.applyToWindow = function(window, corrector) | 
| { | 
| let urlbar = exports.getURLBar(window); | 
| - if (urlbar && urlbar.handleCommand && !("urlfixerOldHandler" in urlbar.handleCommand)) | 
| + if (urlbar && urlbar.handleCommand && !functionHooks.has(window)) | 
| { | 
| // Handle new URLs being entered | 
| - let oldHandler = urlbar.handleCommand; | 
| - urlbar.handleCommand = function() | 
| - { | 
| - try | 
| - { | 
| - let correction = corrector(window, urlbar.value); | 
| - if (correction) | 
| - urlbar.value = correction; | 
| - } | 
| - catch(e) | 
| - { | 
| - if (e == Cr.NS_BINDING_ABORTED) | 
| - return; | 
| - else | 
| - Cu.reportError(e); | 
| - } | 
| - oldHandler.apply(this, arguments); | 
| - } | 
| - urlbar.handleCommand.urlfixerOldHandler = oldHandler; | 
| - urlbar.handleCommand.toString = doNotRecompile; | 
| + let unhook = hook(urlbar, "handleCommand", function() { | 
| + let correction = corrector(window, urlbar.value); | 
| + if (correction) | 
| + urlbar.value = correction; | 
| + }); | 
| + functionHooks.set(window, unhook); | 
| } | 
| }; | 
| exports.removeFromWindow = function(window) | 
| { | 
| - let urlbar = exports.getURLBar(window); | 
| - if (urlbar && urlbar.handleCommand && "urlfixerOldHandler" in urlbar.handleCommand) | 
| - urlbar.handleCommand = urlbar.handleCommand.urlfixerOldHandler; | 
| + if (functionHooks.has(window)) | 
| + { | 
| + let unhook = functionHooks.get(window); | 
| + unhook(); | 
| + functionHooks.delete(window); | 
| + } | 
| }; | 
| - | 
| + | 
| exports.openInfobar = function(window, id, message, buttons, persistence) | 
| { | 
| let browser = exports.getBrowser(window); | 
| let infobar = browser.getNotificationBox(); | 
| let notif = infobar.getNotificationWithValue(id); | 
| - | 
| + | 
| if (notif) | 
| { | 
| infobar.removeNotification(notif); | 
| } | 
| - | 
| + | 
| notif = infobar.appendNotification( | 
| message, | 
| id, | 
| @@ -81,7 +61,7 @@ | 
| ); | 
| notif.persistence = persistence; | 
| }; | 
| - | 
| + | 
| exports.loadURI = function(uri) | 
| { | 
| exports.getBrowser(Services.wm.getMostRecentWindow("navigator:browser")).loadURI(uri); | 
| @@ -91,6 +71,8 @@ | 
| } | 
| case "seamonkey": | 
| { | 
| + let eventListeners = new WeakMap(); | 
| + | 
| // SeaMonkey | 
| exports.isKnownWindow = function(window) window.document.documentElement.getAttribute("windowtype") == "navigator:browser"; | 
| @@ -101,49 +83,63 @@ | 
| exports.applyToWindow = function(window, corrector) | 
| { | 
| let urlbar = exports.getURLBar(window); | 
| - if (urlbar && window.handleURLBarCommand && !("urlfixerOldHandler" in window.handleURLBarCommand)) | 
| + let goButton = window.document.getElementById("go-button-container"); | 
| + | 
| + if (urlbar && urlbar._fireEvent && !functionHooks.has(window)) | 
| { | 
| - // Handle new URLs being entered | 
| - let oldHandler = window.handleURLBarCommand; | 
| - window.handleURLBarCommand = function() | 
| + function correctURL() | 
| { | 
| - try | 
| + let correction = corrector(window, urlbar.value); | 
| + if (correction) | 
| + urlbar.value = correction; | 
| + } | 
| + | 
| + let unhook = hook(urlbar, "_fireEvent", function(eventType) { | 
| 
Wladimir Palant
2012/09/27 14:36:01
This bracket should be on next line.
 | 
| + if (eventType == "textentered") | 
| { | 
| - let correction = corrector(window, urlbar.value); | 
| - if (correction) | 
| - urlbar.value = correction; | 
| + correctURL(); | 
| } | 
| - catch(e) | 
| - { | 
| - if (e == Cr.NS_BINDING_ABORTED) | 
| - return; | 
| - else | 
| - Cu.reportError(e); | 
| - } | 
| - oldHandler.apply(this, arguments); | 
| + }); | 
| + functionHooks.set(window, unhook); | 
| + | 
| + if (goButton) | 
| + { | 
| + goButton.addEventListener("command", correctURL, true); | 
| + eventListeners.set(window, { | 
| + "listener": correctURL, | 
| + "element": goButton | 
| + }); | 
| } | 
| - window.handleURLBarCommand.urlfixerOldHandler = oldHandler; | 
| - window.handleURLBarCommand.toString = doNotRecompile; | 
| } | 
| }; | 
| exports.removeFromWindow = function(window) | 
| { | 
| - if (window.handleURLBarCommand && "urlfixerOldHandler" in window.handleURLBarCommand) | 
| - window.handleURLBarCommand = window.handleURLBarCommand.urlfixerOldHandler; | 
| + if (functionHooks.has(window)) | 
| + { | 
| + let unhook = functionHooks.get(window); | 
| + unhook(); | 
| + functionHooks.delete(window); | 
| + } | 
| + | 
| + if (eventListeners.has(window)) | 
| + { | 
| + let eventListener = eventListeners.get(window); | 
| + eventListener.element.removeEventListener("command", eventListener.listener, true); | 
| 
Wladimir Palant
2012/09/27 14:36:01
eventListeners.delete(window)?
 | 
| + } | 
| }; | 
| - | 
| + | 
| exports.openInfobar = function(window, id, message, buttons, persistence) | 
| { | 
| let browser = exports.getBrowser(window); | 
| let infobar = browser.getNotificationBox(); | 
| let notif = infobar.getNotificationWithValue(id); | 
| - | 
| + | 
| if (notif) | 
| { | 
| infobar.removeNotification(notif); | 
| } | 
| - | 
| + | 
| notif = infobar.appendNotification( | 
| message, | 
| id, | 
| @@ -153,7 +149,7 @@ | 
| ); | 
| notif.persistence = persistence; | 
| }; | 
| - | 
| + | 
| exports.loadURI = function(uri) | 
| { | 
| exports.getBrowser(Services.wm.getMostRecentWindow("navigator:browser")).loadURI(uri); | 
| @@ -187,10 +183,7 @@ | 
| } | 
| catch(e) | 
| { | 
| - if (e == Cr.NS_BINDING_ABORTED) | 
| - return; | 
| - else | 
| - Cu.reportError(e); | 
| + Cu.reportError(e); | 
| } | 
| oldHandler.call(this, url); | 
| } | 
| @@ -204,12 +197,12 @@ | 
| if ("BrowserUI" in window && window.BrowserUI.goToURI && "urlfixerOldHandler" in window.BrowserUI.goToURI) | 
| window.BrowserUI.goToURI = window.BrowserUI.goToURI.urlfixerOldHandler; | 
| }; | 
| - | 
| + | 
| exports.openInfobar = function() | 
| { | 
| // TODO: Implement infobar | 
| }; | 
| - | 
| + | 
| exports.loadURI = function(window, uri) | 
| { | 
| // TODO: Implement infobar | 
| @@ -243,10 +236,7 @@ | 
| } | 
| catch(e) | 
| { | 
| - if (e == Cr.NS_BINDING_ABORTED) | 
| - return null; | 
| - else | 
| - Cu.reportError(e); | 
| + Cu.reportError(e); | 
| } | 
| return oldFunc.apply(this, params); | 
| }; | 
| @@ -288,7 +278,7 @@ | 
| if ("BrowserApp" in window && window.BrowserApp.observe && "urlfixerOldHandler" in window.BrowserApp.observe) | 
| window.BrowserApp.observe = window.BrowserApp.observe.urlfixerOldHandler; | 
| }; | 
| - | 
| + | 
| exports.openInfobar = function(window, id, message, buttons, persistence) | 
| { | 
| if ("BrowserApp" in window && "selectedTab" in window.BrowserApp) | 
| @@ -300,7 +290,7 @@ | 
| ); | 
| } | 
| }; | 
| - | 
| + | 
| exports.loadURI = function(uri) | 
| { | 
| let window = Services.wm.getMostRecentWindow("navigator:browser"); |