| Left: | ||
| Right: |
| LEFT | RIGHT |
|---|---|
| 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 function hook(obj, name, func) | 5 let {hook} = require("hooks"); |
|
Wladimir Palant
2012/09/26 09:27:50
Any reason why you've put it here? I expected it t
| |
| 6 let functionHooks = new WeakMap(); | |
| 7 | |
| 8 exports.removeFromWindow = function(window) | |
| 6 { | 9 { |
| 7 var orig = obj[name]; | 10 if (functionHooks.has(window)) |
| 8 var origGet = obj.__lookupGetter__(name); | 11 { |
| 9 var origSet = obj.__lookupSetter__(name); | 12 let unhook = functionHooks.get(window); |
| 10 var dumbOverrideAttempt = false; | 13 unhook(); |
|
Wladimir Palant
2012/09/26 09:27:50
You should use let instead of var in Firefox code
| |
| 11 | 14 functionHooks.delete(window); |
| 12 var newFunc = function() | 15 } |
| 13 { | 16 }; |
| 14 try | 17 |
| 15 { | |
| 16 func.apply(this, arguments); | |
| 17 } | |
| 18 catch(e) | |
| 19 { | |
| 20 Cu.reportError(e); | |
| 21 } | |
| 22 orig.apply(this, arguments); | |
| 23 } | |
| 24 newFunc.toString = function() | |
| 25 { | |
| 26 dumbOverrideAttempt = true; | |
| 27 return orig.toString(); | |
| 28 } | |
| 29 | |
| 30 obj.__defineGetter__(name, function() | |
| 31 { | |
| 32 dumbOverrideAttempt = false; | |
| 33 return newFunc; | |
| 34 } | |
| 35 ); | |
| 36 | |
| 37 obj.__defineSetter__(name, function(value) | |
| 38 { | |
| 39 if (dumbOverrideAttempt) | |
| 40 { | |
| 41 orig = value; | |
| 42 } | |
| 43 else | |
| 44 { | |
| 45 delete obj[name]; | |
| 46 obj[name] = value; | |
| 47 } | |
| 48 } | |
| 49 ); | |
| 50 | |
| 51 return function() { | |
| 52 delete obj[name]; | |
| 53 obj[name] = orig; | |
| 54 if (origGet) { | |
| 55 obj.__defineGetter__(name, origGet); | |
| 56 } | |
| 57 if (origSet) { | |
| 58 obj.__defineSetter__(name, origSet); | |
| 59 } | |
| 60 } | |
|
Wladimir Palant
2012/09/26 09:27:50
Inconsistent style here (brackets) - plus there is
| |
| 61 } | |
| 62 | |
| 63 let wm = new WeakMap(); | |
| 64 let {Prefs} = require("prefs"); | |
|
Wladimir Palant
2012/09/26 09:27:50
I would be very worried if our generic app-support
| |
| 65 let {application} = require("info"); | 18 let {application} = require("info"); |
| 66 switch (application) | 19 switch (application) |
| 67 { | 20 { |
| 68 case "firefox": | 21 case "firefox": |
| 69 { | 22 { |
| 70 // Firefox | 23 // Firefox |
| 71 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"; |
| 72 | 25 |
| 73 exports.getURLBar = function(window) "gURLBar" in window ? window.gURLBar : null; | 26 exports.getURLBar = function(window) "gURLBar" in window ? window.gURLBar : null; |
| 74 | 27 |
| 75 exports.getBrowser = function(window) "gBrowser" in window ? window.gBrowser : null; | 28 exports.getBrowser = function(window) "gBrowser" in window ? window.gBrowser : null; |
| 76 | 29 |
| 77 exports.applyToWindow = function(window, corrector) | 30 exports.applyToWindow = function(window, corrector) |
| 78 { | 31 { |
| 79 let urlbar = exports.getURLBar(window); | 32 let urlbar = exports.getURLBar(window); |
| 80 if (urlbar && urlbar.handleCommand && !("urlfixerOldHandler" in urlbar.han dleCommand)) | 33 if (urlbar && urlbar.handleCommand && !functionHooks.has(window)) |
| 81 { | 34 { |
| 82 // Handle new URLs being entered | 35 // Handle new URLs being entered |
| 83 let hooks = []; | 36 let unhook = hook(urlbar, "handleCommand", function() |
|
Wladimir Palant
2012/09/26 09:27:50
From the look of it, we never hook more than one f
| |
| 84 if (wm.get(window)) | 37 { |
|
Wladimir Palant
2012/09/26 09:27:50
The window should definitely be unknown here - if
| |
| 85 { | 38 let correction = corrector(window, urlbar.value); |
| 86 hooks = wm.get(window); | 39 if (correction) |
| 87 } | 40 urlbar.value = correction; |
| 88 hooks.push(hook(urlbar, "handleCommand", function() | 41 }); |
| 89 { | 42 functionHooks.set(window, unhook); |
| 90 try | 43 } |
| 91 { | 44 }; |
| 92 let correction = corrector(window, urlbar.value); | 45 |
| 93 if (correction) | |
| 94 urlbar.value = correction; | |
| 95 } | |
| 96 catch(e) | |
| 97 { | |
| 98 Cu.reportError(e); | |
| 99 } | |
|
Wladimir Palant
2012/09/26 09:27:50
The try..catch block here is no longer necessary -
| |
| 100 } | |
| 101 )); | |
| 102 wm.set(window, hooks); | |
| 103 } | |
| 104 }; | |
| 105 | |
| 106 exports.removeFromWindow = function(window) | |
| 107 { | |
| 108 let urlbar = exports.getURLBar(window); | |
| 109 if (urlbar && urlbar.handleCommand && wm.has(window)) | |
| 110 { | |
| 111 let hooks = wm.get(window); | |
| 112 for (let i = 0, len = hooks.length; i < len; i++) | |
| 113 { | |
| 114 hooks[i](); | |
| 115 } | |
| 116 wm.delete(window); | |
| 117 } | |
| 118 }; | |
| 119 | |
| 120 exports.openInfobar = function(window, id, message, buttons, persistence) | 46 exports.openInfobar = function(window, id, message, buttons, persistence) |
| 121 { | 47 { |
| 122 let browser = exports.getBrowser(window); | 48 let browser = exports.getBrowser(window); |
| 123 let infobar = browser.getNotificationBox(); | 49 let infobar = browser.getNotificationBox(); |
| 124 let notif = infobar.getNotificationWithValue(id); | 50 let notif = infobar.getNotificationWithValue(id); |
| 125 | 51 |
| 126 if (notif) | 52 if (notif) |
| 127 { | 53 { |
| 128 infobar.removeNotification(notif); | 54 infobar.removeNotification(notif); |
| 129 } | 55 } |
| 130 | 56 |
| 131 notif = infobar.appendNotification( | 57 notif = infobar.appendNotification( |
| 132 message, | 58 message, |
| 133 id, | 59 id, |
| 134 require("info").addonRoot + "icon64.png", | 60 require("info").addonRoot + "icon64.png", |
| 135 infobar.PRIORITY_INFO_HIGH, | 61 infobar.PRIORITY_INFO_HIGH, |
| 136 buttons | 62 buttons |
| 137 ); | 63 ); |
| 138 notif.persistence = persistence; | 64 notif.persistence = persistence; |
| 139 }; | 65 }; |
| 140 | 66 |
| 141 exports.loadURI = function(uri) | 67 exports.loadURI = function(window, uri) |
| 142 { | 68 { |
| 143 exports.getBrowser(Services.wm.getMostRecentWindow("navigator:browser")).l oadURI(uri); | 69 exports.getBrowser(window).loadURI(uri); |
| 144 }; | 70 }; |
| 145 | 71 |
| 146 break; | 72 break; |
| 147 } | 73 } |
| 148 case "seamonkey": | 74 case "seamonkey": |
| 149 { | 75 { |
| 76 let eventListeners = new WeakMap(); | |
| 77 | |
| 150 // SeaMonkey | 78 // SeaMonkey |
| 151 exports.isKnownWindow = function(window) window.document.documentElement.get Attribute("windowtype") == "navigator:browser"; | 79 exports.isKnownWindow = function(window) window.document.documentElement.get Attribute("windowtype") == "navigator:browser"; |
| 152 | 80 |
| 153 exports.getURLBar = function(window) "gURLBar" in window ? window.gURLBar : null; | 81 exports.getURLBar = function(window) "gURLBar" in window ? window.gURLBar : null; |
| 154 | 82 |
| 155 exports.getBrowser = function(window) "gBrowser" in window ? window.gBrowser : null; | 83 exports.getBrowser = function(window) "gBrowser" in window ? window.gBrowser : null; |
| 156 | 84 |
| 157 exports.applyToWindow = function(window, corrector) | 85 exports.applyToWindow = function(window, corrector) |
| 158 { | 86 { |
| 159 let urlbar = exports.getURLBar(window); | 87 let urlbar = exports.getURLBar(window); |
| 160 if (urlbar && urlbar.handleCommand && !("urlfixerOldHandler" in urlbar.han dleCommand)) | 88 let goButton = window.document.getElementById("go-button-container"); |
|
Wladimir Palant
2012/09/26 09:27:50
Replacing SeaMonkey code by Firefox-specific code
| |
| 161 { | 89 |
| 162 // Handle new URLs being entered | 90 if (urlbar && urlbar._fireEvent && !functionHooks.has(window)) |
| 163 let hooks = []; | 91 { |
| 164 if (wm.get(window)) | 92 function correctURL() |
| 165 { | 93 { |
| 166 hooks = wm.get(window); | 94 let correction = corrector(window, urlbar.value); |
| 167 } | 95 if (correction) |
| 168 hooks.push(hook(urlbar, "handleCommand", function() | 96 urlbar.value = correction; |
| 97 } | |
| 98 | |
| 99 let unhook = hook(urlbar, "_fireEvent", function(eventType) | |
| 100 { | |
| 101 if (eventType == "textentered") | |
| 169 { | 102 { |
| 170 try | 103 correctURL(); |
| 171 { | |
| 172 let correction = corrector(window, urlbar.value); | |
| 173 if (correction) | |
| 174 urlbar.value = correction; | |
| 175 } | |
| 176 catch(e) | |
| 177 { | |
| 178 Cu.reportError(e); | |
| 179 } | |
| 180 oldHandler.apply(this, arguments); | |
| 181 } | 104 } |
| 182 )); | 105 }); |
| 183 wm.set(window, hooks); | 106 functionHooks.set(window, unhook); |
| 184 } | 107 |
| 185 }; | 108 if (goButton) |
| 186 | 109 { |
|
Wladimir Palant
2012/09/26 09:27:50
I suggest the following setting for the Sublime Te
| |
| 110 goButton.addEventListener("command", correctURL, true); | |
| 111 eventListeners.set(window, { | |
| 112 "listener": correctURL, | |
| 113 "element": goButton | |
| 114 }); | |
| 115 } | |
| 116 } | |
| 117 }; | |
| 118 | |
| 119 let basicRemove = exports.removeFromWindow; | |
| 187 exports.removeFromWindow = function(window) | 120 exports.removeFromWindow = function(window) |
| 188 { | 121 { |
| 189 let urlbar = exports.getURLBar(window); | 122 basicRemove(window); |
| 190 if (urlbar && urlbar.handleCommand && wm.has(window)) | 123 |
| 191 { | 124 if (eventListeners.has(window)) |
| 192 let hooks = wm.get(window); | 125 { |
| 193 for (let i = 0, len = hooks.length; i < len; i++) | 126 let eventListener = eventListeners.get(window); |
| 194 { | 127 eventListener.element.removeEventListener("command", eventListener.liste ner, true); |
| 195 hooks[i](); | 128 eventListeners.delete(window); |
| 196 } | 129 } |
| 197 wm.delete(window); | 130 }; |
| 198 } | 131 |
| 199 }; | |
| 200 | |
| 201 exports.openInfobar = function(window, id, message, buttons, persistence) | 132 exports.openInfobar = function(window, id, message, buttons, persistence) |
| 202 { | 133 { |
| 203 let browser = exports.getBrowser(window); | 134 let browser = exports.getBrowser(window); |
| 204 let infobar = browser.getNotificationBox(); | 135 let infobar = browser.getNotificationBox(); |
| 205 let notif = infobar.getNotificationWithValue(id); | 136 let notif = infobar.getNotificationWithValue(id); |
| 206 | 137 |
| 207 if (notif) | 138 if (notif) |
| 208 { | 139 { |
| 209 infobar.removeNotification(notif); | 140 infobar.removeNotification(notif); |
| 210 } | 141 } |
| 211 | 142 |
| 212 notif = infobar.appendNotification( | 143 notif = infobar.appendNotification( |
| 213 message, | 144 message, |
| 214 id, | 145 id, |
| 215 require("info").addonRoot + "icon64.png", | 146 require("info").addonRoot + "icon64.png", |
| 216 infobar.PRIORITY_INFO_HIGH, | 147 infobar.PRIORITY_INFO_HIGH, |
| 217 buttons | 148 buttons |
| 218 ); | 149 ); |
| 219 notif.persistence = persistence; | 150 notif.persistence = persistence; |
| 220 }; | 151 }; |
| 221 | 152 |
| 222 exports.loadURI = function(uri) | 153 exports.loadURI = function(window, uri) |
| 223 { | 154 { |
| 224 exports.getBrowser(Services.wm.getMostRecentWindow("navigator:browser")).l oadURI(uri); | 155 exports.getBrowser(window).loadURI(uri); |
| 225 }; | 156 }; |
| 226 | 157 |
| 227 break; | 158 break; |
| 228 } | 159 } |
| 229 case "fennec": | 160 case "fennec": |
| 230 { | 161 { |
| 231 // XUL Fennec | 162 // XUL Fennec |
| 232 exports.isKnownWindow = function(window) window.document.documentElement.get Attribute("windowtype") == "navigator:browser"; | 163 exports.isKnownWindow = function(window) window.document.documentElement.get Attribute("windowtype") == "navigator:browser"; |
| 233 | 164 |
| 234 exports.getURLBar = function(window) null; | 165 exports.getURLBar = function(window) null; |
| 235 | 166 |
| 236 exports.getBrowser = function(window) null; | 167 exports.getBrowser = function(window) null; |
| 237 | 168 |
| 238 exports.applyToWindow = function(window, corrector) | 169 exports.applyToWindow = function(window, corrector) |
| 239 { | 170 { |
| 240 if ("BrowserUI" in window && window.BrowserUI.goToURI && !("urlfixerOldHan dler" in window.BrowserUI.goToURI)) | 171 if ("BrowserUI" in window && window.BrowserUI.goToURI && !functionHooks.ha s(window)) |
| 241 { | 172 { |
| 242 // Handle new URLs being entered | 173 // Handle new URLs being entered |
| 243 let oldHandler = window.BrowserUI.goToURI; | 174 let unhook = hook(window.BrowserUI, "goToURI", function(url) |
| 244 window.BrowserUI.goToURI = function(url) | |
| 245 { | 175 { |
| 246 url = url || this._edit.value; | 176 url = url || this._edit.value; |
| 247 try | 177 |
| 248 { | 178 let correction = corrector(window, url); |
| 249 let correction = corrector(window, url); | 179 if (correction) |
| 250 if (correction) | 180 url = correction; |
| 251 url = correction; | 181 |
| 252 } | 182 return [url]; |
| 253 catch(e) | 183 }); |
| 254 { | 184 functionHooks.set(window, unhook); |
| 255 Cu.reportError(e); | 185 } |
| 256 } | 186 }; |
| 257 oldHandler.call(this, url); | 187 |
| 258 } | 188 exports.openInfobar = function(window, id, message, buttons, persistence) |
| 259 window.BrowserUI.goToURI.urlfixerOldHandler = oldHandler; | 189 { |
| 260 window.BrowserUI.goToURI.toString = doNotRecompile; | 190 if ("getNotificationBox" in window) |
| 261 } | 191 { |
| 262 }; | 192 let infobar = window.getNotificationBox(); |
| 263 | 193 let notification = infobar.getNotificationWithValue(id); |
| 264 exports.removeFromWindow = function(window) | 194 |
| 265 { | 195 if (notification) |
| 266 if ("BrowserUI" in window && window.BrowserUI.goToURI && "urlfixerOldHandl er" in window.BrowserUI.goToURI) | 196 { |
| 267 window.BrowserUI.goToURI = window.BrowserUI.goToURI.urlfixerOldHandler; | 197 infobar.removeNotification(notification); |
| 268 }; | 198 } |
| 269 | 199 |
| 270 exports.openInfobar = function() | 200 notification = infobar.appendNotification( |
| 271 { | 201 message, |
| 272 // TODO: Implement infobar | 202 id, |
| 273 }; | 203 require("info").addonRoot + "icon64.png", |
| 274 | 204 infobar.PRIORITY_INFO_HIGH, |
| 275 exports.loadURI = function(window, uri) | 205 buttons |
| 276 { | 206 ); |
| 277 // TODO: Implement infobar | 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 } | |
| 278 }; | 217 }; |
| 279 | 218 |
| 280 break; | 219 break; |
| 281 } | 220 } |
| 282 case "fennec2": | 221 case "fennec2": |
| 283 { | 222 { |
| 284 // Native Fennec | 223 // Native Fennec |
| 285 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"; |
| 286 | 225 |
| 287 exports.getURLBar = function(window) null; | 226 exports.getURLBar = function(window) null; |
| 288 | 227 |
| 289 exports.getBrowser = function(window) null; | 228 exports.getBrowser = function(window) null; |
| 290 | 229 |
| 291 exports.applyToWindow = function(window, corrector) | 230 exports.applyToWindow = function(window, corrector) |
| 292 { | 231 { |
| 293 if ("BrowserApp" in window && window.BrowserApp.observe && !("urlfixerOldH andler" in window.BrowserApp.observe)) | 232 if ("BrowserApp" in window && window.BrowserApp.observe && !functionHooks. has(window)) |
| 294 { | 233 { |
| 295 let oldHandler = window.BrowserApp.observe; | 234 let innerUnhook = null; |
| 296 let oldFunc = null; | 235 function cleanup() |
| 297 let handler = function() | 236 { |
| 298 { | 237 if (innerUnhook) |
| 299 let params = Array.prototype.slice.apply(arguments); | 238 innerUnhook(); |
| 300 try | 239 |
| 301 { | 240 innerUnhook = null; |
| 302 let correction = corrector(window, params[0]); | 241 } |
| 303 if (correction) | 242 |
| 304 params[0] = correction; | 243 let unhook = hook(window.BrowserApp, "observe", function(subject, topic, data) |
| 305 } | |
| 306 catch(e) | |
| 307 { | |
| 308 Cu.reportError(e); | |
| 309 } | |
| 310 return oldFunc.apply(this, params); | |
| 311 }; | |
| 312 | |
| 313 window.BrowserApp.observe = function(subject, topic, data) | |
| 314 { | 244 { |
| 315 // Huge hack: we replace addTab/loadURI when the observer is | 245 // Huge hack: we replace addTab/loadURI when the observer is |
| 316 // 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 |
| 317 // originate from user input. | 247 // originate from user input. |
| 318 let method = null; | 248 let method = null; |
| 319 if (topic == "Tab:Add") | 249 if (topic == "Tab:Add") |
| 320 method = "addTab"; | 250 method = "addTab"; |
| 321 else if (topic == "Tab:Load") | 251 else if (topic == "Tab:Load") |
| 322 method = "loadURI"; | 252 method = "loadURI"; |
| 323 | 253 |
| 324 if (method) | 254 if (method) |
| 325 { | 255 { |
| 326 oldFunc = this[method]; | 256 innerUnhook = hook(this, method, function() |
| 327 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 }); | |
| 328 } | 264 } |
| 329 | 265 }, cleanup); |
| 330 try | 266 functionHooks.set(window, unhook); |
| 331 { | 267 } |
| 332 oldHandler.apply(this, arguments); | 268 }; |
| 333 } | 269 |
| 334 finally | |
| 335 { | |
| 336 if (method) | |
| 337 this[method] = oldFunc; | |
| 338 } | |
| 339 }; | |
| 340 window.BrowserApp.observe.urlfixerOldHandler = oldHandler; | |
| 341 window.BrowserApp.observe.toString = doNotRecompile; | |
| 342 } | |
| 343 }; | |
| 344 | |
| 345 exports.removeFromWindow = function(window) | |
| 346 { | |
| 347 if ("BrowserApp" in window && window.BrowserApp.observe && "urlfixerOldHan dler" in window.BrowserApp.observe) | |
| 348 window.BrowserApp.observe = window.BrowserApp.observe.urlfixerOldHandler ; | |
| 349 }; | |
| 350 | |
| 351 exports.openInfobar = function(window, id, message, buttons, persistence) | 270 exports.openInfobar = function(window, id, message, buttons, persistence) |
| 352 { | 271 { |
| 353 if ("BrowserApp" in window && "selectedTab" in window.BrowserApp) | 272 if ("BrowserApp" in window && "selectedTab" in window.BrowserApp) |
| 354 { | 273 { |
| 355 window.NativeWindow.doorhanger.show(message, id, buttons, window.Browser App.selectedTab.id, | 274 window.NativeWindow.doorhanger.show(message, id, buttons, window.Browser App.selectedTab.id, |
| 356 { | 275 { |
| 357 persistence: persistence | 276 persistence: persistence |
| 358 } | 277 } |
| 359 ); | 278 ); |
| 360 } | 279 } |
| 361 }; | 280 }; |
| 362 | 281 |
| 363 exports.loadURI = function(uri) | 282 exports.loadURI = function(window, uri) |
| 364 { | 283 { |
| 365 let window = Services.wm.getMostRecentWindow("navigator:browser"); | |
| 366 if ("BrowserApp" in window && "loadURI" in window.BrowserApp) | 284 if ("BrowserApp" in window && "loadURI" in window.BrowserApp) |
| 367 window.BrowserApp.loadURI(uri); | 285 window.BrowserApp.loadURI(uri); |
| 368 }; | 286 }; |
| 369 | 287 |
| 370 break; | 288 break; |
| 371 } | 289 } |
| 372 default: | 290 default: |
| 373 { | 291 { |
| 374 exports.isKnownWindow = function(window) false; | 292 exports.isKnownWindow = function(window) false; |
| 375 break; | 293 break; |
| 376 } | 294 } |
| 377 } | 295 } |
| LEFT | RIGHT |