gecko/services/healthreport/modules-testing/utils.jsm

220 lines
6.5 KiB
JavaScript

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
this.EXPORTED_SYMBOLS = [
"getAppInfo",
"updateAppInfo",
"createFakeCrash",
"InspectedHealthReporter",
"getHealthReporter",
];
const {classes: Cc, interfaces: Ci, results: Cr, utils: Cu} = Components;
Cu.import("resource://gre/modules/Preferences.jsm");
Cu.import("resource://gre/modules/Promise.jsm");
Cu.import("resource://gre/modules/FileUtils.jsm");
Cu.import("resource://gre/modules/osfile.jsm");
Cu.import("resource://gre/modules/Task.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/services-common/utils.js");
Cu.import("resource://gre/modules/services/datareporting/policy.jsm");
Cu.import("resource://gre/modules/services/healthreport/healthreporter.jsm");
Cu.import("resource://gre/modules/services/healthreport/providers.jsm");
Cu.import("resource://testing-common/services/datareporting/mocks.jsm");
var APP_INFO = {
vendor: "Mozilla",
name: "xpcshell",
ID: "xpcshell@tests.mozilla.org",
version: "1",
appBuildID: "20121107",
platformVersion: "p-ver",
platformBuildID: "20121106",
inSafeMode: false,
logConsoleErrors: true,
OS: "XPCShell",
XPCOMABI: "noarch-spidermonkey",
QueryInterface: XPCOMUtils.generateQI([Ci.nsIXULAppInfo, Ci.nsIXULRuntime]),
invalidateCachesOnRestart: function() {},
};
/**
* Obtain a reference to the current object used to define XULAppInfo.
*/
this.getAppInfo = function () { return APP_INFO; }
/**
* Update the current application info.
*
* If the argument is defined, it will be the object used. Else, APP_INFO is
* used.
*
* To change the current XULAppInfo, simply call this function. If there was
* a previously registered app info object, it will be unloaded and replaced.
*/
this.updateAppInfo = function (obj) {
obj = obj || APP_INFO;
APP_INFO = obj;
let id = Components.ID("{fbfae60b-64a4-44ef-a911-08ceb70b9f31}");
let cid = "@mozilla.org/xre/app-info;1";
let registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
// Unregister an existing factory if one exists.
try {
let existing = Components.manager.getClassObjectByContractID(cid, Ci.nsIFactory);
registrar.unregisterFactory(id, existing);
} catch (ex) {}
let factory = {
createInstance: function (outer, iid) {
if (outer != null) {
throw Cr.NS_ERROR_NO_AGGREGATION;
}
return obj.QueryInterface(iid);
},
};
registrar.registerFactory(id, "XULAppInfo", cid, factory);
};
/**
* Creates a fake crash in the Crash Reports directory.
*
* Currently, we just create a dummy file. A more robust implementation would
* create something that actually resembles a crash report file.
*
* This is very similar to code in crashreporter/tests/browser/head.js.
*
* FUTURE consolidate code in a shared JSM.
*/
this.createFakeCrash = function (submitted=false, date=new Date()) {
let id = CommonUtils.generateUUID();
let filename;
let paths = ["Crash Reports"];
let mode;
if (submitted) {
paths.push("submitted");
filename = "bp-" + id + ".txt";
mode = OS.Constants.libc.S_IRUSR | OS.Constants.libc.S_IWUSR |
OS.Constants.libc.S_IRGRP | OS.Constants.libc.S_IROTH;
} else {
paths.push("pending");
filename = id + ".dmp";
mode = OS.Constants.libc.S_IRUSR | OS.Constants.libc.S_IWUSR;
}
paths.push(filename);
let file = FileUtils.getFile("UAppData", paths, true);
file.create(file.NORMAL_FILE_TYPE, mode);
file.lastModifiedTime = date.getTime();
dump("Created fake crash: " + id + "\n");
return id;
};
/**
* A HealthReporter that is probed with various callbacks and counters.
*
* The purpose of this type is to aid testing of startup and shutdown.
*/
this.InspectedHealthReporter = function (branch, policy, stateLeaf) {
HealthReporter.call(this, branch, policy, stateLeaf);
this.onStorageCreated = null;
this.onProviderManagerInitialized = null;
this.providerManagerShutdownCount = 0;
this.storageCloseCount = 0;
}
InspectedHealthReporter.prototype = {
__proto__: HealthReporter.prototype,
_onStorageCreated: function (storage) {
if (this.onStorageCreated) {
this.onStorageCreated(storage);
}
return HealthReporter.prototype._onStorageCreated.call(this, storage);
},
_initializeProviderManager: Task.async(function* () {
yield HealthReporter.prototype._initializeProviderManager.call(this);
if (this.onInitializeProviderManagerFinished) {
this.onInitializeProviderManagerFinished();
}
}),
_onProviderManagerInitialized: function () {
if (this.onProviderManagerInitialized) {
this.onProviderManagerInitialized();
}
return HealthReporter.prototype._onProviderManagerInitialized.call(this);
},
_onProviderManagerShutdown: function () {
this.providerManagerShutdownCount++;
return HealthReporter.prototype._onProviderManagerShutdown.call(this);
},
_onStorageClose: function () {
this.storageCloseCount++;
return HealthReporter.prototype._onStorageClose.call(this);
},
};
const DUMMY_URI="http://localhost:62013/";
this.getHealthReporter = function (name, uri=DUMMY_URI, inspected=false) {
// The healthreporters use the client id from the datareporting service,
// so we need to ensure it is initialized.
let drs = Cc["@mozilla.org/datareporting/service;1"]
.getService(Ci.nsISupports)
.wrappedJSObject;
drs.observe(null, "app-startup", null);
drs.observe(null, "profile-after-change", null);
let branch = "healthreport.testing." + name + ".";
let prefs = new Preferences(branch + "healthreport.");
prefs.set("documentServerURI", uri);
prefs.set("dbName", name);
let reporter;
let policyPrefs = new Preferences(branch + "policy.");
let listener = new MockPolicyListener();
listener.onRequestDataUpload = function (request) {
let promise = reporter.requestDataUpload(request);
MockPolicyListener.prototype.onRequestDataUpload.call(this, request);
return promise;
}
listener.onRequestRemoteDelete = function (request) {
let promise = reporter.deleteRemoteData(request);
MockPolicyListener.prototype.onRequestRemoteDelete.call(this, request);
return promise;
}
let policy = new DataReportingPolicy(policyPrefs, prefs, listener);
let type = inspected ? InspectedHealthReporter : HealthReporter;
reporter = new type(branch + "healthreport.", policy,
"state-" + name + ".json");
return reporter;
};