Mercurial > nightly_tester_tools
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/leaks/leaks.js Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,585 @@ +var handlers = { + "DOMWINDOW": { + count: 0, + leaked: 0, + windows: {}, + handle_line: function(addr,verb,rest,para) { + if (verb == "created") { + if (rest.substring(1,6)!="outer") + throw "outer expected"; + var out = rest.substring(7); + this.windows[addr] = { outer: out, paras: [], uris: [] }; + ++this.count; + ++this.leaked; + if (para) + this.windows[addr].paras.push(para); + } else if (verb == "destroyed") { + delete this.windows[addr]; + --this.leaked; + } else if (verb == "SetNewDocument") { + var uri = rest.substring(1); + this.windows[addr].uris[uri] = true; + if (para) + this.windows[addr].paras.push(para); + } + }, + mark_leaks: function(addr) + { + for (var i=0; i<this.windows[addr].paras.length; i++) { + this.windows[addr].paras[i].className+=" leaked"; + } + }, + clear: function() + { + this.count=0; + this.leaked=0; + this.windows={}; + } + }, + "DOCUMENT": { + count: 0, + leaked: 0, + docs: {}, + handle_line: function(addr,verb,rest,para) { + if (verb == "created") { + this.docs[addr] = { paras: [], uris: [] }; + ++this.count; + ++this.leaked; + if (para) + this.docs[addr].paras.push(para); + } else if (verb == "destroyed") { + delete this.docs[addr]; + --this.leaked; + } else if (verb == "ResetToURI" || + verb == "StartDocumentLoad") { + var uri = rest.substring(1); + this.docs[addr].uris[uri] = true; + if (para) + this.docs[addr].paras.push(para); + } + }, + mark_leaks: function(addr) + { + for (var i=0; i<this.docs[addr].paras.length; i++) { + var para = this.docs[addr].paras[i].className+=" leaked"; + } + }, + clear: function() + { + this.count=0; + this.leaked=0; + this.docs={}; + } + }, + "DOCSHELL": { + count: 0, + leaked: 0, + shells: {}, + handle_line: function(addr,verb,rest,para) { + if (verb == "created") { + this.shells[addr] = { paras: [], uris: [] }; + ++this.count; + ++this.leaked; + if (para) + this.shells[addr].paras.push(para); + } else if (verb == "destroyed") { + delete this.shells[addr]; + --this.leaked; + } else if (verb == "InternalLoad" || + verb == "SetCurrentURI") { + var uri = rest.substring(1); + this.shells[addr].uris[uri] = true; + if (para) + this.shells[addr].paras.push(para); + } + }, + mark_leaks: function(addr) + { + for (var i=0; i<this.shells[addr].paras.length; i++) { + var para = this.shells[addr].paras[i].className+=" leaked"; + } + }, + clear: function() + { + this.count=0; + this.leaked=0; + this.shells={}; + } + }, + clear: function() + { + this["DOMWINDOW"].clear(); + this["DOCUMENT"].clear(); + this["DOCSHELL"].clear(); + } +}; + +function doParse(storelog) +{ + handlers.clear(); + + var fulllog = document.getElementById("logframe").contentDocument.body; + var datelbl = document.getElementById("date"); + var date = new Date(nsprlog.lastModifiedTime); + datelbl.value=bundle.getFormattedString("nightly.leaks.sessiondate.label", [date.toLocaleString()]); + + var is = Components.classes["@mozilla.org/network/file-input-stream;1"] + .createInstance(Components.interfaces.nsIFileInputStream); + const PR_RDONLY = 0x01; + is.init(nsprlog, PR_RDONLY, 0, 0); + if (!(is instanceof Components.interfaces.nsILineInputStream)) + return; + var line = { value: "" }; + var lines=0; + var para = null; + do + { + lines++; + var more = is.readLine(line); // yuck, returns false for last valid line + + var className=""; + if (storelog) + { + para = fulllog.ownerDocument.createElementNS("http://www.w3.org/1999/xhtml","p"); + fulllog.appendChild(para); + para.appendChild(fulllog.ownerDocument.createTextNode(line.value)); + className="logline"; + } + + // strip off initial "-", thread id, and thread pointer; separate + // first word and rest + var matches = line.value.match(/^\-?[0-9]*\[[0-9a-f]*\]: (\S*) ([0-9a-f]*) (\S*)(.*)$/); + if (matches) { + var handler = matches[1]; + var address = matches[2]; + var verb = matches[3]; + className+=" "+handler+" "+address; + var data = matches[4]; + if (typeof(handlers[handler]) != "undefined") { + handlers[handler].handle_line(address,verb,data,para); + } + else + { + + className+=" ignored"; + } + } + else + { + className+=" ignored"; + } + if (storelog) + para.className=className; + } while (more); + + var details = document.getElementById("details"); + var leaked=false; + + var lbl = document.getElementById("windowLeaks"); + var handler = handlers["DOMWINDOW"]; + lbl.value=bundle.getFormattedString("nightly.leaks.windowleaks.label", [handler.leaked, handler.count]); + if (handler.leaked>0) + { + lbl.className="leaked"; + leaked=true; + } + else + { + lbl.className=""; + } + for (var addr in handler.windows) + { + handler.mark_leaks(addr); + var winobj = handler.windows[addr]; + lbl = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul","label"); + details.appendChild(lbl); + if (winobj.outer=="0") + { + lbl.value=bundle.getFormattedString("nightly.leaks.innerleak.text", [addr, winobj.outer, addr]); + } + else + { + lbl.value=bundle.getFormattedString("nightly.leaks.outerleak.text", [addr, addr]); + } + for (var uri in winobj.uris) + { + lbl = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul","label"); + details.appendChild(lbl); + lbl.value=bundle.getFormattedString("nightly.leaks.urileak.text", [uri]); + lbl.className="uri"; + } + } + + lbl = document.getElementById("documentLeaks"); + handler = handlers["DOCUMENT"]; + lbl.value=bundle.getFormattedString("nightly.leaks.documentleaks.label", [handler.leaked, handler.count]); + if (handler.leaked>0) + { + lbl.className="leaked"; + leaked=true; + } + else + { + lbl.className=""; + } + for (var addr in handler.docs) + { + handler.mark_leaks(addr); + var doc = handler.docs[addr]; + lbl = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul","label"); + details.appendChild(lbl); + lbl.value=bundle.getFormattedString("nightly.leaks.documentleak.text", [addr]); + for (var uri in doc.uris) + { + lbl = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul","label"); + details.appendChild(lbl); + lbl.value=bundle.getFormattedString("nightly.leaks.urileak.text", [uri]); + lbl.className="uri"; + } + } + + lbl = document.getElementById("docshellLeaks"); + handler = handlers["DOCSHELL"]; + lbl.value=bundle.getFormattedString("nightly.leaks.docshellleaks.label", [handler.leaked, handler.count]); + if (handler.leaked>0) + { + lbl.className="leaked"; + leaked=true; + } + else + { + lbl.className=""; + } + for (var addr in handler.shells) + { + handler.mark_leaks(addr); + var doc = handler.shells[addr]; + lbl = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul","label"); + details.appendChild(lbl); + lbl.value=bundle.getFormattedString("nightly.leaks.docshellleak.text", [addr]); + for (var uri in doc.uris) + { + lbl = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul","label"); + details.appendChild(lbl); + lbl.value=bundle.getFormattedString("nightly.leaks.urileak.text", [uri]); + lbl.className="uri"; + } + } + + document.getElementById("detailsbox").collapsed=!leaked; +} +// -------------------------------------------------------------------- + +var nsprlog = null; +var preferences = null; + +var summaryText = ""; +var detailsText = ""; +var logValid = false; +var bundle = null; + +function frameLoaded(event) +{ + var chk = document.getElementById("showlog"); + + var frame = document.getElementById("logframe"); + if (frame.getAttribute("src")=="") + return; + + changeFilter(); + + var details = document.getElementById("details"); + while (details.firstChild) + { + details.removeChild(details.firstChild); + } + + doParse(chk.checked); + + logValid=chk.checked; + + document.getElementById("summary").collapsed=false; + document.getElementById("btnSave").disabled=false; + document.getElementById("btnCopy").disabled=false; + document.getElementById("nsprlog").disabled=false; + document.getElementById("filebrowse").disabled=false; + document.getElementById("showlog").disabled=false; + document.getElementById("tabbox").collapsed=false; +} + +function parseLog() +{ + document.getElementById("nsprlog").disabled=true; + document.getElementById("filebrowse").disabled=true; + document.getElementById("showlog").disabled=false; + document.getElementById("tabbox").collapsed=true; + var frame = document.getElementById("logframe"); + frame.setAttribute("src", "") + window.setTimeout(function() { frame.setAttribute("src", "leaks.html") }, 100); +} + +function init(event) +{ + window.removeEventListener("load", init, false); + + bundle = document.getElementById("bundle"); + + var prefservice = Components.classes['@mozilla.org/preferences-service;1'] + .getService(Components.interfaces.nsIPrefService); + preferences = prefservice.getBranch("nightly.leaks."); + + var buildid = document.getElementById("buildid"); + var appinfo = Components.classes['@mozilla.org/xre/app-info;1'].getService(Components.interfaces.nsIXULAppInfo); + buildid.value=navigator.userAgent+" ID:"+appinfo.appBuildID; + + var frame = document.getElementById("logframe"); + frame.addEventListener("load", frameLoaded, true); + + var chk = document.getElementById("showlog"); + chk.checked = preferences.getBoolPref("showleaklog"); + document.getElementById("tabbox").firstChild.style.display=(chk.checked ? null : 'none'); + + chk = document.getElementById("filterDocshell"); + chk.checked = preferences.getBoolPref("filterDocshell"); + + chk = document.getElementById("filterWindow"); + chk.checked = preferences.getBoolPref("filterWindow"); + + chk = document.getElementById("filterDocument"); + chk.checked = preferences.getBoolPref("filterDocument"); + + chk = document.getElementById("filterLeaked"); + chk.checked = preferences.getBoolPref("filterLeaked"); + + chk = document.getElementById("filterCollected"); + chk.checked = preferences.getBoolPref("filterCollected"); + + chk = document.getElementById("filterIgnored"); + chk.checked = preferences.getBoolPref("filterIgnored"); + + try + { + nsprlog = preferences.getComplexValue("nsprlog", Components.interfaces.nsILocalFile); + } + catch (e) { } + + if (nsprlog && nsprlog.exists()) + { + var logtext = document.getElementById("nsprlog"); + logtext.value=nsprlog.path; + parseLog(); + } +} + +function flipLog() +{ + var chk = document.getElementById("showlog"); + preferences.setBoolPref("showleaklog", chk.checked); + document.getElementById("tabbox").firstChild.style.display=(chk.checked ? null : 'none'); + + if (!chk.checked) + { + document.getElementById("tabbox").selectedIndex=0; + } + + if (chk.checked && !logValid && nsprlog && nsprlog.exists()) + { + parseLog(); + } +} + +function changeFilter() +{ + var style = document.getElementById("logframe").contentDocument.getElementById("filters"); + var filter = ""; + + var chk = document.getElementById("filterDocshell"); + if (!chk.checked) + filter+=".logline.DOCSHELL { display: none }\n"; + preferences.setBoolPref("filterDocshell", chk.checked); + + chk = document.getElementById("filterWindow"); + if (!chk.checked) + filter+=".logline.DOMWINDOW { display: none }\n"; + preferences.setBoolPref("filterWindow", chk.checked); + + chk = document.getElementById("filterDocument"); + if (!chk.checked) + filter+=".logline.DOCUMENT { display: none }\n"; + preferences.setBoolPref("filterDocument", chk.checked); + + chk = document.getElementById("filterLeaked"); + if (!chk.checked) + filter+=".leaked { display: none }\n"; + preferences.setBoolPref("filterLeaked", chk.checked); + + chk = document.getElementById("filterCollected"); + if (!chk.checked) + filter+=".logline:not(.leaked) { display: none }\n"; + preferences.setBoolPref("filterCollected", chk.checked); + + chk = document.getElementById("filterIgnored"); + if (!chk.checked) + filter+=".logline.ignored { display: none }\n"; + preferences.setBoolPref("filterIgnored", chk.checked); + + style.innerHTML=filter; +} + +function pad(value) +{ + if (value<10) + return "0"+value; + return ""+value; +} + +function getTextOverview() +{ + var text=bundle.getString("nightly.leaks.summary.label")+nightlyplatform.eol+nightlyplatform.eol; + var appinfo = Components.classes['@mozilla.org/xre/app-info;1'].getService(Components.interfaces.nsIXULAppInfo); + text+=navigator.userAgent+" ID:"+appinfo.appBuildID+nightlyplatform.eol+nightlyplatform.eol; + var date = new Date(nsprlog.lastModifiedTime); + text+=bundle.getFormattedString("nightly.leaks.sessiondate.label", [date.toLocaleString()])+nightlyplatform.eol+nightlyplatform.eol; + + var leaked = false; + var handler = handlers["DOMWINDOW"]; + if (handler.leaked>0) + leaked=true; + text+=bundle.getFormattedString("nightly.leaks.windowleaks.label", [handler.leaked, handler.count])+nightlyplatform.eol; + handler = handlers["DOCUMENT"]; + if (handler.leaked>0) + leaked=true; + text+=bundle.getFormattedString("nightly.leaks.documentleaks.label", [handler.leaked, handler.count])+nightlyplatform.eol; + handler = handlers["DOCSHELL"]; + if (handler.leaked>0) + leaked=true; + text+=bundle.getFormattedString("nightly.leaks.docshellleaks.label", [handler.leaked, handler.count])+nightlyplatform.eol; + + if (leaked) + { + text+=nightlyplatform.eol+bundle.getString("nightly.leaks.details.label")+nightlyplatform.eol+nightlyplatform.eol; + handler = handlers["DOMWINDOW"]; + for (var addr in handler.windows) + { + var winobj = handler.windows[addr]; + if (winobj.outer=="0") + { + text+=bundle.getFormattedString("nightly.leaks.innerleak.text", [addr, winobj.outer, addr])+nightlyplatform.eol; + } + else + { + text+=bundle.getFormattedString("nightly.leaks.outerleak.text", [addr, addr])+nightlyplatform.eol; + } + for (var uri in winobj.uris) + { + text+=" ... "+bundle.getFormattedString("nightly.leaks.urileak.text", [uri])+nightlyplatform.eol; + } + } + + handler = handlers["DOCUMENT"]; + for (var addr in handler.docs) + { + var doc = handler.docs[addr]; + text += bundle.getFormattedString("nightly.leaks.documentleak.text", [addr])+nightlyplatform.eol; + for (var uri in doc.uris) + { + text+=" ... "+bundle.getFormattedString("nightly.leaks.urileak.text", [uri])+nightlyplatform.eol; + } + } + + handler = handlers["DOCSHELL"]; + for (var addr in handler.shells) + { + var doc = handler.shells[addr]; + text += bundle.getFormattedString("nightly.leaks.docshellleak.text", [addr])+nightlyplatform.eol; + for (var uri in doc.uris) + { + text+=" ... "+bundle.getFormattedString("nightly.leaks.urileak.text", [uri])+nightlyplatform.eol; + } + } + } + return text; +} + +function save() +{ + var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(Components.interfaces.nsIFilePicker); + fp.init(window, bundle.getString("nightly.leaks.filepicker.title"), fp.modeSave); + fp.appendFilter(bundle.getString("nightly.leaks.filepicker.filterlog"), "*.log"); + fp.appendFilter(bundle.getString("nightly.leaks.filepicker.filterall"), "*.*"); + fp.displayDirectory=nsprlog.parent; + + var date = new Date(nsprlog.lastModifiedTime); + fp.defaultString=date.getFullYear()+pad(date.getMonth()+1)+pad(date.getDate())+"-"+pad(date.getHours())+pad(date.getMinutes())+"_leaklog.log"; + + var result = fp.show(); + if (result==fp.returnOK || result==fp.returnReplace) + { + var target=fp.file; + preferences.setComplexValue("leaksave", Components.interfaces.nsILocalFile, target); + + var text = getTextOverview(); + + // file is nsIFile, data is a string + var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"] + .createInstance(Components.interfaces.nsIFileOutputStream); + + // use 0x02 | 0x10 to open file for appending. + foStream.init(target, 0x02 | 0x08 | 0x20, 0664, 0); // write, create, truncate + var os = Components.classes["@mozilla.org/intl/converter-output-stream;1"] + .createInstance(Components.interfaces.nsIConverterOutputStream); + + os.init(foStream, "UTF-8", 0, 0x0000); + os.writeString(text); + os.close(); + foStream.close(); + } +} + +function clipboardCopy() +{ + var clipboard = Components.classes["@mozilla.org/widget/clipboardhelper;1"]. + getService(Components.interfaces.nsIClipboardHelper); + clipboard.copyString(getTextOverview()); +} + +function textEnter() +{ + var logtext = document.getElementById("nsprlog"); + var target = Components.classes["@mozilla.org/file/local;1"] + .createInstance(Components.interfaces.nsILocalFile); + target.initWithPath(logtext.value); + if (target.exists()) + { + nsprlog=target; + preferences.setComplexValue("nsprlog", Components.interfaces.nsILocalFile, nsprlog); + parseLog(); + } + else + { + var prompt = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] + .getService(Components.interfaces.nsIPromptService); + prompt.alert(window, "File Not Found", logtext.value+" does not exist."); + } +} + +function selectLog() +{ + var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(Components.interfaces.nsIFilePicker); + fp.init(window, bundle.getString("nightly.leaks.filepicker.title"), fp.modeOpen); + fp.appendFilter(bundle.getString("nightly.leaks.filepicker.filterlog"), "*.log"); + fp.appendFilter(bundle.getString("nightly.leaks.filepicker.filterall"), "*.*"); + if (nsprlog) + fp.displayDirectory=nsprlog.parent; + + if (fp.show() == fp.returnOK) + { + nsprlog=fp.file; + preferences.setComplexValue("nsprlog", Components.interfaces.nsILocalFile, nsprlog); + var logtext = document.getElementById("nsprlog"); + logtext.value=nsprlog.path; + parseLog(); + } +} + +window.addEventListener("load", init, false);