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);