Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: lib/appIntegration.js

Issue 8433028: added hook function to appIntegration to handle function-overwrites from other extensions (Closed)
Patch Set: applied code review changes Created Sept. 28, 2012, 8:01 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « chrome/content/tests/tests/suffixTreeManipulation.js ('k') | lib/hooks.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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()
36 { 37 {
37 try 38 let correction = corrector(window, urlbar.value);
38 { 39 if (correction)
39 let correction = corrector(window, urlbar.value); 40 urlbar.value = correction;
40 if (correction) 41 });
41 urlbar.value = correction; 42 functionHooks.set(window, unhook);
42 }
43 catch(e)
44 {
45 if (e == Cr.NS_BINDING_ABORTED)
46 return;
47 else
48 Cu.reportError(e);
49 }
50 oldHandler.apply(this, arguments);
51 }
52 urlbar.handleCommand.urlfixerOldHandler = oldHandler;
53 urlbar.handleCommand.toString = doNotRecompile;
54 } 43 }
55 }; 44 };
56 45
57 exports.removeFromWindow = function(window)
58 {
59 let urlbar = exports.getURLBar(window);
60 if (urlbar && urlbar.handleCommand && "urlfixerOldHandler" in urlbar.handl eCommand)
61 urlbar.handleCommand = urlbar.handleCommand.urlfixerOldHandler;
62 };
63
64 exports.openInfobar = function(window, id, message, buttons, persistence) 46 exports.openInfobar = function(window, id, message, buttons, persistence)
65 { 47 {
66 let browser = exports.getBrowser(window); 48 let browser = exports.getBrowser(window);
67 let infobar = browser.getNotificationBox(); 49 let infobar = browser.getNotificationBox();
68 let notif = infobar.getNotificationWithValue(id); 50 let notif = infobar.getNotificationWithValue(id);
69 51
70 if (notif) 52 if (notif)
71 { 53 {
72 infobar.removeNotification(notif); 54 infobar.removeNotification(notif);
73 } 55 }
74 56
75 notif = infobar.appendNotification( 57 notif = infobar.appendNotification(
76 message, 58 message,
77 id, 59 id,
78 require("info").addonRoot + "icon64.png", 60 require("info").addonRoot + "icon64.png",
79 infobar.PRIORITY_INFO_HIGH, 61 infobar.PRIORITY_INFO_HIGH,
80 buttons 62 buttons
81 ); 63 );
82 notif.persistence = persistence; 64 notif.persistence = persistence;
83 }; 65 };
84 66
85 exports.loadURI = function(uri) 67 exports.loadURI = function(window, uri)
86 { 68 {
87 exports.getBrowser(Services.wm.getMostRecentWindow("navigator:browser")).l oadURI(uri); 69 exports.getBrowser(window).loadURI(uri);
88 }; 70 };
89 71
90 break; 72 break;
91 } 73 }
92 case "seamonkey": 74 case "seamonkey":
93 { 75 {
76 let eventListeners = new WeakMap();
77
94 // SeaMonkey 78 // SeaMonkey
95 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";
96 80
97 exports.getURLBar = function(window) "gURLBar" in window ? window.gURLBar : null; 81 exports.getURLBar = function(window) "gURLBar" in window ? window.gURLBar : null;
98 82
99 exports.getBrowser = function(window) "gBrowser" in window ? window.gBrowser : null; 83 exports.getBrowser = function(window) "gBrowser" in window ? window.gBrowser : null;
100 84
101 exports.applyToWindow = function(window, corrector) 85 exports.applyToWindow = function(window, corrector)
102 { 86 {
103 let urlbar = exports.getURLBar(window); 87 let urlbar = exports.getURLBar(window);
104 if (urlbar && window.handleURLBarCommand && !("urlfixerOldHandler" in wind ow.handleURLBarCommand)) 88 let goButton = window.document.getElementById("go-button-container");
89
90 if (urlbar && urlbar._fireEvent && !functionHooks.has(window))
105 { 91 {
106 // Handle new URLs being entered 92 function correctURL()
107 let oldHandler = window.handleURLBarCommand;
108 window.handleURLBarCommand = function()
109 { 93 {
110 try 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")
111 { 102 {
112 let correction = corrector(window, urlbar.value); 103 correctURL();
113 if (correction)
114 urlbar.value = correction;
115 } 104 }
116 catch(e) 105 });
117 { 106 functionHooks.set(window, unhook);
118 if (e == Cr.NS_BINDING_ABORTED) 107
119 return; 108 if (goButton)
120 else 109 {
121 Cu.reportError(e); 110 goButton.addEventListener("command", correctURL, true);
122 } 111 eventListeners.set(window, {
123 oldHandler.apply(this, arguments); 112 "listener": correctURL,
113 "element": goButton
114 });
124 } 115 }
125 window.handleURLBarCommand.urlfixerOldHandler = oldHandler;
126 window.handleURLBarCommand.toString = doNotRecompile;
127 } 116 }
128 }; 117 };
129 118
119 let basicRemove = exports.removeFromWindow;
130 exports.removeFromWindow = function(window) 120 exports.removeFromWindow = function(window)
131 { 121 {
132 if (window.handleURLBarCommand && "urlfixerOldHandler" in window.handleURL BarCommand) 122 basicRemove(window);
133 window.handleURLBarCommand = window.handleURLBarCommand.urlfixerOldHandl er; 123
124 if (eventListeners.has(window))
125 {
126 let eventListener = eventListeners.get(window);
127 eventListener.element.removeEventListener("command", eventListener.liste ner, true);
Wladimir Palant 2012/09/28 09:35:19 Taking over comment from previous review: eventLi
128 }
134 }; 129 };
135 130
136 exports.openInfobar = function(window, id, message, buttons, persistence) 131 exports.openInfobar = function(window, id, message, buttons, persistence)
137 { 132 {
138 let browser = exports.getBrowser(window); 133 let browser = exports.getBrowser(window);
139 let infobar = browser.getNotificationBox(); 134 let infobar = browser.getNotificationBox();
140 let notif = infobar.getNotificationWithValue(id); 135 let notif = infobar.getNotificationWithValue(id);
141 136
142 if (notif) 137 if (notif)
143 { 138 {
144 infobar.removeNotification(notif); 139 infobar.removeNotification(notif);
145 } 140 }
146 141
147 notif = infobar.appendNotification( 142 notif = infobar.appendNotification(
148 message, 143 message,
149 id, 144 id,
150 require("info").addonRoot + "icon64.png", 145 require("info").addonRoot + "icon64.png",
151 infobar.PRIORITY_INFO_HIGH, 146 infobar.PRIORITY_INFO_HIGH,
152 buttons 147 buttons
153 ); 148 );
154 notif.persistence = persistence; 149 notif.persistence = persistence;
155 }; 150 };
156 151
157 exports.loadURI = function(uri) 152 exports.loadURI = function(window, uri)
158 { 153 {
159 exports.getBrowser(Services.wm.getMostRecentWindow("navigator:browser")).l oadURI(uri); 154 exports.getBrowser(window).loadURI(uri);
160 }; 155 };
161 156
162 break; 157 break;
163 } 158 }
164 case "fennec": 159 case "fennec":
165 { 160 {
166 // XUL Fennec 161 // XUL Fennec
167 exports.isKnownWindow = function(window) window.document.documentElement.get Attribute("windowtype") == "navigator:browser"; 162 exports.isKnownWindow = function(window) window.document.documentElement.get Attribute("windowtype") == "navigator:browser";
168 163
169 exports.getURLBar = function(window) null; 164 exports.getURLBar = function(window) null;
170 165
171 exports.getBrowser = function(window) null; 166 exports.getBrowser = function(window) null;
172 167
173 exports.applyToWindow = function(window, corrector) 168 exports.applyToWindow = function(window, corrector)
174 { 169 {
175 if ("BrowserUI" in window && window.BrowserUI.goToURI && !("urlfixerOldHan dler" in window.BrowserUI.goToURI)) 170 if ("BrowserUI" in window && window.BrowserUI.goToURI && !functionHooks.ha s(window))
176 { 171 {
177 // Handle new URLs being entered 172 // Handle new URLs being entered
178 let oldHandler = window.BrowserUI.goToURI; 173 let unhook = hook(window.BrowserUI, "goToURI", function(url)
179 window.BrowserUI.goToURI = function(url)
180 { 174 {
181 url = url || this._edit.value; 175 url = url || this._edit.value;
182 try 176
183 { 177 let correction = corrector(window, url);
184 let correction = corrector(window, url); 178 if (correction)
185 if (correction) 179 url = correction;
186 url = correction; 180
187 } 181 return [url];
188 catch(e) 182 });
189 { 183 functionHooks.set(window, unhook);
190 if (e == Cr.NS_BINDING_ABORTED)
191 return;
192 else
193 Cu.reportError(e);
194 }
195 oldHandler.call(this, url);
196 }
197 window.BrowserUI.goToURI.urlfixerOldHandler = oldHandler;
198 window.BrowserUI.goToURI.toString = doNotRecompile;
199 } 184 }
200 }; 185 };
201 186
202 exports.removeFromWindow = function(window) 187 exports.openInfobar = function(window, id, message, buttons, persistence)
203 { 188 {
204 if ("BrowserUI" in window && window.BrowserUI.goToURI && "urlfixerOldHandl er" in window.BrowserUI.goToURI) 189 if ("getNotificationBox" in window)
205 window.BrowserUI.goToURI = window.BrowserUI.goToURI.urlfixerOldHandler; 190 {
191 let infobar = window.getNotificationBox();
192 let notification = infobar.getNotificationWithValue(id);
193
194 if (notification)
195 {
196 infobar.removeNotification(notification);
197 }
198
199 notification = infobar.appendNotification(
200 message,
201 id,
202 require("info").addonRoot + "icon64.png",
203 infobar.PRIORITY_INFO_HIGH,
204 buttons
205 );
206 notification.persistence = persistence;
207 }
206 }; 208 };
207 209
208 exports.openInfobar = function()
209 {
210 // TODO: Implement infobar
211 };
212
213 exports.loadURI = function(window, uri) 210 exports.loadURI = function(window, uri)
214 { 211 {
215 // TODO: Implement infobar 212 if ("BrowserUI" in window && "goToURI" in window.BrowserUI)
213 {
214 window.BrowserUI.goToURI(uri);
215 }
216 }; 216 };
217 217
218 break; 218 break;
219 } 219 }
220 case "fennec2": 220 case "fennec2":
221 { 221 {
222 // Native Fennec 222 // Native Fennec
223 exports.isKnownWindow = function(window) window.document.documentElement.get Attribute("windowtype") == "navigator:browser"; 223 exports.isKnownWindow = function(window) window.document.documentElement.get Attribute("windowtype") == "navigator:browser";
224 224
225 exports.getURLBar = function(window) null; 225 exports.getURLBar = function(window) null;
226 226
227 exports.getBrowser = function(window) null; 227 exports.getBrowser = function(window) null;
228 228
229 exports.applyToWindow = function(window, corrector) 229 exports.applyToWindow = function(window, corrector)
230 { 230 {
231 if ("BrowserApp" in window && window.BrowserApp.observe && !("urlfixerOldH andler" in window.BrowserApp.observe)) 231 if ("BrowserApp" in window && window.BrowserApp.observe && !functionHooks. has(window))
232 { 232 {
233 let oldHandler = window.BrowserApp.observe; 233 let innerUnhook = null;
234 let oldFunc = null; 234 function cleanup()
235 let handler = function()
236 { 235 {
237 let params = Array.prototype.slice.apply(arguments); 236 if (innerUnhook)
238 try 237 innerUnhook();
239 {
240 let correction = corrector(window, params[0]);
241 if (correction)
242 params[0] = correction;
243 }
244 catch(e)
245 {
246 if (e == Cr.NS_BINDING_ABORTED)
247 return null;
248 else
249 Cu.reportError(e);
250 }
251 return oldFunc.apply(this, params);
252 };
253 238
254 window.BrowserApp.observe = function(subject, topic, data) 239 innerUnhook = null;
240 }
241
242 let unhook = hook(window.BrowserApp, "observe", function(subject, topic, data)
255 { 243 {
256 // Huge hack: we replace addTab/loadURI when the observer is 244 // Huge hack: we replace addTab/loadURI when the observer is
257 // triggered. This seems to be the only way to know that the calls 245 // triggered. This seems to be the only way to know that the calls
258 // originate from user input. 246 // originate from user input.
259 let method = null; 247 let method = null;
260 if (topic == "Tab:Add") 248 if (topic == "Tab:Add")
261 method = "addTab"; 249 method = "addTab";
262 else if (topic == "Tab:Load") 250 else if (topic == "Tab:Load")
263 method = "loadURI"; 251 method = "loadURI";
264 252
265 if (method) 253 if (method)
266 { 254 {
267 oldFunc = this[method]; 255 innerUnhook = hook(this, method, function()
268 this[method] = handler; 256 {
257 let params = Array.prototype.slice.apply(arguments);
258 let correction = corrector(window, params[0]);
259 if (correction)
260 params[0] = correction;
261 return params;
262 });
269 } 263 }
270 264 }, cleanup);
271 try 265 functionHooks.set(window, unhook);
272 {
273 oldHandler.apply(this, arguments);
274 }
275 finally
276 {
277 if (method)
278 this[method] = oldFunc;
279 }
280 };
281 window.BrowserApp.observe.urlfixerOldHandler = oldHandler;
282 window.BrowserApp.observe.toString = doNotRecompile;
283 } 266 }
284 }; 267 };
285 268
286 exports.removeFromWindow = function(window)
287 {
288 if ("BrowserApp" in window && window.BrowserApp.observe && "urlfixerOldHan dler" in window.BrowserApp.observe)
289 window.BrowserApp.observe = window.BrowserApp.observe.urlfixerOldHandler ;
290 };
291
292 exports.openInfobar = function(window, id, message, buttons, persistence) 269 exports.openInfobar = function(window, id, message, buttons, persistence)
293 { 270 {
294 if ("BrowserApp" in window && "selectedTab" in window.BrowserApp) 271 if ("BrowserApp" in window && "selectedTab" in window.BrowserApp)
295 { 272 {
296 window.NativeWindow.doorhanger.show(message, id, buttons, window.Browser App.selectedTab.id, 273 window.NativeWindow.doorhanger.show(message, id, buttons, window.Browser App.selectedTab.id,
297 { 274 {
298 persistence: persistence 275 persistence: persistence
299 } 276 }
300 ); 277 );
301 } 278 }
302 }; 279 };
303 280
304 exports.loadURI = function(uri) 281 exports.loadURI = function(window, uri)
305 { 282 {
306 let window = Services.wm.getMostRecentWindow("navigator:browser");
307 if ("BrowserApp" in window && "loadURI" in window.BrowserApp) 283 if ("BrowserApp" in window && "loadURI" in window.BrowserApp)
308 window.BrowserApp.loadURI(uri); 284 window.BrowserApp.loadURI(uri);
309 }; 285 };
310 286
311 break; 287 break;
312 } 288 }
313 default: 289 default:
314 { 290 {
315 exports.isKnownWindow = function(window) false; 291 exports.isKnownWindow = function(window) false;
316 break; 292 break;
317 } 293 }
318 } 294 }
OLDNEW
« no previous file with comments | « chrome/content/tests/tests/suffixTreeManipulation.js ('k') | lib/hooks.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld