Mercurial > nightly_tester_tools
changeset 0:dada0ac40a8f
initial import
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Tue, 02 Dec 2008 20:31:01 +0900 |
parents | |
children | 93e46514f20d |
files | LICENSE chrome.manifest chrome/nightly.jar components/nightly.xpt components/nttAddonCompatibilityService.js components/nttBreakpadService.js components/nttMultipartFormData.js defaults/preferences/nightlytools.js defaults/preferences/variables.js install.rdf modules/Logging.jsm |
diffstat | 11 files changed, 1143 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LICENSE Tue Dec 02 20:31:01 2008 +0900 @@ -0,0 +1,6 @@ +All files in this extension are assumed to be licensed under the +tri-license (MPL/GPL/LGPL) unless otherwise specified. + +The MPL is available at http://www.mozilla.org/MPL/MPL-1.1.html + +The source code is available on request from dtownsend@oxymoronical.com
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/chrome.manifest Tue Dec 02 20:31:01 2008 +0900 @@ -0,0 +1,25 @@ +content nightly jar:chrome/nightly.jar!/content/ +skin nightly classic/1.0 jar:chrome/nightly.jar!/skin/ + +locale nightly en-US jar:chrome/nightly.jar!/locale/en-US/ + +resource nightly modules/ + +overlay chrome://mozapps/content/extensions/extensions.xul chrome://nightly/content/extensions/addons.xul +override chrome://nightly/content/platform.js chrome://nightly/content/winPlatform.js os=winnt + +style chrome://browser/content/browser.xul chrome://nightly/skin/browser.css +style chrome://messenger/content/messenger.xul chrome://nightly/skin/browser.css +style chrome://navigator/content/navigator.xul chrome://nightly/skin/browser.css +style chrome://calendar/content/calendar.xul chrome://nightly/skin/browser.css +style chrome://global/content/customizeToolbar.xul chrome://nightly/skin/browser.css + +overlay chrome://browser/content/browser.xul chrome://nightly/content/browserOverlay.xul application={ec8030f7-c20a-464f-9b0e-13a3a9e97384} + +overlay chrome://messenger/content/messenger.xul chrome://nightly/content/messengerOverlay.xul application={3550f703-e582-4d05-9a08-453d09bdfdc6} + +overlay chrome://calendar/content/calendar.xul chrome://nightly/content/calendarOverlay.xul application={718e30fb-e89b-41dd-9da7-e25a45638b28} + +overlay chrome://navigator/content/navigator.xul chrome://nightly/content/suiteOverlay.xul application={92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a} + +overlay chrome://songbird/content/xul/layoutBaseOverlay.xul chrome://nightly/content/songbirdOverlay.xul application=songbird@songbirdnest.com
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/nttAddonCompatibilityService.js Tue Dec 02 20:31:01 2008 +0900 @@ -0,0 +1,506 @@ +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cr = Components.results; + +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); + +const PREFIX_NS_EM = "http://www.mozilla.org/2004/em-rdf#"; +const PREFIX_ITEM_URI = "urn:mozilla:item:"; +const RDFURI_INSTALL_MANIFEST_ROOT = "urn:mozilla:install-manifest"; +const FILE_INSTALL_MANIFEST = "install.rdf"; +const TOOLKIT_ID = "toolkit@mozilla.org" + +var gEM = null; +var gRDF = null; +var gApp = null; +var gVC = null; +var gCheckCompatibility = true; +var gCheckUpdateSecurity = true; +var gPrefs = null; + +function EM_NS(property) { + return PREFIX_NS_EM + property; +} + +function EM_R(property) { + return gRDF.GetResource(EM_NS(property)); +} + +function getRDFProperty(ds, source, property) { + var value = ds.GetTarget(source, EM_R(property), true); + if (value && value instanceof Ci.nsIRDFLiteral) + return value.Value; + return null; +} + +function removeRDFProperty(ds, source, property) { + var arc = EM_R(property); + var targets = ds.GetTargets(source, arc, true); + while (targets.hasMoreElements()) + ds.Unassert(source, arc, targets.getNext()); +} + +function extractXPI(xpi) { + // XXX For 1.9 final we can switch to just extracting/compressing install.rdf + var zipReader = Cc["@mozilla.org/libjar/zip-reader;1"]. + createInstance(Ci.nsIZipReader); + zipReader.open(xpi); + if (!zipReader.hasEntry(FILE_INSTALL_MANIFEST)) { + zipReader.close(); + return null; + } + var dirs = Cc["@mozilla.org/file/directory_service;1"]. + getService(Ci.nsIProperties); + var file = dirs.get("TmpD", Ci.nsILocalFile); + file.append("tmpxpi"); + file.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0755); + var entries = zipReader.findEntries("*"); + while (entries.hasMore()) { + var path = entries.getNext(); + var entry = zipReader.getEntry(path); + if (path.substring(path.length - 1) == "/") + path = path.substring(0, entry.length - 1); + var parts = path.split("/"); + var target = file.clone(); + for (var i = 0; i < parts.length; i++) + target.append(parts[i]); + if (entry.isDirectory) { + if (!target.exists()) + target.create(Ci.nsIFile.DIRECTORY_TYPE, 0755); + } + else { + var parent = target.parent; + if (!parent.exists()) + parent.create(Ci.nsIFile.DIRECTORY_TYPE, 0755); + zipReader.extract(path, target); + } + } + zipReader.close(); + return file; +} + +function loadManifest(file) { + var ioServ = Cc["@mozilla.org/network/io-service;1"]. + getService(Ci.nsIIOService); + var fph = ioServ.getProtocolHandler("file") + .QueryInterface(Ci.nsIFileProtocolHandler); + return gRDF.GetDataSourceBlocking(fph.getURLSpecFromFile(file)); +} + +function recursiveUpdate(zipWriter, path, dir) { + var entries = dir.directoryEntries; + while (entries.hasMoreElements()) { + var entry = entries.getNext().QueryInterface(Ci.nsIFile); + if (entry.isDirectory()) { + var newPath = path + entry.leafName + "/"; + zipWriter.addEntryDirectory(newPath, entry.lastModifiedTime, false); + recursiveUpdate(zipWriter, newPath, entry); + } + else { + zipWriter.addEntryFile(path + entry.leafName, Ci.nsIZipWriter.COMPRESSION_NONE, + entry, false); + } + } +} + +function updateXPI(xpi, file) { + // XXX For 1.9 final we can switch to just extracting/compressing install.rdf + var zipWriter = Cc["@mozilla.org/zipwriter;1"]. + createInstance(Ci.nsIZipWriter); + zipWriter.open(xpi, 0x04 | 0x08 | 0x20); + recursiveUpdate(zipWriter, "", file); + zipWriter.close(); +} + +function nttAddonUpdateChecker(addon) { + this.addon = addon; +} + +nttAddonUpdateChecker.prototype = { + addon: null, + busy: null, + + checkForUpdates: function() { + this.busy = true; + LOG("Searching for compatibility information for " + this.addon.id); + gEM.update([this.addon], 1, + Ci.nsIExtensionManager.UPDATE_SYNC_COMPATIBILITY, this); + + // Spin an event loop to wait for the update check to complete. + var tm = Cc["@mozilla.org/thread-manager;1"]. + getService(Ci.nsIThreadManager); + var thread = tm.currentThread; + while (this.busy) + thread.processNextEvent(true); + }, + + // nsIAddonUpdateCheckListener implementation + onUpdateStarted: function() { + }, + + onUpdateEnded: function() { + this.busy = false; + }, + + onAddonUpdateStarted: function(addon) { + }, + + onAddonUpdateEnded: function(addon, status) { + if (status & Ci.nsIAddonUpdateCheckListener.STATUS_DATA_FOUND) { + LOG("Found new compatibility information for " + addon.id + ": " + addon.minAppVersion + " " + addon.maxAppVersion); + this.addon.minAppVersion = addon.minAppVersion; + this.addon.maxAppVersion = addon.maxAppVersion; + this.addon.targetAppID = addon.targetAppID; + this.addon.overrideVersions(); + } + } +}; + +function nttAddonDetail() { +} + +nttAddonDetail.prototype = { + datasource: null, + root: null, + + xpi: null, + file: null, + + id: null, + name: null, + version: null, + type: Ci.nsIUpdateItem.TYPE_EXTENSION, + updateRDF: null, + updateKey: null, + iconURL: "chrome://mozapps/skin/xpinstall/xpinstallItemGeneric.png", + + installLocationKey: null, + xpiURL: null, + xpiHash: null, + + appResource: null, + targetAppID: null, + minAppVersion: null, + maxAppVersion: null, + + init: function() { + if (!this.id) + this.id = getRDFProperty(this.datasource, this.root, "id"); + this.name = getRDFProperty(this.datasource, this.root, "name"); + this.version = getRDFProperty(this.datasource, this.root, "version"); + this.updateRDF = getRDFProperty(this.datasource, this.root, "updateURL"); + this.updateKey = getRDFProperty(this.datasource, this.root, "updateKey"); + + var apps = this.datasource.GetTargets(this.root, EM_R("targetApplication"), true); + while (apps.hasMoreElements()) { + var app = apps.getNext().QueryInterface(Ci.nsIRDFResource); + var id = getRDFProperty(this.datasource, app, "id"); + if (id == gApp.ID || id == TOOLKIT_ID) { + this.minAppVersion = getRDFProperty(this.datasource, app, "minVersion"); + this.maxAppVersion = getRDFProperty(this.datasource, app, "maxVersion"); + if (this.minAppVersion && this.maxAppVersion) { + this.appResource = app; + this.targetAppID = id; + if (id == gApp.ID) + break; + } + } + } + }, + + initWithXPI: function(xpi) { + this.xpi = xpi; + this.file = extractXPI(xpi); + var rdf = this.file.clone(); + rdf.append(FILE_INSTALL_MANIFEST); + this.datasource = loadManifest(rdf); + this.root = gRDF.GetResource(RDFURI_INSTALL_MANIFEST_ROOT); + this.init(); + }, + + initWithDataSource: function(ds, root, id) { + this.datasource = ds; + this.root = root; + this.id = id; + this.init(); + }, + + cleanup: function() { + if (this.file && this.file.exists) + this.file.remove(true); + }, + + overrideVersions: function() { + removeRDFProperty(this.datasource, this.appResource, "minVersion"); + this.datasource.Assert(this.appResource, EM_R("minVersion"), gRDF.GetLiteral(this.minAppVersion), true); + removeRDFProperty(this.datasource, this.appResource, "maxVersion"); + this.datasource.Assert(this.appResource, EM_R("maxVersion"), gRDF.GetLiteral(this.maxAppVersion), true); + this.datasource.QueryInterface(Ci.nsIRDFRemoteDataSource).Flush(); + if (this.xpi && this.file) + updateXPI(this.xpi, this.file); + }, + + overrideCompatibility: function(ignorePrefs) { + if (!this.isValid()) + return; + + var changed = false; + + if (gCheckCompatibility || ignorePrefs) { + var version = (gApp.ID == this.targetAppID) ? gApp.version : gApp.platformVersion; + if (gVC.compare(version, this.minAppVersion) < 0) { + LOG("minVersion " + this.minAppVersion + " is too high, reducing to " + version); + if (!this.datasource.GetTarget(this.appResource, EM_R("oldMinVersion"), true)) + this.datasource.Assert(this.appResource, EM_R("oldMinVersion"), gRDF.GetLiteral(this.minAppVersion), true); + removeRDFProperty(this.datasource, this.appResource, "minVersion"); + this.datasource.Assert(this.appResource, EM_R("minVersion"), gRDF.GetLiteral(version), true); + this.minAppVersion = version; + changed = true; + } + else if (gVC.compare(version, this.maxAppVersion) > 0) { + LOG("maxVersion " + this.maxAppVersion + " is too low, increasing to " + version); + if (!this.datasource.GetTarget(this.appResource, EM_R("oldMaxVersion"), true)) + this.datasource.Assert(this.appResource, EM_R("oldMaxVersion"), gRDF.GetLiteral(this.maxAppVersion), true); + removeRDFProperty(this.datasource, this.appResource, "maxVersion"); + this.datasource.Assert(this.appResource, EM_R("maxVersion"), gRDF.GetLiteral(version), true); + this.maxAppVersion = version; + changed = true; + } + + if (changed && !this.xpi) { + // This updates any UI bound to the datasource + var compatprop = EM_R("compatible"); + var truth = gRDF.GetLiteral("true"); + this.datasource.Assert(this.root, compatprop, truth, true); + this.datasource.Unassert(this.root, compatprop, truth); + } + } + + if (!this.isUpdateSecure(ignorePrefs)) { + LOG("Addon is insecure, removing update URL"); + removeRDFProperty(this.datasource, this.root, "updateURL"); + this.updateRDF = null; + changed = true; + + // This updates any UI bound to the datasource + compatprop = EM_R("providesUpdatesSecurely"); + truth = gRDF.GetLiteral("true"); + this.datasource.Assert(this.root, compatprop, truth, true); + this.datasource.Unassert(this.root, compatprop, truth); + } + + if (changed) { + this.datasource.QueryInterface(Ci.nsIRDFRemoteDataSource).Flush(); + if (this.xpi && this.file) + updateXPI(this.xpi, this.file); + } + }, + + isValid: function() { + return !!this.appResource; + }, + + isCompatible: function(ignorePrefs) { + if (!gCheckCompatibility && !ignorePrefs) + return true; + + var version = (gApp.ID == this.targetAppID) ? gApp.version : gApp.platformVersion; + if (gVC.compare(version, this.minAppVersion) < 0) + return false; + if (gVC.compare(version, this.maxAppVersion) > 0) + return false; + return true; + }, + + isUpdateSecure: function(ignorePrefs) { + if (!gCheckUpdateSecurity && !ignorePrefs) + return true; + + if (!this.updateRDF) + return true; + if (this.updateKey) + return true; + return (this.updateRDF.substring(0, 6) == "https:"); + }, + + needsOverride: function(ignorePrefs) { + return (!this.isCompatible(ignorePrefs) || !this.isUpdateSecure(ignorePrefs)); + }, + + QueryInterface: XPCOMUtils.generateQI([Ci.nttIAddon, Ci.nsIUpdateItem]), +}; + +function nttAddonCompatibilityService() { +} + +nttAddonCompatibilityService.prototype = { + id: null, + + init: function() { + Components.utils.import("resource://nightly/Logging.jsm"); + + gEM = Cc["@mozilla.org/extensions/manager;1"]. + getService(Ci.nsIExtensionManager); + gRDF = Cc["@mozilla.org/rdf/rdf-service;1"]. + getService(Ci.nsIRDFService); + gApp = Cc["@mozilla.org/xre/app-info;1"]. + getService(Ci.nsIXULAppInfo).QueryInterface(Ci.nsIXULRuntime); + gVC = Cc["@mozilla.org/xpcom/version-comparator;1"]. + getService(Ci.nsIVersionComparator); + if (gVC.compare(gApp.platformVersion, "1.9b5") >= 0) + this.id = gEM.addInstallListener(this); + gPrefs = Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefService) + .getBranch("extensions.") + .QueryInterface(Components.interfaces.nsIPrefBranch2); + try { + gCheckCompatibility = gPrefs.getBoolPref("checkCompatibility"); + } + catch (e) { } + try { + gCheckUpdateSecurity = gPrefs.getBoolPref("checkUpdateSecurity"); + } + catch (e) { } + gPrefs.addObserver("", this, false); + }, + + // nsIAddonCompatibilityService implementation + getAddonForID: function(id) { + var addon = new nttAddonDetail(); + addon.initWithDataSource(gEM.datasource, gRDF.GetResource(PREFIX_ITEM_URI + id), id); + return addon; + }, + + confirmOverride: function(addons, count) { + var wm = Cc["@mozilla.org/appshell/window-mediator;1"]. + getService(Ci.nsIWindowMediator); + win = wm.getMostRecentWindow("Extension:Manager"); + if (win && win.top) + win = win.top; + + var params = Cc["@mozilla.org/array;1"]. + createInstance(Ci.nsIMutableArray); + for (var i = 0; i < addons.length; i++) + params.appendElement(addons[i], false); + var ww = Cc["@mozilla.org/embedcomp/window-watcher;1"]. + getService(Ci.nsIWindowWatcher); + ww.openWindow(win, "chrome://nightly/content/extensions/incompatible.xul", "", + "chrome,centerscreen,modal,dialog,titlebar", params); + return true; + }, + + // nsIAddonInstallListener implementation + onDownloadStarted: function(addon) { + }, + + onDownloadProgress: function(addon, value, maxValue) { + }, + + onDownloadEnded: function(addon) { + }, + + onInstallStarted: function(addon) { + LOG("Install Started for " + addon.xpiURL); + var ioServ = Cc["@mozilla.org/network/io-service;1"]. + getService(Ci.nsIIOService); + var fph = ioServ.getProtocolHandler("file") + .QueryInterface(Ci.nsIFileProtocolHandler); + var file = fph.getFileFromURLSpec(addon.xpiURL); + if (file.exists()) { + try { + var addon = new nttAddonDetail(); + addon.initWithXPI(file); + if (addon.isValid()) { + if (!addon.isCompatible(false)) { + // Check if there are remote updates available + var checker = new nttAddonUpdateChecker(addon); + checker.checkForUpdates(); + } + + if (addon.needsOverride(false)) + this.confirmOverride([addon], 1); + else + LOG("Add-on is already compatible: '" + addon.updateRDF + "' " + addon.minAppVersion + "-" + addon.maxAppVersion); + } + else { + WARN("Add-on seems to be invalid"); + } + addon.cleanup(); + } + catch (e) { + ERROR("Exception during compatibility check " + e); + } + } + }, + + onCompatibilityCheckStarted: function(addon) { + }, + + onCompatibilityCheckEnded: function(addon, status) { + }, + + onInstallEnded: function(addon, status) { + }, + + onInstallsCompleted: function() { + }, + + // nsIObserver implementation + observe: function(subject, topic, data) { + switch (topic) { + case "app-startup": + var os = Cc["@mozilla.org/observer-service;1"]. + getService(Ci.nsIObserverService); + os.addObserver(this, "profile-after-change", false); + os.addObserver(this, "quit-application", false); + break; + case "profile-after-change": + this.init(); + break; + case "quit-application": + if (this.id) + gEM.removeInstallListenerAt(this.id); + gEM = null; + gRDF = null; + gApp = null; + gVC = null; + gPrefs.removeObserver("", this); + gPrefs = null; + break; + case "nsPref:changed": + switch (data) { + case "checkCompatibility": + try { + gCheckCompatibility = gPrefs.getBoolPref(data); + } + catch (e) { + gCheckCompatibility = true; + } + break; + case "checkUpdateSecurity": + try { + gCheckUpdateSecurity = gPrefs.getBoolPref(data); + } + catch (e) { + gCheckUpdateSecurity = true; + } + break; + } + break; + default: + WARN("Unknown event " + topic); + } + }, + + classDescription: "Nightly Tester Install Monitor", + contractID: "@oxymoronical.com/nightly/addoncompatibility;1", + classID: Components.ID("{801207d5-037c-4565-80ed-ede8f7a7c100}"), + QueryInterface: XPCOMUtils.generateQI([Ci.nttIAddonCompatibilityService, Ci.nsIAddonInstallListener, Ci.nsIObserver]), + _xpcom_categories: [{ + category: "app-startup", + service: true + }] +} + +function NSGetModule(compMgr, fileSpec) + XPCOMUtils.generateModule([nttAddonCompatibilityService]);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/nttBreakpadService.js Tue Dec 02 20:31:01 2008 +0900 @@ -0,0 +1,265 @@ +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cr = Components.results; + +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); + +const LOAD_DELAY = 50; + +Cc["@mozilla.org/moz/jssubscript-loader;1"] + .getService(Ci.mozIJSSubScriptLoader) + .loadSubScript("chrome://nightly/content/includes/tree-utils.js", null); + +function BP_CreateArray(source) +{ + var result = Cc["@mozilla.org/array;1"] + .createInstance(Ci.nsIMutableArray); + + for (var key in source) + result.appendElement(source[key], false); + + return result; +} + +function nttBreakpadIncident(file) +{ + this.id = file.leafName; + this.id = this.id.substring(0, this.id.length - 4); + this.date = file.lastModifiedTime; + this.file = file; +} + +nttBreakpadIncident.prototype = { +date: null, +id: null, +file: null, + +QueryInterface: XPCOMUtils.generateQI([Ci.nttIBreakpadIncident]) +} + +function nttBreakpadService() { + var obs = Cc["@mozilla.org/observer-service;1"] + .getService(Ci.nsIObserverService); + obs.addObserver(this, "quit-application", false); + + this._dirs = []; + this._databases = []; + this._listeners = []; + this._incidents = []; + this._orderedIncidents = []; + + this._findBreakpad(); + if (this.reportdir) + this._dirs.push(this.reportdir); + else + { + this.loaded = true; + this._loading = true; + } +} + +nttBreakpadService.prototype = { + +reportdir: null, + +loaded: false, +_loading: false, +_dirs: null, +_databases: null, +_loadTimer: null, +_listeners: null, + +incidents: null, +orderedIncidents: null, + +addProgressListener: function(listener) +{ + if (!this.loaded) + this._listeners.push(listener); + else + listener.onDatabaseLoaded(); +}, + +loadDatabase: function() +{ + if (this._loading) + return; + + this._loading = true; + + if (this.reportdir && this.reportdir.exists()) + { + this.incidents = []; + this.orderedIncidents = []; + + this._loadTimer = Cc["@mozilla.org/timer;1"] + .createInstance(Ci.nsITimer); + this._loadTimer.init(this, LOAD_DELAY, Components.interfaces.nsITimer.TYPE_ONE_SHOT); + } + else + this.loaded = true; +}, + +observe: function(subject, topic, data) +{ + switch (topic) + { + case "quit-application": + if (this._loadTimer) + { + // Shutdown during load, clear references + this._loadTimer.cancel(); + this._loadTimer = null; + this._databases = []; + this._dirs = []; + this._listeners = []; + } + var obs = Cc["@mozilla.org/observer-service;1"] + .getService(Ci.nsIObserverService); + obs.removeObserver(this, "quit-application"); + break; + case "timer-callback": + this.run(); + break; + } +}, + +run: function() +{ + if (this._dirs.length>0) + this._scanDir(this._dirs.pop()); + else if (this._databases.length>0) + this._loadDatabase(this._databases.pop()); + else + { + this.loaded = true; + if (this._listeners.length == 0) { + this._loadTimer = null; + return; + } + var listener = this._listeners.pop(); + listener.onDatabaseLoaded(); + if (this._listeners.length == 0) { + this._loadTimer = null; + return; + } + } + this._loadTimer.init(this, LOAD_DELAY, Components.interfaces.nsITimer.TYPE_ONE_SHOT); +}, + +_scanDir: function(dir) +{ + var entries = dir.directoryEntries; + while (entries.hasMoreElements()) + { + var ndir = entries.getNext().QueryInterface(Ci.nsIFile); + if (ndir.isDirectory()) + this._dirs.push(ndir); + else + { + var ext = ndir.leafName; + ext = ext.substring(ext.length - 4); + if (ext == ".txt") + this._databases.push(ndir); + } + } +}, + +_loadDatabase: function(database) +{ + var incident = new nttBreakpadIncident(database); + this._addIncident(incident); +}, + +_findBreakpad: function() +{ + var directoryService = Cc["@mozilla.org/file/directory_service;1"] + .getService(Ci.nsIProperties); + var dir = directoryService.get("DefProfRt", Ci.nsIFile); + if (dir.leafName.toLowerCase() == "profiles") + dir = dir.parent; + dir.append("Crash Reports"); + if (dir.exists() && dir.isDirectory()) + this.reportdir = dir; +}, + +_addIncident: function(incident) +{ + var pos = 0; + while ((pos < this.orderedIncidents.length) && (this.orderedIncidents[pos].date > incident.date)) + pos++; + + this.orderedIncidents.splice(pos, 0, incident); + this.incidents[incident.id]=incident; +}, + +getRecentIncidents: function(date) +{ + var result = Cc["@mozilla.org/array;1"] + .createInstance(Ci.nsIMutableArray); + + for (var i = 0; i < this.orderedIncidents.length; i++) + { + if (this.orderedIncidents[i].date<date) + break; + + result.appendElement(this.orderedIncidents[i], false); + } + + return result; +}, + +getPreviousIncidents: function(count) +{ + var result = Cc["@mozilla.org/array;1"] + .createInstance(Ci.nsIMutableArray); + + count=Math.min(count, this.orderedIncidents.length); + + for (var i = 0; i < count; i++) + result.appendElement(this.orderedIncidents[i], false); + + return result; +}, + +getIncident: function(id) +{ + return this.incidents[id]; +}, + +getIncidents: function() +{ + return TB_CreateArray(this.orderedIncidents); +}, + +getTreeView: function() +{ + var share = {}; + var tv = new XULTreeView(share); + tv.childData.reserveChildren(true); + + var vparent = tv.childData; + + for (var i = 0; i < this.orderedIncidents.length; i++) + { + var incident = this.orderedIncidents[i]; + record = new XULTreeViewRecord(share); + record.setColumnPropertyName("incidentID", "id"); + record.setColumnPropertyName("incidentDate", "date"); + record.setColumnProperties("incidentID", "name incident"); + record.id = incident.id; + record.date = (new Date(incident.date)).toLocaleString(); + tv.childData.appendChild(record); + } + + return tv; +}, + +classDescription: "Nightly Tester Breakpad Service", +contractID: "@blueprintit.co.uk/breakpad;1", +classID: Components.ID("{b33388ca-71b4-4194-b822-2cbd0e89ffc0}"), +QueryInterface: XPCOMUtils.generateQI([Ci.nttIBreakpadService, Ci.nsIObserver]) +} + +function NSGetModule(compMgr, fileSpec) + XPCOMUtils.generateModule([nttBreakpadService]);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/components/nttMultipartFormData.js Tue Dec 02 20:31:01 2008 +0900 @@ -0,0 +1,191 @@ +const Ci = Components.interfaces; +const Cc = Components.classes; +const Cr = Components.results; + +Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); + +function NTT_MakeStream(data) +{ + var stream = Cc["@mozilla.org/io/string-input-stream;1"] + .createInstance(Ci.nsIStringInputStream); + stream.setData(data, data.length); + return stream; +} + +const keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + +function NTT_decode64(input) +{ + var output = ""; + var chr1, chr2, chr3; + var enc1, enc2, enc3, enc4; + var i = 0; + + // remove all characters that are not A-Z, a-z, 0-9, +, /, or = + input = input.replace(/[^A-Za-z0-9\+\/\=]/g, ""); + + do + { + enc1 = keyStr.indexOf(input.charAt(i++)); + enc2 = keyStr.indexOf(input.charAt(i++)); + enc3 = keyStr.indexOf(input.charAt(i++)); + enc4 = keyStr.indexOf(input.charAt(i++)); + + chr1 = (enc1 << 2) | (enc2 >> 4); + chr2 = ((enc2 & 15) << 4) | (enc3 >> 2); + chr3 = ((enc3 & 3) << 6) | enc4; + + output = output + String.fromCharCode(chr1); + + if (enc3 != 64) + { + output = output + String.fromCharCode(chr2); + } + if (enc4 != 64) + { + output = output + String.fromCharCode(chr3); + } + } + while (i < input.length); + + return output; +} + +function MultipartFormData() +{ + this.boundary = "hsdluicmwos"; + this.controls = []; + this.files = []; + this.postdata = ""; +} + +MultipartFormData.prototype = { + +boundary: null, +controls: null, +files: null, +length: null, +postdata: null, + +getPostData: function() +{ + if (this.postdata) + return this.postdata; + + var data = ""; + + for (var name in this.controls) + { + data+="\r\n--"+this.boundary+"\r\n"; + data+="Content-Disposition: form-data; name=\""+name+"\"\r\n\r\n"; + data+=this.controls[name]; + } + + for (var name in this.files) + { + var filedata = this.files[name]; + data+="\r\n--"+this.boundary+"\r\n"; + data+="Content-Disposition: form-data; name=\""+name+"\"; filename=\""+filedata.filename+"\"\r\n"; + data+="Content-Type: "+filedata.contenttype+"\r\n"; + if (filedata.source) + { + data+="Content-Transfer-Encoding: base64\r\n\r\n"; + + var fis = Cc["@mozilla.org/network/file-input-stream;1"] + .createInstance(Ci.nsIFileInputStream); + fis.init(filedata.source, 1, 384, Ci.nsIFileInputStream.CLOSE_ON_EOF); + + var bis = Cc["@mozilla.org/binaryinputstream;1"] + .createInstance(Ci.nsIBinaryInputStream); + bis.setInputStream(fis); + + //TODO this isnt needed as yet + } + else + { + data+="Content-Transfer-Encoding: binary\r\n\r\n"; + if (filedata.encoding == "base64") + { + data+=NTT_decode64(filedata.data); + } + else if (filedata.encoding == "binary") + { + data+=filedata.data; + } + } + } + data+="\r\n--"+this.boundary+"--\r\n"; + + this.length = data.length-2; + this.postdata = data; + + return data; +}, + +getPostDataStream: function() +{ + return NTT_MakeStream(this.getPostData()); +}, + +getHeaders: function() +{ + if (!this.length) + this.getPostData(); + + var headers = ""; + headers+="Content-Type: "+this.getContentType()+"\r\n"; + headers+="Content-Length: "+this.length+"\r\n"; + return headers; +}, + +getHeaderStream: function() +{ + return NTT_MakeStream(this.getHeaders()); +}, + +getContentType: function() +{ + return "multipart/form-data; boundary=\""+this.boundary+"\""; +}, + +addControl: function(name, value) +{ + this.controls[name]=value; + this.postdata = null; + this.length = null; +}, + +addFile: function(name, contenttype, file) +{ + throw Components.results.NS_NOT_IMPLEMENTED; + var filedata = { + filename: file.leafName, + contenttype: contenttype, + source: file + }; + this.files[name] = filedata; + this.postdata = null; + this.length = null; +}, + +addFileData: function(name, filename, contenttype, encoding, data) +{ + var filedata = { + filename: filename, + contenttype: contenttype, + encoding: encoding, + data: data + }; + this.files[name] = filedata; + this.postdata = null; + this.length = null; +}, + +classDescription: "Nightly Tester Multipart Form Data", +contractID: "@blueprintit.co.uk/multipartformdata;1", +classID: Components.ID("{46c8b0c6-216c-41e8-ace2-03d61783e278}"), +QueryInterface: XPCOMUtils.generateQI([Ci.nttIMultipartFormData]) +} + +function NSGetModule(compMgr, fileSpec) + XPCOMUtils.generateModule([MultipartFormData]);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/defaults/preferences/nightlytools.js Tue Dec 02 20:31:01 2008 +0900 @@ -0,0 +1,16 @@ +pref("nightly.idtitle", true); + +pref("nightly.showEnableAll", true); + +pref("nightly.leaks.showleaklog", false); +pref("nightly.leaks.filterDocshell", true); +pref("nightly.leaks.filterDocument", true); +pref("nightly.leaks.filterWindow", true); +pref("nightly.leaks.filterLeaked", true); +pref("nightly.leaks.filterCollected", true); +pref("nightly.leaks.filterIgnored", true); + +pref("nightly.crashreports.recentlist.display", true); +pref("nightly.breakpad.searchurl", "http://crash-stats.mozilla.com/report/index/"); + +pref("extensions.{8620c15f-30dc-4dba-a131-7c5d20cf4a29}.description", "chrome://nightly/locale/nightly.properties");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/defaults/preferences/variables.js Tue Dec 02 20:31:01 2008 +0900 @@ -0,0 +1,2 @@ +pref("nightly.templates.buildid", "${UserAgent} ID:${AppBuildID}${Flags}"); +pref("nightly.templates.title", "${DefaultTitle} (Build ${AppBuildID})");
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/install.rdf Tue Dec 02 20:31:01 2008 +0900 @@ -0,0 +1,62 @@ +<?xml version="1.0"?> + +<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:em="http://www.mozilla.org/2004/em-rdf#"> + + <Description about="urn:mozilla:install-manifest"> + <em:id>{8620c15f-30dc-4dba-a131-7c5d20cf4a29}</em:id> + <em:version>2.0.2</em:version> + + <!-- Firefox version --> + <em:targetApplication> + <Description> + <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id> + <em:minVersion>3.0b5</em:minVersion> + <em:maxVersion>3.0pre</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Thunderbird version --> + <em:targetApplication> + <Description> + <em:id>{3550f703-e582-4d05-9a08-453d09bdfdc6}</em:id> + <em:minVersion>3.0a1</em:minVersion> + <em:maxVersion>3.0a1</em:maxVersion> + </Description> + </em:targetApplication> + + + <!-- Suiterunner version --> + <em:targetApplication> + <Description> + <em:id>{92650c4d-4b8e-4d2a-b7eb-24ecf4f6b63a}</em:id> + <em:minVersion>2.0a1pre</em:minVersion> + <em:maxVersion>2.0a1pre</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Songbird version --> + <em:targetApplication> + <Description> + <em:id>songbird@songbirdnest.com</em:id> + <em:minVersion>0.6pre</em:minVersion> + <em:maxVersion>0.6pre</em:maxVersion> + </Description> + </em:targetApplication> + + <!-- Front End MetaData --> + <em:name>Nightly Tester Tools</em:name> + <em:description>Useful tools for the nightly tester.</em:description> + <em:creator>Mossop</em:creator> + <em:contributor>Peter van der Woude (original idea)</em:contributor> + <em:contributor>Jesse Ruderman (Mac fixes)</em:contributor> + <em:contributor>Steve England (QA)</em:contributor> + <em:contributor>Stephen Lau (Songbird port)</em:contributor> + <em:contributor>FAMFAMFAM (Some icons)</em:contributor> + + <em:iconURL>chrome://nightly/content/brand/icon.png</em:iconURL> + <em:optionsURL>chrome://nightly/content/options/options.xul</em:optionsURL> + <em:homepageURL>http://www.oxymoronical.com/web/firefox/nightly</em:homepageURL> + + </Description> +</RDF>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules/Logging.jsm Tue Dec 02 20:31:01 2008 +0900 @@ -0,0 +1,70 @@ +var EXPORTED_SYMBOLS = ["LOG", "WARN", "ERROR"]; + +const Cc = Components.classes; +const Ci = Components.interfaces; +const Cr = Components.results; + +var gLoggingEnabled = false; + +function logMessage(text, level) { + var caller = null; + try { + caller = Components.stack.caller.caller; + } + catch (e) { } + + var msg = Cc["@mozilla.org/scripterror;1"]. + createInstance(Ci.nsIScriptError); + if (caller) { + var filename = caller.filename; + var sourceLine = caller.sourceLine; + var lineNumber = caller.lineNumber; + } + else { + var filename = ""; + var sourceLine = ""; + var lineNumber = 0; + } + msg.init(text, filename, sourceLine, lineNumber, 0, + level, "XUL JavaScript"); + + var console = Cc["@mozilla.org/consoleservice;1"]. + getService(Ci.nsIConsoleService); + console.logMessage(msg); +} + +function ERROR(string) { + dump("NTT ERROR: " + string + "\n"); + logMessage("NTT: " + string, Ci.nsIScriptError.errorFlag); +} + +function WARN(string) { + dump("NTT WARN : " + string + "\n"); + logMessage("NTT: " + string, Ci.nsIScriptError.warningFlag); +} + +function LOG(string) { + if (gLoggingEnabled) { + dump("NTT LOG : " + string + "\n"); + + var caller = null; + try { + caller = Components.stack.caller; + } + catch (e) { } + + if (caller) + string += " (" + caller.filename + ":" + caller.lineNumber + ")"; + + var console = Cc["@mozilla.org/consoleservice;1"]. + getService(Ci.nsIConsoleService); + console.logStringMessage("NTT: " + string); + } +} + +var prefs = Cc["@mozilla.org/preferences-service;1"]. + getService(Ci.nsIPrefBranch); +try { + gLoggingEnabled = prefs.getBoolPref("nightly.logging"); +} +catch (e) { }