Bug 811159 - Save last submitted health report to profile; r=rnewman

This commit is contained in:
Gregory Szorc 2012-11-16 10:05:19 -08:00
parent ba1800874b
commit 6d778b7eaf
3 changed files with 119 additions and 9 deletions

View File

@ -14,6 +14,7 @@ Cu.import("resource://services-common/observers.js");
Cu.import("resource://services-common/preferences.js");
Cu.import("resource://services-common/utils.js");
Cu.import("resource://gre/modules/commonjs/promise/core.js");
Cu.import("resource://gre/modules/osfile.jsm");
Cu.import("resource://gre/modules/services/healthreport/policy.jsm");
Cu.import("resource://gre/modules/services/metrics/collector.jsm");
@ -150,13 +151,24 @@ HealthReporter.prototype = {
},
/**
* Start background functionality.
* Perform post-construction initialization and start background activity.
*
* If this isn't called, no data upload will occur.
*
* This returns a promise that will be fulfilled when all initialization
* activity is completed. It is not safe for this instance to perform
* additional actions until this promise has been resolved.
*/
start: function start() {
this._policy.startPolling();
this._log.info("HealthReporter started.");
let onExists = function onExists() {
this._policy.startPolling();
this._log.info("HealthReporter started.");
return Promise.resolve();
}.bind(this);
return this._ensureDirectoryExists(this._stateDir)
.then(onExists);
},
/**
@ -370,12 +382,13 @@ HealthReporter.prototype = {
let payload = this.getJSONPayload();
let promise = client.uploadJSON(this.serverNamespace,
id,
payload,
this.lastSubmitID);
return promise.then(this._onBagheeraResult.bind(this, request, false));
return this._saveLastPayload(payload)
.then(client.uploadJSON.bind(client,
this.serverNamespace,
id,
payload,
this.lastSubmitID))
.then(this._onBagheeraResult.bind(this, request, false));
},
_deleteRemoteData: function _deleteRemoteData(request) {
@ -394,6 +407,77 @@ HealthReporter.prototype = {
},
get _stateDir() {
let profD = OS.Constants.Path.profileDir;
// Work around bug 810543 until OS.File is more resilient.
if (!profD || !profD.length) {
throw new Error("Could not obtain profile directory. OS.File not " +
"initialized properly?");
}
return OS.Path.join(profD, "healthreport");
},
_ensureDirectoryExists: function _ensureDirectoryExists(path) {
let deferred = Promise.defer();
OS.File.makeDir(path).then(
function onResult() {
deferred.resolve(true);
},
function onError(error) {
if (error.becauseExists) {
deferred.resolve(true);
return;
}
deferred.reject(error);
}
);
return deferred.promise;
},
get _lastPayloadPath() {
return OS.Path.join(this._stateDir, "lastpayload.json");
},
_saveLastPayload: function _saveLastPayload(payload) {
let path = this._lastPayloadPath;
let pathTmp = path + ".tmp";
let encoder = new TextEncoder();
let buffer = encoder.encode(payload);
return OS.File.writeAtomic(path, buffer, {tmpPath: pathTmp});
},
/**
* Obtain the last uploaded payload.
*
* The promise is resolved to a JSON-decoded object on success. The promise
* is rejected if the last uploaded payload could not be found or there was
* an error reading or parsing it.
*
* @return Promise<object>
*/
getLastPayload: function getLoadPayload() {
let path = this._lastPayloadPath;
return OS.File.read(path).then(
function onData(buffer) {
let decoder = new TextDecoder();
let json = JSON.parse(decoder.decode(buffer));
return Promise.resolve(json);
},
function onError(error) {
return Promise.reject(error);
}
);
},
_now: function _now() {
return new Date();
},

View File

@ -3,6 +3,9 @@
"use strict";
// We need to initialize the profile or OS.File may not work. See bug 810543.
do_get_profile();
(function initMetricsTestingInfrastructure() {
let ns = {};
Components.utils.import("resource://testing-common/services-common/logging.js",

View File

@ -96,6 +96,14 @@ add_test(function test_register_providers_from_category_manager() {
run_next_test();
});
add_test(function test_start() {
let reporter = getReporter("start");
reporter.start().then(function onStarted() {
reporter.stop();
run_next_test();
});
});
add_test(function test_json_payload_simple() {
let reporter = getReporter("json_payload_simple");
@ -260,3 +268,18 @@ add_test(function test_policy_accept_reject() {
server.stop(run_next_test);
});
add_test(function test_upload_save_payload() {
let [reporter, server] = getReporterAndServer("upload_save_payload");
let deferred = Promise.defer();
let request = new DataSubmissionRequest(deferred, new Date(), false);
reporter._uploadData(request).then(function onUpload() {
reporter.getLastPayload().then(function onJSON(json) {
do_check_true("thisPingDate" in json);
server.stop(run_next_test);
});
});
});