michael@0: function create_subdir(dir, subdirname) { michael@0: let subdir = dir.clone(); michael@0: subdir.append(subdirname); michael@0: if (subdir.exists()) { michael@0: subdir.remove(true); michael@0: } michael@0: subdir.create(Ci.nsIFile.DIRECTORY_TYPE, 0755); michael@0: return subdir; michael@0: } michael@0: michael@0: // need to hold on to this to unregister for cleanup michael@0: let _provider = null; michael@0: michael@0: function make_fake_appdir() { michael@0: // Create a directory inside the profile and register it as UAppData, so michael@0: // we can stick fake crash reports inside there. We put it inside the profile michael@0: // just because we know that will get cleaned up after the mochitest run. michael@0: let dirSvc = Cc["@mozilla.org/file/directory_service;1"] michael@0: .getService(Ci.nsIProperties); michael@0: let profD = dirSvc.get("ProfD", Ci.nsILocalFile); michael@0: // create a subdir just to keep our files out of the way michael@0: let appD = create_subdir(profD, "UAppData"); michael@0: michael@0: let crashesDir = create_subdir(appD, "Crash Reports"); michael@0: create_subdir(crashesDir, "pending"); michael@0: create_subdir(crashesDir, "submitted"); michael@0: michael@0: _provider = { michael@0: getFile: function(prop, persistent) { michael@0: persistent.value = true; michael@0: if (prop == "UAppData") { michael@0: return appD.clone(); michael@0: } michael@0: throw Components.results.NS_ERROR_FAILURE; michael@0: }, michael@0: QueryInterface: function(iid) { michael@0: if (iid.equals(Ci.nsIDirectoryServiceProvider) || michael@0: iid.equals(Ci.nsISupports)) { michael@0: return this; michael@0: } michael@0: throw Components.results.NS_ERROR_NO_INTERFACE; michael@0: } michael@0: }; michael@0: // register our new provider michael@0: dirSvc.QueryInterface(Ci.nsIDirectoryService) michael@0: .registerProvider(_provider); michael@0: // and undefine the old value michael@0: try { michael@0: dirSvc.undefine("UAppData"); michael@0: } catch(ex) {} // it's ok if this fails, the value might not be cached yet michael@0: return appD.clone(); michael@0: } michael@0: michael@0: function cleanup_fake_appdir() { michael@0: let dirSvc = Cc["@mozilla.org/file/directory_service;1"] michael@0: .getService(Ci.nsIProperties); michael@0: dirSvc.QueryInterface(Ci.nsIDirectoryService) michael@0: .unregisterProvider(_provider); michael@0: // undefine our value so future calls get the real value michael@0: try { michael@0: dirSvc.undefine("UAppData"); michael@0: } catch(ex) { michael@0: dump("cleanup_fake_appdir: dirSvc.undefine failed: " + ex.message +"\n"); michael@0: } michael@0: } michael@0: michael@0: function add_fake_crashes(crD, count) { michael@0: let results = []; michael@0: let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"] michael@0: .getService(Ci.nsIUUIDGenerator); michael@0: let submitdir = crD.clone(); michael@0: submitdir.append("submitted"); michael@0: // create them from oldest to newest, to ensure that about:crashes michael@0: // displays them in the correct order michael@0: let date = Date.now() - count * 60000; michael@0: for (let i = 0; i < count; i++) { michael@0: let uuid = uuidGenerator.generateUUID().toString(); michael@0: // ditch the {} michael@0: uuid = "bp-" + uuid.substring(1, uuid.length - 2); michael@0: let fn = uuid + ".txt"; michael@0: let file = submitdir.clone(); michael@0: file.append(fn); michael@0: file.create(Ci.nsIFile.NORMAL_FILE_TYPE, 0666); michael@0: file.lastModifiedTime = date; michael@0: results.push({'id': uuid, 'date': date, 'pending': false}); michael@0: michael@0: date += 60000; michael@0: } michael@0: // we want them sorted newest to oldest, since that's the order michael@0: // that about:crashes lists them in michael@0: results.sort(function(a,b) b.date - a.date); michael@0: return results; michael@0: } michael@0: michael@0: function writeDataToFile(file, data) { michael@0: var fstream = Cc["@mozilla.org/network/file-output-stream;1"] michael@0: .createInstance(Ci.nsIFileOutputStream); michael@0: // open, write, truncate michael@0: fstream.init(file, -1, -1, 0); michael@0: var os = Cc["@mozilla.org/intl/converter-output-stream;1"] michael@0: .createInstance(Ci.nsIConverterOutputStream); michael@0: os.init(fstream, "UTF-8", 0, 0x0000); michael@0: os.writeString(data); michael@0: os.close(); michael@0: fstream.close(); michael@0: } michael@0: michael@0: function addPendingCrashreport(crD, date, extra) { michael@0: let pendingdir = crD.clone(); michael@0: pendingdir.append("pending"); michael@0: let uuidGenerator = Cc["@mozilla.org/uuid-generator;1"] michael@0: .getService(Ci.nsIUUIDGenerator); michael@0: let uuid = uuidGenerator.generateUUID().toString(); michael@0: // ditch the {} michael@0: uuid = uuid.substring(1, uuid.length - 1); michael@0: let dumpfile = pendingdir.clone(); michael@0: dumpfile.append(uuid + ".dmp"); michael@0: writeDataToFile(dumpfile, "MDMP"); // that's the start of a valid minidump, anyway michael@0: let extrafile = pendingdir.clone(); michael@0: extrafile.append(uuid + ".extra"); michael@0: let extradata = ""; michael@0: for (let x in extra) { michael@0: extradata += x + "=" + extra[x] + "\n"; michael@0: } michael@0: writeDataToFile(extrafile, extradata); michael@0: dumpfile.lastModifiedTime = date; michael@0: extrafile.lastModifiedTime = date; michael@0: return {'id': uuid, 'date': date, 'pending': true, 'extra': extra}; michael@0: }