| LEFT | RIGHT | 
| (no file at all) |  | 
|    1 /* This Source Code Form is subject to the terms of the Mozilla Public |    1 /* This Source Code Form is subject to the terms of the Mozilla Public | 
|    2  * License, v. 2.0. If a copy of the MPL was not distributed with this file, |    2  * License, v. 2.0. If a copy of the MPL was not distributed with this file, | 
|    3  * You can obtain one at http://mozilla.org/MPL/2.0/. */ |    3  * You can obtain one at http://mozilla.org/MPL/2.0/. */ | 
|    4  |    4  | 
|    5 // Extensions like Tab Mix Plus will try to recompile our handlers and fail |    5 let {hook} = require("hooks"); | 
|    6 // badly - they manage to replace our handler but the recompiled version |    6 let functionHooks = new WeakMap(); | 
|    7 // won't work because the closure is missing its variables. We replace |    7  | 
|    8 // toString() function to prevent this kind of recompiling on earlier stages |    8 exports.removeFromWindow = function(window) | 
|    9 // (produce a syntax error but still leave the source code viewable). |  | 
|   10 function doNotRecompile() |  | 
|   11 { |    9 { | 
|   12   let result = Function.prototype.toString.apply(this); |   10   if (functionHooks.has(window)) | 
|   13   return result + "\n$%&!/DO_NOT_RECOMPILE" |   11   { | 
|   14 } |   12     let unhook = functionHooks.get(window); | 
 |   13     unhook(); | 
 |   14     functionHooks.delete(window); | 
 |   15   } | 
 |   16 }; | 
