Bug 810132 - Add remote deletion requests to policy; r=rnewman

This commit is contained in:
Gregory Szorc 2012-11-09 13:59:40 -08:00
parent 21080df09a
commit 80740451d8
3 changed files with 355 additions and 85 deletions

View File

@ -15,20 +15,29 @@ this.MockPolicyListener = function MockPolicyListener() {
this._log = Log4Moz.repository.getLogger("HealthReport.Testing.MockPolicyListener");
this._log.level = Log4Moz.Level["Debug"];
this.requestDataSubmissionCount = 0;
this.requestDataUploadCount = 0;
this.lastDataRequest = null;
this.requestRemoteDeleteCount = 0;
this.lastRemoteDeleteRequest = null;
this.notifyUserCount = 0;
this.lastNotifyRequest = null;
}
MockPolicyListener.prototype = {
onRequestDataSubmission: function onRequestDataSubmission(request) {
this._log.info("onRequestDataSubmission invoked.");
this.requestDataSubmissionCount++;
onRequestDataUpload: function onRequestDataUpload(request) {
this._log.info("onRequestDataUpload invoked.");
this.requestDataUploadCount++;
this.lastDataRequest = request;
},
onRequestRemoteDelete: function onRequestRemoteDelete(request) {
this._log.info("onRequestRemoteDelete invoked.");
this.requestRemoteDeleteCount++;
this.lastRemoteDeleteRequest = request;
},
onNotifyDataPolicy: function onNotifyDataPolicy(request) {
this._log.info("onNotifyUser invoked.");
this.notifyUserCount++;

View File

@ -107,7 +107,9 @@ Object.freeze(NotifyPolicyRequest.prototype);
/**
* Represents a request to submit data.
*
* Instances of this are created when the policy requests data submission.
* Instances of this are created when the policy requests data upload or
* deletion.
*
* Receivers are expected to call one of the provided on* functions to signal
* completion of the request.
*
@ -115,9 +117,10 @@ Object.freeze(NotifyPolicyRequest.prototype);
* Receivers of instances of this type should not attempt to do anything with
* the instance except call one of the on* methods.
*/
function DataSubmissionRequest(promise, expiresDate) {
function DataSubmissionRequest(promise, expiresDate, isDelete) {
this.promise = promise;
this.expiresDate = expiresDate;
this.isDelete = isDelete;
this.state = null;
this.reason = null;
@ -131,6 +134,10 @@ DataSubmissionRequest.prototype = {
/**
* No submission was attempted because no data was available.
*
* In the case of upload, this means there is no data to upload (perhaps
* it isn't available yet). In case of remote deletion, it means that there
* is no remote data to delete.
*/
onNoDataAvailable: function onNoDataAvailable() {
this.state = this.NO_DATA_AVAILABLE;
@ -140,6 +147,9 @@ DataSubmissionRequest.prototype = {
/**
* Data submission has completed successfully.
*
* In case of upload, this means the upload completed successfully. In case
* of deletion, the data was deleted successfully.
*
* @param date
* (Date) When data submission occurred.
*/
@ -204,11 +214,16 @@ Object.freeze(DataSubmissionRequest.prototype);
* The listener passed into the instance must have the following properties
* (which are callbacks that will be invoked at certain key events):
*
* * onRequestDataSubmission(request) - Called when the policy is requesting
* * onRequestDataUpload(request) - Called when the policy is requesting
* data to be submitted. The function is passed a `DataSubmissionRequest`.
* The listener should call one of the special resolving functions on that
* instance (see the documentation for that type).
*
* * onRequestRemoteDelete(request) - Called when the policy is requesting
* deletion of remotely stored data. The function is passed a
* `DataSubmissionRequest`. The listener should call one of the special
* resolving functions on that instance (just like `onRequestDataUpload`).
*
* * onNotifyDataPolicy(request) - Called when the policy is requesting the
* user to be notified that data submission will occur. The function
* receives a `NotifyPolicyRequest` instance. The callee should call one or
@ -321,7 +336,11 @@ HealthReportPolicy.prototype = {
STATE_NOTIFY_WAIT: "waiting",
STATE_NOTIFY_COMPLETE: "ok",
REQUIRED_LISTENERS: ["onRequestDataSubmission", "onNotifyDataPolicy"],
REQUIRED_LISTENERS: [
"onRequestDataUpload",
"onRequestRemoteDelete",
"onNotifyDataPolicy",
],
/**
* The first time the health report policy came into existence.
@ -402,8 +421,8 @@ HealthReportPolicy.prototype = {
/**
* Whether submission of data is allowed.
*
* This is the master switch for data submission. If it is off, we will
* never submit data, even if the user has agreed to it.
* This is the master switch for remote server communication. If it is
* false, we never request upload or deletion.
*/
get dataSubmissionEnabled() {
// Default is true because we are opt-out.
@ -414,6 +433,22 @@ HealthReportPolicy.prototype = {
this._prefs.set("dataSubmissionEnabled", !!value);
},
/**
* Whether upload of data is allowed.
*
* This is a kill switch for upload. It is meant to reflect a system or
* deployment policy decision. User intent should be reflected in the
* "dataSubmissionPolicy" prefs.
*/
get dataUploadEnabled() {
// Default is true because we are opt-out.
return this._prefs.get("dataUploadEnabled", true);
},
set dataUploadEnabled(value) {
this._prefs.set("dataUploadEnabled", !!value);
},
/**
* Whether the user has accepted that data submission can occur.
*
@ -541,6 +576,21 @@ HealthReportPolicy.prototype = {
this._prefs.set("currentDaySubmissionFailureCount", value);
},
/**
* Whether a request to delete remote data is awaiting completion.
*
* If this is true, the policy will request that remote data be deleted.
* Furthermore, no new data will be uploaded (if it's even allowed) until
* the remote deletion is fulfilled.
*/
get pendingDeleteRemoteData() {
return !!this._prefs.get("pendingDeleteRemoteData", false);
},
set pendingDeleteRemoteData(value) {
this._prefs.set("pendingDeleteRemoteData", !!value);
},
/**
* Record user acceptance of data submission policy.
*
@ -578,6 +628,25 @@ HealthReportPolicy.prototype = {
this.dataSubmissionPolicyAccepted = false;
},
/**
* Request that remote data be deleted.
*
* This will record an intent that previously uploaded data is to be deleted.
* The policy will eventually issue a request to the listener for data
* deletion. It will keep asking for deletion until the listener acknowledges
* that data has been deleted.
*/
deleteRemoteData: function deleteRemoteData(reason="no-reason") {
this._log.info("Remote data deletion requested: " + reason);
this.pendingDeleteRemoteData = true;
// We want delete deletion to occur as soon as possible. Move up any
// pending scheduled data submission and try to trigger.
this.nextDataSubmissionDate = this.now();
this.checkStateAndTrigger();
},
/**
* Start background polling for activity.
*
@ -654,7 +723,29 @@ HealthReportPolicy.prototype = {
// should be pretty safe.
this._moveScheduleForward24h();
// Fall through and prompt for user notification, if necessary.
// Fall through since we may have other actions.
}
// Tend to any in progress work.
if (this._processInProgressSubmission()) {
return;
}
// Requests to delete remote data take priority above everything else.
if (this.pendingDeleteRemoteData) {
if (nowT < nextSubmissionDate.getTime()) {
this._log.debug("Deletion request is scheduled for the future: " +
nextSubmissionDate);
return;
}
this._dispatchSubmissionRequest("onRequestRemoteDelete", true);
return;
}
if (!this.dataUploadEnabled) {
this._log.debug("Data upload is disabled. Doing nothing.");
return;
}
// If the user hasn't responded to the data policy, don't do anything.
@ -677,53 +768,7 @@ HealthReportPolicy.prototype = {
return;
}
if (this._inProgressSubmissionRequest) {
if (this._inProgressSubmissionRequest.expiresDate.getTime() > nowT) {
this._log.info("Waiting on in-progress submission request to finish.");
return;
}
this._log.warn("Old submission request has expired from no activity.");
this._inProgressSubmissionRequest.promise.reject(new Error("Request has expired."));
this._inProgressSubmissionRequest = null;
if (!this._handleSubmissionFailure()) {
return;
}
}
// We're past our scheduled next data submission date, so let's do it!
this.lastDataSubmissionRequestedDate = now;
let deferred = Promise.defer();
let requestExpiresDate =
this._futureDate(this.SUBMISSION_REQUEST_EXPIRE_INTERVAL_MSEC);
this._inProgressSubmissionRequest = new DataSubmissionRequest(deferred,
requestExpiresDate);
let onSuccess = function onSuccess(result) {
this._inProgressSubmissionRequest = null;
this._handleSubmissionResult(result);
}.bind(this);
let onError = function onError(error) {
this._log.error("Error when handling data submission result: " +
CommonUtils.exceptionStr(result));
this._inProgressSubmissionRequest = null;
this._handleSubmissionFailure();
}.bind(this);
deferred.promise.then(onSuccess, onError);
this._log.info("Requesting data submission. Will expire at " +
requestExpiresDate);
try {
this._listener.onRequestDataSubmission(this._inProgressSubmissionRequest);
} catch (ex) {
this._log.warn("Exception when calling onRequestDataSubmission: " +
CommonUtils.exceptionStr(ex));
this._inProgressSubmissionRequest = null;
this._handleSubmissionFailure();
return;
}
this._dispatchSubmissionRequest("onRequestDataUpload", false);
},
/**
@ -797,26 +842,109 @@ HealthReportPolicy.prototype = {
return true;
},
_processInProgressSubmission: function _processInProgressSubmission() {
if (!this._inProgressSubmissionRequest) {
return false;
}
let now = this.now().getTime();
if (this._inProgressSubmissionRequest.expiresDate.getTime() > now) {
this._log.info("Waiting on in-progress submission request to finish.");
return true;
}
this._log.warn("Old submission request has expired from no activity.");
this._inProgressSubmissionRequest.promise.reject(new Error("Request has expired."));
this._inProgressSubmissionRequest = null;
this._handleSubmissionFailure();
return false;
},
_dispatchSubmissionRequest: function _dispatchSubmissionRequest(handler, isDelete) {
let now = this.now();
// We're past our scheduled next data submission date, so let's do it!
this.lastDataSubmissionRequestedDate = now;
let deferred = Promise.defer();
let requestExpiresDate =
this._futureDate(this.SUBMISSION_REQUEST_EXPIRE_INTERVAL_MSEC);
this._inProgressSubmissionRequest = new DataSubmissionRequest(deferred,
requestExpiresDate,
isDelete);
let onSuccess = function onSuccess(result) {
this._inProgressSubmissionRequest = null;
this._handleSubmissionResult(result);
}.bind(this);
let onError = function onError(error) {
this._log.error("Error when handling data submission result: " +
CommonUtils.exceptionStr(result));
this._inProgressSubmissionRequest = null;
this._handleSubmissionFailure();
}.bind(this);
deferred.promise.then(onSuccess, onError);
this._log.info("Requesting data submission. Will expire at " +
requestExpiresDate);
try {
this._listener[handler](this._inProgressSubmissionRequest);
} catch (ex) {
this._log.warn("Exception when calling " + handler + ": " +
CommonUtils.exceptionStr(ex));
this._inProgressSubmissionRequest = null;
this._handleSubmissionFailure();
return;
}
},
_handleSubmissionResult: function _handleSubmissionResult(request) {
let state = request.state;
let reason = request.reason || "no reason";
this._log.info("Got submission request result: " + state);
if (state == request.SUBMISSION_SUCCESS) {
this._log.info("Successful data submission reported.");
if (request.isDelete) {
this.pendingDeleteRemoteData = false;
this._log.info("Successful data delete reported.");
} else {
this._log.info("Successful data upload reported.");
}
this.lastDataSubmissionSuccessfulDate = request.submissionDate;
this.nextDataSubmissionDate =
let nextSubmissionDate =
new Date(request.submissionDate.getTime() + MILLISECONDS_PER_DAY);
// Schedule pending deletes immediately. This has potential to overload
// the server. However, the frequency of delete requests across all
// clients should be low, so this shouldn't pose a problem.
if (this.pendingDeleteRemoteData) {
nextSubmissionDate = this.now();
}
this.nextDataSubmissionDate = nextSubmissionDate;
this.currentDaySubmissionFailureCount = 0;
return;
}
if (state == request.NO_DATA_AVAILABLE) {
if (request.isDelete) {
this._log.info("Remote data delete requested but no remote data was stored.");
this.pendingDeleteRemoteData = false;
return;
}
this._log.info("No data was available to submit. May try later.");
this._handleSubmissionFailure();
return;
}
// We don't special case request.isDelete for these failures because it
// likely means there was a server error.
if (state == request.SUBMISSION_FAILURE_SOFT) {
this._log.warn("Soft error submitting data: " + reason);
this.lastDataSubmissionFailureDate = this.now();
@ -862,3 +990,4 @@ HealthReportPolicy.prototype = {
};
Object.freeze(HealthReportPolicy.prototype);

View File

@ -34,7 +34,8 @@ function run_test() {
add_test(function test_constructor() {
let prefs = new Preferences("foo.bar");
let listener = {
onRequestDataSubmission: function() {},
onRequestDataUpload: function() {},
onRequestRemoteDelete: function() {},
onNotifyDataPolicy: function() {},
};
@ -99,6 +100,10 @@ add_test(function test_prefs() {
do_check_eq(prefs.get("currentDaySubmissionFailureCount", 0), 2);
do_check_eq(policy.currentDaySubmissionFailureCount, 2);
policy.pendingDeleteRemoteData = true;
do_check_true(prefs.get("pendingDeleteRemoteData"));
do_check_true(policy.pendingDeleteRemoteData);
run_next_test();
});
@ -233,7 +238,7 @@ add_test(function test_notification_rejected() {
// No requests for submission should occur if user has rejected.
defineNow(policy, new Date(policy.nextDataSubmissionDate.getTime() + 10000));
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataSubmissionCount, 0);
do_check_eq(listener.requestDataUploadCount, 0);
run_next_test();
});
@ -245,13 +250,30 @@ add_test(function test_submission_kill_switch() {
policy.nextDataSubmissionDate = new Date(Date.now() - 24 * 60 * 60 * 1000);
policy.recordUserAcceptance("accept-old-ack");
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataSubmissionCount, 1);
do_check_eq(listener.requestDataUploadCount, 1);
defineNow(policy,
new Date(Date.now() + policy.SUBMISSION_REQUEST_EXPIRE_INTERVAL_MSEC + 100));
policy.dataSubmissionEnabled = false;
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataSubmissionCount, 1);
do_check_eq(listener.requestDataUploadCount, 1);
run_next_test();
});
add_test(function test_upload_kill_switch() {
let [policy, prefs, listener] = getPolicy("upload_kill_switch");
defineNow(policy, policy._futureDate(-24 * 60 * 60 * 1000));
policy.recordUserAcceptance();
defineNow(policy, policy.nextDataSubmissionDate);
policy.dataUploadEnabled = false;
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataUploadCount, 0);
policy.dataUploadEnabled = true;
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataUploadCount, 1);
run_next_test();
});
@ -263,15 +285,15 @@ add_test(function test_data_submission_no_data() {
policy.dataSubmissionPolicyAccepted = true;
let now = new Date(policy.nextDataSubmissionDate.getTime() + 1);
defineNow(policy, now);
do_check_eq(listener.requestDataSubmissionCount, 0);
do_check_eq(listener.requestDataUploadCount, 0);
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataSubmissionCount, 1);
do_check_eq(listener.requestDataUploadCount, 1);
listener.lastDataRequest.onNoDataAvailable();
// The next trigger should try again.
defineNow(policy, new Date(now.getTime() + 155 * 60 * 1000));
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataSubmissionCount, 2);
do_check_eq(listener.requestDataUploadCount, 2);
run_next_test();
});
@ -286,7 +308,7 @@ add_test(function test_data_submission_submit_failure_hard() {
defineNow(policy, now);
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataSubmissionCount, 1);
do_check_eq(listener.requestDataUploadCount, 1);
listener.lastDataRequest.onSubmissionFailureHard();
do_check_eq(listener.lastDataRequest.state,
listener.lastDataRequest.SUBMISSION_FAILURE_HARD);
@ -296,7 +318,7 @@ add_test(function test_data_submission_submit_failure_hard() {
defineNow(policy, new Date(now.getTime() + 10));
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataSubmissionCount, 1);
do_check_eq(listener.requestDataUploadCount, 1);
run_next_test();
});
@ -327,7 +349,7 @@ add_test(function test_submission_daily_scheduling() {
let now = new Date(policy.nextDataSubmissionDate.getTime());
defineNow(policy, now);
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataSubmissionCount, 1);
do_check_eq(listener.requestDataUploadCount, 1);
do_check_eq(policy.lastDataSubmissionRequestedDate.getTime(), now.getTime());
let finishedDate = new Date(now.getTime() + 250);
@ -344,11 +366,11 @@ add_test(function test_submission_daily_scheduling() {
// Fast forward some arbitrary time. We shouldn't do any work yet.
defineNow(policy, new Date(now.getTime() + 40000));
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataSubmissionCount, 1);
do_check_eq(listener.requestDataUploadCount, 1);
defineNow(policy, nextScheduled);
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataSubmissionCount, 2);
do_check_eq(listener.requestDataUploadCount, 2);
listener.lastDataRequest.onSubmissionSuccess(new Date(nextScheduled.getTime() + 200));
do_check_eq(policy.nextDataSubmissionDate.getTime(),
new Date(nextScheduled.getTime() + 24 * 60 * 60 * 1000 + 200).getTime());
@ -368,12 +390,12 @@ add_test(function test_submission_far_future_scheduling() {
let nextDate = policy._futureDate(3 * 24 * 60 * 60 * 1000 - 1);
policy.nextDataSubmissionDate = nextDate;
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataSubmissionCount, 0);
do_check_eq(listener.requestDataUploadCount, 0);
do_check_eq(policy.nextDataSubmissionDate.getTime(), nextDate.getTime());
policy.nextDataSubmissionDate = new Date(nextDate.getTime() + 1);
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataSubmissionCount, 0);
do_check_eq(listener.requestDataUploadCount, 0);
do_check_eq(policy.nextDataSubmissionDate.getTime(),
policy._futureDate(24 * 60 * 60 * 1000).getTime());
@ -391,7 +413,7 @@ add_test(function test_submission_backoff() {
let now = new Date(policy.nextDataSubmissionDate.getTime());
defineNow(policy, now);
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataSubmissionCount, 1);
do_check_eq(listener.requestDataUploadCount, 1);
do_check_eq(policy.currentDaySubmissionFailureCount, 0);
now = new Date(now.getTime() + 5000);
@ -408,13 +430,13 @@ add_test(function test_submission_backoff() {
now = new Date(policy.nextDataSubmissionDate.getTime() - 1);
defineNow(policy, now);
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataSubmissionCount, 1);
do_check_eq(listener.requestDataUploadCount, 1);
// 2nd request for submission.
now = new Date(policy.nextDataSubmissionDate.getTime());
defineNow(policy, now);
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataSubmissionCount, 2);
do_check_eq(listener.requestDataUploadCount, 2);
now = new Date(now.getTime() + 5000);
defineNow(policy, now);
@ -428,7 +450,7 @@ add_test(function test_submission_backoff() {
now = new Date(policy.nextDataSubmissionDate.getTime());
defineNow(policy, now);
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataSubmissionCount, 3);
do_check_eq(listener.requestDataUploadCount, 3);
now = new Date(now.getTime() + 5000);
defineNow(policy, now);
@ -452,16 +474,126 @@ add_test(function test_submission_expiring() {
let now = new Date(policy.nextDataSubmissionDate.getTime());
defineNow(policy, now);
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataSubmissionCount, 1);
do_check_eq(listener.requestDataUploadCount, 1);
defineNow(policy, new Date(now.getTime() + 500));
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataSubmissionCount, 1);
do_check_eq(listener.requestDataUploadCount, 1);
defineNow(policy, new Date(policy.now().getTime() +
policy.SUBMISSION_REQUEST_EXPIRE_INTERVAL_MSEC));
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataSubmissionCount, 2);
do_check_eq(listener.requestDataUploadCount, 2);
run_next_test();
});
add_test(function test_delete_remote_data() {
let [policy, prefs, listener] = getPolicy("delete_remote_data");
do_check_false(policy.pendingDeleteRemoteData);
let nextSubmissionDate = policy.nextDataSubmissionDate;
let now = new Date();
defineNow(policy, now);
policy.deleteRemoteData();
do_check_true(policy.pendingDeleteRemoteData);
do_check_neq(nextSubmissionDate.getTime(),
policy.nextDataSubmissionDate.getTime());
do_check_eq(now.getTime(), policy.nextDataSubmissionDate.getTime());
do_check_eq(listener.requestRemoteDeleteCount, 1);
do_check_true(listener.lastRemoteDeleteRequest.isDelete);
defineNow(policy, policy._futureDate(1000));
listener.lastRemoteDeleteRequest.onSubmissionSuccess(policy.now());
do_check_false(policy.pendingDeleteRemoteData);
run_next_test();
});
// Ensure that deletion requests take priority over regular data submission.
add_test(function test_delete_remote_data_priority() {
let [policy, prefs, listener] = getPolicy("delete_remote_data_priority");
let now = new Date();
defineNow(policy, policy._futureDate(-24 * 60 * 60 * 1000));
policy.recordUserAcceptance();
defineNow(policy, new Date(now.getTime() + 3 * 24 * 60 * 60 * 1000));
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataUploadCount, 1);
policy._inProgressSubmissionRequest = null;
policy.deleteRemoteData();
policy.checkStateAndTrigger();
do_check_eq(listener.requestRemoteDeleteCount, 1);
do_check_eq(listener.requestDataUploadCount, 1);
run_next_test();
});
add_test(function test_delete_remote_data_backoff() {
let [policy, prefs, listener] = getPolicy("delete_remote_data_backoff");
let now = new Date();
defineNow(policy, policy._futureDate(-24 * 60 * 60 * 1000));
policy.recordUserAcceptance();
defineNow(policy, now);
policy.nextDataSubmissionDate = now;
policy.deleteRemoteData();
policy.checkStateAndTrigger();
do_check_eq(listener.requestRemoteDeleteCount, 1);
defineNow(policy, policy._futureDate(1000));
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataUploadCount, 0);
do_check_eq(listener.requestRemoteDeleteCount, 1);
defineNow(policy, policy._futureDate(500));
listener.lastRemoteDeleteRequest.onSubmissionFailureSoft();
defineNow(policy, policy._futureDate(50));
policy.checkStateAndTrigger();
do_check_eq(listener.requestRemoteDeleteCount, 1);
defineNow(policy, policy._futureDate(policy.FAILURE_BACKOFF_INTERVALS[0] - 50));
policy.checkStateAndTrigger();
do_check_eq(listener.requestRemoteDeleteCount, 2);
run_next_test();
});
// If we request delete while an upload is in progress, delete should be
// scheduled immediately after upload.
add_test(function test_delete_remote_data_in_progress_upload() {
let [policy, prefs, listener] = getPolicy("delete_remote_data_in_progress_upload");
let now = new Date();
defineNow(policy, policy._futureDate(-24 * 60 * 60 * 1000));
policy.recordUserAcceptance();
defineNow(policy, policy.nextDataSubmissionDate);
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataUploadCount, 1);
defineNow(policy, policy._futureDate(50 * 1000));
// If we request a delete during a pending request, nothing should be done.
policy.deleteRemoteData();
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataUploadCount, 1);
do_check_eq(listener.requestRemoteDeleteCount, 0);
// Now wait a little bit and finish the request.
defineNow(policy, policy._futureDate(10 * 1000));
listener.lastDataRequest.onSubmissionSuccess(policy._futureDate(1000));
defineNow(policy, policy._futureDate(5000));
policy.checkStateAndTrigger();
do_check_eq(listener.requestDataUploadCount, 1);
do_check_eq(listener.requestRemoteDeleteCount, 1);
run_next_test();
});
@ -489,7 +621,7 @@ add_test(function test_polling() {
policy.stopPolling();
do_check_eq(listener.notifyUserCount, 0);
do_check_eq(listener.requestDataSubmissionCount, 0);
do_check_eq(listener.requestDataUploadCount, 0);
run_next_test();
}
@ -539,16 +671,16 @@ add_test(function test_polling_implicit_acceptance() {
if (count < 4) {
do_check_false(policy.dataSubmissionPolicyAccepted);
do_check_eq(listener.requestDataSubmissionCount, 0);
do_check_eq(listener.requestDataUploadCount, 0);
} else {
do_check_true(policy.dataSubmissionPolicyAccepted);
do_check_eq(policy.dataSubmissionPolicyResponseType,
"accepted-implicit-time-elapsed");
do_check_eq(listener.requestDataSubmissionCount, 1);
do_check_eq(listener.requestDataUploadCount, 1);
}
if (count > 4) {
do_check_eq(listener.requestDataSubmissionCount, 1);
do_check_eq(listener.requestDataUploadCount, 1);
policy.stopPolling();
run_next_test();
}