Mercurial > nightly_tester_tools
changeset 2:472a16863ecc
expanded nightly.jar
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/.buildrc Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,7 @@ +[dependencies] +calendaroverlay.xul = /Users/dave/workspace/Nightly/src/chrome/content/calendarOverlay.xul,/Users/dave/workspace/Nightly/src/chrome/content/crashreports/crashreports.inc.xul +songbirdoverlay.xul = /Users/dave/workspace/Nightly/src/chrome/content/songbirdOverlay.xul,/Users/dave/workspace/Nightly/src/chrome/content/screenshot/screenshot.inc.xul,/Users/dave/workspace/Nightly/src/chrome/content/crashreports/crashreports.inc.xul +messengeroverlay.xul = /Users/dave/workspace/Nightly/src/chrome/content/messengerOverlay.xul,/Users/dave/workspace/Nightly/src/chrome/content/crashreports/crashreports.inc.xul +suiteoverlay.xul = /Users/dave/workspace/Nightly/src/chrome/content/suiteOverlay.xul,/Users/dave/workspace/Nightly/src/chrome/content/crashreports/crashreports.inc.xul +browseroverlay.xul = /Users/dave/workspace/Nightly/src/chrome/content/browserOverlay.xul,/Users/dave/workspace/Nightly/src/chrome/content/screenshot/screenshot.inc.xul,/Users/dave/workspace/Nightly/src/chrome/content/crashreports/crashreports.inc.xul +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/browser.js Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,61 @@ +var nightlyApp = { + +storedTitle: document.documentElement.getAttribute("titlemodifier"), + +init: function() +{ + var brandbundle = document.getElementById("bundle_brand"); + if (nightly.variables.name==null) + { + nightly.variables.name=brandbundle.getString("brandShortName"); + } + nightly.variables.brandname=brandbundle.getString("brandFullName"); + nightly.variables.defaulttitle=nightlyApp.storedTitle; + document.getElementById("content").addEventListener("DOMTitleChanged",nightlyApp.titleUpdated,false); +}, + +detectLeaks: function(event) +{ + this.openURL('chrome://nightly/content/leaks/leaks.xul', event); +}, + +openURL: function(url, event) +{ + openUILink(url, event, false, true); +}, + +titleUpdated: function() +{ + if (!gBrowser.mTabbedMode) + { + gBrowser.updateTitlebar(); + } +}, + +updateTitlebar: function() +{ + window.setTimeout("gBrowser.updateTitlebar();", 50); +}, + +setCustomTitle: function(title) +{ + document.documentElement.setAttribute("titlemodifier",title); + document.documentElement.setAttribute("titlemenuseparator"," - "); + nightlyApp.updateTitlebar(); +}, + +setBlankTitle: function() +{ + document.documentElement.setAttribute("titlemodifier",""); + document.documentElement.setAttribute("titlemenuseparator",""); + nightlyApp.updateTitlebar(); +}, + +setStandardTitle: function() +{ + document.documentElement.setAttribute("titlemodifier",nightlyApp.storedTitle); + document.documentElement.setAttribute("titlemenuseparator"," - "); + nightlyApp.updateTitlebar(); +} + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/browserOverlay.xul Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,81 @@ +<?xml version="1.0"?> + +<!DOCTYPE window [ +<!ENTITY % nightlyDTD SYSTEM "chrome://nightly/locale/nightly.dtd"> +%nightlyDTD; +<!ENTITY % leaksDTD SYSTEM "chrome://nightly/locale/leaks.dtd"> +%leaksDTD; +]> + +<overlay id="NightlyBrowserOverlay" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <script type="application/x-javascript" src="nightly.js" /> + <script type="application/x-javascript" src="browser.js" /> + <script type="application/x-javascript" src="session/session.js" /> + <script type="application/x-javascript" src="crashreports/crashreports.js" /> + <script type="application/x-javascript" src="chrome://nightly/content/platform.js" /> + + <!-- Sidebar --> + <broadcasterset id="mainBroadcasterSet"> + <broadcaster id="viewCrashReportsSidebar" + autoCheck="false" + label="&nightly.crashreports.sidebar.title;" + type="checkbox" + group="sidebar" + sidebarurl="chrome://nightly/content/crashreports/sidebar.xul" + oncommand="toggleSidebar('viewCrashReportsSidebar');"/> + </broadcasterset> + + <keyset id="mainKeyset"> + <key key="s" modifiers="accel,shift" oncommand="nightly.getScreenshot();"/> + </keyset> + + <toolbarpalette id="BrowserToolbarPalette"> + <toolbarbutton id="nightly-tester-enter" + class="toolbarbutton-1" + label="&nightly.id.insert.label;" + tooltiptext="&nightly.id.insert.tooltip;" + oncommand="nightly.insertTemplate('buildid');"/> + </toolbarpalette> + + <popupset id="mainPopupSet"> + <tooltip orient="vertical" id="nightly-crashreport-tooltip" onpopupshowing="return crashreports.popupTooltip(event)"> + <label/> + </tooltip> + <popup id="nightly-crashreport-context"> + <menuitem oncommand="crashreports.copy(event)" label="&nightly.crashreports.copyid;"/> + </popup> + </popupset> + + <menupopup id="goPopup"> + <menuitem id="nightly-session-restore" label="&nightly.session.restore;" insertbefore="endUndoSeparator" oncommand="session.restore()"/> + </menupopup> + + <menupopup id="menu_ToolsPopup"> + <menu id="nightly-menu" label="Nightly Tester Tools" insertafter="devToolsSeparator"> + <menupopup onpopupshowing="nightly.menuPopup(event,this);"> + <menuitem id="build-copy" label="&nightly.id.copy.label;" oncommand="nightly.copyTemplate('buildid');"/> + <menuitem id="build-insert" label="&nightly.id.insert.label;" oncommand="nightly.insertTemplate('buildid');"/> + <menuitem id="list-copy" label="&nightly.extensions.copy.label;" oncommand="nightly.copyExtensions();"/> + <menuitem id="list-insert" label="&nightly.extensions.insert.label;" oncommand="nightly.insertExtensions();"/> + <menuseparator/> + <menuitem label="&nightly.screenshot.full.label;" oncommand="nightly.getScreenshot();"/> + <menuseparator/> + <menuitem label="&nightly.openprofile.label;" oncommand="nightly.openProfileDir();"/> + <menuseparator id="nightly-crashreports-separator"/> + <menu id="nightly-crashreports-recent" label="&nightly.crashreports.recentlist;" oncommand="crashreports.viewIncident(event);" onclick="checkForMiddleClick(this, event);"> + <menupopup id="nightly-crashreports-incidents"> + <menuitem disabled="true" label="&nightly.leaks.loading.label;"/> + </menupopup> + </menu> + <menuitem id="nightly-crashreports-sidebar" observes="viewCrashReportsSidebar"/> + <menuseparator/> + <menuitem label="&nightly.leakreporter.label;" oncommand="nightlyApp.detectLeaks(event);" onclick="checkForMiddleClick(this, event);"/> + <menuseparator/> + <menuitem label="&nightly.options.label;" oncommand="nightly.launchOptions();"/> + </menupopup> + </menu> + </menupopup> + +</overlay>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/calendar.js Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,54 @@ +var nightlyApp = { + +storedTitle: '', + +init: function() +{ + nightlyApp.storedTitle = document.title; + var brandbundle = document.getElementById("bundle_branding"); + if (nightly.variables.name==null) + { + nightly.variables.name = brandbundle.getString("brandShortName"); + } + nightly.variables.defaulttitle = nightlyApp.storedTitle; + nightly.variables.brandname = brandbundle.getString("brandFullName"); +}, + +openURL: function(url, event) +{ + var uri = Components.classes["@mozilla.org/network/io-service;1"] + .getService(Components.interfaces.nsIIOService) + .newURI(url, null, null); + + var protocolSvc = Components.classes["@mozilla.org/uriloader/external-protocol-service;1"] + .getService(Components.interfaces.nsIExternalProtocolService); + protocolSvc.loadUrl(uri); +}, + +detectLeaks: function(event) +{ + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] + .getService(Components.interfaces.nsIWindowMediator); + var win = wm.getMostRecentWindow("Nightly:LeakReporter"); + if (win) + win.focus(); + else + window.openDialog("chrome://nightly/content/leaks/leaks.xul", "_blank", "chrome,all,dialog=no"); +}, + +setCustomTitle: function(title) +{ + document.title = title; +}, + +setBlankTitle: function() +{ + document.title = ''; +}, + +setStandardTitle: function() +{ + document.title = nightlyApp.storedTitle; +} + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/calendarOverlay.xul Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,58 @@ +<?xml version="1.0"?> + +<!DOCTYPE window [ +<!ENTITY % nightlyDTD SYSTEM "chrome://nightly/locale/nightly.dtd"> +%nightlyDTD; +<!ENTITY % leaksDTD SYSTEM "chrome://nightly/locale/leaks.dtd"> +%leaksDTD; +]> + +<overlay id="NightlyCalendarOverlay" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <script type="application/x-javascript" src="nightly.js" /> + <script type="application/x-javascript" src="calendar.js" /> + <script type="application/x-javascript" src="breakpad/breakpad.js" /> + <script type="application/x-javascript" src="chrome://nightly/content/platform.js" /> + + <toolbarpalette id="calendarToolbarPalette"> + <toolbarbutton id="nightly-tester-enter" + class="toolbarbutton-1" + label="&nightly.id.insert.label;" + tooltiptext="&nightly.id.insert.tooltip;" + oncommand="nightly.insertTemplate('buildid');"/> + </toolbarpalette> + + <window id="calendar-window"> + <tooltip orient="vertical" id="nightly-crashreport-tooltip" onpopupshowing="return crashreports.popupTooltip(event)"> + <label/> + </tooltip> + <popup id="nightly-crashreport-context"> + <menuitem oncommand="crashreports.copy(event)" label="&nightly.crashreports.copyid;"/> + </popup> + </window> + + <menupopup id="toolsPopup"> + <menu id="nightly-menu" label="Nightly Tester Tools" insertafter="addonsManager"> + <menupopup onpopupshowing="nightly.menuPopup(event,this);"> + <menuitem id="build-copy" label="&nightly.id.copy.label;" oncommand="nightly.copyTemplate('buildid');"/> + <menuitem id="build-insert" label="&nightly.id.insert.label;" oncommand="nightly.insertTemplate('buildid');"/> + <menuitem id="list-copy" label="&nightly.extensions.copy.label;" oncommand="nightly.copyExtensions();"/> + <menuitem id="list-insert" label="&nightly.extensions.insert.label;" oncommand="nightly.insertExtensions();"/> + <menuseparator/> + <menuitem label="&nightly.openprofile.label;" oncommand="nightly.openProfileDir();"/> + <menuseparator id="nightly-crashreports-separator"/> + <menu id="nightly-crashreports-recent" label="&nightly.crashreports.recentlist;" oncommand="crashreports.viewIncident(event);" onclick="checkForMiddleClick(this, event);"> + <menupopup id="nightly-crashreports-incidents"> + <menuitem disabled="true" label="&nightly.leaks.loading.label;"/> + </menupopup> + </menu> + <menuseparator/> + <menuitem label="&nightly.leakreporter.label;" oncommand="nightlyApp.detectLeaks(event);"/> + <menuseparator/> + <menuitem label="&nightly.options.label;" oncommand="nightly.launchOptions();"/> + </menupopup> + </menu> + </menupopup> + +</overlay>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/configwarning.js Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,64 @@ +const Cc = Components.classes; +const Ci = Components.interfaces; + +var gOS = null; + +var observer = { + observe: function(subject, topic, data) { + window.focus(); + } +} + +function init() { + var bundle = document.getElementById("bundle"); + setLabelForButton(document.documentElement.getButton("accept"), bundle.getString("Yes")); + setLabelForButton(document.documentElement.getButton("cancel"), bundle.getString("No")); + + gOS = Cc["@mozilla.org/observer-service;1"]. + getService(Ci.nsIObserverService); + gOS.addObserver(observer, "xul-window-visible", false); +} + +function unload() { + gOS.removeObserver(observer, "xul-window-visible"); + gOS = null; +} + +function setLabelForButton(button, label) +{ + var accessKey = null; + if (/ *\(\&([^&])\)(:)?$/.test(label)) { + label = RegExp.leftContext + RegExp.$2; + accessKey = RegExp.$1; + } else if (/^(.*[^&])?\&(([^&]).*$)/.test(label)) { + label = RegExp.$1 + RegExp.$2; + accessKey = RegExp.$3; + } + // && is the magic sequence to embed an & in your label. + label = label.replace(/\&\&/g, "&"); + button.label = label; + if (accessKey) + button.accessKey = accessKey; +} + +function accept() { + var cs = Cc["@oxymoronical.com/nightly/addoncompatibility;1"]. + createInstance(Ci.nttIAddonCompatibilityService); + var em = Cc["@mozilla.org/extensions/manager;1"]. + getService(Ci.nsIExtensionManager); + var items = em.getItemList(Ci.nsIUpdateItem.TYPE_ADDON, {}); + for (var i = 0; i < items.length; i++) { + var addon = cs.getAddonForID(items[i].id); + if (!addon.isValid()) + continue; + if (!addon.needsOverride(false) && addon.needsOverride(true)) + addon.overrideCompatibility(true); + } + + var prefs = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefBranch); + if (prefs.prefHasUserValue("extensions.checkCompatibility")) + prefs.clearUserPref("extensions.checkCompatibility"); + if (prefs.prefHasUserValue("extensions.checkUpdateSecurity")) + prefs.clearUserPref("extensions.checkUpdateSecurity"); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/configwarning.xul Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,31 @@ +<?xml version="1.0"?> + +<!DOCTYPE dialog [ +<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> +%brandDTD; +<!ENTITY % firstrunDTD SYSTEM "chrome://nightly/locale/configwarning.dtd"> +%firstrunDTD; +]> + +<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> +<?xml-stylesheet href="chrome://nightly/skin/configwarning.css" type="text/css"?> + +<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + title="&dialog.title;" style="&dialog.style;" buttons="accept,cancel" + windowtype="NightlyTester:ConfigWarning" + onload="init()" onunload="unload()" ondialogaccept="accept()"> + + <script src="configwarning.js"/> + + <stringbundle id="bundle" src="chrome://global/locale/commonDialogs.properties"/> + + <hbox id="banner" align="start"> + <image class="alert-icon"/> + <vbox flex="1"> + <label id="title">&title;</label> + <description>&subtitle;</description> + <description>&question;</description> + </vbox> + </hbox> + +</dialog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/crashreports/crashreports.js Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,107 @@ +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); + +var crashreports = { + +init: function(event) +{ + window.removeEventListener("load", crashreports.init, false); + if (Components.interfaces.nsICrashReporter) + { + var service = Components.classes["@blueprintit.co.uk/breakpad;1"] + .getService(Components.interfaces.nttIBreakpadService); + + if (nightly.preferences.getBoolPref("crashreports.recentlist.display")) + { + service.loadDatabase(); + service.addProgressListener(crashreports); + } + else + { + document.getElementById("nightly-crashreports-incidents").parentNode.hidden=true; + } + } + else + { + document.getElementById("nightly-crashreports-separator").hidden = true; + document.getElementById("nightly-crashreports-recent").hidden = true; + document.getElementById("nightly-crashreports-sidebar").hidden = true; + } +}, + +copy: function(event) +{ + var node = document.popupNode; + if (node.id.substring(0,12)=="breakpad-id-") + { + var id = node.id.substring(12); + var clipboard = Components.classes["@mozilla.org/widget/clipboardhelper;1"] + .getService(Components.interfaces.nsIClipboardHelper); + clipboard.copyString(id); + closeMenus(node); + } +}, + +onDatabaseLoaded: function() +{ + var service = Components.classes["@blueprintit.co.uk/breakpad;1"] + .getService(Components.interfaces.nttIBreakpadService); + + var incidents = null; + + incidents = service.getPreviousIncidents(10); + + var parent = document.getElementById("nightly-crashreports-incidents"); + if ((incidents) && (incidents.length > 0)) + { + while (parent.firstChild) + parent.removeChild(parent.firstChild); + + var en = incidents.enumerate(); + while (en.hasMoreElements()) + { + var incident = en.getNext().QueryInterface(Components.interfaces.nttIBreakpadIncident); + + var item = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "menuitem"); + item.setAttribute("id", "breakpad-id-"+incident.id); + item.setAttribute("tooltip", "nightly-crashreport-tooltip"); + item.setAttribute("context", "nightly-crashreport-context"); + item.setAttribute("label", incident.id+" ("+(new Date(incident.date)).toLocaleDateString()+")"); + parent.appendChild(item); + } + } + else + { + parent.parentNode.disabled=true; + } +}, + +popupTooltip: function(event) +{ + var node = document.tooltipNode; + if (node.id.substring(0,12)=="breakpad-id-") + { + var id = node.id.substring(12); + var service = Components.classes["@blueprintit.co.uk/breakpad;1"] + .getService(Components.interfaces.nttIBreakpadService); + var incident = service.getIncident(id); + var label = document.getElementById("nightly-crashreport-tooltip").firstChild; + label.value=(new Date(incident.date)).toLocaleString(); + return true; + } + return false; +}, + +viewIncident: function(event) +{ + if (event.target.id.substring(0,12)=="breakpad-id-") + { + var url = nightly.preferences.getCharPref("breakpad.searchurl"); + var id = event.target.id.substring(15); + nightlyApp.openURL(url+id, event); + } +}, + +QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nttIBreakpadProgressListener]) +} + +window.addEventListener("load", crashreports.init, false);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/crashreports/sidebar.js Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,74 @@ +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cr = Components.results; + +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); + +const xulns = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + +var sidebar = { + +db: null, + +init: function() +{ + var service = Cc["@blueprintit.co.uk/breakpad;1"]. + getService(Ci.nttIBreakpadService); + + service.loadDatabase(); + service.addProgressListener(sidebar); +}, + +onDatabaseLoaded: function() +{ + var service = Cc["@blueprintit.co.uk/breakpad;1"]. + getService(Ci.nttIBreakpadService); + + var tree = document.getElementById("tree"); + tree.view = service.getTreeView(); + + document.getElementById("loading").hidden=true; + tree.hidden=false; +}, + +copy: function(event) +{ + var tree = document.getElementById("tree"); + var id = tree.view.getCellText(tree.currentIndex, tree.columns.getNamedColumn("incidentID")); + var clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"]. + getService(Ci.nsIClipboardHelper); + clipboard.copyString(id); +}, + +command: function(tree, event, row) +{ + var prefservice = Cc['@mozilla.org/preferences-service;1']. + getService(Ci.nsIPrefBranch); + var url = prefservice.getCharPref("nightly.breakpad.searchurl"); + var id = tree.view.getCellText(row, tree.columns.getNamedColumn("incidentID")).substring(3); + window.parent.openUILink(url+id, event, false, true); +}, + +selectedCommand: function(event) +{ + var tree = document.getElementById("tree"); + sidebar.command(tree, event, tree.currentIndex); +}, + +clickCommand: function(event) +{ + var tree = document.getElementById("tree"); + var row = {}, col = {}; + tree.treeBoxObject.getCellAt(event.clientX, event.clientY, row, col, {}); + sidebar.command(tree, event, row.value); +}, + +checkPopup: function(event) +{ + var tree = document.getElementById("tree"); + var type = tree.view.getCellText(tree.currentIndex, tree.columns.getNamedColumn("type")); + return type=="incident"; +}, + +QueryInterface: XPCOMUtils.generateQI([Ci.nttIBreakpadProgressListener]) +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/crashreports/sidebar.xul Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,40 @@ +<?xml version="1.0"?> + +<!DOCTYPE window [ +<!ENTITY % nightlyDTD SYSTEM "chrome://nightly/locale/nightly.dtd"> +%nightlyDTD; +<!ENTITY % leaksDTD SYSTEM "chrome://nightly/locale/leaks.dtd"> +%leaksDTD; +]> + +<?xml-stylesheet href="chrome://global/skin/global.css"?> +<?xml-stylesheet href="chrome://nightly/skin/crashreports/sidebar.css"?> + +<page id="CrashReportsSidebar" onload="sidebar.init();" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <script src="sidebar.js"/> + + <popupset> + <popup id="crashReportContext" onpopupshowing="return sidebar.checkPopup(event)"> + <menuitem oncommand="sidebar.copy(event)" label="&nightly.crashreports.copyid;"/> + </popup> + </popupset> + + <vbox id="loading" align="center" pack="center" flex="1"> + <label style="font-size: 150%;" value="&nightly.leaks.loading.label;"/> + </vbox> + + <tree id="tree" hidden="true" flex="1" seltype="single" onkeypress="if (event.keyCode==13) sidebar.selectedCommand(event);"> + <treecols> + <treecol id="incidentID" label="&nightly.crashreports.id;" primary="true" flex="1" persist="width"/> + <splitter class="tree-splitter"/> + <treecol id="incidentDate" label="&nightly.crashreports.date;" flex="2" hidden="true" persist="width hidden"/> + </treecols> + + <treechildren id="treeroot" context="crashReportContext" + onclick="if (event.button==1) sidebar.clickCommand(event);" + ondblclick="if (event.button==0) sidebar.clickCommand(event);"/> + </tree> + +</page>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/extensions/addons.xul Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,28 @@ +<?xml version="1.0"?> + +<!DOCTYPE window SYSTEM "chrome://nightly/locale/nightly.dtd"> + +<?xml-stylesheet href="chrome://nightly/skin/extensions/extensions.css" type="text/css"?> + +<overlay id="NightlyExtensionsOverlay" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <script type="application/x-javascript" src="extensions.js" /> + + <stringbundleset id="extensionsSet"> + <stringbundle id="nightlylocale" src="chrome://nightly/locale/nightly.properties"/> + </stringbundleset> + + <vbox id="addonContextMenuPalette"> + <menuitem id="menuitem_appenable" insertafter="menuitem_disable" + oncommand="extensionAppEnabler.appEnable();" label="&nightly.appenable.label;"/> + </vbox> + + <hbox id="commandBarBottom"> + <button id="enableallButton" hidden="true" label="&nightly.enableall.label;" + oncommand="extensionAppEnabler.enableAll()" + tooltiptext="&nightly.enableall.tooltip;" insertbefore="restartAppButton"/> + <separator class="commandBarSeparator" insertbefore="restartAppButton"/> + </hbox> + +</overlay>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/extensions/extensions.js Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,106 @@ +var extensionAppEnabler = { + +prefs: null, +cs: null, + +init: function() { + var pos = gAddonContextMenus.indexOf("menuitem_enable"); + gAddonContextMenus.splice(pos, 0, "menuitem_appenable"); + this.cs = Components.classes["@oxymoronical.com/nightly/addoncompatibility;1"] + .createInstance(Components.interfaces.nttIAddonCompatibilityService); +}, + +initView: function() { + var enableb = document.getElementById("enableallButton"); + + if (!this.prefs.getBoolPref("showEnableAll")) { + enableb.hidden = true; + return; + } + + var parent = document.getElementById("viewGroup"); + var node = parent.firstChild; + while (node != null) { + if (node.selected) { + switch (node.id) { + case "extensions-view": + case "themes-view": + case "locales-view": + enableb.hidden = false; + break; + default: + enableb.hidden = true; + } + return; + } + node = node.nextSibling; + } + + enableb.hidden = true; +}, + +load: function() { + var prefservice = Components.classes['@mozilla.org/preferences-service;1'] + .getService(Components.interfaces.nsIPrefService); + this.prefs = prefservice.getBranch("nightly.") + .QueryInterface(Components.interfaces.nsIPrefBranchInternal); + + var context = document.getElementById("addonContextMenu"); + context.addEventListener("popupshowing", function() { extensionAppEnabler.popupShowing(); }, false); + + var radios = document.getElementById("viewGroup"); + radios.addEventListener("select", function() { extensionAppEnabler.initView(); }, false); + this.initView(); +}, + +popupShowing: function() { + var item = gExtensionsView.selectedItem; + var menu = document.getElementById("menuitem_appenable"); + var menuclone = document.getElementById("menuitem_appenable_clone"); + var addon = this.cs.getAddonForID(item.getAttribute("addonID")); + menu.hidden = !(addon.isValid() && addon.needsOverride(false)); + if (menuclone) + menuclone.hidden = menu.hidden; +}, + +appEnable: function() { + var ev = gExtensionsView; + var item = ev.selectedItem; + this.cs.confirmOverride([this.cs.getAddonForID(item.getAttribute("addonID"))], 1); + this.syncCompatibility(); +}, + +enableAll: function() { + var addons = []; + var items = gExtensionsView.children; + for (var i = 0; i < items.length; i++) { + var addon = this.cs.getAddonForID(items[i].getAttribute("addonID")); + if (addon.isValid() && addon.needsOverride(false)) + addons.push(addon); + } + if (addons.length > 0) { + this.cs.confirmOverride(addons, addons.length); + this.syncCompatibility(); + } +}, + +syncCompatibility: function() { + var prefService = Components.classes['@mozilla.org/preferences-service;1'] + .getService(Components.interfaces.nsIPrefBranch); + try { + var checkCompatibility = prefService.getBoolPref("extensions.checkCompatibility"); + prefService.setBoolPref("extensions.checkCompatibility", !checkCompatibility); + prefService.setBoolPref("extensions.checkCompatibility", checkCompatibility); + } + catch (e) { + prefService.setBoolPref("extensions.checkCompatibility", false); + prefService.setBoolPref("extensions.checkCompatibility", true); + } + updateOptionalViews(); + updateGlobalCommands(); +} +} + +extensionAppEnabler.init(); + +window.addEventListener("load", function() { extensionAppEnabler.load(); }, false);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/extensions/incompatible.css Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,3 @@ +richlistitem { + -moz-binding: url(chrome://nightly/content/extensions/incompatible.xml#incompatible); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/extensions/incompatible.js Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,25 @@ +const Cc = Components.classes; +const Ci = Components.interfaces; + +var gItems; + +function Startup() { + gItems = window.arguments; + var list = document.getElementById("addonlist"); + for (var i = 0; i < gItems.length; i++) { + gItems[i].QueryInterface(Ci.nsIUpdateItem) + .QueryInterface(Ci.nttIAddon); + var ri = document.createElement("richlistitem"); + ri.setAttribute("name", gItems[i].name); + ri.setAttribute("version", gItems[i].version); + ri.setAttribute("icon", gItems[i].iconURL); + ri.setAttribute("secure", gItems[i].isUpdateSecure(false) ? "true" : "false"); + ri.setAttribute("compatible", gItems[i].isCompatible(false) ? "true" : "false"); + list.appendChild(ri); + } +} + +function Accept() { + for (var i = 0; i < gItems.length; i++) + gItems[i].overrideCompatibility(false); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/extensions/incompatible.xml Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,29 @@ +<?xml version="1.0"?> + +<!DOCTYPE bindings [ +<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> +%brandDTD; +<!ENTITY % incompatibleDTD SYSTEM "chrome://nightly/locale/incompatible.dtd"> +%incompatibleDTD; +]> + +<bindings xmlns="http://www.mozilla.org/xbl" xmlns:xbl="http://www.mozilla.org/xbl" + xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <binding id="incompatible" name="incompatible"> + <content> + <xul:hbox align="center"> + <xul:image xbl:inherits="src=icon"/> + <xul:vbox flex="1"> + <xul:hbox class="name-version"> + <xul:label xbl:inherits="value=name"/> + <xul:label xbl:inherits="value=version"/> + </xul:hbox> + <xul:label class="warning incompatible" value="&incompatible.label;"/> + <xul:label class="warning insecure" value="&insecure.label;"/> + </xul:vbox> + </xul:hbox> + </content> + </binding> + +</bindings>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/extensions/incompatible.xul Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,29 @@ +<?xml version="1.0"?> + +<!DOCTYPE window [ +<!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd"> +%brandDTD; +<!ENTITY % incompatibleDTD SYSTEM "chrome://nightly/locale/incompatible.dtd"> +%incompatibleDTD; +]> + +<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> +<?xml-stylesheet href="chrome://nightly/content/extensions/incompatible.css" type="text/css"?> +<?xml-stylesheet href="chrome://nightly/skin/extensions/incompatible.css" type="text/css"?> + +<dialog title="&window.title;" onload="Startup()" style="&window.style;" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" + buttonlabelcancel="&window.cancel;" buttonlabelaccept="&window.accept;" + ondialogaccept="Accept()"> + + <script src="incompatible.js" type="application/x-javascript"/> + + <hbox align="center"> + <image class="alert-icon"/> + <description flex="1" id="warning">&warning.label;</description> + </hbox> + + <richlistbox id="addonlist" flex="1"> + </richlistbox> + +</dialog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/includes/tree-utils.js Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,1679 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is The JavaScript Debugger. + * + * The Initial Developer of the Original Code is + * Netscape Communications Corporation. + * Portions created by the Initial Developer are Copyright (C) 1998 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Robert Ginda, <rginda@netscape.com>, original author + * Dave Townsend, <mossop@blueprintit.co.uk>, Added cell and row property support + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +/* + * BasicOView provides functionality of tree whose elements have no children. + * Usage: + * var myTree = new BasicOView() + * myTree.setColumnNames (["col 1", "col 2"]); + * myTree.data = [["row 1, col 1", "row 1, col 2"], + * ["row 2, col 1", "row 2, col 2"]]; + * { override get*Properties, etc, as suits your purpose. } + * + * treeBoxObject.view = myTree; + * + * You'll need to make the appropriate myTree.tree.invalidate calls + * when myTree.data changes. + */ + +function BasicOView() +{ + this.tree = null; +} + +/* functions *you* should call to initialize and maintain the tree state */ + +/* scroll the line specified by |line| to the center of the tree */ +BasicOView.prototype.centerLine = +function bov_ctrln (line) +{ + var first = this.tree.getFirstVisibleRow(); + var last = this.tree.getLastVisibleRow(); + this.scrollToRow(line - (last - first + 1) / 2); +} + +/* call this to set the association between column names and data columns */ +BasicOView.prototype.setColumnNames = +function bov_setcn (aryNames) +{ + this.columnNames = new Object(); + for (var i = 0; i < aryNames.length; ++i) + this.columnNames[aryNames[i]] = i; +} + +/* + * scroll the source so |line| is at either the top, center, or bottom + * of the view, depending on the value of |align|. + * + * line is the one based target line. + * if align is negative, the line will be scrolled to the top, if align is + * zero the line will be centered, and if align is greater than 0 the line + * will be scrolled to the bottom. 0 is the default. + */ +BasicOView.prototype.scrollTo = +function bov_scrollto (line, align) +{ + if (!this.tree) + return; + + var headerRows = 1; + + var first = this.tree.getFirstVisibleRow(); + var last = this.tree.getLastVisibleRow(); + var viz = last - first + 1 - headerRows; /* total number of visible rows */ + + /* all rows are visible, nothing to scroll */ + if (first == 0 && last >= this.rowCount) + return; + + /* tree lines are 0 based, we accept one based lines, deal with it */ + --line; + + /* safety clamp */ + if (line < 0) + line = 0; + if (line >= this.rowCount) + line = this.rowCount - 1; + + if (align < 0) + { + if (line > this.rowCount - viz) /* overscroll, can't put a row from */ + line = this.rowCount - viz; /* last page at the top. */ + this.tree.scrollToRow(line); + } + else if (align > 0) + { + if (line < viz) /* underscroll, can't put a row from the first page */ + line = 0; /* at the bottom. */ + else + line = line - viz + headerRows; + + this.tree.scrollToRow(line); + } + else + { + var half_viz = viz / 2; + /* lines past this line can't be centered without causing the tree + * to show more rows than we have. */ + var lastCenterable = this.rowCount - half_viz; + if (line > half_viz) + line = lastCenterable; + /* lines before this can't be centered without causing the tree + * to attempt to display negative rows. */ + else if (line < half_viz) + line = half_viz; + else + /* round the vizible rows down to a whole number, or we try to end up + * on a N + 0.5 row! */ + half_viz = Math.floor(half_viz); + + this.tree.scrollToRow(line - half_viz); + } +} + +BasicOView.prototype.__defineGetter__("selectedIndex", bov_getsel); +function bov_getsel() +{ + if (!this.tree || this.tree.view.selection.getRangeCount() < 1) + return -1; + + var min = new Object(); + this.tree.view.selection.getRangeAt(0, min, {}); + return min.value; +} + +BasicOView.prototype.__defineSetter__("selectedIndex", bov_setsel); +function bov_setsel(i) +{ + if (i == -1) + this.tree.view.selection.clearSelection(); + else + this.tree.view.selection.timedSelect (i, 500); + return i; +} + +/* + * functions the tree will call to retrieve the list state (nsITreeView.) + */ + +BasicOView.prototype.rowCount = 0; + +BasicOView.prototype.getCellProperties = +function bov_cellprops (row, col, properties) +{ +} + +BasicOView.prototype.getColumnProperties = +function bov_colprops (col, properties) +{ +} + +BasicOView.prototype.getRowProperties = +function bov_rowprops (index, properties) +{ +} + +BasicOView.prototype.isContainer = +function bov_isctr (index) +{ + return false; +} + +BasicOView.prototype.isContainerOpen = +function bov_isctropen (index) +{ + return false; +} + +BasicOView.prototype.isContainerEmpty = +function bov_isctrempt (index) +{ + return false; +} + +BasicOView.prototype.isSeparator = +function bov_isseparator (index) +{ + return false; +} + +BasicOView.prototype.isSorted = +function bov_issorted (index) +{ + return false; +} + +BasicOView.prototype.canDrop = +function bov_drop (index, orientation) +{ + return false; +} + +BasicOView.prototype.drop = +function bov_drop (index, orientation) +{ + return false; +} + +BasicOView.prototype.getParentIndex = +function bov_getpi (index) +{ + if (index < 0) + return -1; + + return 0; +} + +BasicOView.prototype.hasNextSibling = +function bov_hasnxtsib (rowIndex, afterIndex) +{ + return (afterIndex < (this.rowCount - 1)); +} + +BasicOView.prototype.getLevel = +function bov_getlvl (index) +{ + return 0; +} + +BasicOView.prototype.getImageSrc = +function bov_getimgsrc (row, col) +{ +} + +BasicOView.prototype.getProgressMode = +function bov_getprgmode (row, col) +{ +} + +BasicOView.prototype.getCellValue = +function bov_getcellval (row, col) +{ +} + +BasicOView.prototype.getCellText = +function bov_getcelltxt (row, col) +{ + if (!this.columnNames) + return ""; + + if (typeof col == "object") + col = col.id; + + var ary = col.match (/:(.*)/); + if (ary) + col = ary[1]; + + var colName = this.columnNames[col]; + + if (typeof colName == "undefined") + return ""; + + return this.data[row][colName]; +} + +BasicOView.prototype.setTree = +function bov_seto (tree) +{ + this.tree = tree; +} + +BasicOView.prototype.toggleOpenState = +function bov_toggleopen (index) +{ +} + +BasicOView.prototype.cycleHeader = +function bov_cyclehdr (col) +{ +} + +BasicOView.prototype.selectionChanged = +function bov_selchg () +{ +} + +BasicOView.prototype.cycleCell = +function bov_cyclecell (row, col) +{ +} + +BasicOView.prototype.isEditable = +function bov_isedit (row, col) +{ + return false; +} + +BasicOView.prototype.setCellValue = +function bov_setct (row, col, value) +{ +} + +BasicOView.prototype.setCellText = +function bov_setct (row, col, value) +{ +} + +BasicOView.prototype.onRouteFocus = +function bov_rfocus (event) +{ + if ("onFocus" in this) + this.onFocus(event); +} + +BasicOView.prototype.onRouteBlur = +function bov_rblur (event) +{ + if ("onBlur" in this) + this.onBlur(event); +} + +BasicOView.prototype.onRouteDblClick = +function bov_rdblclick (event) +{ + if (!("onRowCommand" in this) || event.target.localName != "treechildren") + return; + + var rowIndex = this.tree.view.selection.currentIndex; + if (rowIndex == -1 || rowIndex > this.rowCount) + return; + var rec = this.childData.locateChildByVisualRow(rowIndex); + if (!rec) + { + ASSERT (0, "bogus row index " + rowIndex); + return; + } + + this.onRowCommand(rec, event); +} + +BasicOView.prototype.onRouteKeyPress = +function bov_rkeypress (event) +{ + var rec; + var rowIndex; + + if ("onRowCommand" in this && (event.keyCode == 13 || event.charCode == 32)) + { + if (!this.selection) + return; + + rowIndex = this.tree.view.selection.currentIndex; + if (rowIndex == -1 || rowIndex > this.rowCount) + return; + rec = this.childData.locateChildByVisualRow(rowIndex); + if (!rec) + { + ASSERT (0, "bogus row index " + rowIndex); + return; + } + + this.onRowCommand(rec, event); + } + else if ("onKeyPress" in this) + { + rowIndex = this.tree.view.selection.currentIndex; + if (rowIndex != -1 && rowIndex < this.rowCount) + { + rec = this.childData.locateChildByVisualRow(rowIndex); + if (!rec) + { + ASSERT (0, "bogus row index " + rowIndex); + return; + } + } + else + { + rec = null; + } + + this.onKeyPress(rec, event); + } +} + +BasicOView.prototype.performAction = +function bov_pact (action) +{ +} + +BasicOView.prototype.performActionOnRow = +function bov_pactrow (action) +{ +} + +BasicOView.prototype.performActionOnCell = +function bov_pactcell (action) +{ +} + +/* + * record for the XULTreeView. these things take care of keeping the + * XULTreeView properly informed of changes in value and child count. you + * shouldn't have to maintain tree state at all. + * + * |share| should be an otherwise empty object to store cache data. + * you should use the same object as the |share| for the XULTreeView that you + * indend to contain these records. + * + */ +function XULTreeViewRecord(share) +{ + this._share = share; + this.visualFootprint = 1; + this.isHidden = true; /* records are considered hidden until they are + * inserted into a live tree */ +} + +XULTreeViewRecord.prototype.properties = ""; + +XULTreeViewRecord.prototype.isContainerOpen = false; + +/* + * walk the parent tree to find our tree container. return null if there is + * none + */ +XULTreeViewRecord.prototype.findContainerTree = +function xtvr_gettree () +{ + if (!("parentRecord" in this)) + return null; + var parent = this.parentRecord; + + while (parent) + { + if ("_treeView" in parent) + return parent._treeView; + if ("parentRecord" in parent) + parent = parent.parentRecord; + else + parent = null; + } + + return null; +} + +XULTreeViewRecord.prototype.__defineGetter__("childIndex", xtvr_getChildIndex); +function xtvr_getChildIndex () +{ + //dd ("getChildIndex {"); + + if (!("parentRecord" in this)) + { + delete this._childIndex; + //dd ("} -1"); + return -1; + } + + if ("_childIndex" in this) + { + if ("childData" in this && this._childIndex in this.childData && + this.childData[this._childIndex] == this) + { + //dd ("} " + this._childIndex); + return this._childIndex; + } + } + + var childData = this.parentRecord.childData; + var len = childData.length; + for (var i = 0; i < len; ++i) + { + if (childData[i] == this) + { + this._childIndex = i; + //dd ("} " + this._childIndex); + return i; + } + } + + delete this._childIndex; + //dd ("} -1"); + return -1; +} + +XULTreeViewRecord.prototype.__defineSetter__("childIndex", xtvr_setChildIndex); +function xtvr_setChildIndex () +{ + dd("xtvr: childIndex is read only, ignore attempt to write to it\n"); + if (typeof getStackTrace == "function") + dd(getStackTrace()); +} + +/* count the number of parents, not including the root node */ +XULTreeViewRecord.prototype.__defineGetter__("level", xtvr_getLevel); +function xtvr_getLevel () +{ + if (!("parentRecord" in this)) + return -1; + + var rv = 0; + var parentRecord = this.parentRecord; + while ("parentRecord" in parentRecord && + (parentRecord = parentRecord.parentRecord)) ++rv; + return rv; +} + +/* + * associates a property name on this record, with a column in the tree. This + * method will set up a get/set pair for the property name you specify which + * will take care of updating the tree when the value changes. DO NOT try + * to change your mind later. Do not attach a different name to the same colID, + * and do not rename the colID. You have been warned. + */ +XULTreeViewRecord.prototype.setColumnPropertyName = +function xtvr_setcol (colID, propertyName) +{ + function xtvr_getValueShim () + { + return this._colValues[colID]; + } + function xtvr_setValueShim (newValue) + { + this._colValues[colID] = newValue; + return newValue; + } + + if (!("_colValues" in this)) + this._colValues = new Object(); + if (!("_colProperties" in this)) + this._colProperties = new Object(); + + if (typeof propertyName == "function") + { + this._colValues.__defineGetter__(colID, propertyName); + } + else + { + this.__defineGetter__(propertyName, xtvr_getValueShim); + this.__defineSetter__(propertyName, xtvr_setValueShim); + } +} + +XULTreeViewRecord.prototype.setColumnPropertyValue = +function xtvr_setcolv (colID, value) +{ + this._colValues[colID] = value; +} + +XULTreeViewRecord.prototype.setColumnProperties = +function xtvr_setcolp (colID, value) +{ + this._colProperties[colID] = value; +} + +/* + * set the default sort column and reSort. + */ +XULTreeViewRecord.prototype.setSortColumn = +function xtvr_setcol (colID, dir) +{ + //dd ("setting sort column to " + colID); + this._share.sortColumn = colID; + this._share.sortDirection = (typeof dir == "undefined") ? 1 : dir; + this.reSort(); +} + +/* + * set the default sort direction. 1 is ascending, -1 is descending, 0 is no + * sort. setting this to 0 will *not* recover the natural insertion order, + * it will only affect newly added items. + */ +XULTreeViewRecord.prototype.setSortDirection = +function xtvr_setdir (dir) +{ + this._share.sortDirection = dir; +} + +/* + * invalidate this row in the tree + */ +XULTreeViewRecord.prototype.invalidate = +function xtvr_invalidate() +{ + var tree = this.findContainerTree(); + if (tree) + { + var row = this.calculateVisualRow(); + if (row != -1) + tree.tree.invalidateRow(row); + } +} + +/* + * invalidate any data in the cache. + */ +XULTreeViewRecord.prototype.invalidateCache = +function xtvr_killcache() +{ + this._share.rowCache = new Object(); + this._share.lastComputedIndex = -1; + this._share.lastIndexOwner = null; +} + +/* + * default comparator function for sorts. if you want a custom sort, override + * this method. We declare xtvr_sortcmp as a top level function, instead of + * a function expression so we can refer to it later. + */ +XULTreeViewRecord.prototype.sortCompare = xtvr_sortcmp; +function xtvr_sortcmp (a, b) +{ + var sc = a._share.sortColumn; + var sd = a._share.sortDirection; + + a = a[sc]; + b = b[sc]; + + if (a < b) + return -1 * sd; + + if (a > b) + return 1 * sd; + + return 0; +} + +/* + * this method will cause all child records to be reSorted. any records + * with the default sortCompare method will be sorted by the colID passed to + * setSortColumn. + * + * the local parameter is used internally to control whether or not the + * sorted rows are invalidated. don't use it yourself. + */ +XULTreeViewRecord.prototype.reSort = +function xtvr_resort (leafSort) +{ + if (!("childData" in this) || this.childData.length < 1 || + (this.childData[0].sortCompare == xtvr_sortcmp && + !("sortColumn" in this._share) || this._share.sortDirection == 0)) + { + /* if we have no children, or we have the default sort compare and no + * sort flags, then just exit */ + return; + } + + this.childData.sort(this.childData[0].sortCompare); + + for (var i = 0; i < this.childData.length; ++i) + { + if ("isContainerOpen" in this.childData[i] && + this.childData[i].isContainerOpen) + this.childData[i].reSort(true); + else + this.childData[i].sortIsInvalid = true; + } + + if (!leafSort) + { + this.invalidateCache(); + var tree = this.findContainerTree(); + if (tree && tree.tree) + { + var rowIndex = this.calculateVisualRow(); + /* + dd ("invalidating " + rowIndex + " - " + + (rowIndex + this.visualFootprint - 1)); + */ + tree.tree.invalidateRange (rowIndex, + rowIndex + this.visualFootprint - 1); + } + } + delete this.sortIsInvalid; +} + +/* + * call this to indicate that this node may have children at one point. make + * sure to call it before adding your first child. + */ +XULTreeViewRecord.prototype.reserveChildren = +function xtvr_rkids (always) +{ + if (!("childData" in this)) + this.childData = new Array(); + if (!("isContainerOpen" in this)) + this.isContainerOpen = false; + if (always) + this.alwaysHasChildren = true; + else + delete this.alwaysHasChildren; +} + +/* + * add a child to the end of the child list for this record. takes care of + * updating the tree as well. + */ +XULTreeViewRecord.prototype.appendChild = +function xtvr_appchild (child) +{ + if (!(child instanceof XULTreeViewRecord)) + throw Components.results.NS_ERROR_INVALID_ARG; + + child.isHidden = false; + child.parentRecord = this; + this.childData.push(child); + + if ("isContainerOpen" in this && this.isContainerOpen) + { + //dd ("appendChild: " + xtv_formatRecord(child, "")); + if (this.calculateVisualRow() >= 0) + { + var tree = this.findContainerTree(); + if (tree && tree.frozen) + this.needsReSort = true; + else + this.reSort(true); /* reSort, don't invalidate. we're going + * to do that in the + * onVisualFootprintChanged call. */ + } + this.onVisualFootprintChanged(child.calculateVisualRow(), + child.visualFootprint); + } +} + +/* + * add a list of children to the end of the child list for this record. + * faster than multiple appendChild() calls. + */ +XULTreeViewRecord.prototype.appendChildren = +function xtvr_appchild (children) +{ + var idx = this.childData.length; + var delta = 0; + var len = children.length; + for (var i = 0; i < len; ++i) + { + var child = children[i]; + child.isHidden = false; + child.parentRecord = this; + this.childData.push(child); + delta += child.visualFootprint; + } + + if ("isContainerOpen" in this && this.isContainerOpen) + { + if (this.calculateVisualRow() >= 0) + { + this.reSort(true); /* reSort, don't invalidate. we're going to do + * that in the onVisualFootprintChanged call. */ + } + this.onVisualFootprintChanged(this.childData[0].calculateVisualRow(), + delta); + } +} + +/* + * remove a child from this record. updates the tree too. DON'T call this with + * an index not actually contained by this record. + */ +XULTreeViewRecord.prototype.removeChildAtIndex = +function xtvr_remchild (index) +{ + if (!ASSERT(this.childData.length, "removing from empty childData")) + return; + + var orphan = this.childData[index]; + var fpDelta = -orphan.visualFootprint; + var changeStart = orphan.calculateVisualRow(); + delete orphan.parentRecord; + arrayRemoveAt (this.childData, index); + + if (!orphan.isHidden && "isContainerOpen" in this && this.isContainerOpen) + { + this.onVisualFootprintChanged (changeStart, fpDelta); + } +} + +/* + * hide this record and all descendants. + */ +XULTreeViewRecord.prototype.hide = +function xtvr_hide () +{ + if (this.isHidden) + return; + + /* get the row before hiding */ + var row = this.calculateVisualRow(); + this.invalidateCache(); + this.isHidden = true; + /* go right to the parent so we don't muck with our own visualFootprint + * record, we'll need it to be correct if we're ever unHidden. */ + if ("parentRecord" in this) + this.parentRecord.onVisualFootprintChanged (row, -this.visualFootprint); +} + +/* + * unhide this record and all descendants. + */ +XULTreeViewRecord.prototype.unHide = +function xtvr_uhide () +{ + if (!this.isHidden) + return; + + this.isHidden = false; + this.invalidateCache(); + var row = this.calculateVisualRow(); + if (this.parentRecord) + this.parentRecord.onVisualFootprintChanged (row, this.visualFootprint); +} + +/* + * open this record, exposing it's children. DON'T call this method if the + * record has no children. + */ +XULTreeViewRecord.prototype.open = +function xtvr_open () +{ + if (this.isContainerOpen) + return; + + if ("onPreOpen" in this) + this.onPreOpen(); + + this.isContainerOpen = true; + var delta = 0; + for (var i = 0; i < this.childData.length; ++i) + { + if (!this.childData[i].isHidden) + delta += this.childData[i].visualFootprint; + } + + /* this reSort should only happen if the sort column changed */ + this.reSort(true); + this.visualFootprint += delta; + if ("parentRecord" in this) + { + this.parentRecord.onVisualFootprintChanged(this.calculateVisualRow(), + 0); + this.parentRecord.onVisualFootprintChanged(this.calculateVisualRow() + + 1, delta); + } +} + +/* + * close this record, hiding it's children. DON'T call this method if the record + * has no children, or if it is already closed. + */ +XULTreeViewRecord.prototype.close = +function xtvr_close () +{ + if (!this.isContainerOpen) + return; + + this.isContainerOpen = false; + var delta = 1 - this.visualFootprint; + this.visualFootprint += delta; + if ("parentRecord" in this) + { + this.parentRecord.onVisualFootprintChanged(this.calculateVisualRow(), + 0); + this.parentRecord.onVisualFootprintChanged(this.calculateVisualRow() + + 1, delta); + } + + if ("onPostClose" in this) + this.onPostClose(); +} + +/* + * called when a node above this one grows or shrinks. we need to adjust + * our own visualFootprint to match the change, and pass the message on. + */ +XULTreeViewRecord.prototype.onVisualFootprintChanged = +function xtvr_vpchange (start, amount) +{ + /* if we're not hidden, but this notification came from a hidden node + * (start == -1), ignore it, it doesn't affect us. */ + if (start == -1 && !this.isHidden) + { + + //dd ("vfp change (" + amount + ") from hidden node ignored."); + return; + } + + this.visualFootprint += amount; + + if ("parentRecord" in this) + this.parentRecord.onVisualFootprintChanged(start, amount); +} + +/* + * calculate the "visual" row for this record. If the record isn't actually + * visible return -1. + * eg. + * Name Visual Row + * node1 0 + * node11 1 + * node12 2 + * node2 3 + * node21 4 + * node3 5 + */ +XULTreeViewRecord.prototype.calculateVisualRow = +function xtvr_calcrow () +{ + /* if this is the second time in a row that someone asked us, fetch the last + * result from the cache. */ + if (this._share.lastIndexOwner == this) + return this._share.lastComputedIndex; + + var vrow; + + /* if this is an uninserted or hidden node, or... */ + if (!("parentRecord" in this) || (this.isHidden) || + /* if parent isn't open, or... */ + (!this.parentRecord.isContainerOpen) || + /* parent isn't visible */ + ((vrow = this.parentRecord.calculateVisualRow()) == -1)) + { + /* then we're not visible, return -1 */ + //dd ("cvr: returning -1"); + return -1; + } + + /* parent is the root node XXX parent is not visible */ + if (vrow == null) + vrow = 0; + else + /* parent is not the root node, add one for the space they take up. */ + ++vrow; + + /* add in the footprint for all of the earlier siblings */ + var ci = this.childIndex; + for (var i = 0; i < ci; ++i) + { + if (!this.parentRecord.childData[i].isHidden) + vrow += this.parentRecord.childData[i].visualFootprint; + } + + /* save this calculation to the cache. */ + this._share.lastIndexOwner = this; + this._share.lastComputedIndex = vrow; + + return vrow; +} + +/* + * locates the child record for the visible row |targetRow|. DO NOT call this + * with a targetRow less than this record's visual row, or greater than this + * record's visual row + the number of visible children it has. + */ +XULTreeViewRecord.prototype.locateChildByVisualRow = +function xtvr_find (targetRow, myRow) +{ + if (targetRow in this._share.rowCache) + return this._share.rowCache[targetRow]; + + /* if this is true, we *are* the index */ + if (targetRow == myRow) + return (this._share.rowCache[targetRow] = this); + + /* otherwise, we've got to search the kids */ + var childStart = myRow; /* childStart represents the starting visual row + * for the child we're examining. */ + for (var i = 0; i < this.childData.length; ++i) + { + var child = this.childData[i]; + /* ignore hidden children */ + if (child.isHidden) + continue; + /* if this kid is the targetRow, we're done */ + if (childStart == targetRow) + return (this._share.rowCache[targetRow] = child); + /* if this kid contains the index, ask *it* to find the record */ + else if (targetRow <= childStart + child.visualFootprint) { + /* this *has* to succeed */ + var rv = child.locateChildByVisualRow(targetRow, childStart + 1); + //XXXASSERT (rv, "Can't find a row that *has* to be there."); + /* don't cache this, the previous call to locateChildByVisualRow + * just did. */ + return rv; + } + + /* otherwise, get ready to ask the next kid */ + childStart += child.visualFootprint; + } + + return null; +} + +/* XTLabelRecords can be used to drop a label into an arbitrary place in an + * arbitrary tree. normally, specializations of XULTreeViewRecord are tied to + * a specific tree because of implementation details. XTLabelRecords are + * specially designed (err, hacked) to work around these details. this makes + * them slower, but more generic. + * + * we set up a getter for _share that defers to the parent object. this lets + * XTLabelRecords work in any tree. + */ +function XTLabelRecord (columnName, label, blankCols) +{ + this.setColumnPropertyName (columnName, "label"); + this.label = label; + this.property = null; + + if (typeof blankCols == "object") + { + for (var i in blankCols) + this._colValues[blankCols[i]] = ""; + } +} + +XTLabelRecord.prototype = new XULTreeViewRecord (null); + +XTLabelRecord.prototype.__defineGetter__("_share", tolr_getshare); +function tolr_getshare() +{ + if ("parentRecord" in this) + return this.parentRecord._share; + + ASSERT (0, "XTLabelRecord cannot be the root of a visible tree."); + return null; +} + +/* XTRootRecord is used internally by XULTreeView, you probably don't need to + * make any of these */ +function XTRootRecord (tree, share) +{ + this._share = share; + this._treeView = tree; + this.visualFootprint = 0; + this.isHidden = false; + this.reserveChildren(); + this.isContainerOpen = true; +} + +/* no cache passed in here, we set it in the XTRootRecord contructor instead. */ +XTRootRecord.prototype = new XULTreeViewRecord (null); + +XTRootRecord.prototype.open = +XTRootRecord.prototype.close = +function torr_notimplemented() +{ + /* don't do this on a root node */ +} + +XTRootRecord.prototype.calculateVisualRow = +function torr_calcrow () +{ + return null; +} + +XTRootRecord.prototype.reSort = +function torr_resort () +{ + if ("_treeView" in this && this._treeView.frozen) + { + this._treeView.needsReSort = true; + return; + } + + if (!("childData" in this) || this.childData.length < 1 || + (this.childData[0].sortCompare == xtvr_sortcmp && + !("sortColumn" in this._share) || this._share.sortDirection == 0)) + { + /* if we have no children, or we have the default sort compare but we're + * missing a sort flag, then just exit */ + return; + } + + this.childData.sort(this.childData[0].sortCompare); + + for (var i = 0; i < this.childData.length; ++i) + { + if ("isContainerOpen" in this.childData[i] && + this.childData[i].isContainerOpen) + this.childData[i].reSort(true); + else + this.childData[i].sortIsInvalid = true; + } + + if ("_treeView" in this && this._treeView.tree) + { + /* + dd ("root node: invalidating 0 - " + this.visualFootprint + + " for sort"); + */ + this.invalidateCache(); + this._treeView.tree.invalidateRange (0, this.visualFootprint); + } +} + +XTRootRecord.prototype.locateChildByVisualRow = +function torr_find (targetRow) +{ + if (targetRow in this._share.rowCache) + return this._share.rowCache[targetRow]; + + var childStart = -1; /* childStart represents the starting visual row + * for the child we're examining. */ + for (var i = 0; i < this.childData.length; ++i) + { + var child = this.childData[i]; + /* ignore hidden children */ + if (child.isHidden) + continue; + /* if this kid is the targetRow, we're done */ + if (childStart == targetRow) + return (this._share.rowCache[targetRow] = child); + /* if this kid contains the index, ask *it* to find the record */ + else if (targetRow <= childStart + child.visualFootprint) { + /* this *has* to succeed */ + var rv = child.locateChildByVisualRow(targetRow, childStart + 1); + //XXXASSERT (rv, "Can't find a row that *has* to be there."); + /* don't cache this, the previous call to locateChildByVisualRow + * just did. */ + return rv; + } + + /* otherwise, get ready to ask the next kid */ + childStart += child.visualFootprint; + } + + return null; +} + +XTRootRecord.prototype.onVisualFootprintChanged = +function torr_vfpchange (start, amount) +{ + if (!this._treeView.frozen) + { + this.invalidateCache(); + this.visualFootprint += amount; + if ("_treeView" in this && "tree" in this._treeView && + this._treeView.tree) + { + if (amount != 0) + this._treeView.tree.rowCountChanged (start, amount); + else + this._treeView.tree.invalidateRow (start); + } + } + else + { + if ("changeAmount" in this._treeView) + this._treeView.changeAmount += amount; + else + this._treeView.changeAmount = amount; + if ("changeStart" in this._treeView) + this._treeView.changeStart = + Math.min (start, this._treeView.changeStart); + else + this._treeView.changeStart = start; + } +} + +/* + * XULTreeView provides functionality of tree whose elements have multiple + * levels of children. + */ + +function XULTreeView(share) +{ + if (!share) + share = new Object(); + this.childData = new XTRootRecord(this, share); + this.childData.invalidateCache(); + this.tree = null; + this.share = share; + this.frozen = 0; +} + +/* functions *you* should call to initialize and maintain the tree state */ + +/* + * Changes to the tree contents will not cause the tree to be invalidated + * until thaw() is called. All changes will be pooled into a single invalidate + * call. + * + * Freeze/thaws are nestable, the tree will not update until the number of + * thaw() calls matches the number of freeze() calls. + */ +XULTreeView.prototype.freeze = +function xtv_freeze () +{ + if (++this.frozen == 1) + { + this.changeStart = 0; + this.changeAmount = 0; + } + //dd ("freeze " + this.frozen); +} + +/* + * Reflect any changes to the tree content since the last freeze. + */ +XULTreeView.prototype.thaw = +function xtv_thaw () +{ + if (this.frozen == 0) + { + ASSERT (0, "not frozen"); + return; + } + + if (--this.frozen == 0 && "changeStart" in this) + { + this.childData.onVisualFootprintChanged(this.changeStart, + this.changeAmount); + } + + if ("needsReSort" in this) { + this.childData.reSort(); + delete this.needsReSort; + } + + + delete this.changeStart; + delete this.changeAmount; +} + +XULTreeView.prototype.saveBranchState = +function xtv_savebranch (target, source, recurse) +{ + var len = source.length; + for (var i = 0; i < len; ++i) + { + if (source[i].isContainerOpen) + { + target[i] = new Object(); + target[i].name = source[i]._colValues["col-0"]; + if (recurse) + this.saveBranchState (target[i], source[i].childData, true); + } + } +} + +XULTreeView.prototype.restoreBranchState = +function xtv_restorebranch (target, source, recurse) +{ + for (var i in source) + { + if (typeof source[i] == "object") + { + var name = source[i].name; + var len = target.length; + for (var j = 0; j < len; ++j) + { + if (target[j]._colValues["col-0"] == name && + "childData" in target[j]) + { + //dd ("opening " + name); + target[j].open(); + if (recurse) + { + this.restoreBranchState (target[j].childData, + source[i], true); + } + break; + } + } + } + } +} + +/* scroll the line specified by |line| to the center of the tree */ +XULTreeView.prototype.centerLine = +function xtv_ctrln (line) +{ + var first = this.tree.getFirstVisibleRow(); + var last = this.tree.getLastVisibleRow(); + this.scrollToRow(line - (last - first + 1) / 2); +} + +/* + * functions the tree will call to retrieve the list state (nsITreeView.) + */ + +XULTreeView.prototype.__defineGetter__("rowCount", xtv_getRowCount); +function xtv_getRowCount () +{ + if (!this.childData) + return 0; + + return this.childData.visualFootprint; +} + +XULTreeView.prototype.isContainer = +function xtv_isctr (index) +{ + var row = this.childData.locateChildByVisualRow (index); + + return Boolean(row && ("alwaysHasChildren" in row || "childData" in row)); +} + +XULTreeView.prototype.__defineGetter__("selectedIndex", xtv_getsel); +function xtv_getsel() +{ + if (!this.tree || this.tree.view.selection.getRangeCount() < 1) + return -1; + + var min = new Object(); + this.tree.view.selection.getRangeAt(0, min, {}); + return min.value; +} + +XULTreeView.prototype.__defineSetter__("selectedIndex", xtv_setsel); +function xtv_setsel(i) +{ + this.tree.view.selection.clearSelection(); + if (i != -1) + this.tree.view.selection.timedSelect (i, 500); + return i; +} + +XULTreeView.prototype.scrollTo = BasicOView.prototype.scrollTo; + +XULTreeView.prototype.isContainerOpen = +function xtv_isctropen (index) +{ + var row = this.childData.locateChildByVisualRow (index); + return row && row.isContainerOpen; +} + +XULTreeView.prototype.toggleOpenState = +function xtv_toggleopen (index) +{ + var row = this.childData.locateChildByVisualRow (index); + //ASSERT(row, "bogus row"); + if (row) + { + if (row.isContainerOpen) + row.close(); + else + row.open(); + } +} + +XULTreeView.prototype.isContainerEmpty = +function xtv_isctrempt (index) +{ + var row = this.childData.locateChildByVisualRow (index); + if ("alwaysHasChildren" in row) + return false; + + if (!row || !("childData" in row)) + return true; + + return !row.childData.length; +} + +XULTreeView.prototype.isSeparator = +function xtv_isseparator (index) +{ + return false; +} + +XULTreeView.prototype.getParentIndex = +function xtv_getpi (index) +{ + if (index < 0) + return -1; + + var row = this.childData.locateChildByVisualRow (index); + + var rv = row.parentRecord.calculateVisualRow(); + //dd ("getParentIndex: row " + index + " returning " + rv); + return (rv != null) ? rv : -1; +} + +XULTreeView.prototype.hasNextSibling = +function xtv_hasnxtsib (rowIndex, afterIndex) +{ + var row = this.childData.locateChildByVisualRow (rowIndex); + return row.childIndex < row.parentRecord.childData.length - 1; +} + +XULTreeView.prototype.getLevel = +function xtv_getlvl (index) +{ + var row = this.childData.locateChildByVisualRow (index); + if (!row) + return 0; + + return row.level; +} + +XULTreeView.prototype.getImageSrc = +function xtv_getimgsrc (index, col) +{ +} + +XULTreeView.prototype.getProgressMode = +function xtv_getprgmode (index, col) +{ +} + +XULTreeView.prototype.getCellValue = +function xtv_getcellval (index, col) +{ +} + +XULTreeView.prototype.getCellText = +function xtv_getcelltxt (index, col) +{ + var row = this.childData.locateChildByVisualRow (index); + //ASSERT(row, "bogus row " + index); + + if (typeof col == "object") + col = col.id; + + var ary = col.match (/:(.*)/); + if (ary) + col = ary[1]; + + if (row && row._colValues && col in row._colValues) + return row._colValues[col]; + else + return ""; +} + +XULTreeView.prototype.getCellProperties = +function xtv_cellprops (row, col, properties) +{ + var row = this.childData.locateChildByVisualRow (row); + + if (typeof col == "object") + col = col.id; + + var ary = col.match (/:(.*)/); + if (ary) + col = ary[1]; + + if (row && row._colProperties && col in row._colProperties) + xtv_atomizeText(row._colProperties[col], properties); +} + +XULTreeView.prototype.getColumnProperties = +function xtv_colprops (col, properties) +{} + +XULTreeView.prototype.getRowProperties = +function xtv_rowprops (index, properties) +{ + var row = this.childData.locateChildByVisualRow (index); + + xtv_atomizeText(row.properties, properties); +} + +XULTreeView.prototype.isSorted = +function xtv_issorted (index) +{ + return false; +} + +XULTreeView.prototype.canDrop = +function xtv_drop (index, orientation) +{ + var row = this.childData.locateChildByVisualRow (index); + //ASSERT(row, "bogus row " + index); + return (row && ("canDrop" in row) && row.canDrop(orientation)); +} + +XULTreeView.prototype.drop = +function xtv_drop (index, orientation) +{ + var row = this.childData.locateChildByVisualRow (index); + //ASSERT(row, "bogus row " + index); + return (row && ("drop" in row) && row.drop(orientation)); +} + +XULTreeView.prototype.setTree = +function xtv_seto (tree) +{ + this.childData.invalidateCache(); + this.tree = tree; +} + +XULTreeView.prototype.cycleHeader = +function xtv_cyclehdr (col) +{ +} + +XULTreeView.prototype.selectionChanged = +function xtv_selchg () +{ +} + +XULTreeView.prototype.cycleCell = +function xtv_cyclecell (row, col) +{ +} + +XULTreeView.prototype.isEditable = +function xtv_isedit (row, col) +{ + return false; +} + +XULTreeView.prototype.setCellValue = +function xtv_setct (row, col, value) +{ +} + +XULTreeView.prototype.setCellText = +function xtv_setct (row, col, value) +{ +} + +XULTreeView.prototype.performAction = +function xtv_pact (action) +{ +} + +XULTreeView.prototype.performActionOnRow = +function xtv_pactrow (action) +{ +} + +XULTreeView.prototype.performActionOnCell = +function xtv_pactcell (action) +{ +} + +XULTreeView.prototype.onRouteFocus = +function xtv_rfocus (event) +{ + if ("onFocus" in this) + this.onFocus(event); +} + +XULTreeView.prototype.onRouteBlur = +function xtv_rblur (event) +{ + if ("onBlur" in this) + this.onBlur(event); +} + +XULTreeView.prototype.onRouteDblClick = +function xtv_rdblclick (event) +{ + if (!("onRowCommand" in this) || event.target.localName != "treechildren") + return; + + var rowIndex = this.tree.view.selection.currentIndex; + if (rowIndex == -1 || rowIndex > this.rowCount) + return; + var rec = this.childData.locateChildByVisualRow(rowIndex); + if (!rec) + { + ASSERT (0, "bogus row index " + rowIndex); + return; + } + + this.onRowCommand(rec, event); +} + +XULTreeView.prototype.onRouteKeyPress = +function xtv_rkeypress (event) +{ + var rec; + var rowIndex; + + if ("onRowCommand" in this && (event.keyCode == 13 || event.charCode == 32)) + { + if (!this.selection) + return; + + rowIndex = this.tree.view.selection.currentIndex; + if (rowIndex == -1 || rowIndex > this.rowCount) + return; + rec = this.childData.locateChildByVisualRow(rowIndex); + if (!rec) + { + ASSERT (0, "bogus row index " + rowIndex); + return; + } + + this.onRowCommand(rec, event); + } + else if ("onKeyPress" in this) + { + rowIndex = this.tree.view.selection.currentIndex; + if (rowIndex != -1 && rowIndex < this.rowCount) + { + rec = this.childData.locateChildByVisualRow(rowIndex); + if (!rec) + { + ASSERT (0, "bogus row index " + rowIndex); + return; + } + } + else + { + rec = null; + } + + this.onKeyPress(rec, event); + } +} + +/******************************************************************************/ + +function xtv_atomizeText (text, array) +{ + var atomservice = Components.classes["@mozilla.org/atom-service;1"] + .getService(Components.interfaces.nsIAtomService); + + var parts = text.split(" "); + for (var i = 0; i<parts.length; i++) + { + var atom = atomservice.getAtom(parts[i]); + array.AppendElement(atom); + } +} + +function xtv_formatRecord (rec, indent) +{ + var str = ""; + + for (var i in rec._colValues) + str += rec._colValues[i] + ", "; + + str += "["; + + str += rec.calculateVisualRow() + ", "; + str += rec.childIndex + ", "; + str += rec.level + ", "; + str += rec.visualFootprint + ", "; + str += rec.isHidden + "]"; + + return (indent + str); +} + +function xtv_formatBranch (rec, indent, recurse) +{ + var str = ""; + for (var i = 0; i < rec.childData.length; ++i) + { + str += xtv_formatRecord (rec.childData[i], indent) + "\n"; + if (recurse) + { + if ("childData" in rec.childData[i]) + str += xtv_formatBranch(rec.childData[i], indent + " ", + --recurse); + } + } + + return str; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/leaks/leaks.html Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,22 @@ +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<style> +p { + font-family: monospace; + margin: 0; +} + +.leaked { + color: red; +} + +.ignored { + color: grey; +} +</style> +<style id="filters"> +</style> +</head> +<body> +</body> +</html>
--- /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);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/leaks/leaks.xul Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,89 @@ +<?xml version="1.0"?> + +<!DOCTYPE window SYSTEM "chrome://nightly/locale/leaks.dtd"> + +<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?> +<?xml-stylesheet href="chrome://nightly/skin/leaks/leaks.css" type="text/css"?> + +<window id="LeakReporter" type="Nightly:LeakReporter" + title="&nightly.leaks.title;" style="padding: 10px; width: 80em; height: 60em" + persist="width height screenX screenY" + xmlns:xhtml="http://www.w3.org/1999/xhtml" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + +<xhtml:style> +.leaked { + color: red; +} + +.uri { + padding-left: 2em; +} +</xhtml:style> + + <script type="application/x-javascript" src="leaks.js"/> + <script type="application/x-javascript" src="chrome://nightly/content/platform.js" /> + + <stringbundleset> + <stringbundle id="bundle" src="chrome://nightly/locale/leaks.properties"/> + </stringbundleset> + + <vbox style="padding-bottom: 1em"> + <hbox align="center"> + <label value="&nightly.leaks.logfile.label;"/> + <textbox id="nsprlog" onchange="textEnter()" flex="1"/> + <button id="filebrowse" oncommand="selectLog()" label="&nightly.leaks.browse.label;"/> + </hbox> + + <checkbox id="showlog" oncommand="flipLog()" label="&nightly.leaks.displayfull.label;"/> + </vbox> + + <stack flex="1"> + <vbox align="center" pack="center"> + <label style="font-size: 200%;" value="&nightly.leaks.loading.label;"/> + </vbox> + <tabbox id="tabbox" flex="1"> + <tabs> + <tab label="&nightly.leaks.overview.label;"/> + <tab label="&nightly.leaks.fulllog.label;"/> + </tabs> + <tabpanels flex="1"> + <tabpanel orient="vertical"> + <hbox pack="start"> + <button id="btnCopy" disabled="true" oncommand="clipboardCopy()" label="&nightly.leaks.copy.label;"/> + <button id="btnSave" disabled="true" oncommand="save()" label="&nightly.leaks.save.label;"/> + </hbox> + <vbox id="summary" collapsed="true"> + <label style="font-size: 200%;" value="&nightly.leaks.summary.label;"/> + <separator/> + <label id="buildid"/> + <hbox><label id="date"/></hbox> + <separator/> + <label id="windowLeaks"/> + <label id="documentLeaks"/> + <label id="docshellLeaks"/> + </vbox> + <separator/> + <vbox id="detailsbox" flex="1" collapsed="true"> + <label style="font-size: 200%;" value="&nightly.leaks.details.label;"/> + <separator/> + <vbox flex="1" id="details" style="overflow: auto"/> + </vbox> + </tabpanel> + <tabpanel orient="vertical"> + <hbox pack="start" align="center"> + <label value="&nightly.leaks.display.label;"/> + <checkbox checked="true" oncommand="changeFilter()" id="filterDocshell" label="&nightly.leaks.docshellfilter.label;"/> + <checkbox checked="true" oncommand="changeFilter()" id="filterWindow" label="&nightly.leaks.windowfilter.label;"/> + <checkbox checked="true" oncommand="changeFilter()" id="filterDocument" label="&nightly.leaks.documentfilter.label;"/> + <checkbox checked="true" oncommand="changeFilter()" id="filterLeaked" label="&nightly.leaks.leakedfilter.label;"/> + <checkbox checked="true" oncommand="changeFilter()" id="filterCollected" label="&nightly.leaks.collectedfilter.label;"/> + <checkbox checked="true" oncommand="changeFilter()" id="filterIgnored" label="&nightly.leaks.unknownfilter.label;"/> + </hbox> + <iframe id="logframe" style="border: 1px solid threedshadow" flex="1"/> + </tabpanel> + </tabpanels> + </tabbox> + </stack> + +</window>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/messenger.js Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,98 @@ +var nightlyApp = { + +savedSetTitleFromFolder: window.setTitleFromFolder, +customTitle: '', + +init: function() +{ + var brandbundle = document.getElementById("bundle_brand"); + if (nightly.variables.name==null) + { + nightly.variables.name=brandbundle.getString("brandShortName"); + } + nightly.variables.defaulttitle=brandbundle.getString("brandShortName"); + nightly.variables.brandname=brandbundle.getString("brandFullName"); +}, + +openURL: function(url, event) +{ + var uri = Components.classes["@mozilla.org/network/io-service;1"] + .getService(Components.interfaces.nsIIOService) + .newURI(url, null, null); + + var protocolSvc = Components.classes["@mozilla.org/uriloader/external-protocol-service;1"] + .getService(Components.interfaces.nsIExternalProtocolService); + protocolSvc.loadUrl(uri); +}, + +detectLeaks: function(event) +{ + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] + .getService(Components.interfaces.nsIWindowMediator); + var win = wm.getMostRecentWindow("Nightly:LeakReporter"); + if (win) + win.focus(); + else + window.openDialog("chrome://nightly/content/leaks/leaks.xul", "_blank", "chrome,all,dialog=no"); +}, + +customSetTitleFromFolder: function(msgfolder, subject) +{ + var brandbundle = document.getElementById("bundle_brand"); + var end = " - "+brandbundle.getString("brandShortName"); + nightlyApp.savedSetTitleFromFolder(msgfolder,subject); + + var title; + if ((document.title)&&(document.title.length>0)) + { + title = document.title; + } + else + { + title = window.title; + } + + if (title.substring(title.length-end.length)==end) + { + title=title.substring(0,title.length-end.length); + if (nightlyApp.customTitle && nightlyApp.customTitle.length>0) + title=title+' - '+nightlyApp.customTitle; + } + + if ((document.title)&&(document.title.length>0)) + { + document.title=title; + } + else + { + window.title=title; + } +}, + +updateTitle: function() +{ + if (gDBView) + window.setTitleFromFolder(gDBView.msgFolder,null); +}, + +setCustomTitle: function(title) +{ + nightlyApp.customTitle=title; + window.setTitleFromFolder=nightlyApp.customSetTitleFromFolder; + nightlyApp.updateTitle(); +}, + +setBlankTitle: function() +{ + nightlyApp.customTitle=''; + window.setTitleFromFolder=nightlyApp.customSetTitleFromFolder; + nightlyApp.updateTitle(); +}, + +setStandardTitle: function() +{ + window.setTitleFromFolder=nightlyApp.savedSetTitleFromFolder; + nightlyApp.updateTitle(); +} + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/messengerOverlay.xul Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,58 @@ +<?xml version="1.0"?> + +<!DOCTYPE window [ +<!ENTITY % nightlyDTD SYSTEM "chrome://nightly/locale/nightly.dtd"> +%nightlyDTD; +<!ENTITY % leaksDTD SYSTEM "chrome://nightly/locale/leaks.dtd"> +%leaksDTD; +]> + +<overlay id="NightlyMessengerOverlay" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <script type="application/x-javascript" src="nightly.js" /> + <script type="application/x-javascript" src="messenger.js" /> + <script type="application/x-javascript" src="breakpad/breakpad.js" /> + <script type="application/x-javascript" src="chrome://nightly/content/platform.js" /> + + <toolbarpalette id="MailToolbarPalette"> + <toolbarbutton id="nightly-tester-enter" + class="toolbarbutton-1" + label="&nightly.id.insert.label;" + tooltiptext="&nightly.id.insert.tooltip;" + oncommand="nightly.insertTemplate('buildid');"/> + </toolbarpalette> + + <popupset id="mainPopupSet"> + <tooltip orient="vertical" id="nightly-crashreport-tooltip" onpopupshowing="return crashreports.popupTooltip(event)"> + <label/> + </tooltip> + <popup id="nightly-crashreport-context"> + <menuitem oncommand="crashreports.copy(event)" label="&nightly.crashreports.copyid;"/> + </popup> + </popupset> + + <menupopup id="taskPopup"> + <menu id="nightly-menu" label="Nightly Tester Tools" insertafter="devToolsSeparator"> + <menupopup onpopupshowing="nightly.menuPopup(event,this);"> + <menuitem id="build-copy" label="&nightly.id.copy.label;" oncommand="nightly.copyTemplate('buildid');"/> + <menuitem id="build-insert" label="&nightly.id.insert.label;" oncommand="nightly.insertTemplate('buildid');"/> + <menuitem id="list-copy" label="&nightly.extensions.copy.label;" oncommand="nightly.copyExtensions();"/> + <menuitem id="list-insert" label="&nightly.extensions.insert.label;" oncommand="nightly.insertExtensions();"/> + <menuseparator/> + <menuitem label="&nightly.openprofile.label;" oncommand="nightly.openProfileDir();"/> + <menuseparator id="nightly-crashreports-separator"/> + <menu id="nightly-crashreports-recent" label="&nightly.crashreports.recentlist;" oncommand="crashreports.viewIncident(event);" onclick="checkForMiddleClick(this, event);"> + <menupopup id="nightly-crashreports-incidents"> + <menuitem disabled="true" label="&nightly.leaks.loading.label;"/> + </menupopup> + </menu> + <menuseparator/> + <menuitem label="&nightly.leakreporter.label;" oncommand="nightlyApp.detectLeaks(event);"/> + <menuseparator/> + <menuitem label="&nightly.options.label;" oncommand="nightly.launchOptions();"/> + </menupopup> + </menu> + </menupopup> + +</overlay>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/nightly.js Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,369 @@ +var nightly = { + +variables: { + _appInfo: null, + get appInfo() { + if (!this._appInfo) { + this._appInfo = Components.classes["@mozilla.org/xre/app-info;1"] + .getService(Components.interfaces.nsIXULAppInfo) + .QueryInterface(Components.interfaces.nsIXULRuntime); + } + return this._appInfo; + }, + + get appid() this.appInfo.ID, + get vendor() this.appInfo.vendor, + get name() this.appInfo.name, + get version() this.appInfo.version, + get appbuildid() this.appInfo.appBuildID, + get platformbuildid() this.appInfo.platformBuildID, + get platformversion() this.appInfo.platformVersion, + get geckobuildid() this.appInfo.platformBuildID, + get geckoversion() this.appInfo.platformVersion, + brandname: null, + get useragent() navigator.userAgent, + get locale() { + var registry = Components.classes["@mozilla.org/chrome/chrome-registry;1"] + .getService(Components.interfaces.nsIXULChromeRegistry); + return registry.getSelectedLocale("global"); + }, + get os() this.appInfo.OS, + get processor() this.appInfo.XPCOMABI.split("-")[0], + get compiler() this.appInfo.XPCOMABI.split("-")[1], + defaulttitle: null, + profile: null, + toolkit: "cairo", + flags: "" +}, + +templates: { +}, + +preferences: null, + +showAlert: function(id, args) { + var sbs = Components.classes["@mozilla.org/intl/stringbundle;1"] + .getService(Components.interfaces.nsIStringBundleService); + var bundle = sbs.createBundle("chrome://nightly/locale/nightly.properties"); + var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] + .getService(Components.interfaces.nsIPromptService); + var text=bundle.formatStringFromName(id, args, args.length); + promptService.alert(null, "Nightly Tester Tools", text); +}, + +init: function() { + window.removeEventListener("load", nightly.init, false); + var prefs = Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefService); + nightly.preferences = prefs.getBranch("nightly.") + .QueryInterface(Components.interfaces.nsIPrefBranchInternal); + nightly.preferences.addObserver("", nightly, false); + + var profd = Components.classes["@mozilla.org/file/directory_service;1"] + .getService(Components.interfaces.nsIProperties) + .get("ProfD", Components.interfaces.nsILocalFile); + var profservice = Components.classes["@mozilla.org/toolkit/profile-service;1"] + .getService(Components.interfaces.nsIToolkitProfileService); + var profiles = profservice.profiles; + while (profiles.hasMoreElements()) { + var profile = profiles.getNext().QueryInterface(Components.interfaces.nsIToolkitProfile); + if (profile.rootDir.path == profd.path) { + nightly.variables.profile = profile.name; + break; + } + } + + if (!nightly.variables.profile) + nightly.variables.profile = profd.leafName; + + nightlyApp.init(); + nightly.prefChange("idtitle"); + + var lastVersion = 0; + try { + lastVersion = nightly.preferences.getCharPref("lastVersion"); + if (lastVersion != "2.0.2") { + } + } + catch (e) { + var checkCompatibility = true; + var checkUpdateSecurity = true; + if (prefs.prefHasUserValue("extensions.checkCompatibility")) + checkCompatibility = prefs.getBoolPref("extensions.checkCompatibility"); + if (prefs.prefHasUserValue("extensions.checkUpdateSecurity")) + checkUpdateSecurity = prefs.getBoolPref("extensions.checkUpdateSecurity"); + if (!checkCompatibility || !checkUpdateSecurity) { + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] + .getService(Components.interfaces.nsIWindowMediator); + var win = wm.getMostRecentWindow("NightlyTester:ConfigWarning"); + if (win) { + win.focus(); + return; + } + + window.openDialog("chrome://nightly/content/configwarning.xul", "", + "dialog=no,titlebar,centerscreen,resizable=no"); + } + } + nightly.preferences.setCharPref("lastVersion", "2.0.2"); +}, + +unload: function(pref) { + window.removeEventListener("unload",nightly.unload,false); + nightly.preferences.removeObserver("",nightly); +}, + +prefChange: function(pref) { + if ((pref == "idtitle") || (pref == "templates.title")) { + if (nightly.preferences.getBoolPref("idtitle")) { + var title = nightly.getTemplate("title"); + if (title && title.length>0) + nightlyApp.setCustomTitle(nightly.generateText(title)); + else + nightlyApp.setBlankTitle(); + } + else { + nightlyApp.setStandardTitle(); + } + } +}, + +observe: function(prefBranch, subject, pref) { + nightly.prefChange(pref); +}, + +getStoredItem: function(type, name) { + name = name.toLowerCase(); + var varvalue = null; + try { + return nightly.preferences.getCharPref(type+"."+name); + } + catch (e) {} + return nightly[type][name]; +}, + +getVariable: function(name) { + return nightly.getStoredItem("variables",name); +}, + +getTemplate: function(name) { + return nightly.getStoredItem("templates",name); +}, + +generateText: function(template) { + var start = 0; + var pos = template.indexOf("${",start); + while (pos >= 0) { + if ((pos == 0) || (template.charAt(pos - 1) != "$")) { + var endpos = template.indexOf("}", pos + 2); + if (endpos >= 0) { + var varname = template.substring(pos+2,endpos); + var varvalue = nightly.getVariable(varname); + if (varvalue !== null) { + template = template.substring(0, pos) + varvalue + + template.substring(endpos + 1, template.length); + start = pos + varvalue.length; + } + else { + start = pos + 2; + } + } + else { + start = pos + 2; + } + } + else { + start = pos + 2; + } + pos = template.indexOf("${", start); + } + return template; +}, + +copyText: function(text) { + var clipboard = Components.classes["@mozilla.org/widget/clipboardhelper;1"]. + getService(Components.interfaces.nsIClipboardHelper); + clipboard.copyString(text); +}, + +copyTemplate: function(template) { + nightly.copyText(nightly.generateText(nightly.getTemplate(template))); +}, + +menuPopup: function(event, menupopup) { + if (menupopup == event.target) { + var attext = false; + + var element = document.commandDispatcher.focusedElement; + if (element) { + var type = element.localName.toLowerCase(); + attext = ((type == "input") || (type == "textarea")) + } + + var node=menupopup.firstChild; + while (node && node.localName!='menuseparator') { + if (node.id.substring(node.id.length - 7) == "-insert") + node.hidden = !attext; + if (node.id.substring(node.id.length - 5) == "-copy") + node.hidden = attext; + node=node.nextSibling; + } + } +}, + +insertTemplate: function(template) { + var element = document.commandDispatcher.focusedElement; + if (element) { + var type = element.localName.toLowerCase(); + if ((type == "input") || (type == "textarea")) { + var text = nightly.generateText(nightly.getTemplate(template)); + var newpos = element.selectionStart+text.length; + var value = element.value; + element.value = value.substring(0, element.selectionStart) + text + + value.substring(element.selectionEnd); + element.selectionStart = newpos; + element.selectionEnd = newpos; + return; + } + } + nightly.showAlert("nightly.notextbox.message", []); +}, + +insensitiveSort: function(a, b) { + a = a.toLowerCase(); + b = b.toLowerCase(); + if (a < b) + return -1 + if (a > b) + return 1 + // a must be equal to b + return 0 +}, + +getExtensionList: function() { + var em = Components.classes["@mozilla.org/extensions/manager;1"] + .getService(Components.interfaces.nsIExtensionManager); + + var items = em.getItemList(Components.interfaces.nsIUpdateItem.TYPE_EXTENSION, {}); + + if (items.length == 0) { + nightly.showAlert("nightly.noextensions.message", []); + return null; + } + + var rdfS = Components.classes["@mozilla.org/rdf/rdf-service;1"] + .getService(Components.interfaces.nsIRDFService); + var ds = em.datasource; + var disabledResource = rdfS.GetResource("http://www.mozilla.org/2004/em-rdf#disabled"); + var isDisabledResource = rdfS.GetResource("http://www.mozilla.org/2004/em-rdf#isDisabled"); + var text = []; + for (var i = 0; i < items.length; i++) { + text[i] = items[i].name + " " + items[i].version; + var source = rdfS.GetResource("urn:mozilla:item:" + items[i].id); + var disabled = ds.GetTarget(source, disabledResource, true); + if (!disabled) + disabled = ds.GetTarget(source, isDisabledResource, true); + try { + disabled=disabled.QueryInterface(Components.interfaces.nsIRDFLiteral); + if (disabled.Value=="true") + text[i]+=" [DISABLED]"; + } + catch (e) { } + } + text.sort(nightly.insensitiveSort); + return text.join("\n"); +}, + +insertExtensions: function() { + var element = document.commandDispatcher.focusedElement; + if (element) { + var type = element.localName.toLowerCase(); + if ((type == "input") || (type == "textarea")) { + var text = nightly.getExtensionList(); + var newpos = element.selectionStart + text.length; + var value = element.value; + element.value = value.substring(0, element.selectionStart) + text + + value.substring(element.selectionEnd); + element.selectionStart = newpos; + element.selectionEnd = newpos; + return; + } + } + nightly.showAlert("nightly.notextbox.message",[]); +}, + +copyExtensions: function() { + var text = nightly.getExtensionList(); + if (text) + nightly.copyText(text); +}, + +openProfileDir: function() { + var stream = Components.classes["@mozilla.org/network/file-input-stream;1"] + .createInstance(Components.interfaces.nsIFileInputStream); + var directoryService = Components.classes["@mozilla.org/file/directory_service;1"] + .getService(Components.interfaces.nsIProperties); + + var profile = directoryService.get("ProfD",Components.interfaces.nsILocalFile); + try { + profile.reveal(); + } + catch (ex) { + var uri = Components.classes["@mozilla.org/network/io-service;1"] + .getService(Components.interfaces.nsIIOService) + .newFileURI(profile); + var protocolSvc = Components.classes["@mozilla.org/uriloader/external-protocol-service;1"] + .getService(Components.interfaces.nsIExternalProtocolService); + protocolSvc.loadUrl(uri); + } +}, + +launch: function(file, args) { + var process = Components.classes["@mozilla.org/process/util;1"] + .createInstance(Components.interfaces.nsIProcess); + process.init(file); + if (args) + process.run(false, args, args.length); + else + process.run(false, null, 0); +}, + +alertType: function(type) { + var directoryService = Components.classes["@mozilla.org/file/directory_service;1"] + .getService(Components.interfaces.nsIProperties); + + var dir = directoryService.get(type, Components.interfaces.nsIFile); + window.alert(dir.path); +}, + +getScreenshot: function() { + window.openDialog("chrome://nightly/content/screenshot/screenshot.xul", "_blank", "chrome,all,dialog=no"); +}, + +launchOptions: function() { + var wm = Components.classes['@mozilla.org/appshell/window-mediator;1'] + .getService(Components.interfaces.nsIWindowMediator); + + var win = wm.getMostRecentWindow("NightlyTester:Options"); + if (win) { + win.focus(); + return; + } + + var features; + try { + var prefservice = Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefBranch); + var instantApply = prefservice.getBoolPref("browser.preferences.instantApply"); + features = "chrome,titlebar,toolbar,centerscreen" + (instantApply ? ",dialog=no" : ",modal"); + } + catch (e) { + features = "chrome,titlebar,toolbar,centerscreen,modal"; + } + openDialog("chrome://nightly/content/options/options.xul", "", features); +} + +} + +window.addEventListener("load", nightly.init, false); +window.addEventListener("unload", nightly.unload, false);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/options/options.xul Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,51 @@ +<?xml version="1.0"?> + +<?xml-stylesheet href="chrome://global/skin/global.css" type="text/css"?> +<?xml-stylesheet href="chrome://nightly/skin/options/options.css" type="text/css"?> + +<!DOCTYPE window SYSTEM "chrome://nightly/locale/options.dtd"> + +<prefwindow id="NightlyTesterOptions" windowtype="NightlyTester:Options" + title="&nightly.options.title;" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <script type="application/x-javascript" src="prefs.js"/> + + <prefpane id="paneTitle" label="&nightly.options.title;"> + + <preferences> + <preference id="idtitle" type="bool" name="nightly.idtitle" onchange="paneTitle.toggled();"/> + <preference id="title" type="string" name="nightly.templates.title"/> + </preferences> + + <script type="application/x-javascript" src="title.js"/> + + <stringbundle id="variablesBundle" src="chrome://nightly/locale/variables.properties"/> + + <description style="padding-bottom: 5px">&nightly.paneTitlebar.description;</description> + + <checkbox preference="idtitle" style="padding-bottom: 5px" id="enableTitleBar" label="&nightly.customtitle.label;"/> + + <hbox style="padding-bottom: 5px" align="center"> + <label value="&nightly.customtemplate.label;" control="customTitle"/> + <textbox preference="title" id="customTitle" flex="1"/> + </hbox> + + <description style="padding-bottom: 5px">&nightly.variables.description;</description> + + <listbox id="varList" flex="1"> + <listhead> + <listheader label="&nightly.variable.label;"/> + <listheader label="&nightly.variabledesc.label;"/> + <listheader label="&nightly.variablevalue.label;"/> + </listhead> + <listcols> + <listcol style="width: 9em"/> + <listcol flex="1"/> + <listcol style="width: 15em"/> + </listcols> + </listbox> + + </prefpane> + +</prefwindow>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/options/prefs.js Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,22 @@ +var prefs = { + +nightly: null, + +init: function() +{ + var mediator = Components.classes['@mozilla.org/appshell/window-mediator;1'] + .getService(Components.interfaces.nsIWindowMediator); + + var window = mediator.getMostRecentWindow("navigator:browser"); + if (!window) + window=mediator.getMostRecentWindow("mail:3pane"); + if (!window) + window=mediator.getMostRecentWindow("calendarMainWindow"); + if (!window) + window=mediator.getMostRecentWindow("Songbird:Main"); + if (window) + prefs.nightly=window.nightly; +} +} + +window.addEventListener("load",prefs.init,false);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/options/subpane.xml Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,107 @@ +<?xml version="1.0"?> + +<bindings id="SubPaneBindings" xmlns="http://www.mozilla.org/xbl" xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <binding id="subpane" name="subpane"> + + <content preference-editable="true" orient="vertical"> + </content> + + <implementation> + + <property name="action"> + <getter> + return this.getAttribute("action"); + </getter> + </property> + + <property name="_attribute"> + <getter> + if (this.action == "hide") + { + return "hidden"; + } + else if (this.action == "disable") + { + return "disabled"; + } + return ""; + </getter> + </property> + + <property name="_invert"> + <getter> + <![CDATA[ + var invert = false; + + if (this.action == "hide") + { + invert=true; + } + else if (this.action == "disable") + { + invert=true; + } + + if (this.hasAttribute("invert") && this.getAttribute("invert") == "true") + invert=!invert; + + return invert; + ]]> + </getter> + </property> + + <field name="_value"/> + <property name="value"> + <setter> + if (val == this._value) + return val; + + this._value = val; + this._updateElements(val); + + return val; + </setter> + <getter> + return this._value; + </getter> + </property> + + <method name="_setElementState"> + <parameter name="element"/> + <parameter name="state"/> + <body> + var attribute = this._attribute; + state = this._invert ? !state : state; + + if (attribute in element) + element[attribute] = state; + else + element.setAttribute(attribute, state); + </body> + </method> + + <method name="_updateElements"> + <parameter name="state"/> + <body> + if (this.action=="hide") + { + this.hidden = this._invert ? !state : state; + } + else + { + var element = this.firstChild; + while (element) + { + this._setElementState(element,state); + element = element.nextSibling; + } + } + </body> + </method> + + </implementation> + + </binding> + +</bindings> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/options/title.js Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,62 @@ +var paneTitle = { + +bundle: null, + +init: function() +{ + paneTitle.toggled(); + + paneTitle.bundle=document.getElementById("variablesBundle"); + + paneTitle.addVariable("DefaultTitle"); + paneTitle.addVariable("AppID"); + paneTitle.addVariable("Vendor"); + paneTitle.addVariable("Name"); + paneTitle.addVariable("Version"); + paneTitle.addVariable("AppBuildID"); + paneTitle.addVariable("PlatformBuildID"); + paneTitle.addVariable("PlatformVersion"); + paneTitle.addVariable("GeckoVersion"); + paneTitle.addVariable("BrandName"); + paneTitle.addVariable("UserAgent"); + paneTitle.addVariable("Locale"); + paneTitle.addVariable("OS"); + paneTitle.addVariable("Processor"); + paneTitle.addVariable("Compiler"); + paneTitle.addVariable("Toolkit"); + paneTitle.addVariable("Profile"); +}, + +addVariable: function(name) +{ + var list = document.getElementById("varList"); + var item = document.createElement("listitem"); + item.appendChild(document.createElement("listcell")).setAttribute('label',"${"+name+"}"); + var text = null; + try + { + var text = paneTitle.bundle.getString("variable."+name+".description"); + } catch (e) { } + if (text==null) + { + text=""; + } + item.appendChild(document.createElement("listcell")).setAttribute('label',text); + var value = prefs.nightly.getVariable(name); + if (value==null) + { + value="Undefined"; + } + item.appendChild(document.createElement("listcell")).setAttribute('label',value); + list.appendChild(item); +}, + +toggled: function() +{ + var checkbox = document.getElementById("enableTitleBar"); + var text = document.getElementById("customTitle"); + text.disabled=!checkbox.checked; +} +} + +window.addEventListener("load",paneTitle.init,false);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/platform.js Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,4 @@ +var nightlyplatform = { + eol: "\n" +} + \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/screenshot/providers.js Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,79 @@ +var Providers = { + _providers: [], + _selected: null, + + addProvider: function(provider) + { + this._providers.push(provider); + if (this._selected == null) + this._selected = provider; + }, + + selectProvider: function(provider) + { + this._selected = provider; + }, + + getSelectedProvider: function() + { + return this._selected; + }, + + getProviders: function() + { + return this._providers; + } +} + +var ImageShack = { + addFormFields: function(formdata) + { + formdata.addControl("uploadtype", "on"); + formdata.addControl("url", "paste image url here"); + formdata.addControl("MAX_FILE_SIZE", "3145728"); + formdata.addControl("refer", ""); + formdata.addControl("brand", ""); + formdata.addControl("optsize", "320x320"); + }, + + getFileFormField: function() + { + return "fileupload"; + }, + + getReferer: function() + { + return "http://www.imageshack.us/"; + }, + + getSubmissionURL: function() + { + return "http://www.imageshack.us/"; + } +} + +var AllYouCanUpload = { + addFormFields: function(formdata) + { + formdata.addControl("images[0].submittedPhotoSize", "100%"); + formdata.addControl("imagesCount", "1"); + }, + + getFileFormField: function() + { + return "images[0].fileName"; + }, + + getReferer: function() + { + return "http://allyoucanupload.webshots.com/"; + }, + + getSubmissionURL: function() + { + return "http://allyoucanupload.webshots.com/uploadcomplete"; + } +} + +Providers.addProvider(ImageShack); +//Providers.addProvider(AllYouCanUpload);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/screenshot/screenshot.js Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,292 @@ +const Ci = Components.interfaces; +const Cc = Components.classes; + +var shotWindow = window.opener; + +var timer = 0; + +var canvas = null; +var bundle = null; + +var windows = []; + +function init(event) +{ + canvas = document.getElementById("canvas"); + drawScreenshot(); + //canvas.parentNode.addEventListener("mousedown", startAreaSelect, true); + + buildWinPopup() + + var winlist = document.getElementById("winlist"); + winlist.addEventListener("ValueChange", winChange, false); + + var winpopup = document.getElementById("winpopup"); + winpopup.addEventListener("popupshowing", buildWinPopup, false); + + bundle = document.getElementById("bundle"); + + try + { + var win = getTopWin(); + var webnav = win.content.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation); + if (webnav.loadURI) + document.getElementById("imgsubmit").hidden = false; + } + catch (e) + { + } +} + +function getTopWin() +{ + var windowManager = Cc['@mozilla.org/appshell/window-mediator;1'] + .getService(Ci.nsIWindowMediator); + return windowManager.getMostRecentWindow("navigator:browser"); +} + +function timedCapture() +{ + if (timer==0) + { + timer = 5; + var button = document.getElementById("timerbtn"); + button.checked = true; + window.setTimeout(captureTimer, 1000); + } +} + +function captureTimer() +{ + var button = document.getElementById("timerbtn"); + timer--; + if (timer==0) + { + drawScreenshot(); + button.setAttribute("label", bundle.getFormattedString("screenshot.timer.label", [5])); + button.checked = false; + } + else + { + button.setAttribute("label", bundle.getFormattedString("screenshot.timer.label", [timer])); + window.setTimeout(captureTimer, 1000); + } +} + +function submitScreenshot() +{ + var fileService = ImageShack; + + var data = canvas.toDataURL("image/png"); + var pos = data.indexOf(";",5); + var contenttype = data.substring(5,pos); + var npos = data.indexOf(",",pos+1); + var encoding = data.substring(pos+1,npos); + data = data.substring(npos+1); + + var fd = Cc["@blueprintit.co.uk/multipartformdata;1"] + .createInstance(Ci.nttIMultipartFormData); + fileService.addFormFields(fd); + fd.addFileData(fileService.getFileFormField(), "screenshot.png", contenttype, encoding, data); + + var ioService = Cc["@mozilla.org/network/io-service;1"] + .getService(Ci.nsIIOService); + + var referer = ioService.newURI(fileService.getReferer(), "UTF8", null); + + var win = getTopWin(); + var webnav = win.content.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation); + webnav.loadURI(fileService.getSubmissionURL(), Ci.nsIWebNavigation.LOAD_FLAGS_NONE + , referer, fd.getPostDataStream(), fd.getHeaderStream()); +} + +function saveScreenshot() +{ + var fp = Cc["@mozilla.org/filepicker;1"] + .createInstance(Ci.nsIFilePicker); + fp.init(window, bundle.getString("screenshot.filepicker.title"), fp.modeSave); + fp.appendFilter(bundle.getString("screenshot.filepicker.filterPNG"), "*.png"); + fp.appendFilter(bundle.getString("screenshot.filepicker.filterJPG"), "*.jpg"); + fp.filterIndex = 0; + fp.defaultString="screenshot"; + + var result = fp.show(); + if (result==fp.returnOK || result==fp.returnReplace) + { + var file = fp.file; + var mimetype = "image/png"; + var options = ""; + var extension = "png"; + if (fp.filterIndex == 1) + { + extension = "jpg"; + mimetype = "image/jpeg"; + options = "quality=80"; + } + + if (file.leafName.indexOf(".") < 0) + file.leafName += "." + extension; + + var ioService = Cc["@mozilla.org/network/io-service;1"] + .getService(Ci.nsIIOService); + + var source = ioService.newURI(canvas.toDataURL(mimetype, options), "UTF8", null); + var target = ioService.newFileURI(file) + + var persist = Cc["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"] + .createInstance(Ci.nsIWebBrowserPersist); + + persist.persistFlags = Ci.nsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES; + persist.persistFlags |= Ci.nsIWebBrowserPersist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION; + + var tr = Cc["@mozilla.org/transfer;1"] + .createInstance(Ci.nsITransfer); + + tr.init(source, target, "", null, null, null, persist); + persist.progressListener = tr; + persist.saveURI(source, null, null, null, null, file); + } +} + +function copyScreenshot() +{ + var image = document.getElementById("previewImage"); + var docshell = window.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell); + var edit = docshell.contentViewer.QueryInterface(Ci.nsIContentViewerEdit); + document.popupNode = image; + edit.copyImage(Ci.nsIContentViewerEdit.COPY_IMAGE_DATA); +} + +function buildWinPopup(event) +{ + var winlist = document.getElementById("winlist"); + var winpopup = document.getElementById("winpopup"); + + windows = []; + while (winpopup.firstChild) + winpopup.removeChild(winpopup.firstChild); + + var wm = Cc["@mozilla.org/appshell/window-mediator;1"] + .getService(Ci.nsIWindowMediator); + var wins = wm.getEnumerator(null); + var pos = 0; + while (wins.hasMoreElements()) + { + var win = wins.getNext().QueryInterface(Ci.nsIDOMWindow); + if (win != window) + { + windows[pos] = win; + var item = document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul", "menuitem"); + if (win.document.title) + item.setAttribute("label", win.document.title); + else + item.setAttribute("label", win.document.location.href); + item.setAttribute("value", pos); + winpopup.appendChild(item); + + if (!event && win==shotWindow) + winlist.value=pos; + + pos++; + } + } +} + +function winChange(event) +{ + var winlist = document.getElementById("winlist"); + shotWindow = windows[winlist.value]; + drawScreenshot(); +} + +function drawScreenshot() +{ + var width = shotWindow.innerWidth; + var height = shotWindow.innerHeight; + canvas.width = width; + canvas.height = height; + canvas.style.width = width + "px"; + canvas.style.minWidth = width + "px"; + canvas.style.maxWidth = width + "px"; + canvas.style.height = height + "px"; + canvas.style.minHeight = height + "px"; + canvas.style.maxHeight = height + "px"; + + var ctx = canvas.getContext("2d"); + + var winbo = shotWindow.document.getBoxObjectFor(shotWindow.document.documentElement); + var winx = winbo.screenX; + var winy = winbo.screenY; + + // This draws the main window + try + { + ctx.drawWindow(shotWindow, shotWindow.scrollX, shotWindow.scrollY, + shotWindow.innerWidth, shotWindow.innerHeight, + "rgba(255,255,255,255)"); + } + catch (e) + { + } + + // Must also draw inner windows as inner-content from chrome are not included + var docshell = shotWindow.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIWebNavigation) + .QueryInterface(Ci.nsIDocShell); + var shells = docshell.getDocShellEnumerator(Ci.nsIDocShellTreeItem.typeAll, Ci.nsIDocShell.ENUMERATE_FORWARDS); + while (shells.hasMoreElements()) + { + var shell = shells.getNext().QueryInterface(Ci.nsIDocShell); + try + { + if (shell == docshell) + continue; + + shell.QueryInterface(Ci.nsIBaseWindow); + if (!shell.visibility) + continue; + + var shellwin = shell.QueryInterface(Ci.nsIInterfaceRequestor) + .getInterface(Ci.nsIDOMWindow); + var shellbo = shellwin.document.getBoxObjectFor(shellwin.document.documentElement); + + ctx.save(); + try + { + ctx.translate(shellbo.screenX - winx + shellwin.scrollX, + shellbo.screenY - winy + shellwin.scrollY); + ctx.drawWindow(shellwin, shellwin.scrollX, shellwin.scrollY, + shellwin.innerWidth, shellwin.innerHeight, + "rgba(255,255,255,255)"); + } + catch (e) + { + } + ctx.restore(); + } + catch (e) + { + } + } + + var url = canvas.toDataURL(); + var oldImage = document.getElementById("previewImage"); + if (oldImage) + oldImage.parentNode.removeChild(oldImage); + + var image = document.createElementNS("http://www.w3.org/1999/xhtml", "img"); + image.id = "previewImage"; + document.getElementById("container").appendChild(image); + + image.style.width = width + "px"; + image.style.height = height + "px"; + image.width = width; + image.height = height; + image.src = url; +} + +window.addEventListener("load", init, false);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/screenshot/screenshot.xul Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,45 @@ +<?xml version="1.0"?> + +<!DOCTYPE window SYSTEM "chrome://nightly/locale/screenshot.dtd"> + +<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> +<?xml-stylesheet href="chrome://nightly/skin/screenshot/screenshot.css" type="text/css"?> + +<window title="&screenshot.window.title;" id="NightlyScreenshot" + persist="width height screenX screenY sizemode" + xmlns:xhtml="http://www.w3.org/1999/xhtml" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <script src="screenshot.js" type="application/x-javascript"/> + <script src="providers.js" type="application/x-javascript"/> + + <stringbundleset> + <stringbundle id="bundle" src="chrome://nightly/locale/screenshot.properties"/> + </stringbundleset> + + <toolbox> + <toolbar> + <toolbarbutton label="&screenshot.save.label;" oncommand="saveScreenshot()"/> + <toolbarbutton label="&screenshot.copy.label;" oncommand="copyScreenshot()"/> + <toolbarbutton id="imgsubmit" hidden="true" label="&screenshot.submit.label;" oncommand="submitScreenshot(); window.close();"/> + <toolbaritem align="center"> + <label control="winlist" value="&screenshot.window.label;"/> + <menulist id="winlist"> + <menupopup id="winpopup"> + </menupopup> + </menulist> + </toolbaritem> + <toolbarbutton label="&screenshot.redraw.label;" oncommand="drawScreenshot();"/> + <toolbarbutton id="timerbtn" label="&screenshot.timer.label;" oncommand="timedCapture();"/> + </toolbar> + </toolbox> + + <scrollbox flex="1" style="overflow: auto" align="start" pack="start" id="container"> + <xhtml:img id="previewImage"/> + </scrollbox> + + <vbox height="0" style="overflow: hidden"> + <xhtml:canvas id="canvas" style="visibility: hidden"/> + </vbox> + +</window>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/session/dialog.js Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,77 @@ +const XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + +var gArgs = null; + +function acceptRestore() +{ + for (var w in gArgs.state.windows) + { + var win = gArgs.state.windows[w]; + for (var t = win.tabs.length-1; t>=0; t--) + { + var tab = win.tabs[t]; + if (tab._control.getAttribute("value") !== "true") + { + win.tabs.splice(t, 1); + if (t < win.selected) + win.selected--; + } + else + delete tab["_control"]; + } + } + gArgs.result = true; +} + +function addTab(parent, tab) +{ + var item = document.createElementNS(XULNS, "treeitem"); + item.setAttribute("container", "false"); + parent.appendChild(item); + var row = document.createElementNS(XULNS, "treerow"); + item.appendChild(row); + var cell = document.createElementNS(XULNS, "treecell"); + if (tab.entries[tab.index-1].title) + cell.setAttribute("label", tab.entries[tab.index-1].title); + else + cell.setAttribute("label", "(Untitled)"); + cell.setAttribute("editable", "false"); + row.appendChild(cell); + cell = document.createElementNS(XULNS, "treecell"); + cell.setAttribute("value", "true"); + row.appendChild(cell); + tab._control = cell; +} + +function addWindow(parent, win) +{ + var item = document.createElementNS(XULNS, "treeitem"); + item.setAttribute("container", "true"); + item.setAttribute("open", "true"); + parent.appendChild(item); + var row = document.createElementNS(XULNS, "treerow"); + item.appendChild(row); + var cell = document.createElementNS(XULNS, "treecell"); + cell.setAttribute("label", "Window"); + cell.setAttribute("editable", "false"); + row.appendChild(cell); + cell = document.createElementNS(XULNS, "treecell"); + cell.setAttribute("editable", "false"); + row.appendChild(cell); + var children = document.createElementNS(XULNS, "treechildren"); + item.appendChild(children); + for (var i in win.tabs) + addTab(children, win.tabs[i]); +} + +function loadState(event) +{ + gArgs = window.arguments[0]; + var parent = document.getElementById("treechildren"); + var windows = gArgs.state.windows; + for (var i in windows) + addWindow(parent, windows[i]); +} + +window.addEventListener("load", loadState, false); + \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/session/session.js Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,78 @@ +var session = { + +init: function(event) +{ + var menu = document.getElementById("nightly-session-restore"); + var ds = Components.classes["@mozilla.org/file/directory_service;1"] + .getService(Components.interfaces.nsIProperties); + var file = ds.get("ProfD", Ci.nsIFile); + file.append("sessionstore.bak"); + if (!file.exists) + menu.setAttribute("disabled", "true"); +}, + +_readFile: function(file) +{ + try + { + var stream = Components.classes["@mozilla.org/network/file-input-stream;1"] + .createInstance(Components.interfaces.nsIFileInputStream); + stream.init(file, 0x01, 0, 0); + var cvstream = Components.classes["@mozilla.org/intl/converter-input-stream;1"] + .createInstance(Components.interfaces.nsIConverterInputStream); + cvstream.init(stream, "UTF-8", 1024, Components.interfaces.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER); + + var content = ""; + var data = {}; + while (cvstream.readString(4096, data)) + content += data.value; + cvstream.close(); + + return content.replace(/\r\n?/g, "\n"); + } + catch (ex) { } + + return null; +}, + +restore: function() +{ + var ds = Components.classes["@mozilla.org/file/directory_service;1"] + .getService(Components.interfaces.nsIProperties); + var file = ds.get("ProfD", Ci.nsIFile); + file.append("sessionstore.bak"); + if (file.exists) + { + var data = this._readFile(file); + if (data) + { + try + { + var s = Components.utils.Sandbox("about:blank"); + var state = Components.utils.evalInSandbox(data, s); + var args = { + state: state, + result: false + }; + window.openDialog("chrome://nightly/content/session/session.xul", "_blank", "chrome,all,modal", args); + if (args.result) + { + var ss = Components.classes["@mozilla.org/browser/sessionstore;1"] + .getService(Components.interfaces.nsISessionStore); + var win = OpenBrowserWindow(); + win.addEventListener("load", function() { ss.setWindowState(win, args.state.toSource(), true); }, false); + } + return; + } + catch (ex) + { + } + } + alert("Unable to read from file, this is unrecoverable."); + } + else + alert("There is no session information to restore."); +} +} + +window.addEventListener("load", session.init, false);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/session/session.xul Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,23 @@ +<?xml version="1.0"?> + +<!DOCTYPE window SYSTEM "chrome://nightly/locale/nightly.dtd"> + +<?xml-stylesheet href="chrome://global/skin/" type="text/css"?> +<?xml-stylesheet href="chrome://nightly/skin/session/session.css" type="text/css"?> + +<dialog id="NightlySessionRestore" buttons="accept,cancel" style="width: 30em; height: 25em" + ondialogaccept="acceptRestore();" buttonlabelaccept="Restore" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <script type="application/x-javascript" src="dialog.js" /> + + <tree flex="1" hidecolumnpicker="true" editable="true"> + <treecols> + <treecol id="name" label="Title" flex="1" editable="false" primary="true"/> + <treecol id="restore" label="Restore" type="checkbox" editable="true"/> + </treecols> + <treechildren id="treechildren"> + </treechildren> + </tree> + +</dialog>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/songbird.js Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,55 @@ +var nightlyApp = { + +storedTitle: document.documentElement.getAttribute("titlemodifier"), + +init: function() +{ + // var brandbundle = document.getElementById("bundle_brand"); + var bundleSvc = Components.classes["@mozilla.org/intl/stringbundle;1"] + .getService(Components.interfaces.nsIStringBundleService); + var brandbundle = bundleSvc. + createBundle("chrome://branding/locale/brand.properties"); + + if (nightly.variables.name==null) + { + nightly.variables.name=brandbundle.GetStringFromName("brandShortName"); + } + nightly.variables.brandname=brandbundle.GetStringFromName("brandFullName"); + nightly.variables.defaulttitle=nightlyApp.storedTitle; +}, + +detectLeaks: function(event) +{ + var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"] + .getService(Components.interfaces.nsIWindowMediator); + var win = wm.getMostRecentWindow("Nightly:LeakReporter"); + if (win) + win.focus(); + else + window.openDialog("chrome://nightly/content/leaks/leaks.xul", "_blank", "chrome,all,dialog=no"); +}, + +openURL: function(url, event) +{ + openUILink(url, event, false, true); +}, + +setCustomTitle: function(title) +{ + var titlebar = document.getElementsByTagName("sb-sys-titlebar")[0]; + titlebar.setAttribute("value", title); +}, + +setBlankTitle: function() +{ + var titlebar = document.getElementsByTagName("sb-sys-titlebar")[0]; + titlebar.setAttribute("value", ""); +}, + +setStandardTitle: function() +{ + var titlebar = document.getElementsByTagName("sb-sys-titlebar")[0]; + titlebar.setAttribute("value", nightlyApp.storedTitle); +} + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/songbirdOverlay.xul Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,56 @@ +<?xml version="1.0"?> + +<!DOCTYPE window [ +<!ENTITY % nightlyDTD SYSTEM "chrome://nightly/locale/nightly.dtd"> +%nightlyDTD; +<!ENTITY % leaksDTD SYSTEM "chrome://nightly/locale/leaks.dtd"> +%leaksDTD; +]> + +<overlay id="NightlySongbirdOverlay" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <script type="application/x-javascript" src="nightly.js" /> + <script type="application/x-javascript" src="songbird.js" /> + <script type="application/x-javascript" src="breakpad/breakpad.js" /> + <script type="application/x-javascript" src="chrome://nightly/content/platform.js" /> + + <keyset id="mainKeyset"> + <key key="s" modifiers="accel,shift" oncommand="nightly.getScreenshot();"/> + </keyset> + + <popupset id="mainPopupSet"> + <tooltip orient="vertical" id="nightly-crashreport-tooltip" onpopupshowing="return crashreports.popupTooltip(event)"> + <label/> + </tooltip> + <popup id="nightly-crashreport-context"> + <menuitem oncommand="crashreports.copy(event)" label="&nightly.crashreports.copyid;"/> + </popup> + </popupset> + + <menupopup id="menu_ToolsPopup"> + <menu id="nightly-menu" label="Nightly Tester Tools" insertafter="devToolsSeparator"> + <menupopup onpopupshowing="nightly.menuPopup(event,this);"> + <menuitem id="build-copy" label="&nightly.id.copy.label;" oncommand="nightly.copyTemplate('buildid');"/> + <menuitem id="build-insert" label="&nightly.id.insert.label;" oncommand="nightly.insertTemplate('buildid');"/> + <menuitem id="list-copy" label="&nightly.extensions.copy.label;" oncommand="nightly.copyExtensions();"/> + <menuitem id="list-insert" label="&nightly.extensions.insert.label;" oncommand="nightly.insertExtensions();"/> + <menuseparator/> + <menuitem label="&nightly.screenshot.full.label;" oncommand="nightly.getScreenshot();"/> + <menuseparator/> + <menuitem label="&nightly.openprofile.label;" oncommand="nightly.openProfileDir();"/> + <menuseparator id="nightly-crashreports-separator"/> + <menu id="nightly-crashreports-recent" label="&nightly.crashreports.recentlist;" oncommand="crashreports.viewIncident(event);" onclick="checkForMiddleClick(this, event);"> + <menupopup id="nightly-crashreports-incidents"> + <menuitem disabled="true" label="&nightly.leaks.loading.label;"/> + </menupopup> + </menu> + <menuseparator/> + <menuitem label="&nightly.leakreporter.label;" oncommand="nightlyApp.detectLeaks(event);" onclick="checkForMiddleClick(this, event);"/> + <menuseparator/> + <menuitem label="&nightly.options.label;" oncommand="nightly.launchOptions();"/> + </menupopup> + </menu> + </menupopup> + +</overlay>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/suite.js Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,36 @@ +var nightlyApp = { + +init: function() +{ + var brandbundle = document.getElementById("bundle_brand"); + if (nightly.variables.name==null) + { + nightly.variables.name=brandbundle.getString("brandShortName"); + } + nightly.variables.brandname=brandbundle.getString("brandFullName"); + nightly.variables.defaulttitle=nightlyApp.storedTitle; +}, + +detectLeaks: function(event) +{ + this.openURL('chrome://nightly/content/leaks/leaks.xul', event); +}, + +openURL: function(url, event) +{ + openTopWin(url); +}, + +setCustomTitle: function(title) +{ +}, + +setBlankTitle: function() +{ +}, + +setStandardTitle: function() +{ +} + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/suiteOverlay.xul Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,66 @@ +<?xml version="1.0"?> + +<!DOCTYPE window [ +<!ENTITY % nightlyDTD SYSTEM "chrome://nightly/locale/nightly.dtd"> +%nightlyDTD; +<!ENTITY % leaksDTD SYSTEM "chrome://nightly/locale/leaks.dtd"> +%leaksDTD; +]> + +<overlay id="NightlySuiteOverlay" + xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"> + + <script type="application/x-javascript" src="nightly.js" /> + <script type="application/x-javascript" src="suite.js" /> + <script type="application/x-javascript" src="breakpad/breakpad.js" /> + <script type="application/x-javascript" src="chrome://nightly/content/platform.js" /> + + <!-- Sidebar --> + <broadcasterset id="mainBroadcasterSet"> + <broadcaster id="viewCrashReportsSidebar" + autoCheck="false" + label="&nightly.crashreports.sidebar.title;" + type="checkbox" + group="sidebar" + sidebarurl="chrome://nightly/content/breakpad/sidebar.xul" + oncommand="toggleSidebar('viewCrashReportsSidebar');"/> + </broadcasterset> + + <keyset id="navKeys"> + <key key="s" modifiers="accel,shift" oncommand="nightly.getScreenshot();"/> + </keyset> + + <popupset id="mainPopupSet"> + <tooltip orient="vertical" id="nightly-crashreport-tooltip" onpopupshowing="return crashreports.popupTooltip(event)"> + <label/> + </tooltip> + <popup id="nightly-crashreport-context"> + <menuitem oncommand="crashreports.copy(event)" label="&nightly.crashreports.copyid;"/> + </popup> + </popupset> + + <menupopup id="taskPopup"> + <menu id="nightly-menu" label="Nightly Tester Tools" insertbefore="sep_switchprofile"> + <menupopup onpopupshowing="nightly.menuPopup(event,this);"> + <menuitem id="build-copy" label="&nightly.id.copy.label;" oncommand="nightly.copyTemplate('buildid');"/> + <menuitem id="build-insert" label="&nightly.id.insert.label;" oncommand="nightly.insertTemplate('buildid');"/> + <menuitem id="list-copy" label="&nightly.extensions.copy.label;" oncommand="nightly.copyExtensions();"/> + <menuitem id="list-insert" label="&nightly.extensions.insert.label;" oncommand="nightly.insertExtensions();"/> + <menuseparator/> + <menuitem label="&nightly.openprofile.label;" oncommand="nightly.openProfileDir();"/> + <menuseparator id="nightly-crashreports-separator"/> + <menu id="nightly-crashreports-recent" label="&nightly.crashreports.recentlist;" oncommand="crashreports.viewIncident(event);" onclick="checkForMiddleClick(this, event);"> + <menupopup id="nightly-crashreports-incidents"> + <menuitem disabled="true" label="&nightly.leaks.loading.label;"/> + </menupopup> + </menu> + <menuitem id="nightly-breakpad-sidebar" observes="viewBreakpadSidebar"/> + <menuseparator/> + <menuitem label="&nightly.leakreporter.label;" oncommand="nightlyApp.detectLeaks(event);"/> + <menuseparator/> + <menuitem label="&nightly.options.label;" oncommand="nightly.launchOptions();"/> + </menupopup> + </menu> + </menupopup> + +</overlay>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/content/winPlatform.js Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,4 @@ +var nightlyplatform = { + eol: "\r\n" +} + \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/locale/en-US/configwarning.dtd Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,8 @@ +<!ENTITY dialog.title "Nightly Tester Tools"> +<!ENTITY dialog.style "width: 45em"> + +<!ENTITY title "&brandShortName; is ignoring add-on compatibility"> +<!ENTITY subtitle "Nightly Tester Tools can manage add-on compatibility + using a safer method that works on an individual basis."> +<!ENTITY question "Do you want to switch to use Nightly Tester Tools to + control compatibility?">
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/locale/en-US/incompatible.dtd Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,11 @@ +<!ENTITY window.title "Make Compatible"> +<!ENTITY window.style "width: 40em; height: 25em"> +<!ENTITY window.accept "Force Install"> +<!ENTITY window.cancel "Skip"> + +<!ENTITY warning.label "Forcing incompatible add-ons to run could cause + hangs, crashes, memory leaks, data corruption or + other problems."> + +<!ENTITY incompatible.label "This add-on is incompatible with this version of &brandShortName;."> +<!ENTITY insecure.label "This add-on cannot update securely. Updates must be disabled.">
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/locale/en-US/leaks.dtd Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,20 @@ +<!ENTITY nightly.leaks.title "Leak Log Analyzer"> + +<!ENTITY nightly.leaks.logfile.label "Log file:"> +<!ENTITY nightly.leaks.browse.label "Browse..."> +<!ENTITY nightly.leaks.displayfull.label "Display full log"> +<!ENTITY nightly.leaks.loading.label "Loading..."> +<!ENTITY nightly.leaks.overview.label "Overview"> +<!ENTITY nightly.leaks.fulllog.label "Complete Log"> +<!ENTITY nightly.leaks.copy.label "Copy to Clipboard"> +<!ENTITY nightly.leaks.save.label "Save As..."> +<!ENTITY nightly.leaks.summary.label "Summary"> +<!ENTITY nightly.leaks.details.label "Details"> + +<!ENTITY nightly.leaks.display.label "Display:"> +<!ENTITY nightly.leaks.docshellfilter.label "Docshells"> +<!ENTITY nightly.leaks.windowfilter.label "Windows"> +<!ENTITY nightly.leaks.documentfilter.label "Documents"> +<!ENTITY nightly.leaks.leakedfilter.label "Leaked"> +<!ENTITY nightly.leaks.collectedfilter.label "Collected"> +<!ENTITY nightly.leaks.unknownfilter.label "Unknown">
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/locale/en-US/leaks.properties Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,14 @@ +nightly.leaks.sessiondate.label=Session ended %S +nightly.leaks.windowleaks.label=Leaked %S out of %S DOM windows +nightly.leaks.documentleaks.label=Leaked %S out of %S documents +nightly.leaks.docshellleaks.label=Leaked %S out of %S docshells +nightly.leaks.summary.label=Summary +nightly.leaks.details.label=Details +nightly.leaks.outerleak.text=Leaked outer window %S at address %S. +nightly.leaks.innerleak.text=Leaked inner window %S (outer %S) at address %S. +nightly.leaks.documentleak.text=Leaked document at address %S. +nightly.leaks.docshellleak.text=Leaked docshell at address %S. +nightly.leaks.urileak.text=with URI "%S". +nightly.leaks.filepicker.title=Select Log File +nightly.leaks.filepicker.filterlog=Log Files (*.log) +nightly.leaks.filepicker.filterall=All Files (*.*)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/locale/en-US/nightly.dtd Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,25 @@ +<!ENTITY nightly.openprofile.label "Open Profile Folder"> + +<!ENTITY nightly.id.copy.label "Copy Build ID to Clipboard"> +<!ENTITY nightly.id.insert.label "Insert Build ID into Textbox"> +<!ENTITY nightly.id.insert.tooltip "Inserts the build identifier into the current text box."> + +<!ENTITY nightly.extensions.copy.label "Copy List of Extensions to Clipboard"> +<!ENTITY nightly.extensions.insert.label "Insert List of Extensions into Textbox"> +<!ENTITY nightly.appenable.label "Override compatibility"> +<!ENTITY nightly.enableall.label "Override all compatibility"> +<!ENTITY nightly.enableall.tooltip "Overrides compatibility for all listed incompatible add-ons"> + +<!ENTITY nightly.leakreporter.label "Analyse Leak Log"> + +<!ENTITY nightly.options.label "Options"> + +<!ENTITY nightly.screenshot.full.label "Take Screenshot"> + +<!ENTITY nightly.crashreports.sidebar.title "Crash Reports Sidebar"> +<!ENTITY nightly.crashreports.copyid "Copy"> +<!ENTITY nightly.crashreports.id "ID"> +<!ENTITY nightly.crashreports.date "Date"> +<!ENTITY nightly.crashreports.recentlist "Recent Incidents"> + +<!ENTITY nightly.session.restore "Restore from last session...">
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/locale/en-US/nightly.properties Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,3 @@ +extensions.{8620c15f-30dc-4dba-a131-7c5d20cf4a29}.description=Useful tools for the nightly tester. +nightly.notextbox.message=You must select a text box before using this function. +nightly.noextensions.message=No extensions were found.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/locale/en-US/options.dtd Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,14 @@ +<!ENTITY nightly.options.height "30em"> + +<!ENTITY nightly.options.title "Nightly Tester Options"> + + +<!ENTITY nightly.paneTitlebar.title "Titlebar"> +<!ENTITY nightly.paneTitlebar.description "You can use a custom title to always display the current build in the titlebar."> + +<!ENTITY nightly.customtitle.label "Use custom title"> +<!ENTITY nightly.customtemplate.label "Custom title template:"> +<!ENTITY nightly.variables.description "The following variables can be used in the title (case insensitive)."> +<!ENTITY nightly.variable.label "Variable"> +<!ENTITY nightly.variabledesc.label "Description"> +<!ENTITY nightly.variablevalue.label "Value">
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/locale/en-US/screenshot.dtd Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,9 @@ +<!ENTITY screenshot.window.title "Screenshot Grabber"> + +<!ENTITY screenshot.save.label "Save As..."> +<!ENTITY screenshot.submit.label "Submit to ImageShack..."> +<!ENTITY screenshot.copy.label "Copy to Clipboard"> +<!ENTITY screenshot.redraw.label "Redraw"> +<!ENTITY screenshot.zoom.label "Zoom:"> +<!ENTITY screenshot.window.label "Window:"> +<!ENTITY screenshot.timer.label "Capture in: 5">
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/locale/en-US/screenshot.properties Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,4 @@ +screenshot.filepicker.title=Save Screenshot As... +screenshot.filepicker.filterJPG=JPG files. (*.jpg) +screenshot.filepicker.filterPNG=PNG files. (*.png) +screenshot.timer.label=Capture in: %S
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/locale/en-US/variables.properties Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,18 @@ +variable.AppID.description=Application Identifier +variable.Vendor.description=Application Vendor +variable.Name.description=Application Name +variable.Version.description=Application Version +variable.AppBuildID.description=Application Build Identifier +variable.PlatformBuildID.description=XUL Platform Build Identifier +variable.PlatformVersion.description=XUL Platform Version +variable.GeckoBuildID.description=Gecko Build Identifier +variable.GeckoVersion.description=Gecko Version +variable.BrandName.description=Application Brand Name +variable.UserAgent.description=User Agent String +variable.Locale.description=Current Locale +variable.OS.description=Compilation OS +variable.Processor.description=Compilation Processor +variable.Compiler.description=Compiler +variable.DefaultTitle.description=Default Application Title +variable.Profile.description=Current Profile +variable.Toolkit.description=Graphics Toolkit
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/skin/browser.css Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,7 @@ +#nightly-tester-enter { + list-style-image: url("chrome://nightly/skin/idlarge.png"); +} + +toolbar[iconsize="small"] #nightly-tester-enter { + list-style-image: url("chrome://nightly/skin/idsmall.png"); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/skin/configwarning.css Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,9 @@ +dialog { + padding: 1em; +} + +#title { + font-weight: bold; + font-size: 110%; + margin-bottom: 1em; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/skin/crashreports/sidebar.css Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,5 @@ +treechildren#treeroot::-moz-tree-image(name) { + padding-right: 2px; + margin: 0px 2px; + list-style-image: url("chrome://nightly/skin/crashreports/crash.png") !important; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/skin/extensions/extensions.css Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,3 @@ +#enableallButton { + list-style-image: none !important; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/skin/extensions/incompatible.css Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,20 @@ +#warning { + font-weight: bold; +} + +richlistitem { + padding: 2px; + border-bottom: 1px dotted; +} + +.name-version label { + font-weight: bold; +} + +[secure="true"] .insecure { + display: none; +} + +[compatible="true"] .incompatible { + display: none; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/skin/leaks/leaks.css Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,4 @@ +browser { + background-color: white; + border: 1px solid threedshadow; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome/skin/options/options.css Tue Dec 02 20:38:20 2008 +0900 @@ -0,0 +1,14 @@ +.content-box { + -moz-box-flex: 1; +} + +subpane { + -moz-binding: url('chrome://nightly/content/options/subpane.xml#subpane'); + padding-left: 2em; +} + +#NightlyTesterOptions { + padding: 0; + width: 40em; + height: 35em; +}