|   15  |   17  | 
|   16 let {application} = require("info"); |   18 let {application} = require("info"); | 
|   17 switch (application) |   19 switch (application) | 
|   18 { |   20 { | 
|   19   case "firefox": |   21   case "firefox": | 
|   20   { |   22   { | 
|   21     // Firefox |   23     // Firefox | 
|   22     exports.isKnownWindow = function(window) window.document.documentElement.get
     Attribute("windowtype") == "navigator:browser"; |   24     exports.isKnownWindow = function(window) window.document.documentElement.get
     Attribute("windowtype") == "navigator:browser"; | 
|   23  |   25  | 
|   24     exports.getURLBar = function(window) "gURLBar" in window ? window.gURLBar : 
     null; |   26     exports.getURLBar = function(window) "gURLBar" in window ? window.gURLBar : 
     null; | 
|   25  |   27  | 
|   26     exports.getBrowser = function(window) "gBrowser" in window ? window.gBrowser
      : null; |   28     exports.getBrowser = function(window) "gBrowser" in window ? window.gBrowser
      : null; | 
|   27  |   29  | 
|   28     exports.applyToWindow = function(window, corrector) |   30     exports.applyToWindow = function(window, corrector) | 
|   29     { |   31     { | 
|   30       let urlbar = exports.getURLBar(window); |   32       let urlbar = exports.getURLBar(window); | 
|   31       if (urlbar && urlbar.handleCommand && !("urlfixerOldHandler" in urlbar.han
     dleCommand)) |   33       if (urlbar && urlbar.handleCommand && !functionHooks.has(window)) | 
|   32       { |   34       { | 
|   33         // Handle new URLs being entered |   35         // Handle new URLs being entered | 
|   34         let oldHandler = urlbar.handleCommand; |   36         let unhook = hook(urlbar, "handleCommand", function() | 
|   35         urlbar.handleCommand = function() |   37         { | 
|   36         { |   38           let correction = corrector(window, urlbar.value); | 
|   37           try |   39           if (correction) | 
 |   40             urlbar.value = correction; | 
 |   41         }); | 
 |   42         functionHooks.set(window, unhook); | 
 |   43       } | 
 |   44     }; | 
 |   45  | 
 |   46     exports.openInfobar = function(window, id, message, buttons, persistence) | 
 |   47     { | 
 |   48       let browser = exports.getBrowser(window); | 
 |   49       let infobar = browser.getNotificationBox(); | 
 |   50       let notification = infobar.getNotificationWithValue(id); | 
 |   51  | 
 |   52       if (notification) | 
 |   53       { | 
 |   54         infobar.removeNotification(notification); | 
 |   55       } | 
 |   56  | 
 |   57       notification = infobar.appendNotification( | 
 |   58         message, | 
 |   59         id, | 
 |   60         require("info").addonRoot + "icon64.png", | 
 |   61         infobar.PRIORITY_INFO_HIGH, | 
 |   62         buttons | 
 |   63       ); | 
 |   64       notification.persistence = persistence; | 
 |   65     }; | 
 |   66  | 
 |   67     exports.loadURI = function(window, uri) | 
 |   68     { | 
 |   69       exports.getBrowser(window).loadURI(uri); | 
 |   70     }; | 
 |   71  | 
 |   72     break; | 
 |   73   } | 
 |   74   case "seamonkey": | 
 |   75   { | 
 |   76     let eventListeners = new WeakMap(); | 
 |   77  | 
 |   78     // SeaMonkey | 
 |   79     exports.isKnownWindow = function(window) window.document.documentElement.get
     Attribute("windowtype") == "navigator:browser"; | 
 |   80  | 
 |   81     exports.getURLBar = function(window) "gURLBar" in window ? window.gURLBar : 
     null; | 
 |   82  | 
 |   83     exports.getBrowser = function(window) "gBrowser" in window ? window.gBrowser
      : null; | 
 |   84  | 
 |   85     exports.applyToWindow = function(window, corrector) | 
 |   86     { | 
 |   87       let urlbar = exports.getURLBar(window); | 
 |   88       let goButton = window.document.getElementById("go-button-container"); | 
 |   89  | 
 |   90       if (urlbar && urlbar._fireEvent && !functionHooks.has(window)) | 
 |   91       { | 
 |   92         function correctURL() | 
 |   93         { | 
 |   94           let correction = corrector(window, urlbar.value); | 
 |   95           if (correction) | 
 |   96             urlbar.value = correction; | 
 |   97         } | 
 |   98  | 
 |   99         let unhook = hook(urlbar, "_fireEvent", function(eventType) | 
 |  100         { | 
 |  101           if (eventType == "textentered") | 
|   38           { |  102           { | 
|   39             let correction = corrector(window, urlbar.value); |  103             correctURL(); | 
|   40             if (correction) |  | 
|   41               urlbar.value = correction; |  | 
|   42           } |  104           } | 
|   43           catch(e) |  105         }); | 
|   44           { |  106         functionHooks.set(window, unhook); | 
|   45             if (e == Cr.NS_BINDING_ABORTED) |  107  | 
|   46               return; |  108         if (goButton) | 
|   47             else |  109         { | 
|   48               Cu.reportError(e); |  110           goButton.addEventListener("command", correctURL, true); | 
|   49           } |  111           eventListeners.set(window, { | 
|   50           oldHandler.apply(this, arguments); |  112             "listener": correctURL, | 
|   51         } |  113             "element": goButton | 
|   52         urlbar.handleCommand.urlfixerOldHandler = oldHandler; |  114           }); | 
|   53         urlbar.handleCommand.toString = doNotRecompile; |  115         } | 
|   54       } |  116       } | 
|   55     }; |  117     }; | 
|   56  |  118  | 
 |  119     let basicRemove = exports.removeFromWindow; | 
|   57     exports.removeFromWindow = function(window) |  120     exports.removeFromWindow = function(window) | 
|   58     { |  121     { | 
|   59       let urlbar = exports.getURLBar(window); |  122       basicRemove(window); | 
|   60       if (urlbar && urlbar.handleCommand && "urlfixerOldHandler" in urlbar.handl
     eCommand) |  123  | 
|   61         urlbar.handleCommand = urlbar.handleCommand.urlfixerOldHandler; |  124       if (eventListeners.has(window)) | 
|   62     }; |  125       { | 
|   63  |  126         let eventListener = eventListeners.get(window); | 
|   64     break; |  127         eventListener.element.removeEventListener("command", eventListener.liste
     ner, true); | 
|   65   } |  128         eventListeners.delete(window); | 
|   66   case "seamonkey": |  129       } | 
|   67   { |  130     }; | 
|   68     // SeaMonkey |  131  | 
|   69     exports.isKnownWindow = function(window) window.document.documentElement.get
     Attribute("windowtype") == "navigator:browser"; |  132     exports.openInfobar = function(window, id, message, buttons, persistence) | 
|   70  |  133     { | 
|   71     exports.getURLBar = function(window) "gURLBar" in window ? window.gURLBar : 
     null; |  134       let browser = exports.getBrowser(window); | 
|   72  |  135       let infobar = browser.getNotificationBox(); | 
|   73     exports.getBrowser = function(window) "gBrowser" in window ? window.gBrowser
      : null; |  136       let notification = infobar.getNotificationWithValue(id); | 
|   74  |  137  | 
|   75     exports.applyToWindow = function(window, corrector) |  138       if (notification) | 
|   76     { |  139       { | 
|   77       let urlbar = exports.getURLBar(window); |  140         infobar.removeNotification(notification); | 
|   78       if (urlbar && window.handleURLBarCommand && !("urlfixerOldHandler" in wind
     ow.handleURLBarCommand)) |  141       } | 
 |  142  | 
 |  143       notification = infobar.appendNotification( | 
 |  144         message, | 
 |  145         id, | 
 |  146         require("info").addonRoot + "icon64.png", | 
 |  147         infobar.PRIORITY_INFO_HIGH, | 
 |  148         buttons | 
 |  149       ); | 
 |  150       notification.persistence = persistence; | 
 |  151     }; | 
 |  152  | 
 |  153     exports.loadURI = function(window, uri) | 
 |  154     { | 
 |  155       exports.getBrowser(window).loadURI(uri); | 
 |  156     }; | 
 |  157  | 
 |  158     break; | 
 |  159   } | 
 |  160   case "fennec": | 
 |  161   { | 
 |  162     // XUL Fennec | 
 |  163     exports.isKnownWindow = function(window) window.document.documentElement.get
     Attribute("windowtype") == "navigator:browser"; | 
 |  164  | 
 |  165     exports.getURLBar = function(window) null; | 
 |  166  | 
 |  167     exports.getBrowser = function(window) null; | 
 |  168  | 
 |  169     exports.applyToWindow = function(window, corrector) | 
 |  170     { | 
 |  171       if ("BrowserUI" in window && window.BrowserUI.goToURI && !functionHooks.ha
     s(window)) | 
|   79       { |  172       { | 
|   80         // Handle new URLs being entered |  173         // Handle new URLs being entered | 
|   81         let oldHandler = window.handleURLBarCommand; |  174         let unhook = hook(window.BrowserUI, "goToURI", function(url) | 
|   82         window.handleURLBarCommand = function() |  175         { | 
|   83         { |  176           url = url || this._edit.value; | 
|   84           try |  177  | 
|   85           { |  178           let correction = corrector(window, url); | 
|   86             let correction = corrector(window, urlbar.value); |  179           if (correction) | 
|   87             if (correction) |  180             url = correction; | 
|   88               urlbar.value = correction; |  181  | 
|   89           } |  182           return [url]; | 
|   90           catch(e) |  183         }); | 
|   91           { |  184         functionHooks.set(window, unhook); | 
|   92             if (e == Cr.NS_BINDING_ABORTED) |  185       } | 
|   93               return; |  186     }; | 
|   94             else |  187  | 
|   95               Cu.reportError(e); |  188     exports.openInfobar = function(window, id, message, buttons, persistence) | 
|   96           } |  189     { | 
|   97           oldHandler.apply(this, arguments); |  190       if ("getNotificationBox" in window) | 
|   98         } |  191       { | 
|   99         window.handleURLBarCommand.urlfixerOldHandler = oldHandler; |  192         let infobar = window.getNotificationBox(); | 
|  100         window.handleURLBarCommand.toString = doNotRecompile; |  193         let notification = infobar.getNotificationWithValue(id); | 
|  101       } |  194  | 
|  102     }; |  195         if (notification) | 
|  103  |  196         { | 
|  104     exports.removeFromWindow = function(window) |  197           infobar.removeNotification(notification); | 
|  105     { |  198         } | 
|  106       if (window.handleURLBarCommand && "urlfixerOldHandler" in window.handleURL
     BarCommand) |  199  | 
|  107         window.handleURLBarCommand = window.handleURLBarCommand.urlfixerOldHandl
     er; |  200         notification = infobar.appendNotification( | 
|  108     }; |  201           message, | 
|  109  |  202           id, | 
|  110     break; |  203           require("info").addonRoot + "icon64.png", | 
|  111   } |  204           infobar.PRIORITY_INFO_HIGH, | 
|  112   case "fennec": |  205           buttons | 
|  113   { |  206         ); | 
|  114     // XUL Fennec |  207         notification.persistence = persistence; | 
 |  208       } | 
 |  209     }; | 
 |  210  | 
 |  211     exports.loadURI = function(window, uri) | 
 |  212     { | 
 |  213       if ("BrowserUI" in window && "goToURI" in window.BrowserUI) | 
 |  214       { | 
 |  215         window.BrowserUI.goToURI(uri); | 
 |  216       } | 
 |  217     }; | 
 |  218  | 
 |  219     break; | 
 |  220   } | 
 |  221   case "fennec2": | 
 |  222   { | 
 |  223     // Native Fennec | 
|  115     exports.isKnownWindow = function(window) window.document.documentElement.get
     Attribute("windowtype") == "navigator:browser"; |  224     exports.isKnownWindow = function(window) window.document.documentElement.get
     Attribute("windowtype") == "navigator:browser"; | 
|  116  |  225  | 
|  117     exports.getURLBar = function(window) null; |  226     exports.getURLBar = function(window) null; | 
|  118  |  227  | 
|  119     exports.getBrowser = function(window) null; |  228     exports.getBrowser = function(window) null; | 
|  120  |  229  | 
|  121     exports.applyToWindow = function(window, corrector) |  230     exports.applyToWindow = function(window, corrector) | 
|  122     { |  231     { | 
|  123       if ("BrowserUI" in window && window.BrowserUI.goToURI && !("urlfixerOldHan
     dler" in window.BrowserUI.goToURI)) |  232       if ("BrowserApp" in window && window.BrowserApp.observe && !functionHooks.
     has(window)) | 
|  124       { |  233       { | 
|  125         // Handle new URLs being entered |  234         let innerUnhook = null; | 
|  126         let oldHandler = window.BrowserUI.goToURI; |  235         function cleanup() | 
|  127         window.BrowserUI.goToURI = function(url) |  236         { | 
|  128         { |  237           if (innerUnhook) | 
|  129           url = url || this._edit.value; |  238             innerUnhook(); | 
|  130           try |  239  | 
|  131           { |  240           innerUnhook = null; | 
|  132             let correction = corrector(window, url); |  241         } | 
|  133             if (correction) |  242  | 
|  134               url = correction; |  243         let unhook = hook(window.BrowserApp, "observe", function(subject, topic,
      data) | 
|  135           } |  | 
|  136           catch(e) |  | 
|  137           { |  | 
|  138             if (e == Cr.NS_BINDING_ABORTED) |  | 
|  139               return; |  | 
|  140             else |  | 
|  141               Cu.reportError(e); |  | 
|  142           } |  | 
|  143           oldHandler.call(this, url); |  | 
|  144         } |  | 
|  145         window.BrowserUI.goToURI.urlfixerOldHandler = oldHandler; |  | 
|  146         window.BrowserUI.goToURI.toString = doNotRecompile; |  | 
|  147       } |  | 
|  148     }; |  | 
|  149  |  | 
|  150     exports.removeFromWindow = function(window) |  | 
|  151     { |  | 
|  152       if ("BrowserUI" in window && window.BrowserUI.goToURI && "urlfixerOldHandl
     er" in window.BrowserUI.goToURI) |  | 
|  153         window.BrowserUI.goToURI = window.BrowserUI.goToURI.urlfixerOldHandler; |  | 
|  154     }; |  | 
|  155  |  | 
|  156     break; |  | 
|  157   } |  | 
|  158   case "fennec2": |  | 
|  159   { |  | 
|  160     // Native Fennec |  | 
|  161     exports.isKnownWindow = function(window) window.document.documentElement.get
     Attribute("windowtype") == "navigator:browser"; |  | 
|  162  |  | 
|  163     exports.getURLBar = function(window) null; |  | 
|  164  |  | 
|  165     exports.getBrowser = function(window) null; |  | 
|  166  |  | 
|  167     exports.applyToWindow = function(window, corrector) |  | 
|  168     { |  | 
|  169       if ("BrowserApp" in window && window.BrowserApp.observe && !("urlfixerOldH
     andler" in window.BrowserApp.observe)) |  | 
|  170       { |  | 
|  171         let oldHandler = window.BrowserApp.observe; |  | 
|  172         let oldFunc = null; |  | 
|  173         let handler = function() |  | 
|  174         { |  | 
|  175           let params = Array.prototype.slice.apply(arguments); |  | 
|  176           try |  | 
|  177           { |  | 
|  178             let correction = corrector(window, params[0]); |  | 
|  179             if (correction) |  | 
|  180               params[0] = correction; |  | 
|  181           } |  | 
|  182           catch(e) |  | 
|  183           { |  | 
|  184             if (e == Cr.NS_BINDING_ABORTED) |  | 
|  185               return null; |  | 
|  186             else |  | 
|  187               Cu.reportError(e); |  | 
|  188           } |  | 
|  189           return oldFunc.apply(this, params); |  | 
|  190         }; |  | 
|  191  |  | 
|  192         window.BrowserApp.observe = function(subject, topic, data) |  | 
|  193         { |  244         { | 
|  194           // Huge hack: we replace addTab/loadURI when the observer is |  245           // Huge hack: we replace addTab/loadURI when the observer is | 
|  195           // triggered. This seems to be the only way to know that the calls |  246           // triggered. This seems to be the only way to know that the calls | 
|  196           // originate from user input. |  247           // originate from user input. | 
|  197           let method = null; |  248           let method = null; | 
|  198           if (topic == "Tab:Add") |  249           if (topic == "Tab:Add") | 
|  199             method = "addTab"; |  250             method = "addTab"; | 
|  200           else if (topic == "Tab:Load") |  251           else if (topic == "Tab:Load") | 
|  201             method = "loadURI"; |  252             method = "loadURI"; | 
|  202  |  253  | 
|  203           if (method) |  254           if (method) | 
|  204           { |  255           { | 
|  205             oldFunc = this[method]; |  256             innerUnhook = hook(this, method, function() | 
|  206             this[method] = handler; |  257             { | 
 |  258               let params = Array.prototype.slice.apply(arguments); | 
 |  259               let correction = corrector(window, params[0]); | 
 |  260               if (correction) | 
 |  261                 params[0] = correction; | 
 |  262               return params; | 
 |  263             }); | 
|  207           } |  264           } | 
|  208  |  265         }, cleanup); | 
|  209           try |  266         functionHooks.set(window, unhook); | 
 |  267       } | 
 |  268     }; | 
 |  269  | 
 |  270     exports.openInfobar = function(window, id, message, buttons, persistence) | 
 |  271     { | 
 |  272       if ("BrowserApp" in window && "selectedTab" in window.BrowserApp) | 
 |  273       { | 
 |  274         window.NativeWindow.doorhanger.show(message, id, buttons, window.Browser
     App.selectedTab.id, | 
|  210           { |  275           { | 
|  211             oldHandler.apply(this, arguments); |  276             persistence: persistence | 
|  212           } |  277           } | 
|  213           finally |  278         ); | 
|  214           { |  279       } | 
|  215             if (method) |  280     }; | 
|  216               this[method] = oldFunc; |  281  | 
|  217           } |  282     exports.loadURI = function(window, uri) | 
|  218         }; |  283     { | 
|  219         window.BrowserApp.observe.urlfixerOldHandler = oldHandler; |  284       if ("BrowserApp" in window && "loadURI" in window.BrowserApp) | 
|  220         window.BrowserApp.observe.toString = doNotRecompile; |  285         window.BrowserApp.loadURI(uri); | 
|  221       } |  | 
|  222     }; |  | 
|  223  |  | 
|  224     exports.removeFromWindow = function(window) |  | 
|  225     { |  | 
|  226       if ("BrowserApp" in window && window.BrowserApp.observe && "urlfixerOldHan
     dler" in window.BrowserApp.observe) |  | 
|  227         window.BrowserApp.observe = window.BrowserApp.observe.urlfixerOldHandler
     ; |  | 
|  228     }; |  286     }; | 
|  229  |  287  | 
|  230     break; |  288     break; | 
|  231   } |  289   } | 
|  232   default: |  290   default: | 
|  233   { |  291   { | 
|  234     exports.isKnownWindow = function(window) false; |  292     exports.isKnownWindow = function(window) false; | 
|  235     break; |  293     break; | 
|  236   } |  294   } | 
|  237 } |  295 } | 
| LEFT | RIGHT |