Mercurial > nightly_tester_tools
comparison chrome/content/leaks/leaks.js @ 2:472a16863ecc
expanded nightly.jar
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Tue, 02 Dec 2008 20:38:20 +0900 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
1:93e46514f20d | 2:472a16863ecc |
---|---|
1 var handlers = { | |
2 "DOMWINDOW": { | |
3 count: 0, | |
4 leaked: 0, | |
5 windows: {}, | |
6 handle_line: function(addr,verb,rest,para) { | |
7 if (verb == "created") { | |
8 if (rest.substring(1,6)!="outer") | |
9 throw "outer expected"; | |
10 var out = rest.substring(7); | |
11 this.windows[addr] = { outer: out, paras: [], uris: [] }; | |
12 ++this.count; | |
13 ++this.leaked; | |
14 if (para) | |
15 this.windows[addr].paras.push(para); | |
16 } else if (verb == "destroyed") { | |
17 delete this.windows[addr]; | |
18 --this.leaked; | |
19 } else if (verb == "SetNewDocument") { | |
20 var uri = rest.substring(1); | |
21 this.windows[addr].uris[uri] = true; | |
22 if (para) | |
23 this.windows[addr].paras.push(para); | |
24 } | |
25 }, | |
26 mark_leaks: function(addr) | |
27 { | |
28 for (var i=0; i<this.windows[addr].paras.length; i++) { | |
29 this.windows[addr].paras[i].className+=" leaked"; | |
30 } | |
31 }, | |
32 clear: function() | |
33 { | |
34 this.count=0; | |
35 this.leaked=0; | |
36 this.windows={}; | |
37 } | |
38 }, | |
39 "DOCUMENT": { | |
40 count: 0, | |
41 leaked: 0, | |
42 docs: {}, | |
43 handle_line: function(addr,verb,rest,para) { | |
44 if (verb == "created") { | |
45 this.docs[addr] = { paras: [], uris: [] }; | |
46 ++this.count; | |
47 ++this.leaked; | |
48 if (para) | |
49 this.docs[addr].paras.push(para); | |
50 } else if (verb == "destroyed") { | |
51 delete this.docs[addr]; | |
52 --this.leaked; | |
53 } else if (verb == "ResetToURI" || | |
54 verb == "StartDocumentLoad") { | |
55 var uri = rest.substring(1); | |
56 this.docs[addr].uris[uri] = true; | |
57 if (para) | |
58 this.docs[addr].paras.push(para); | |
59 } | |
60 }, | |
61 mark_leaks: function(addr) | |
62 { | |
63 for (var i=0; i<this.docs[addr].paras.length; i++) { | |
64 var para = this.docs[addr].paras[i].className+=" leaked"; | |
65 } | |
66 }, | |
67 clear: function() | |
68 { | |
69 this.count=0; | |
70 this.leaked=0; | |
71 this.docs={}; | |
72 } | |
73 }, | |
74 "DOCSHELL": { | |
75 count: 0, | |
76 leaked: 0, | |
77 shells: {}, | |
78 handle_line: function(addr,verb,rest,para) { | |
79 if (verb == "created") { | |
80 this.shells[addr] = { paras: [], uris: [] }; | |
81 ++this.count; | |
82 ++this.leaked; | |
83 if (para) | |
84 this.shells[addr].paras.push(para); | |
85 } else if (verb == "destroyed") { | |
86 delete this.shells[addr]; | |
87 --this.leaked; | |
88 } else if (verb == "InternalLoad" || | |
89 verb == "SetCurrentURI") { | |
90 var uri = rest.substring(1); | |
91 this.shells[addr].uris[uri] = true; | |
92 if (para) | |
93 this.shells[addr].paras.push(para); | |
94 } | |
95 }, | |
96 mark_leaks: function(addr) | |
97 { | |
98 for (var i=0; i<this.shells[addr].paras.length; i++) { | |
99 var para = this.shells[addr].paras[i].className+=" leaked"; | |
100 } | |
101 }, | |
102 clear: function() | |
103 { | |
104 this.count=0; | |
105 this.leaked=0; | |
106 this.shells={}; | |
107 } | |
108 }, | |
109 clear: function() | |
110 { | |
111 this["DOMWINDOW"].clear(); | |
112 this["DOCUMENT"].clear(); | |
113 this["DOCSHELL"].clear(); | |
114 } | |
115 }; | |
116 | |
117 function doParse(storelog) | |
118 { | |
119 handlers.clear(); | |
120 | |
121 var fulllog = document.getElementById("logframe").contentDocument.body; | |
122 var datelbl = document.getElementById("date"); | |
123 var date = new Date(nsprlog.lastModifiedTime); | |
124 datelbl.value=bundle.getFormattedString("nightly.leaks.sessiondate.label", [date.toLocaleString()]); | |
125 | |
126 var is = Components.classes["@mozilla.org/network/file-input-stream;1"] | |
127 .createInstance(Components.interfaces.nsIFileInputStream); | |
128 const PR_RDONLY = 0x01; | |
129 is.init(nsprlog, PR_RDONLY, 0, 0); | |
130 if (!(is instanceof Components.interfaces.nsILineInputStream)) | |
131 return; | |
132 var line = { value: "" }; | |
133 var lines=0; | |
134 var para = null; | |
135 do | |
136 { | |
137 lines++; | |
138 var more = is.readLine(line); // yuck, returns false for last valid line | |
139 | |
140 var className=""; | |
141 if (storelog) | |
142 { | |
143 para = fulllog.ownerDocument.createElementNS("http://www.w3.org/1999/xhtml","p"); | |
144 fulllog.appendChild(para); | |
145 para.appendChild(fulllog.ownerDocument.createTextNode(line.value)); | |
146 className="logline"; | |
147 } | |
148 | |
149 // strip off initial "-", thread id, and thread pointer; separate | |
150 // first word and rest | |
151 var matches = line.value.match(/^\-?[0-9]*\[[0-9a-f]*\]: (\S*) ([0-9a-f]*) (\S*)(.*)$/); | |
152 if (matches) { | |
153 var handler = matches[1]; | |
154 var address = matches[2]; | |
155 var verb = matches[3]; | |
156 className+=" "+handler+" "+address; | |
157 var data = matches[4]; | |
158 if (typeof(handlers[handler]) != "undefined") { | |
159 handlers[handler].handle_line(address,verb,data,para); | |
160 } | |
161 else | |
162 { | |
163 | |
164 className+=" ignored"; | |
165 } | |
166 } | |
167 else | |
168 { | |
169 className+=" ignored"; | |
170 } | |
171 if (storelog) | |
172 para.className=className; | |
173 } while (more); | |
174 | |
175 var details = document.getElementById("details"); | |
176 var leaked=false; | |
177 | |
178 var lbl = document.getElementById("windowLeaks"); | |
179 var handler = handlers["DOMWINDOW"]; | |
180 lbl.value=bundle.getFormattedString("nightly.leaks.windowleaks.label", [handler.leaked, handler.count]); | |
181 if (handler.leaked>0) | |
182 { | |
183 lbl.className="leaked"; | |
184 leaked=true; | |
185 } | |
186 else | |
187 { | |
188 lbl.className=""; | |
189 } | |
190 for (var addr in handler.windows) | |
191 { | |
192 handler.mark_leaks(addr); | |
193 var winobj = handler.windows[addr]; | |
194 lbl = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul","label"); | |
195 details.appendChild(lbl); | |
196 if (winobj.outer=="0") | |
197 { | |
198 lbl.value=bundle.getFormattedString("nightly.leaks.innerleak.text", [addr, winobj.outer, addr]); | |
199 } | |
200 else | |
201 { | |
202 lbl.value=bundle.getFormattedString("nightly.leaks.outerleak.text", [addr, addr]); | |
203 } | |
204 for (var uri in winobj.uris) | |
205 { | |
206 lbl = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul","label"); | |
207 details.appendChild(lbl); | |
208 lbl.value=bundle.getFormattedString("nightly.leaks.urileak.text", [uri]); | |
209 lbl.className="uri"; | |
210 } | |
211 } | |
212 | |
213 lbl = document.getElementById("documentLeaks"); | |
214 handler = handlers["DOCUMENT"]; | |
215 lbl.value=bundle.getFormattedString("nightly.leaks.documentleaks.label", [handler.leaked, handler.count]); | |
216 if (handler.leaked>0) | |
217 { | |
218 lbl.className="leaked"; | |
219 leaked=true; | |
220 } | |
221 else | |
222 { | |
223 lbl.className=""; | |
224 } | |
225 for (var addr in handler.docs) | |
226 { | |
227 handler.mark_leaks(addr); | |
228 var doc = handler.docs[addr]; | |
229 lbl = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul","label"); | |
230 details.appendChild(lbl); | |
231 lbl.value=bundle.getFormattedString("nightly.leaks.documentleak.text", [addr]); | |
232 for (var uri in doc.uris) | |
233 { | |
234 lbl = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul","label"); | |
235 details.appendChild(lbl); | |
236 lbl.value=bundle.getFormattedString("nightly.leaks.urileak.text", [uri]); | |
237 lbl.className="uri"; | |
238 } | |
239 } | |
240 | |
241 lbl = document.getElementById("docshellLeaks"); | |
242 handler = handlers["DOCSHELL"]; | |
243 lbl.value=bundle.getFormattedString("nightly.leaks.docshellleaks.label", [handler.leaked, handler.count]); | |
244 if (handler.leaked>0) | |
245 { | |
246 lbl.className="leaked"; | |
247 leaked=true; | |
248 } | |
249 else | |
250 { | |
251 lbl.className=""; | |
252 } | |
253 for (var addr in handler.shells) | |
254 { | |
255 handler.mark_leaks(addr); | |
256 var doc = handler.shells[addr]; | |
257 lbl = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul","label"); | |
258 details.appendChild(lbl); | |
259 lbl.value=bundle.getFormattedString("nightly.leaks.docshellleak.text", [addr]); | |
260 for (var uri in doc.uris) | |
261 { | |
262 lbl = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul","label"); | |
263 details.appendChild(lbl); | |
264 lbl.value=bundle.getFormattedString("nightly.leaks.urileak.text", [uri]); | |
265 lbl.className="uri"; | |
266 } | |
267 } | |
268 | |
269 document.getElementById("detailsbox").collapsed=!leaked; | |
270 } | |
271 // -------------------------------------------------------------------- | |
272 | |
273 var nsprlog = null; | |
274 var preferences = null; | |
275 | |
276 var summaryText = ""; | |
277 var detailsText = ""; | |
278 var logValid = false; | |
279 var bundle = null; | |
280 | |
281 function frameLoaded(event) | |
282 { | |
283 var chk = document.getElementById("showlog"); | |
284 | |
285 var frame = document.getElementById("logframe"); | |
286 if (frame.getAttribute("src")=="") | |
287 return; | |
288 | |
289 changeFilter(); | |
290 | |
291 var details = document.getElementById("details"); | |
292 while (details.firstChild) | |
293 { | |
294 details.removeChild(details.firstChild); | |
295 } | |
296 | |
297 doParse(chk.checked); | |
298 | |
299 logValid=chk.checked; | |
300 | |
301 document.getElementById("summary").collapsed=false; | |
302 document.getElementById("btnSave").disabled=false; | |
303 document.getElementById("btnCopy").disabled=false; | |
304 document.getElementById("nsprlog").disabled=false; | |
305 document.getElementById("filebrowse").disabled=false; | |
306 document.getElementById("showlog").disabled=false; | |
307 document.getElementById("tabbox").collapsed=false; | |
308 } | |
309 | |
310 function parseLog() | |
311 { | |
312 document.getElementById("nsprlog").disabled=true; | |
313 document.getElementById("filebrowse").disabled=true; | |
314 document.getElementById("showlog").disabled=false; | |
315 document.getElementById("tabbox").collapsed=true; | |
316 var frame = document.getElementById("logframe"); | |
317 frame.setAttribute("src", "") | |
318 window.setTimeout(function() { frame.setAttribute("src", "leaks.html") }, 100); | |
319 } | |
320 | |
321 function init(event) | |
322 { | |
323 window.removeEventListener("load", init, false); | |
324 | |
325 bundle = document.getElementById("bundle"); | |
326 | |
327 var prefservice = Components.classes['@mozilla.org/preferences-service;1'] | |
328 .getService(Components.interfaces.nsIPrefService); | |
329 preferences = prefservice.getBranch("nightly.leaks."); | |
330 | |
331 var buildid = document.getElementById("buildid"); | |
332 var appinfo = Components.classes['@mozilla.org/xre/app-info;1'].getService(Components.interfaces.nsIXULAppInfo); | |
333 buildid.value=navigator.userAgent+" ID:"+appinfo.appBuildID; | |
334 | |
335 var frame = document.getElementById("logframe"); | |
336 frame.addEventListener("load", frameLoaded, true); | |
337 | |
338 var chk = document.getElementById("showlog"); | |
339 chk.checked = preferences.getBoolPref("showleaklog"); | |
340 document.getElementById("tabbox").firstChild.style.display=(chk.checked ? null : 'none'); | |
341 | |
342 chk = document.getElementById("filterDocshell"); | |
343 chk.checked = preferences.getBoolPref("filterDocshell"); | |
344 | |
345 chk = document.getElementById("filterWindow"); | |
346 chk.checked = preferences.getBoolPref("filterWindow"); | |
347 | |
348 chk = document.getElementById("filterDocument"); | |
349 chk.checked = preferences.getBoolPref("filterDocument"); | |
350 | |
351 chk = document.getElementById("filterLeaked"); | |
352 chk.checked = preferences.getBoolPref("filterLeaked"); | |
353 | |
354 chk = document.getElementById("filterCollected"); | |
355 chk.checked = preferences.getBoolPref("filterCollected"); | |
356 | |
357 chk = document.getElementById("filterIgnored"); | |
358 chk.checked = preferences.getBoolPref("filterIgnored"); | |
359 | |
360 try | |
361 { | |
362 nsprlog = preferences.getComplexValue("nsprlog", Components.interfaces.nsILocalFile); | |
363 } | |
364 catch (e) { } | |
365 | |
366 if (nsprlog && nsprlog.exists()) | |
367 { | |
368 var logtext = document.getElementById("nsprlog"); | |
369 logtext.value=nsprlog.path; | |
370 parseLog(); | |
371 } | |
372 } | |
373 | |
374 function flipLog() | |
375 { | |
376 var chk = document.getElementById("showlog"); | |
377 preferences.setBoolPref("showleaklog", chk.checked); | |
378 document.getElementById("tabbox").firstChild.style.display=(chk.checked ? null : 'none'); | |
379 | |
380 if (!chk.checked) | |
381 { | |
382 document.getElementById("tabbox").selectedIndex=0; | |
383 } | |
384 | |
385 if (chk.checked && !logValid && nsprlog && nsprlog.exists()) | |
386 { | |
387 parseLog(); | |
388 } | |
389 } | |
390 | |
391 function changeFilter() | |
392 { | |
393 var style = document.getElementById("logframe").contentDocument.getElementById("filters"); | |
394 var filter = ""; | |
395 | |
396 var chk = document.getElementById("filterDocshell"); | |
397 if (!chk.checked) | |
398 filter+=".logline.DOCSHELL { display: none }\n"; | |
399 preferences.setBoolPref("filterDocshell", chk.checked); | |
400 | |
401 chk = document.getElementById("filterWindow"); | |
402 if (!chk.checked) | |
403 filter+=".logline.DOMWINDOW { display: none }\n"; | |
404 preferences.setBoolPref("filterWindow", chk.checked); | |
405 | |
406 chk = document.getElementById("filterDocument"); | |
407 if (!chk.checked) | |
408 filter+=".logline.DOCUMENT { display: none }\n"; | |
409 preferences.setBoolPref("filterDocument", chk.checked); | |
410 | |
411 chk = document.getElementById("filterLeaked"); | |
412 if (!chk.checked) | |
413 filter+=".leaked { display: none }\n"; | |
414 preferences.setBoolPref("filterLeaked", chk.checked); | |
415 | |
416 chk = document.getElementById("filterCollected"); | |
417 if (!chk.checked) | |
418 filter+=".logline:not(.leaked) { display: none }\n"; | |
419 preferences.setBoolPref("filterCollected", chk.checked); | |
420 | |
421 chk = document.getElementById("filterIgnored"); | |
422 if (!chk.checked) | |
423 filter+=".logline.ignored { display: none }\n"; | |
424 preferences.setBoolPref("filterIgnored", chk.checked); | |
425 | |
426 style.innerHTML=filter; | |
427 } | |
428 | |
429 function pad(value) | |
430 { | |
431 if (value<10) | |
432 return "0"+value; | |
433 return ""+value; | |
434 } | |
435 | |
436 function getTextOverview() | |
437 { | |
438 var text=bundle.getString("nightly.leaks.summary.label")+nightlyplatform.eol+nightlyplatform.eol; | |
439 var appinfo = Components.classes['@mozilla.org/xre/app-info;1'].getService(Components.interfaces.nsIXULAppInfo); | |
440 text+=navigator.userAgent+" ID:"+appinfo.appBuildID+nightlyplatform.eol+nightlyplatform.eol; | |
441 var date = new Date(nsprlog.lastModifiedTime); | |
442 text+=bundle.getFormattedString("nightly.leaks.sessiondate.label", [date.toLocaleString()])+nightlyplatform.eol+nightlyplatform.eol; | |
443 | |
444 var leaked = false; | |
445 var handler = handlers["DOMWINDOW"]; | |
446 if (handler.leaked>0) | |
447 leaked=true; | |
448 text+=bundle.getFormattedString("nightly.leaks.windowleaks.label", [handler.leaked, handler.count])+nightlyplatform.eol; | |
449 handler = handlers["DOCUMENT"]; | |
450 if (handler.leaked>0) | |
451 leaked=true; | |
452 text+=bundle.getFormattedString("nightly.leaks.documentleaks.label", [handler.leaked, handler.count])+nightlyplatform.eol; | |
453 handler = handlers["DOCSHELL"]; | |
454 if (handler.leaked>0) | |
455 leaked=true; | |
456 text+=bundle.getFormattedString("nightly.leaks.docshellleaks.label", [handler.leaked, handler.count])+nightlyplatform.eol; | |
457 | |
458 if (leaked) | |
459 { | |
460 text+=nightlyplatform.eol+bundle.getString("nightly.leaks.details.label")+nightlyplatform.eol+nightlyplatform.eol; | |
461 handler = handlers["DOMWINDOW"]; | |
462 for (var addr in handler.windows) | |
463 { | |
464 var winobj = handler.windows[addr]; | |
465 if (winobj.outer=="0") | |
466 { | |
467 text+=bundle.getFormattedString("nightly.leaks.innerleak.text", [addr, winobj.outer, addr])+nightlyplatform.eol; | |
468 } | |
469 else | |
470 { | |
471 text+=bundle.getFormattedString("nightly.leaks.outerleak.text", [addr, addr])+nightlyplatform.eol; | |
472 } | |
473 for (var uri in winobj.uris) | |
474 { | |
475 text+=" ... "+bundle.getFormattedString("nightly.leaks.urileak.text", [uri])+nightlyplatform.eol; | |
476 } | |
477 } | |
478 | |
479 handler = handlers["DOCUMENT"]; | |
480 for (var addr in handler.docs) | |
481 { | |
482 var doc = handler.docs[addr]; | |
483 text += bundle.getFormattedString("nightly.leaks.documentleak.text", [addr])+nightlyplatform.eol; | |
484 for (var uri in doc.uris) | |
485 { | |
486 text+=" ... "+bundle.getFormattedString("nightly.leaks.urileak.text", [uri])+nightlyplatform.eol; | |
487 } | |
488 } | |
489 | |
490 handler = handlers["DOCSHELL"]; | |
491 for (var addr in handler.shells) | |
492 { | |
493 var doc = handler.shells[addr]; | |
494 text += bundle.getFormattedString("nightly.leaks.docshellleak.text", [addr])+nightlyplatform.eol; | |
495 for (var uri in doc.uris) | |
496 { | |
497 text+=" ... "+bundle.getFormattedString("nightly.leaks.urileak.text", [uri])+nightlyplatform.eol; | |
498 } | |
499 } | |
500 } | |
501 return text; | |
502 } | |
503 | |
504 function save() | |
505 { | |
506 var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(Components.interfaces.nsIFilePicker); | |
507 fp.init(window, bundle.getString("nightly.leaks.filepicker.title"), fp.modeSave); | |
508 fp.appendFilter(bundle.getString("nightly.leaks.filepicker.filterlog"), "*.log"); | |
509 fp.appendFilter(bundle.getString("nightly.leaks.filepicker.filterall"), "*.*"); | |
510 fp.displayDirectory=nsprlog.parent; | |
511 | |
512 var date = new Date(nsprlog.lastModifiedTime); | |
513 fp.defaultString=date.getFullYear()+pad(date.getMonth()+1)+pad(date.getDate())+"-"+pad(date.getHours())+pad(date.getMinutes())+"_leaklog.log"; | |
514 | |
515 var result = fp.show(); | |
516 if (result==fp.returnOK || result==fp.returnReplace) | |
517 { | |
518 var target=fp.file; | |
519 preferences.setComplexValue("leaksave", Components.interfaces.nsILocalFile, target); | |
520 | |
521 var text = getTextOverview(); | |
522 | |
523 // file is nsIFile, data is a string | |
524 var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"] | |
525 .createInstance(Components.interfaces.nsIFileOutputStream); | |
526 | |
527 // use 0x02 | 0x10 to open file for appending. | |
528 foStream.init(target, 0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate | |
529 var os = Components.classes["@mozilla.org/intl/converter-output-stream;1"] | |
530 .createInstance(Components.interfaces.nsIConverterOutputStream); | |
531 | |
532 os.init(foStream, "UTF-8", 0, 0x0000); | |
533 os.writeString(text); | |
534 os.close(); | |
535 foStream.close(); | |
536 } | |
537 } | |
538 | |
539 function clipboardCopy() | |
540 { | |
541 var clipboard = Components.classes["@mozilla.org/widget/clipboardhelper;1"]. | |
542 getService(Components.interfaces.nsIClipboardHelper); | |
543 clipboard.copyString(getTextOverview()); | |
544 } | |
545 | |
546 function textEnter() | |
547 { | |
548 var logtext = document.getElementById("nsprlog"); | |
549 var target = Components.classes["@mozilla.org/file/local;1"] | |
550 .createInstance(Components.interfaces.nsILocalFile); | |
551 target.initWithPath(logtext.value); | |
552 if (target.exists()) | |
553 { | |
554 nsprlog=target; | |
555 preferences.setComplexValue("nsprlog", Components.interfaces.nsILocalFile, nsprlog); | |
556 parseLog(); | |
557 } | |
558 else | |
559 { | |
560 var prompt = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] | |
561 .getService(Components.interfaces.nsIPromptService); | |
562 prompt.alert(window, "File Not Found", logtext.value+" does not exist."); | |
563 } | |
564 } | |
565 | |
566 function selectLog() | |
567 { | |
568 var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(Components.interfaces.nsIFilePicker); | |
569 fp.init(window, bundle.getString("nightly.leaks.filepicker.title"), fp.modeOpen); | |
570 fp.appendFilter(bundle.getString("nightly.leaks.filepicker.filterlog"), "*.log"); | |
571 fp.appendFilter(bundle.getString("nightly.leaks.filepicker.filterall"), "*.*"); | |
572 if (nsprlog) | |
573 fp.displayDirectory=nsprlog.parent; | |
574 | |
575 if (fp.show() == fp.returnOK) | |
576 { | |
577 nsprlog=fp.file; | |
578 preferences.setComplexValue("nsprlog", Components.interfaces.nsILocalFile, nsprlog); | |
579 var logtext = document.getElementById("nsprlog"); | |
580 logtext.value=nsprlog.path; | |
581 parseLog(); | |
582 } | |
583 } | |
584 | |
585 window.addEventListener("load", init, false); |