mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 22:05:44 +00:00
Backed out 2 changesets (bug 1439777) for xpcshell failures on /test_errorhandler_2.js
Backed out changeset d99402ad9ecc (bug 1439777) Backed out changeset 1af3426dc956 (bug 1439777)
This commit is contained in:
parent
97b67fe961
commit
8c7d795b53
@ -565,7 +565,7 @@ var gSync = {
|
||||
const state = UIState.get();
|
||||
if (state.status == UIState.STATUS_SIGNED_IN) {
|
||||
this.updateSyncStatus({ syncing: true });
|
||||
Services.tm.dispatchToMainThread(() => Weave.Service.sync());
|
||||
setTimeout(() => Weave.Service.errorHandler.syncAndReportErrors(), 0);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -69,7 +69,8 @@ function mockFunctions() {
|
||||
email: "user@mozilla.com"
|
||||
});
|
||||
|
||||
service.sync = mocked_syncAndReportErrors;
|
||||
// mock service.errorHandler.syncAndReportErrors()
|
||||
service.errorHandler.syncAndReportErrors = mocked_syncAndReportErrors;
|
||||
}
|
||||
|
||||
function mocked_syncAndReportErrors() {
|
||||
@ -78,10 +79,10 @@ function mocked_syncAndReportErrors() {
|
||||
|
||||
function restoreValues() {
|
||||
UIState.get = getState;
|
||||
service.sync = originalSync;
|
||||
service.syncAndReportErrors = originalSync;
|
||||
}
|
||||
|
||||
function storeInitialValues() {
|
||||
getState = UIState.get;
|
||||
originalSync = service.sync;
|
||||
originalSync = service.syncAndReportErrors;
|
||||
}
|
||||
|
@ -106,6 +106,7 @@ CREDENTIALS_CHANGED: "error.sync.reason.credentials_changed",
|
||||
ABORT_SYNC_COMMAND: "aborting sync, process commands said so",
|
||||
NO_SYNC_NODE_FOUND: "error.sync.reason.no_node_found",
|
||||
OVER_QUOTA: "error.sync.reason.over_quota",
|
||||
PROLONGED_SYNC_FAILURE: "error.sync.prolonged_failure",
|
||||
SERVER_MAINTENANCE: "error.sync.reason.serverMaintenance",
|
||||
|
||||
RESPONSE_OVER_QUOTA: "14",
|
||||
|
@ -57,6 +57,7 @@ SyncScheduler.prototype = {
|
||||
this.idleInterval = getThrottledIntervalPreference("scheduler.idleInterval");
|
||||
this.activeInterval = getThrottledIntervalPreference("scheduler.activeInterval");
|
||||
this.immediateInterval = getThrottledIntervalPreference("scheduler.immediateInterval");
|
||||
this.eolInterval = getThrottledIntervalPreference("scheduler.eolInterval");
|
||||
|
||||
// A user is non-idle on startup by default.
|
||||
this.idle = false;
|
||||
@ -405,6 +406,12 @@ SyncScheduler.prototype = {
|
||||
},
|
||||
|
||||
adjustSyncInterval: function adjustSyncInterval() {
|
||||
if (Status.eol) {
|
||||
this._log.debug("Server status is EOL; using eolInterval.");
|
||||
this.syncInterval = this.eolInterval;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.numClients <= 1) {
|
||||
this._log.trace("Adjusting syncInterval to singleDeviceInterval.");
|
||||
this.syncInterval = this.singleDeviceInterval;
|
||||
@ -654,7 +661,21 @@ function ErrorHandler(service) {
|
||||
this.init();
|
||||
}
|
||||
ErrorHandler.prototype = {
|
||||
init() {
|
||||
MINIMUM_ALERT_INTERVAL_MSEC: 604800000, // One week.
|
||||
|
||||
/**
|
||||
* Flag that turns on error reporting for all errors, incl. network errors.
|
||||
*/
|
||||
dontIgnoreErrors: false,
|
||||
|
||||
/**
|
||||
* Flag that indicates if we have already reported a prolonged failure.
|
||||
* Once set, we don't report it again, meaning this error is only reported
|
||||
* one per run.
|
||||
*/
|
||||
didReportProlongedError: false,
|
||||
|
||||
init: function init() {
|
||||
Svc.Obs.add("weave:engine:sync:applied", this);
|
||||
Svc.Obs.add("weave:engine:sync:error", this);
|
||||
Svc.Obs.add("weave:service:login:error", this);
|
||||
@ -680,7 +701,7 @@ ErrorHandler.prototype = {
|
||||
this._logManager = new LogManager(Svc.Prefs, logs, "sync");
|
||||
},
|
||||
|
||||
observe(subject, topic, data) {
|
||||
observe: function observe(subject, topic, data) {
|
||||
this._log.trace("Handling " + topic);
|
||||
switch (topic) {
|
||||
case "weave:engine:sync:applied":
|
||||
@ -711,6 +732,14 @@ ErrorHandler.prototype = {
|
||||
case "weave:service:login:error":
|
||||
this._log.error("Sync encountered a login error");
|
||||
this.resetFileLog();
|
||||
|
||||
if (this.shouldReportError()) {
|
||||
this.notifyOnNextTick("weave:ui:login:error");
|
||||
} else {
|
||||
this.notifyOnNextTick("weave:ui:clear-error");
|
||||
}
|
||||
|
||||
this.dontIgnoreErrors = false;
|
||||
break;
|
||||
case "weave:service:sync:error": {
|
||||
if (Status.sync == CREDENTIALS_CHANGED) {
|
||||
@ -729,6 +758,14 @@ ErrorHandler.prototype = {
|
||||
// Not a shutdown related exception...
|
||||
this._log.error("Sync encountered an error", exception);
|
||||
this.resetFileLog();
|
||||
|
||||
if (this.shouldReportError()) {
|
||||
this.notifyOnNextTick("weave:ui:sync:error");
|
||||
} else {
|
||||
this.notifyOnNextTick("weave:ui:sync:finish");
|
||||
}
|
||||
|
||||
this.dontIgnoreErrors = false;
|
||||
break;
|
||||
}
|
||||
case "weave:service:sync:finish":
|
||||
@ -747,8 +784,18 @@ ErrorHandler.prototype = {
|
||||
|
||||
if (Status.service == SYNC_FAILED_PARTIAL) {
|
||||
this._log.error("Some engines did not sync correctly.");
|
||||
this.resetFileLog();
|
||||
|
||||
if (this.shouldReportError()) {
|
||||
this.dontIgnoreErrors = false;
|
||||
this.notifyOnNextTick("weave:ui:sync:error");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
this.resetFileLog();
|
||||
}
|
||||
this.resetFileLog();
|
||||
this.dontIgnoreErrors = false;
|
||||
this.notifyOnNextTick("weave:ui:sync:finish");
|
||||
break;
|
||||
case "weave:service:start-over:finish":
|
||||
// ensure we capture any logs between the last sync and the reset completing.
|
||||
@ -757,6 +804,27 @@ ErrorHandler.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
notifyOnNextTick: function notifyOnNextTick(topic) {
|
||||
CommonUtils.nextTick(function() {
|
||||
this._log.trace("Notifying " + topic +
|
||||
". Status.login is " + Status.login +
|
||||
". Status.sync is " + Status.sync);
|
||||
Svc.Obs.notify(topic);
|
||||
}, this);
|
||||
},
|
||||
|
||||
/**
|
||||
* Trigger a sync and don't muffle any errors, particularly network errors.
|
||||
*/
|
||||
syncAndReportErrors: function syncAndReportErrors() {
|
||||
this._log.debug("Beginning user-triggered sync.");
|
||||
|
||||
this.dontIgnoreErrors = true;
|
||||
CommonUtils.nextTick(() => {
|
||||
this.service.sync({why: "user"});
|
||||
}, this);
|
||||
},
|
||||
|
||||
async _dumpAddons() {
|
||||
// Just dump the items that sync may be concerned with. Specifically,
|
||||
// active extensions that are not hidden.
|
||||
@ -778,16 +846,170 @@ ErrorHandler.prototype = {
|
||||
* Generate a log file for the sync that just completed
|
||||
* and refresh the input & output streams.
|
||||
*/
|
||||
async resetFileLog() {
|
||||
resetFileLog: function resetFileLog() {
|
||||
let onComplete = logType => {
|
||||
Svc.Obs.notify("weave:service:reset-file-log");
|
||||
this._log.trace("Notified: " + Date.now());
|
||||
if (logType == this._logManager.ERROR_LOG_WRITTEN) {
|
||||
Cu.reportError("Sync encountered an error - see about:sync-log for the log file.");
|
||||
}
|
||||
};
|
||||
|
||||
// If we're writing an error log, dump extensions that may be causing problems.
|
||||
let beforeResetLog;
|
||||
if (this._logManager.sawError) {
|
||||
await this._dumpAddons();
|
||||
beforeResetLog = this._dumpAddons();
|
||||
} else {
|
||||
beforeResetLog = Promise.resolve();
|
||||
}
|
||||
const logType = await this._logManager.resetFileLog();
|
||||
if (logType == this._logManager.ERROR_LOG_WRITTEN) {
|
||||
Cu.reportError("Sync encountered an error - see about:sync-log for the log file.");
|
||||
// Note we do not return the promise here - the caller doesn't need to wait
|
||||
// for this to complete.
|
||||
beforeResetLog
|
||||
.then(() => this._logManager.resetFileLog())
|
||||
.then(onComplete, onComplete);
|
||||
},
|
||||
|
||||
/**
|
||||
* Translates server error codes to meaningful strings.
|
||||
*
|
||||
* @param code
|
||||
* server error code as an integer
|
||||
*/
|
||||
errorStr: function errorStr(code) {
|
||||
switch (code.toString()) {
|
||||
case "1":
|
||||
return "illegal-method";
|
||||
case "2":
|
||||
return "invalid-captcha";
|
||||
case "3":
|
||||
return "invalid-username";
|
||||
case "4":
|
||||
return "cannot-overwrite-resource";
|
||||
case "5":
|
||||
return "userid-mismatch";
|
||||
case "6":
|
||||
return "json-parse-failure";
|
||||
case "7":
|
||||
return "invalid-password";
|
||||
case "8":
|
||||
return "invalid-record";
|
||||
case "9":
|
||||
return "weak-password";
|
||||
default:
|
||||
return "generic-server-error";
|
||||
}
|
||||
},
|
||||
|
||||
// A function to indicate if Sync errors should be "reported" - which in this
|
||||
// context really means "should be notify observers of an error" - but note
|
||||
// that since bug 1180587, no one is going to surface an error to the user.
|
||||
shouldReportError: function shouldReportError() {
|
||||
if (Status.login == MASTER_PASSWORD_LOCKED) {
|
||||
this._log.trace("shouldReportError: false (master password locked).");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.dontIgnoreErrors) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Status.login == LOGIN_FAILED_LOGIN_REJECTED) {
|
||||
// An explicit LOGIN_REJECTED state is always reported (bug 1081158)
|
||||
this._log.trace("shouldReportError: true (login was rejected)");
|
||||
return true;
|
||||
}
|
||||
|
||||
let lastSync = Svc.Prefs.get("lastSync");
|
||||
if (lastSync && ((Date.now() - Date.parse(lastSync)) >
|
||||
Svc.Prefs.get("errorhandler.networkFailureReportTimeout") * 1000)) {
|
||||
Status.sync = PROLONGED_SYNC_FAILURE;
|
||||
if (this.didReportProlongedError) {
|
||||
this._log.trace("shouldReportError: false (prolonged sync failure, but" +
|
||||
" we've already reported it).");
|
||||
return false;
|
||||
}
|
||||
this._log.trace("shouldReportError: true (first prolonged sync failure).");
|
||||
this.didReportProlongedError = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
// We got a 401 mid-sync. Wait for the next sync before actually handling
|
||||
// an error. This assumes that we'll get a 401 again on a login fetch in
|
||||
// order to report the error.
|
||||
if (!this.service.clusterURL) {
|
||||
this._log.trace("shouldReportError: false (no cluster URL; " +
|
||||
"possible node reassignment).");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
let result = (![Status.login, Status.sync].includes(SERVER_MAINTENANCE) &&
|
||||
![Status.login, Status.sync].includes(LOGIN_FAILED_NETWORK_ERROR));
|
||||
this._log.trace("shouldReportError: ${result} due to login=${login}, sync=${sync}",
|
||||
{result, login: Status.login, sync: Status.sync});
|
||||
return result;
|
||||
},
|
||||
|
||||
get currentAlertMode() {
|
||||
return Svc.Prefs.get("errorhandler.alert.mode");
|
||||
},
|
||||
|
||||
set currentAlertMode(str) {
|
||||
return Svc.Prefs.set("errorhandler.alert.mode", str);
|
||||
},
|
||||
|
||||
get earliestNextAlert() {
|
||||
return Svc.Prefs.get("errorhandler.alert.earliestNext", 0) * 1000;
|
||||
},
|
||||
|
||||
set earliestNextAlert(msec) {
|
||||
return Svc.Prefs.set("errorhandler.alert.earliestNext", msec / 1000);
|
||||
},
|
||||
|
||||
clearServerAlerts() {
|
||||
// If we have any outstanding alerts, apparently they're no longer relevant.
|
||||
Svc.Prefs.resetBranch("errorhandler.alert");
|
||||
},
|
||||
|
||||
/**
|
||||
* X-Weave-Alert headers can include a JSON object:
|
||||
*
|
||||
* {
|
||||
* "code": // One of "hard-eol", "soft-eol".
|
||||
* "url": // For "Learn more" link.
|
||||
* "message": // Logged in Sync logs.
|
||||
* }
|
||||
*/
|
||||
handleServerAlert(xwa) {
|
||||
if (!xwa.code) {
|
||||
this._log.warn("Got structured X-Weave-Alert, but no alert code.");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (xwa.code) {
|
||||
// Gently and occasionally notify the user that this service will be
|
||||
// shutting down.
|
||||
case "soft-eol":
|
||||
// Fall through.
|
||||
|
||||
// Tell the user that this service has shut down, and drop our syncing
|
||||
// frequency dramatically.
|
||||
case "hard-eol":
|
||||
// Note that both of these alerts should be subservient to future "sign
|
||||
// in with your Firefox Account" storage alerts.
|
||||
if ((this.currentAlertMode != xwa.code) ||
|
||||
(this.earliestNextAlert < Date.now())) {
|
||||
CommonUtils.nextTick(function() {
|
||||
Svc.Obs.notify("weave:eol", xwa);
|
||||
}, this);
|
||||
this._log.error("X-Weave-Alert: " + xwa.code + ": " + xwa.message);
|
||||
this.earliestNextAlert = Date.now() + this.MINIMUM_ALERT_INTERVAL_MSEC;
|
||||
this.currentAlertMode = xwa.code;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
this._log.debug("Got unexpected X-Weave-Alert code: " + xwa.code);
|
||||
}
|
||||
Svc.Obs.notify("weave:service:reset-file-log");
|
||||
},
|
||||
|
||||
/**
|
||||
@ -799,6 +1021,27 @@ ErrorHandler.prototype = {
|
||||
checkServerError(resp) {
|
||||
// In this case we were passed a resolved value of Resource#_doRequest.
|
||||
switch (resp.status) {
|
||||
case 200:
|
||||
case 404:
|
||||
case 513:
|
||||
let xwa = resp.headers["x-weave-alert"];
|
||||
|
||||
// Only process machine-readable alerts.
|
||||
if (!xwa || !xwa.startsWith("{")) {
|
||||
this.clearServerAlerts();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
xwa = JSON.parse(xwa);
|
||||
} catch (ex) {
|
||||
this._log.warn("Malformed X-Weave-Alert from server: " + xwa);
|
||||
return;
|
||||
}
|
||||
|
||||
this.handleServerAlert(xwa);
|
||||
break;
|
||||
|
||||
case 400:
|
||||
if (resp == RESPONSE_OVER_QUOTA) {
|
||||
Status.sync = OVER_QUOTA;
|
||||
|
@ -520,7 +520,7 @@ Sync11Service.prototype = {
|
||||
throw ex;
|
||||
}
|
||||
|
||||
// Always check for errors.
|
||||
// Always check for errors; this is also where we look for X-Weave-Alert.
|
||||
this.errorHandler.checkServerError(info);
|
||||
if (!info.success) {
|
||||
this._log.error("Aborting sync: failed to get collections.");
|
||||
|
@ -59,6 +59,15 @@ var Status = {
|
||||
this.service = code == SYNC_SUCCEEDED ? STATUS_OK : SYNC_FAILED;
|
||||
},
|
||||
|
||||
get eol() {
|
||||
let modePref = PREFS_BRANCH + "errorhandler.alert.mode";
|
||||
try {
|
||||
return Services.prefs.getCharPref(modePref) == "hard-eol";
|
||||
} catch (ex) {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
get engines() {
|
||||
return this._engines;
|
||||
},
|
||||
|
@ -7,6 +7,7 @@
|
||||
pref("services.sync.lastversion", "firstrun");
|
||||
pref("services.sync.sendVersionInfo", true);
|
||||
|
||||
pref("services.sync.scheduler.eolInterval", 604800); // 1 week
|
||||
pref("services.sync.scheduler.idleInterval", 3600); // 1 hour
|
||||
pref("services.sync.scheduler.activeInterval", 600); // 10 minutes
|
||||
pref("services.sync.scheduler.immediateInterval", 90); // 1.5 minutes
|
||||
@ -14,6 +15,8 @@ pref("services.sync.scheduler.idleTime", 300); // 5 minutes
|
||||
|
||||
pref("services.sync.scheduler.fxa.singleDeviceInterval", 3600); // 1 hour
|
||||
|
||||
pref("services.sync.errorhandler.networkFailureReportTimeout", 1209600); // 2 weeks
|
||||
|
||||
// Note that new engines are typically added with a default of disabled, so
|
||||
// when an existing sync user gets the Firefox upgrade that supports the engine
|
||||
// it starts as disabled until the user has explicitly opted in.
|
||||
|
@ -12,9 +12,8 @@ ChromeUtils.import("resource://services-sync/util.js");
|
||||
ChromeUtils.import("resource://gre/modules/FileUtils.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/PromiseUtils.jsm");
|
||||
|
||||
const fakeServer = new SyncServer();
|
||||
var fakeServer = new SyncServer();
|
||||
fakeServer.start();
|
||||
const fakeServerUrl = "http://localhost:" + fakeServer.port;
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
return promiseStopServer(fakeServer).finally(() => {
|
||||
@ -22,7 +21,25 @@ registerCleanupFunction(function() {
|
||||
});
|
||||
});
|
||||
|
||||
var fakeServerUrl = "http://localhost:" + fakeServer.port;
|
||||
|
||||
const logsdir = FileUtils.getDir("ProfD", ["weave", "logs"], true);
|
||||
|
||||
const PROLONGED_ERROR_DURATION =
|
||||
(Svc.Prefs.get("errorhandler.networkFailureReportTimeout") * 2) * 1000;
|
||||
|
||||
const NON_PROLONGED_ERROR_DURATION =
|
||||
(Svc.Prefs.get("errorhandler.networkFailureReportTimeout") / 2) * 1000;
|
||||
|
||||
function setLastSync(lastSyncValue) {
|
||||
Svc.Prefs.set("lastSync", (new Date(Date.now() - lastSyncValue)).toString());
|
||||
}
|
||||
|
||||
// This relies on Service/ErrorHandler being a singleton. Fixing this will take
|
||||
// a lot of work.
|
||||
let errorHandler = Service.errorHandler;
|
||||
let engine;
|
||||
|
||||
add_task(async function setup() {
|
||||
await Service.engineManager.clear();
|
||||
await Service.engineManager.register(EHTestsCommon.CatapultEngine);
|
||||
@ -35,6 +52,7 @@ async function clean() {
|
||||
await promiseLogReset;
|
||||
Status.resetSync();
|
||||
Status.resetBackoff();
|
||||
errorHandler.didReportProlongedError = false;
|
||||
// Move log levels back to trace (startOver will have reversed this), sicne
|
||||
syncTestLogging();
|
||||
}
|
||||
@ -112,27 +130,259 @@ add_task(async function test_credentials_changed_logout() {
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_login_non_network_error() {
|
||||
add_task(function test_no_lastSync_pref() {
|
||||
syncTestLogging();
|
||||
// Test reported error.
|
||||
Status.resetSync();
|
||||
errorHandler.dontIgnoreErrors = true;
|
||||
Status.sync = CREDENTIALS_CHANGED;
|
||||
Assert.ok(errorHandler.shouldReportError());
|
||||
|
||||
// Test unreported error.
|
||||
Status.resetSync();
|
||||
errorHandler.dontIgnoreErrors = true;
|
||||
Status.login = LOGIN_FAILED_NETWORK_ERROR;
|
||||
Assert.ok(errorHandler.shouldReportError());
|
||||
|
||||
});
|
||||
|
||||
add_task(function test_shouldReportError() {
|
||||
Status.login = MASTER_PASSWORD_LOCKED;
|
||||
Assert.ok(!errorHandler.shouldReportError());
|
||||
|
||||
// Give ourselves a clusterURL so that the temporary 401 no-error situation
|
||||
// doesn't come into play.
|
||||
Service.clusterURL = fakeServerUrl;
|
||||
|
||||
// Test dontIgnoreErrors, non-network, non-prolonged, sync error reported
|
||||
Status.resetSync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = true;
|
||||
Status.sync = CREDENTIALS_CHANGED;
|
||||
Assert.ok(errorHandler.shouldReportError());
|
||||
|
||||
// Test dontIgnoreErrors, non-network, prolonged, sync error reported
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = true;
|
||||
Status.sync = CREDENTIALS_CHANGED;
|
||||
Assert.ok(errorHandler.shouldReportError());
|
||||
|
||||
// Test dontIgnoreErrors, network, non-prolonged, login error reported
|
||||
Status.resetSync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = true;
|
||||
Status.login = LOGIN_FAILED_NETWORK_ERROR;
|
||||
Assert.ok(errorHandler.shouldReportError());
|
||||
|
||||
// Test dontIgnoreErrors, network, non-prolonged, sync error reported
|
||||
Status.resetSync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = true;
|
||||
Status.sync = LOGIN_FAILED_NETWORK_ERROR;
|
||||
Assert.ok(errorHandler.shouldReportError());
|
||||
|
||||
// Test dontIgnoreErrors, network, prolonged, login error reported
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = true;
|
||||
Status.login = LOGIN_FAILED_NETWORK_ERROR;
|
||||
Assert.ok(errorHandler.shouldReportError());
|
||||
|
||||
// Test dontIgnoreErrors, network, prolonged, sync error reported
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = true;
|
||||
Status.sync = LOGIN_FAILED_NETWORK_ERROR;
|
||||
Assert.ok(errorHandler.shouldReportError());
|
||||
|
||||
// Test non-network, prolonged, sync error reported
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
errorHandler.didReportProlongedError = false;
|
||||
Status.sync = CREDENTIALS_CHANGED;
|
||||
Assert.ok(errorHandler.shouldReportError());
|
||||
Assert.ok(errorHandler.didReportProlongedError);
|
||||
errorHandler.didReportProlongedError = false;
|
||||
|
||||
// Test network, prolonged, login error reported
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
Status.login = LOGIN_FAILED_NETWORK_ERROR;
|
||||
Assert.ok(errorHandler.shouldReportError());
|
||||
Assert.ok(errorHandler.didReportProlongedError);
|
||||
errorHandler.didReportProlongedError = false;
|
||||
|
||||
// Test network, prolonged, sync error reported
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
Status.sync = LOGIN_FAILED_NETWORK_ERROR;
|
||||
Assert.ok(errorHandler.shouldReportError());
|
||||
Assert.ok(errorHandler.didReportProlongedError);
|
||||
errorHandler.didReportProlongedError = false;
|
||||
|
||||
// Test non-network, non-prolonged, sync error reported
|
||||
Status.resetSync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
Status.sync = CREDENTIALS_CHANGED;
|
||||
Assert.ok(errorHandler.shouldReportError());
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
// Test network, non-prolonged, login error reported
|
||||
Status.resetSync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
Status.login = LOGIN_FAILED_NETWORK_ERROR;
|
||||
Assert.ok(!errorHandler.shouldReportError());
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
// Test network, non-prolonged, sync error reported
|
||||
Status.resetSync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
Status.sync = LOGIN_FAILED_NETWORK_ERROR;
|
||||
Assert.ok(!errorHandler.shouldReportError());
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
// Test server maintenance, sync errors are not reported
|
||||
Status.resetSync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
Status.sync = SERVER_MAINTENANCE;
|
||||
Assert.ok(!errorHandler.shouldReportError());
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
// Test server maintenance, login errors are not reported
|
||||
Status.resetSync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
Status.login = SERVER_MAINTENANCE;
|
||||
Assert.ok(!errorHandler.shouldReportError());
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
// Test prolonged, server maintenance, sync errors are reported
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
Status.sync = SERVER_MAINTENANCE;
|
||||
Assert.ok(errorHandler.shouldReportError());
|
||||
Assert.ok(errorHandler.didReportProlongedError);
|
||||
errorHandler.didReportProlongedError = false;
|
||||
|
||||
// Test prolonged, server maintenance, login errors are reported
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = false;
|
||||
Status.login = SERVER_MAINTENANCE;
|
||||
Assert.ok(errorHandler.shouldReportError());
|
||||
Assert.ok(errorHandler.didReportProlongedError);
|
||||
errorHandler.didReportProlongedError = false;
|
||||
|
||||
// Test dontIgnoreErrors, server maintenance, sync errors are reported
|
||||
Status.resetSync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = true;
|
||||
Status.sync = SERVER_MAINTENANCE;
|
||||
Assert.ok(errorHandler.shouldReportError());
|
||||
// dontIgnoreErrors means we don't set didReportProlongedError
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
// Test dontIgnoreErrors, server maintenance, login errors are reported
|
||||
Status.resetSync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = true;
|
||||
Status.login = SERVER_MAINTENANCE;
|
||||
Assert.ok(errorHandler.shouldReportError());
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
// Test dontIgnoreErrors, prolonged, server maintenance,
|
||||
// sync errors are reported
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = true;
|
||||
Status.sync = SERVER_MAINTENANCE;
|
||||
Assert.ok(errorHandler.shouldReportError());
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
// Test dontIgnoreErrors, prolonged, server maintenance,
|
||||
// login errors are reported
|
||||
Status.resetSync();
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
errorHandler.dontIgnoreErrors = true;
|
||||
Status.login = SERVER_MAINTENANCE;
|
||||
Assert.ok(errorHandler.shouldReportError());
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
});
|
||||
|
||||
add_task(async function test_shouldReportError_master_password() {
|
||||
_("Test error ignored due to locked master password");
|
||||
let server = await EHTestsCommon.sync_httpd_setup();
|
||||
await EHTestsCommon.setUp(server);
|
||||
|
||||
// Monkey patch Service.verifyLogin to imitate
|
||||
// master password being locked.
|
||||
Service._verifyLogin = Service.verifyLogin;
|
||||
Service.verifyLogin = async function() {
|
||||
Status.login = MASTER_PASSWORD_LOCKED;
|
||||
return false;
|
||||
};
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
await Service.sync();
|
||||
Assert.ok(!errorHandler.shouldReportError());
|
||||
|
||||
// Clean up.
|
||||
Service.verifyLogin = Service._verifyLogin;
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
// Test that even if we don't have a cluster URL, a login failure due to
|
||||
// authentication errors is always reported.
|
||||
add_task(function test_shouldReportLoginFailureWithNoCluster() {
|
||||
// Ensure no clusterURL - any error not specific to login should not be reported.
|
||||
Service.clusterURL = "";
|
||||
|
||||
// Test explicit "login rejected" state.
|
||||
Status.resetSync();
|
||||
// If we have a LOGIN_REJECTED state, we always report the error.
|
||||
Status.login = LOGIN_FAILED_LOGIN_REJECTED;
|
||||
Assert.ok(errorHandler.shouldReportError());
|
||||
// But any other status with a missing clusterURL is treated as a mid-sync
|
||||
// 401 (ie, should be treated as a node reassignment)
|
||||
Status.login = LOGIN_SUCCEEDED;
|
||||
Assert.ok(!errorHandler.shouldReportError());
|
||||
});
|
||||
|
||||
add_task(async function test_login_syncAndReportErrors_non_network_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test non-network errors are reported
|
||||
// when calling sync
|
||||
// when calling syncAndReportErrors
|
||||
let server = await EHTestsCommon.sync_httpd_setup();
|
||||
await EHTestsCommon.setUp(server);
|
||||
Service.identity._syncKeyBundle = null;
|
||||
|
||||
await Service.sync();
|
||||
let promiseObserved = promiseOneObserver("weave:ui:login:error");
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
errorHandler.syncAndReportErrors();
|
||||
await promiseObserved;
|
||||
Assert.equal(Status.login, LOGIN_FAILED_NO_PASSPHRASE);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_sync_non_network_error() {
|
||||
add_task(async function test_sync_syncAndReportErrors_non_network_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test non-network errors are reported
|
||||
// when calling sync
|
||||
// when calling syncAndReportErrors
|
||||
let server = await EHTestsCommon.sync_httpd_setup();
|
||||
await EHTestsCommon.setUp(server);
|
||||
|
||||
@ -143,12 +393,16 @@ add_task(async function test_sync_non_network_error() {
|
||||
|
||||
await EHTestsCommon.generateCredentialsChangedFailure();
|
||||
|
||||
let ping = await sync_and_validate_telem(true);
|
||||
let promiseObserved = promiseOneObserver("weave:ui:sync:error");
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
let ping = await wait_for_ping(() => errorHandler.syncAndReportErrors(), true);
|
||||
equal(ping.status.sync, CREDENTIALS_CHANGED);
|
||||
deepEqual(ping.failureReason, {
|
||||
name: "unexpectederror",
|
||||
error: "Error: Aborting sync, remote setup failed"
|
||||
});
|
||||
await promiseObserved;
|
||||
|
||||
Assert.equal(Status.sync, CREDENTIALS_CHANGED);
|
||||
// If we clean this tick, telemetry won't get the right error
|
||||
@ -157,33 +411,219 @@ add_task(async function test_sync_non_network_error() {
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_login_sync_network_error() {
|
||||
add_task(async function test_login_syncAndReportErrors_prolonged_non_network_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test network errors are reported when calling sync.
|
||||
// Test prolonged, non-network errors are
|
||||
// reported when calling syncAndReportErrors.
|
||||
let server = await EHTestsCommon.sync_httpd_setup();
|
||||
await EHTestsCommon.setUp(server);
|
||||
Service.identity._syncKeyBundle = null;
|
||||
|
||||
let promiseObserved = promiseOneObserver("weave:ui:login:error");
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
errorHandler.syncAndReportErrors();
|
||||
await promiseObserved;
|
||||
Assert.equal(Status.login, LOGIN_FAILED_NO_PASSPHRASE);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_sync_syncAndReportErrors_prolonged_non_network_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test prolonged, non-network errors are
|
||||
// reported when calling syncAndReportErrors.
|
||||
let server = await EHTestsCommon.sync_httpd_setup();
|
||||
await EHTestsCommon.setUp(server);
|
||||
|
||||
// By calling sync, we ensure we're logged in.
|
||||
await Service.sync();
|
||||
Assert.equal(Status.sync, SYNC_SUCCEEDED);
|
||||
Assert.ok(Service.isLoggedIn);
|
||||
|
||||
await EHTestsCommon.generateCredentialsChangedFailure();
|
||||
|
||||
let promiseObserved = promiseOneObserver("weave:ui:sync:error");
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
let ping = await wait_for_ping(() => errorHandler.syncAndReportErrors(), true);
|
||||
equal(ping.status.sync, CREDENTIALS_CHANGED);
|
||||
deepEqual(ping.failureReason, {
|
||||
name: "unexpectederror",
|
||||
error: "Error: Aborting sync, remote setup failed"
|
||||
});
|
||||
await promiseObserved;
|
||||
|
||||
Assert.equal(Status.sync, CREDENTIALS_CHANGED);
|
||||
// If we clean this tick, telemetry won't get the right error
|
||||
await Async.promiseYield();
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_login_syncAndReportErrors_network_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test network errors are reported when calling syncAndReportErrors.
|
||||
await configureIdentity({username: "broken.wipe"});
|
||||
Service.clusterURL = fakeServerUrl;
|
||||
|
||||
await Service.sync();
|
||||
let promiseObserved = promiseOneObserver("weave:ui:login:error");
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
errorHandler.syncAndReportErrors();
|
||||
await promiseObserved;
|
||||
|
||||
Assert.equal(Status.login, LOGIN_FAILED_NETWORK_ERROR);
|
||||
|
||||
await clean();
|
||||
});
|
||||
|
||||
|
||||
add_task(async function test_sync_network_error() {
|
||||
add_task(async function test_sync_syncAndReportErrors_network_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test network errors are reported when calling sync.
|
||||
// Test network errors are reported when calling syncAndReportErrors.
|
||||
Services.io.offline = true;
|
||||
|
||||
await Service.sync();
|
||||
let promiseUISyncError = promiseOneObserver("weave:ui:sync:error");
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
errorHandler.syncAndReportErrors();
|
||||
await promiseUISyncError;
|
||||
Assert.equal(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
|
||||
|
||||
Services.io.offline = false;
|
||||
await clean();
|
||||
});
|
||||
|
||||
add_task(async function test_login_syncAndReportErrors_prolonged_network_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test prolonged, network errors are reported
|
||||
// when calling syncAndReportErrors.
|
||||
await configureIdentity({username: "johndoe"});
|
||||
|
||||
Service.clusterURL = fakeServerUrl;
|
||||
|
||||
let promiseObserved = promiseOneObserver("weave:ui:login:error");
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
errorHandler.syncAndReportErrors();
|
||||
await promiseObserved;
|
||||
Assert.equal(Status.login, LOGIN_FAILED_NETWORK_ERROR);
|
||||
|
||||
await clean();
|
||||
});
|
||||
|
||||
add_task(async function test_sync_syncAndReportErrors_prolonged_network_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test prolonged, network errors are reported
|
||||
// when calling syncAndReportErrors.
|
||||
Services.io.offline = true;
|
||||
|
||||
let promiseUISyncError = promiseOneObserver("weave:ui:sync:error");
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
errorHandler.syncAndReportErrors();
|
||||
await promiseUISyncError;
|
||||
Assert.equal(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
|
||||
|
||||
Services.io.offline = false;
|
||||
await clean();
|
||||
});
|
||||
|
||||
add_task(async function test_login_prolonged_non_network_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test prolonged, non-network errors are reported
|
||||
let server = await EHTestsCommon.sync_httpd_setup();
|
||||
await EHTestsCommon.setUp(server);
|
||||
Service.identity._syncKeyBundle = null;
|
||||
|
||||
let promiseObserved = promiseOneObserver("weave:ui:login:error");
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
await Service.sync();
|
||||
await promiseObserved;
|
||||
Assert.equal(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
Assert.ok(errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_sync_prolonged_non_network_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test prolonged, non-network errors are reported
|
||||
let server = await EHTestsCommon.sync_httpd_setup();
|
||||
await EHTestsCommon.setUp(server);
|
||||
|
||||
// By calling sync, we ensure we're logged in.
|
||||
await Service.sync();
|
||||
Assert.equal(Status.sync, SYNC_SUCCEEDED);
|
||||
Assert.ok(Service.isLoggedIn);
|
||||
|
||||
await EHTestsCommon.generateCredentialsChangedFailure();
|
||||
|
||||
let promiseObserved = promiseOneObserver("weave:ui:sync:error");
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
|
||||
let ping = await sync_and_validate_telem(true);
|
||||
equal(ping.status.sync, PROLONGED_SYNC_FAILURE);
|
||||
deepEqual(ping.failureReason, {
|
||||
name: "unexpectederror",
|
||||
error: "Error: Aborting sync, remote setup failed"
|
||||
});
|
||||
await promiseObserved;
|
||||
Assert.equal(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
Assert.ok(errorHandler.didReportProlongedError);
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_login_prolonged_network_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test prolonged, network errors are reported
|
||||
await configureIdentity({username: "johndoe"});
|
||||
Service.clusterURL = fakeServerUrl;
|
||||
|
||||
let promiseObserved = promiseOneObserver("weave:ui:login:error");
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
await Service.sync();
|
||||
await promiseObserved;
|
||||
Assert.equal(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
Assert.ok(errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
});
|
||||
|
||||
add_task(async function test_sync_prolonged_network_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test prolonged, network errors are reported
|
||||
Services.io.offline = true;
|
||||
|
||||
let promiseUISyncError = promiseOneObserver("weave:ui:sync:error");
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
await Service.sync();
|
||||
await promiseUISyncError;
|
||||
Assert.equal(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
Assert.ok(errorHandler.didReportProlongedError);
|
||||
|
||||
Services.io.offline = false;
|
||||
await clean();
|
||||
});
|
||||
|
||||
add_task(async function test_login_non_network_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
@ -192,8 +632,13 @@ add_task(async function test_login_non_network_error() {
|
||||
await EHTestsCommon.setUp(server);
|
||||
Service.identity._syncKeyBundle = null;
|
||||
|
||||
let promiseObserved = promiseOneObserver("weave:ui:login:error");
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
await Service.sync();
|
||||
await promiseObserved;
|
||||
Assert.equal(Status.login, LOGIN_FAILED_NO_PASSPHRASE);
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
@ -213,8 +658,13 @@ add_task(async function test_sync_non_network_error() {
|
||||
|
||||
await EHTestsCommon.generateCredentialsChangedFailure();
|
||||
|
||||
let promiseObserved = promiseOneObserver("weave:ui:sync:error");
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
await Service.sync();
|
||||
await promiseObserved;
|
||||
Assert.equal(Status.sync, CREDENTIALS_CHANGED);
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
@ -226,10 +676,14 @@ add_task(async function test_login_network_error() {
|
||||
await configureIdentity({username: "johndoe"});
|
||||
Service.clusterURL = fakeServerUrl;
|
||||
|
||||
let promiseObserved = promiseOneObserver("weave:ui:clear-error");
|
||||
// Test network errors are not reported.
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
await Service.sync();
|
||||
await promiseObserved;
|
||||
Assert.equal(Status.login, LOGIN_FAILED_NETWORK_ERROR);
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
Services.io.offline = false;
|
||||
await clean();
|
||||
@ -241,8 +695,13 @@ add_task(async function test_sync_network_error() {
|
||||
// Test network errors are not reported.
|
||||
Services.io.offline = true;
|
||||
|
||||
let promiseSyncFinished = promiseOneObserver("weave:ui:sync:finish");
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
await Service.sync();
|
||||
await promiseSyncFinished;
|
||||
Assert.equal(Status.sync, LOGIN_FAILED_NETWORK_ERROR);
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
Services.io.offline = false;
|
||||
await clean();
|
||||
@ -260,14 +719,24 @@ add_task(async function test_sync_server_maintenance_error() {
|
||||
engine.exception = {status: 503,
|
||||
headers: {"retry-after": BACKOFF}};
|
||||
|
||||
function onSyncError() {
|
||||
do_throw("Shouldn't get here!");
|
||||
}
|
||||
Svc.Obs.add("weave:ui:sync:error", onSyncError);
|
||||
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
let promiseObserved = promiseOneObserver("weave:ui:sync:finish");
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
let ping = await sync_and_validate_telem(true);
|
||||
equal(ping.status.sync, SERVER_MAINTENANCE);
|
||||
deepEqual(ping.engines.find(e => e.failureReason).failureReason, { name: "httperror", code: 503 });
|
||||
|
||||
await promiseObserved;
|
||||
Assert.equal(Status.service, SYNC_FAILED_PARTIAL);
|
||||
Assert.equal(Status.sync, SERVER_MAINTENANCE);
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
@ -288,16 +757,27 @@ add_task(async function test_info_collections_login_server_maintenance_error() {
|
||||
backoffInterval = subject;
|
||||
});
|
||||
|
||||
function onUIUpdate() {
|
||||
do_throw("Shouldn't experience UI update!");
|
||||
}
|
||||
Svc.Obs.add("weave:ui:login:error", onUIUpdate);
|
||||
|
||||
Assert.ok(!Status.enforceBackoff);
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
let promiseObserved = promiseOneObserver("weave:ui:clear-error");
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
await Service.sync();
|
||||
await promiseObserved;
|
||||
|
||||
Assert.ok(Status.enforceBackoff);
|
||||
Assert.equal(backoffInterval, 42);
|
||||
Assert.equal(Status.service, LOGIN_FAILED);
|
||||
Assert.equal(Status.login, SERVER_MAINTENANCE);
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
@ -317,16 +797,27 @@ add_task(async function test_meta_global_login_server_maintenance_error() {
|
||||
backoffInterval = subject;
|
||||
});
|
||||
|
||||
function onUIUpdate() {
|
||||
do_throw("Shouldn't get here!");
|
||||
}
|
||||
Svc.Obs.add("weave:ui:login:error", onUIUpdate);
|
||||
|
||||
Assert.ok(!Status.enforceBackoff);
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
let promiseObserved = promiseOneObserver("weave:ui:clear-error");
|
||||
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
await Service.sync();
|
||||
await promiseObserved;
|
||||
|
||||
Assert.ok(Status.enforceBackoff);
|
||||
Assert.equal(backoffInterval, 42);
|
||||
Assert.equal(Status.service, LOGIN_FAILED);
|
||||
Assert.equal(Status.login, SERVER_MAINTENANCE);
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
@ -12,16 +12,15 @@ ChromeUtils.import("resource://services-sync/util.js");
|
||||
ChromeUtils.import("resource://gre/modules/FileUtils.jsm");
|
||||
ChromeUtils.import("resource://gre/modules/PromiseUtils.jsm");
|
||||
|
||||
const fakeServer = new SyncServer();
|
||||
var fakeServer = new SyncServer();
|
||||
fakeServer.start();
|
||||
const fakeServerUrl = "http://localhost:" + fakeServer.port;
|
||||
|
||||
registerCleanupFunction(function() {
|
||||
return promiseStopServer(fakeServer).finally(() => {
|
||||
Svc.Prefs.resetBranch("");
|
||||
});
|
||||
return promiseStopServer(fakeServer);
|
||||
});
|
||||
|
||||
var fakeServerUrl = "http://localhost:" + fakeServer.port;
|
||||
|
||||
const logsdir = FileUtils.getDir("ProfD", ["weave", "logs"], true);
|
||||
|
||||
function removeLogFiles() {
|
||||
@ -41,7 +40,38 @@ function getLogFiles() {
|
||||
return result;
|
||||
}
|
||||
|
||||
const PROLONGED_ERROR_DURATION =
|
||||
(Svc.Prefs.get("errorhandler.networkFailureReportTimeout") * 2) * 1000;
|
||||
|
||||
const NON_PROLONGED_ERROR_DURATION =
|
||||
(Svc.Prefs.get("errorhandler.networkFailureReportTimeout") / 2) * 1000;
|
||||
|
||||
function setLastSync(lastSyncValue) {
|
||||
Svc.Prefs.set("lastSync", (new Date(Date.now() - lastSyncValue)).toString());
|
||||
}
|
||||
|
||||
// This relies on Service/ErrorHandler being a singleton. Fixing this will take
|
||||
// a lot of work.
|
||||
var errorHandler = Service.errorHandler;
|
||||
let engine;
|
||||
|
||||
async function syncAndWait(topic) {
|
||||
let promise1 = promiseOneObserver(topic);
|
||||
// also wait for the log file to be written
|
||||
let promise2 = promiseOneObserver("weave:service:reset-file-log");
|
||||
await Service.sync();
|
||||
await promise1;
|
||||
await promise2;
|
||||
}
|
||||
|
||||
async function syncAndReportErrorsAndWait(topic) {
|
||||
let promise1 = promiseOneObserver(topic);
|
||||
// also wait for the log file to be written
|
||||
let promise2 = promiseOneObserver("weave:service:reset-file-log");
|
||||
errorHandler.syncAndReportErrors();
|
||||
await promise1;
|
||||
await promise2;
|
||||
}
|
||||
add_task(async function setup() {
|
||||
await Service.engineManager.clear();
|
||||
await Service.engineManager.register(EHTestsCommon.CatapultEngine);
|
||||
@ -54,6 +84,7 @@ async function clean() {
|
||||
await promiseLogReset;
|
||||
Status.resetSync();
|
||||
Status.resetBackoff();
|
||||
errorHandler.didReportProlongedError = false;
|
||||
removeLogFiles();
|
||||
// Move log levels back to trace (startOver will have reversed this), sicne
|
||||
syncTestLogging();
|
||||
@ -78,16 +109,24 @@ add_task(async function test_crypto_keys_login_server_maintenance_error() {
|
||||
backoffInterval = subject;
|
||||
});
|
||||
|
||||
function onUIUpdate() {
|
||||
do_throw("Shouldn't get here!");
|
||||
}
|
||||
Svc.Obs.add("weave:ui:login:error", onUIUpdate);
|
||||
|
||||
Assert.ok(!Status.enforceBackoff);
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
await Service.sync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
await syncAndWait("weave:ui:clear-error");
|
||||
|
||||
Assert.ok(Status.enforceBackoff);
|
||||
Assert.equal(backoffInterval, 42);
|
||||
Assert.equal(Status.service, LOGIN_FAILED);
|
||||
Assert.equal(Status.login, SERVER_MAINTENANCE);
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
Svc.Obs.remove("weave:ui:login:error", onUIUpdate);
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
@ -127,6 +166,204 @@ add_task(async function test_lastSync_not_updated_on_complete_failure() {
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_info_collections_login_prolonged_server_maintenance_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test info/collections prolonged server maintenance errors are reported.
|
||||
let server = await EHTestsCommon.sync_httpd_setup();
|
||||
await EHTestsCommon.setUp(server);
|
||||
|
||||
await configureIdentity({username: "broken.info"}, server);
|
||||
|
||||
let backoffInterval;
|
||||
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
|
||||
Svc.Obs.remove("weave:service:backoff:interval", observe);
|
||||
backoffInterval = subject;
|
||||
});
|
||||
|
||||
Assert.ok(!Status.enforceBackoff);
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
await syncAndWait("weave:ui:login:error");
|
||||
|
||||
Assert.ok(Status.enforceBackoff);
|
||||
Assert.equal(backoffInterval, 42);
|
||||
Assert.equal(Status.service, SYNC_FAILED);
|
||||
Assert.equal(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
Assert.ok(errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_meta_global_login_prolonged_server_maintenance_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test meta/global prolonged server maintenance errors are reported.
|
||||
let server = await EHTestsCommon.sync_httpd_setup();
|
||||
await EHTestsCommon.setUp(server);
|
||||
|
||||
await configureIdentity({username: "broken.meta"}, server);
|
||||
|
||||
let backoffInterval;
|
||||
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
|
||||
Svc.Obs.remove("weave:service:backoff:interval", observe);
|
||||
backoffInterval = subject;
|
||||
});
|
||||
|
||||
Assert.ok(!Status.enforceBackoff);
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
await syncAndWait("weave:ui:login:error");
|
||||
|
||||
Assert.ok(Status.enforceBackoff);
|
||||
Assert.equal(backoffInterval, 42);
|
||||
Assert.equal(Status.service, SYNC_FAILED);
|
||||
Assert.equal(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
Assert.ok(errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_download_crypto_keys_login_prolonged_server_maintenance_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test crypto/keys prolonged server maintenance errors are reported.
|
||||
let server = await EHTestsCommon.sync_httpd_setup();
|
||||
await EHTestsCommon.setUp(server);
|
||||
|
||||
await configureIdentity({username: "broken.keys"}, server);
|
||||
// Force re-download of keys
|
||||
Service.collectionKeys.clear();
|
||||
|
||||
let backoffInterval;
|
||||
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
|
||||
Svc.Obs.remove("weave:service:backoff:interval", observe);
|
||||
backoffInterval = subject;
|
||||
});
|
||||
|
||||
Assert.ok(!Status.enforceBackoff);
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
await syncAndWait("weave:ui:login:error");
|
||||
Assert.ok(Status.enforceBackoff);
|
||||
Assert.equal(backoffInterval, 42);
|
||||
Assert.equal(Status.service, SYNC_FAILED);
|
||||
Assert.equal(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
Assert.ok(errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_upload_crypto_keys_login_prolonged_server_maintenance_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test crypto/keys prolonged server maintenance errors are reported.
|
||||
let server = await EHTestsCommon.sync_httpd_setup();
|
||||
|
||||
// Start off with an empty account, do not upload a key.
|
||||
await configureIdentity({username: "broken.keys"}, server);
|
||||
|
||||
let backoffInterval;
|
||||
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
|
||||
Svc.Obs.remove("weave:service:backoff:interval", observe);
|
||||
backoffInterval = subject;
|
||||
});
|
||||
|
||||
Assert.ok(!Status.enforceBackoff);
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
await syncAndWait("weave:ui:login:error");
|
||||
|
||||
Assert.ok(Status.enforceBackoff);
|
||||
Assert.equal(backoffInterval, 42);
|
||||
Assert.equal(Status.service, SYNC_FAILED);
|
||||
Assert.equal(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
Assert.ok(errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_wipeServer_login_prolonged_server_maintenance_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test that we report prolonged server maintenance errors that occur whilst
|
||||
// wiping the server.
|
||||
let server = await EHTestsCommon.sync_httpd_setup();
|
||||
|
||||
// Start off with an empty account, do not upload a key.
|
||||
await configureIdentity({username: "broken.wipe"}, server);
|
||||
|
||||
let backoffInterval;
|
||||
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
|
||||
Svc.Obs.remove("weave:service:backoff:interval", observe);
|
||||
backoffInterval = subject;
|
||||
});
|
||||
|
||||
Assert.ok(!Status.enforceBackoff);
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
await syncAndWait("weave:ui:login:error");
|
||||
|
||||
Assert.ok(Status.enforceBackoff);
|
||||
Assert.equal(backoffInterval, 42);
|
||||
Assert.equal(Status.service, SYNC_FAILED);
|
||||
Assert.equal(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
Assert.ok(errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_wipeRemote_prolonged_server_maintenance_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test that we report prolonged server maintenance errors that occur whilst
|
||||
// wiping all remote devices.
|
||||
let server = await EHTestsCommon.sync_httpd_setup();
|
||||
|
||||
server.registerPathHandler("/1.1/broken.wipe/storage/catapult", EHTestsCommon.service_unavailable);
|
||||
await configureIdentity({username: "broken.wipe"}, server);
|
||||
await EHTestsCommon.generateAndUploadKeys();
|
||||
|
||||
engine.exception = null;
|
||||
engine.enabled = true;
|
||||
|
||||
let backoffInterval;
|
||||
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
|
||||
Svc.Obs.remove("weave:service:backoff:interval", observe);
|
||||
backoffInterval = subject;
|
||||
});
|
||||
|
||||
let promiseObserved = promiseOneObserver("weave:ui:sync:error");
|
||||
|
||||
Assert.ok(!Status.enforceBackoff);
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
Svc.Prefs.set("firstSync", "wipeRemote");
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
let ping = await sync_and_validate_telem(true);
|
||||
deepEqual(ping.failureReason, { name: "httperror", code: 503 });
|
||||
await promiseObserved;
|
||||
|
||||
Assert.ok(Status.enforceBackoff);
|
||||
Assert.equal(backoffInterval, 42);
|
||||
Assert.equal(Status.service, SYNC_FAILED);
|
||||
Assert.equal(Status.sync, PROLONGED_SYNC_FAILURE);
|
||||
Assert.equal(Svc.Prefs.get("firstSync"), "wipeRemote");
|
||||
Assert.ok(errorHandler.didReportProlongedError);
|
||||
await promiseStopServer(server);
|
||||
await clean();
|
||||
});
|
||||
|
||||
add_task(async function test_sync_syncAndReportErrors_server_maintenance_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
@ -142,10 +379,12 @@ add_task(async function test_sync_syncAndReportErrors_server_maintenance_error()
|
||||
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
await Service.sync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
await syncAndReportErrorsAndWait("weave:ui:sync:error");
|
||||
|
||||
Assert.equal(Status.service, SYNC_FAILED_PARTIAL);
|
||||
Assert.equal(Status.sync, SERVER_MAINTENANCE);
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
@ -170,12 +409,14 @@ add_task(async function test_info_collections_login_syncAndReportErrors_server_m
|
||||
Assert.ok(!Status.enforceBackoff);
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
await Service.sync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
await syncAndReportErrorsAndWait("weave:ui:login:error");
|
||||
|
||||
Assert.ok(Status.enforceBackoff);
|
||||
Assert.equal(backoffInterval, 42);
|
||||
Assert.equal(Status.service, LOGIN_FAILED);
|
||||
Assert.equal(Status.login, SERVER_MAINTENANCE);
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
@ -200,12 +441,14 @@ add_task(async function test_meta_global_login_syncAndReportErrors_server_mainte
|
||||
Assert.ok(!Status.enforceBackoff);
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
await Service.sync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
await syncAndReportErrorsAndWait("weave:ui:login:error");
|
||||
|
||||
Assert.ok(Status.enforceBackoff);
|
||||
Assert.equal(backoffInterval, 42);
|
||||
Assert.equal(Status.service, LOGIN_FAILED);
|
||||
Assert.equal(Status.login, SERVER_MAINTENANCE);
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
@ -232,12 +475,14 @@ add_task(async function test_download_crypto_keys_login_syncAndReportErrors_serv
|
||||
Assert.ok(!Status.enforceBackoff);
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
await Service.sync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
await syncAndReportErrorsAndWait("weave:ui:login:error");
|
||||
|
||||
Assert.ok(Status.enforceBackoff);
|
||||
Assert.equal(backoffInterval, 42);
|
||||
Assert.equal(Status.service, LOGIN_FAILED);
|
||||
Assert.equal(Status.login, SERVER_MAINTENANCE);
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
@ -262,12 +507,14 @@ add_task(async function test_upload_crypto_keys_login_syncAndReportErrors_server
|
||||
Assert.ok(!Status.enforceBackoff);
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
await Service.sync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
await syncAndReportErrorsAndWait("weave:ui:login:error");
|
||||
|
||||
Assert.ok(Status.enforceBackoff);
|
||||
Assert.equal(backoffInterval, 42);
|
||||
Assert.equal(Status.service, LOGIN_FAILED);
|
||||
Assert.equal(Status.login, SERVER_MAINTENANCE);
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
@ -292,12 +539,14 @@ add_task(async function test_wipeServer_login_syncAndReportErrors_server_mainten
|
||||
Assert.ok(!Status.enforceBackoff);
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
await Service.sync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
await syncAndReportErrorsAndWait("weave:ui:login:error");
|
||||
|
||||
Assert.ok(Status.enforceBackoff);
|
||||
Assert.equal(backoffInterval, 42);
|
||||
Assert.equal(Status.service, LOGIN_FAILED);
|
||||
Assert.equal(Status.login, SERVER_MAINTENANCE);
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
@ -326,13 +575,215 @@ add_task(async function test_wipeRemote_syncAndReportErrors_server_maintenance_e
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
Svc.Prefs.set("firstSync", "wipeRemote");
|
||||
await Service.sync();
|
||||
setLastSync(NON_PROLONGED_ERROR_DURATION);
|
||||
await syncAndReportErrorsAndWait("weave:ui:sync:error");
|
||||
|
||||
Assert.ok(Status.enforceBackoff);
|
||||
Assert.equal(backoffInterval, 42);
|
||||
Assert.equal(Status.service, SYNC_FAILED);
|
||||
Assert.equal(Status.sync, SERVER_MAINTENANCE);
|
||||
Assert.equal(Svc.Prefs.get("firstSync"), "wipeRemote");
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_sync_syncAndReportErrors_prolonged_server_maintenance_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test prolonged server maintenance errors are
|
||||
// reported when calling syncAndReportErrors.
|
||||
let server = await EHTestsCommon.sync_httpd_setup();
|
||||
await EHTestsCommon.setUp(server);
|
||||
|
||||
const BACKOFF = 42;
|
||||
engine.enabled = true;
|
||||
engine.exception = {status: 503,
|
||||
headers: {"retry-after": BACKOFF}};
|
||||
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
await syncAndReportErrorsAndWait("weave:ui:sync:error");
|
||||
|
||||
Assert.equal(Status.service, SYNC_FAILED_PARTIAL);
|
||||
Assert.equal(Status.sync, SERVER_MAINTENANCE);
|
||||
// syncAndReportErrors means dontIgnoreErrors, which means
|
||||
// didReportProlongedError not touched.
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_info_collections_login_syncAndReportErrors_prolonged_server_maintenance_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test info/collections server maintenance errors are reported
|
||||
// when calling syncAndReportErrors.
|
||||
let server = await EHTestsCommon.sync_httpd_setup();
|
||||
await EHTestsCommon.setUp(server);
|
||||
|
||||
await configureIdentity({username: "broken.info"}, server);
|
||||
|
||||
let backoffInterval;
|
||||
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
|
||||
Svc.Obs.remove("weave:service:backoff:interval", observe);
|
||||
backoffInterval = subject;
|
||||
});
|
||||
|
||||
Assert.ok(!Status.enforceBackoff);
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
await syncAndReportErrorsAndWait("weave:ui:login:error");
|
||||
|
||||
Assert.ok(Status.enforceBackoff);
|
||||
Assert.equal(backoffInterval, 42);
|
||||
Assert.equal(Status.service, LOGIN_FAILED);
|
||||
Assert.equal(Status.login, SERVER_MAINTENANCE);
|
||||
// syncAndReportErrors means dontIgnoreErrors, which means
|
||||
// didReportProlongedError not touched.
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_meta_global_login_syncAndReportErrors_prolonged_server_maintenance_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test meta/global server maintenance errors are reported
|
||||
// when calling syncAndReportErrors.
|
||||
let server = await EHTestsCommon.sync_httpd_setup();
|
||||
await EHTestsCommon.setUp(server);
|
||||
|
||||
await configureIdentity({username: "broken.meta"}, server);
|
||||
|
||||
let backoffInterval;
|
||||
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
|
||||
Svc.Obs.remove("weave:service:backoff:interval", observe);
|
||||
backoffInterval = subject;
|
||||
});
|
||||
|
||||
Assert.ok(!Status.enforceBackoff);
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
await syncAndReportErrorsAndWait("weave:ui:login:error");
|
||||
|
||||
Assert.ok(Status.enforceBackoff);
|
||||
Assert.equal(backoffInterval, 42);
|
||||
Assert.equal(Status.service, LOGIN_FAILED);
|
||||
Assert.equal(Status.login, SERVER_MAINTENANCE);
|
||||
// syncAndReportErrors means dontIgnoreErrors, which means
|
||||
// didReportProlongedError not touched.
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_download_crypto_keys_login_syncAndReportErrors_prolonged_server_maintenance_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test crypto/keys server maintenance errors are reported
|
||||
// when calling syncAndReportErrors.
|
||||
let server = await EHTestsCommon.sync_httpd_setup();
|
||||
await EHTestsCommon.setUp(server);
|
||||
|
||||
await configureIdentity({username: "broken.keys"}, server);
|
||||
// Force re-download of keys
|
||||
Service.collectionKeys.clear();
|
||||
|
||||
let backoffInterval;
|
||||
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
|
||||
Svc.Obs.remove("weave:service:backoff:interval", observe);
|
||||
backoffInterval = subject;
|
||||
});
|
||||
|
||||
Assert.ok(!Status.enforceBackoff);
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
await syncAndReportErrorsAndWait("weave:ui:login:error");
|
||||
|
||||
Assert.ok(Status.enforceBackoff);
|
||||
Assert.equal(backoffInterval, 42);
|
||||
Assert.equal(Status.service, LOGIN_FAILED);
|
||||
Assert.equal(Status.login, SERVER_MAINTENANCE);
|
||||
// syncAndReportErrors means dontIgnoreErrors, which means
|
||||
// didReportProlongedError not touched.
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_upload_crypto_keys_login_syncAndReportErrors_prolonged_server_maintenance_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test crypto/keys server maintenance errors are reported
|
||||
// when calling syncAndReportErrors.
|
||||
let server = await EHTestsCommon.sync_httpd_setup();
|
||||
|
||||
// Start off with an empty account, do not upload a key.
|
||||
await configureIdentity({username: "broken.keys"}, server);
|
||||
|
||||
let backoffInterval;
|
||||
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
|
||||
Svc.Obs.remove("weave:service:backoff:interval", observe);
|
||||
backoffInterval = subject;
|
||||
});
|
||||
|
||||
Assert.ok(!Status.enforceBackoff);
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
await syncAndReportErrorsAndWait("weave:ui:login:error");
|
||||
|
||||
Assert.ok(Status.enforceBackoff);
|
||||
Assert.equal(backoffInterval, 42);
|
||||
Assert.equal(Status.service, LOGIN_FAILED);
|
||||
Assert.equal(Status.login, SERVER_MAINTENANCE);
|
||||
// syncAndReportErrors means dontIgnoreErrors, which means
|
||||
// didReportProlongedError not touched.
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_wipeServer_login_syncAndReportErrors_prolonged_server_maintenance_error() {
|
||||
enableValidationPrefs();
|
||||
|
||||
// Test crypto/keys server maintenance errors are reported
|
||||
// when calling syncAndReportErrors.
|
||||
let server = await EHTestsCommon.sync_httpd_setup();
|
||||
|
||||
// Start off with an empty account, do not upload a key.
|
||||
await configureIdentity({username: "broken.wipe"}, server);
|
||||
|
||||
let backoffInterval;
|
||||
Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) {
|
||||
Svc.Obs.remove("weave:service:backoff:interval", observe);
|
||||
backoffInterval = subject;
|
||||
});
|
||||
|
||||
Assert.ok(!Status.enforceBackoff);
|
||||
Assert.equal(Status.service, STATUS_OK);
|
||||
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
await syncAndReportErrorsAndWait("weave:ui:login:error");
|
||||
|
||||
Assert.ok(Status.enforceBackoff);
|
||||
Assert.equal(backoffInterval, 42);
|
||||
Assert.equal(Status.service, LOGIN_FAILED);
|
||||
Assert.equal(Status.login, SERVER_MAINTENANCE);
|
||||
// syncAndReportErrors means dontIgnoreErrors, which means
|
||||
// didReportProlongedError not touched.
|
||||
Assert.ok(!errorHandler.didReportProlongedError);
|
||||
|
||||
await clean();
|
||||
await promiseStopServer(server);
|
||||
@ -394,7 +845,7 @@ add_task(async function test_sync_engine_generic_fail() {
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_logs_on_sync_error() {
|
||||
add_task(async function test_logs_on_sync_error_despite_shouldReportError() {
|
||||
enableValidationPrefs();
|
||||
|
||||
_("Ensure that an error is still logged when weave:service:sync:error " +
|
||||
@ -406,6 +857,7 @@ add_task(async function test_logs_on_sync_error() {
|
||||
|
||||
// Ensure that we report no error.
|
||||
Status.login = MASTER_PASSWORD_LOCKED;
|
||||
Assert.ok(!errorHandler.shouldReportError());
|
||||
|
||||
let promiseObserved = promiseOneObserver("weave:service:reset-file-log");
|
||||
Svc.Obs.notify("weave:service:sync:error", {});
|
||||
@ -419,7 +871,7 @@ add_task(async function test_logs_on_sync_error() {
|
||||
await clean();
|
||||
});
|
||||
|
||||
add_task(async function test_logs_on_login_error() {
|
||||
add_task(async function test_logs_on_login_error_despite_shouldReportError() {
|
||||
enableValidationPrefs();
|
||||
|
||||
_("Ensure that an error is still logged when weave:service:login:error " +
|
||||
@ -431,6 +883,7 @@ add_task(async function test_logs_on_login_error() {
|
||||
|
||||
// Ensure that we report no error.
|
||||
Status.login = MASTER_PASSWORD_LOCKED;
|
||||
Assert.ok(!errorHandler.shouldReportError());
|
||||
|
||||
let promiseObserved = promiseOneObserver("weave:service:reset-file-log");
|
||||
Svc.Obs.notify("weave:service:login:error", {});
|
||||
|
121
services/sync/tests/unit/test_errorhandler_eol.js
Normal file
121
services/sync/tests/unit/test_errorhandler_eol.js
Normal file
@ -0,0 +1,121 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
ChromeUtils.import("resource://services-sync/service.js");
|
||||
ChromeUtils.import("resource://services-sync/status.js");
|
||||
ChromeUtils.import("resource://services-sync/util.js");
|
||||
|
||||
ChromeUtils.import("resource://testing-common/services/sync/fakeservices.js");
|
||||
|
||||
function baseHandler(eolCode, request, response, statusCode, status, body) {
|
||||
let alertBody = {
|
||||
code: eolCode,
|
||||
message: "Service is EOLed.",
|
||||
url: "http://getfirefox.com",
|
||||
};
|
||||
response.setHeader("X-Weave-Timestamp", "" + new_timestamp(), false);
|
||||
response.setHeader("X-Weave-Alert", "" + JSON.stringify(alertBody), false);
|
||||
response.setStatusLine(request.httpVersion, statusCode, status);
|
||||
response.bodyOutputStream.write(body, body.length);
|
||||
}
|
||||
|
||||
function handler513(request, response) {
|
||||
let statusCode = 513;
|
||||
let status = "Upgrade Required";
|
||||
let body = "{}";
|
||||
baseHandler("hard-eol", request, response, statusCode, status, body);
|
||||
}
|
||||
|
||||
function handler200(eolCode) {
|
||||
return function(request, response) {
|
||||
let statusCode = 200;
|
||||
let status = "OK";
|
||||
let body = "{\"meta\": 123456789010}";
|
||||
baseHandler(eolCode, request, response, statusCode, status, body);
|
||||
};
|
||||
}
|
||||
|
||||
function sync_httpd_setup(infoHandler) {
|
||||
let handlers = {
|
||||
"/1.1/johndoe/info/collections": infoHandler,
|
||||
};
|
||||
return httpd_setup(handlers);
|
||||
}
|
||||
|
||||
async function setUp(server) {
|
||||
await configureIdentity({username: "johndoe"}, server);
|
||||
new FakeCryptoService();
|
||||
}
|
||||
|
||||
function do_check_soft_eol(eh, start) {
|
||||
// We subtract 1000 because the stored value is in second precision.
|
||||
Assert.ok(eh.earliestNextAlert >= (start + eh.MINIMUM_ALERT_INTERVAL_MSEC - 1000));
|
||||
Assert.equal("soft-eol", eh.currentAlertMode);
|
||||
}
|
||||
function do_check_hard_eol(eh, start) {
|
||||
// We subtract 1000 because the stored value is in second precision.
|
||||
Assert.ok(eh.earliestNextAlert >= (start + eh.MINIMUM_ALERT_INTERVAL_MSEC - 1000));
|
||||
Assert.equal("hard-eol", eh.currentAlertMode);
|
||||
Assert.ok(Status.eol);
|
||||
}
|
||||
|
||||
add_task(async function test_200_hard() {
|
||||
let eh = Service.errorHandler;
|
||||
let start = Date.now();
|
||||
let server = sync_httpd_setup(handler200("hard-eol"));
|
||||
await setUp(server);
|
||||
|
||||
let promiseObserved = promiseOneObserver("weave:eol");
|
||||
|
||||
await Service._fetchInfo();
|
||||
Service.scheduler.adjustSyncInterval(); // As if we failed or succeeded in syncing.
|
||||
|
||||
let { subject } = await promiseObserved;
|
||||
Assert.equal("hard-eol", subject.code);
|
||||
do_check_hard_eol(eh, start);
|
||||
Assert.equal(Service.scheduler.eolInterval, Service.scheduler.syncInterval);
|
||||
eh.clearServerAlerts();
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_513_hard() {
|
||||
let eh = Service.errorHandler;
|
||||
let start = Date.now();
|
||||
let server = sync_httpd_setup(handler513);
|
||||
await setUp(server);
|
||||
|
||||
let promiseObserved = promiseOneObserver("weave:eol");
|
||||
|
||||
try {
|
||||
await Service._fetchInfo();
|
||||
Service.scheduler.adjustSyncInterval(); // As if we failed or succeeded in syncing.
|
||||
} catch (ex) {
|
||||
// Because fetchInfo will fail on a 513.
|
||||
}
|
||||
let { subject } = await promiseObserved;
|
||||
Assert.equal("hard-eol", subject.code);
|
||||
do_check_hard_eol(eh, start);
|
||||
Assert.equal(Service.scheduler.eolInterval, Service.scheduler.syncInterval);
|
||||
eh.clearServerAlerts();
|
||||
|
||||
await promiseStopServer(server);
|
||||
});
|
||||
|
||||
add_task(async function test_200_soft() {
|
||||
let eh = Service.errorHandler;
|
||||
let start = Date.now();
|
||||
let server = sync_httpd_setup(handler200("soft-eol"));
|
||||
await setUp(server);
|
||||
|
||||
let promiseObserved = promiseOneObserver("weave:eol");
|
||||
|
||||
await Service._fetchInfo();
|
||||
Service.scheduler.adjustSyncInterval(); // As if we failed or succeeded in syncing.
|
||||
let { subject } = await promiseObserved;
|
||||
Assert.equal("soft-eol", subject.code);
|
||||
do_check_soft_eol(eh, start);
|
||||
Assert.equal(Service.scheduler.singleDeviceInterval, Service.scheduler.syncInterval);
|
||||
eh.clearServerAlerts();
|
||||
|
||||
await promiseStopServer(server);
|
||||
});
|
@ -18,8 +18,15 @@ const logsdir = FileUtils.getDir("ProfD", ["weave", "logs"], true);
|
||||
const CLEANUP_DELAY = 2000;
|
||||
const DELAY_BUFFER = 500; // Buffer for timers on different OS platforms.
|
||||
|
||||
const PROLONGED_ERROR_DURATION =
|
||||
(Svc.Prefs.get("errorhandler.networkFailureReportTimeout") * 2) * 1000;
|
||||
|
||||
var errorHandler = Service.errorHandler;
|
||||
|
||||
function setLastSync(lastSyncValue) {
|
||||
Svc.Prefs.set("lastSync", (new Date(Date.now() - lastSyncValue)).toString());
|
||||
}
|
||||
|
||||
function run_test() {
|
||||
validate_all_future_pings();
|
||||
run_next_test();
|
||||
@ -135,7 +142,8 @@ add_test(function test_sync_error_logOnError_false() {
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
// Fake an unsuccessful sync.
|
||||
// Fake an unsuccessful sync due to prolonged failure.
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
Svc.Obs.notify("weave:service:sync:error");
|
||||
});
|
||||
|
||||
@ -175,7 +183,8 @@ add_test(function test_sync_error_logOnError_true() {
|
||||
});
|
||||
});
|
||||
|
||||
// Fake an unsuccessful sync.
|
||||
// Fake an unsuccessful sync due to prolonged failure.
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
Svc.Obs.notify("weave:service:sync:error");
|
||||
});
|
||||
|
||||
@ -194,7 +203,8 @@ add_test(function test_login_error_logOnError_false() {
|
||||
run_next_test();
|
||||
});
|
||||
|
||||
// Fake an unsuccessful login.
|
||||
// Fake an unsuccessful login due to prolonged failure.
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
Svc.Obs.notify("weave:service:login:error");
|
||||
});
|
||||
|
||||
@ -234,7 +244,8 @@ add_test(function test_login_error_logOnError_true() {
|
||||
});
|
||||
});
|
||||
|
||||
// Fake an unsuccessful login.
|
||||
// Fake an unsuccessful login due to prolonged failure.
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
Svc.Obs.notify("weave:service:login:error");
|
||||
});
|
||||
|
||||
@ -342,7 +353,8 @@ add_test(function test_errorLog_dumpAddons() {
|
||||
});
|
||||
});
|
||||
|
||||
// Fake an unsuccessful sync.
|
||||
// Fake an unsuccessful sync due to prolonged failure.
|
||||
setLastSync(PROLONGED_ERROR_DURATION);
|
||||
Svc.Obs.notify("weave:service:sync:error");
|
||||
});
|
||||
|
||||
|
@ -25,6 +25,13 @@ add_task(async function setup() {
|
||||
|
||||
// Setup the FxA identity manager and cluster manager.
|
||||
Status.__authManager = Service.identity = new BrowserIDManager();
|
||||
|
||||
// None of the failures in this file should result in a UI error.
|
||||
function onUIError() {
|
||||
do_throw("Errors should not be presented in the UI.");
|
||||
}
|
||||
Svc.Obs.add("weave:ui:login:error", onUIError);
|
||||
Svc.Obs.add("weave:ui:sync:error", onUIError);
|
||||
});
|
||||
|
||||
|
||||
|
@ -16,6 +16,13 @@ ChromeUtils.import("resource://gre/modules/PromiseUtils.jsm");
|
||||
|
||||
add_task(async function setup() {
|
||||
validate_all_future_pings();
|
||||
|
||||
// None of the failures in this file should result in a UI error.
|
||||
function onUIError() {
|
||||
do_throw("Errors should not be presented in the UI.");
|
||||
}
|
||||
Svc.Obs.add("weave:ui:login:error", onUIError);
|
||||
Svc.Obs.add("weave:ui:sync:error", onUIError);
|
||||
});
|
||||
|
||||
/**
|
||||
|
@ -220,8 +220,11 @@ add_task(async function test_disabledLocally_wipe503() {
|
||||
Service._ignorePrefObserver = false;
|
||||
engine.enabled = false;
|
||||
|
||||
let promiseObserved = promiseOneObserver("weave:ui:sync:error");
|
||||
|
||||
_("Sync.");
|
||||
await Service.sync();
|
||||
Service.errorHandler.syncAndReportErrors();
|
||||
await promiseObserved;
|
||||
Assert.equal(Service.status.sync, SERVER_MAINTENANCE);
|
||||
|
||||
await Service.startOver();
|
||||
|
@ -104,6 +104,7 @@ skip-if = os == "android"
|
||||
[test_errorhandler_sync_checkServerError.js]
|
||||
# Bug 676978: test hangs on Android (see also testing/xpcshell/xpcshell.ini)
|
||||
skip-if = os == "android"
|
||||
[test_errorhandler_eol.js]
|
||||
[test_hmac_error.js]
|
||||
[test_interval_triggers.js]
|
||||
[test_node_reassignment.js]
|
||||
|
@ -268,6 +268,7 @@ var TPS = {
|
||||
* directly called via TPS.Sync()!
|
||||
*/
|
||||
delayAutoSync: function TPS_delayAutoSync() {
|
||||
Weave.Svc.Prefs.set("scheduler.eolInterval", 7200);
|
||||
Weave.Svc.Prefs.set("scheduler.immediateInterval", 7200);
|
||||
Weave.Svc.Prefs.set("scheduler.idleInterval", 7200);
|
||||
Weave.Svc.Prefs.set("scheduler.activeInterval", 7200);
|
||||
|
@ -29,7 +29,7 @@
|
||||
"collection_repair.js": ["getRepairRequestor", "getAllRepairRequestors", "CollectionRepairRequestor", "getRepairResponder", "CollectionRepairResponder"],
|
||||
"collection_validator.js": ["CollectionValidator", "CollectionProblemData"],
|
||||
"Console.jsm": ["console", "ConsoleAPI"],
|
||||
"constants.js": ["WEAVE_VERSION", "SYNC_API_VERSION", "STORAGE_VERSION", "PREFS_BRANCH", "DEFAULT_KEYBUNDLE_NAME", "SYNC_KEY_ENCODED_LENGTH", "SYNC_KEY_DECODED_LENGTH", "NO_SYNC_NODE_INTERVAL", "MAX_ERROR_COUNT_BEFORE_BACKOFF", "MINIMUM_BACKOFF_INTERVAL", "MAXIMUM_BACKOFF_INTERVAL", "HMAC_EVENT_INTERVAL", "MASTER_PASSWORD_LOCKED_RETRY_INTERVAL", "DEFAULT_GUID_FETCH_BATCH_SIZE", "DEFAULT_DOWNLOAD_BATCH_SIZE", "SINGLE_USER_THRESHOLD", "MULTI_DEVICE_THRESHOLD", "SCORE_INCREMENT_SMALL", "SCORE_INCREMENT_MEDIUM", "SCORE_INCREMENT_XLARGE", "SCORE_UPDATE_DELAY", "IDLE_OBSERVER_BACK_DELAY", "URI_LENGTH_MAX", "MAX_HISTORY_UPLOAD", "MAX_HISTORY_DOWNLOAD", "STATUS_OK", "SYNC_FAILED", "LOGIN_FAILED", "SYNC_FAILED_PARTIAL", "CLIENT_NOT_CONFIGURED", "STATUS_DISABLED", "MASTER_PASSWORD_LOCKED", "LOGIN_SUCCEEDED", "SYNC_SUCCEEDED", "ENGINE_SUCCEEDED", "LOGIN_FAILED_NO_USERNAME", "LOGIN_FAILED_NO_PASSPHRASE", "LOGIN_FAILED_NETWORK_ERROR", "LOGIN_FAILED_SERVER_ERROR", "LOGIN_FAILED_INVALID_PASSPHRASE", "LOGIN_FAILED_LOGIN_REJECTED", "METARECORD_DOWNLOAD_FAIL", "VERSION_OUT_OF_DATE", "CREDENTIALS_CHANGED", "ABORT_SYNC_COMMAND", "NO_SYNC_NODE_FOUND", "OVER_QUOTA", "SERVER_MAINTENANCE", "RESPONSE_OVER_QUOTA", "ENGINE_UPLOAD_FAIL", "ENGINE_DOWNLOAD_FAIL", "ENGINE_UNKNOWN_FAIL", "ENGINE_APPLY_FAIL", "ENGINE_BATCH_INTERRUPTED", "kSyncMasterPasswordLocked", "kSyncWeaveDisabled", "kSyncNetworkOffline", "kSyncBackoffNotMet", "kFirstSyncChoiceNotMade", "kSyncNotConfigured", "kFirefoxShuttingDown", "DEVICE_TYPE_DESKTOP", "DEVICE_TYPE_MOBILE", "SQLITE_MAX_VARIABLE_NUMBER"],
|
||||
"constants.js": ["WEAVE_VERSION", "SYNC_API_VERSION", "STORAGE_VERSION", "PREFS_BRANCH", "DEFAULT_KEYBUNDLE_NAME", "SYNC_KEY_ENCODED_LENGTH", "SYNC_KEY_DECODED_LENGTH", "NO_SYNC_NODE_INTERVAL", "MAX_ERROR_COUNT_BEFORE_BACKOFF", "MINIMUM_BACKOFF_INTERVAL", "MAXIMUM_BACKOFF_INTERVAL", "HMAC_EVENT_INTERVAL", "MASTER_PASSWORD_LOCKED_RETRY_INTERVAL", "DEFAULT_GUID_FETCH_BATCH_SIZE", "DEFAULT_DOWNLOAD_BATCH_SIZE", "SINGLE_USER_THRESHOLD", "MULTI_DEVICE_THRESHOLD", "SCORE_INCREMENT_SMALL", "SCORE_INCREMENT_MEDIUM", "SCORE_INCREMENT_XLARGE", "SCORE_UPDATE_DELAY", "IDLE_OBSERVER_BACK_DELAY", "URI_LENGTH_MAX", "MAX_HISTORY_UPLOAD", "MAX_HISTORY_DOWNLOAD", "STATUS_OK", "SYNC_FAILED", "LOGIN_FAILED", "SYNC_FAILED_PARTIAL", "CLIENT_NOT_CONFIGURED", "STATUS_DISABLED", "MASTER_PASSWORD_LOCKED", "LOGIN_SUCCEEDED", "SYNC_SUCCEEDED", "ENGINE_SUCCEEDED", "LOGIN_FAILED_NO_USERNAME", "LOGIN_FAILED_NO_PASSPHRASE", "LOGIN_FAILED_NETWORK_ERROR", "LOGIN_FAILED_SERVER_ERROR", "LOGIN_FAILED_INVALID_PASSPHRASE", "LOGIN_FAILED_LOGIN_REJECTED", "METARECORD_DOWNLOAD_FAIL", "VERSION_OUT_OF_DATE", "CREDENTIALS_CHANGED", "ABORT_SYNC_COMMAND", "NO_SYNC_NODE_FOUND", "OVER_QUOTA", "PROLONGED_SYNC_FAILURE", "SERVER_MAINTENANCE", "RESPONSE_OVER_QUOTA", "ENGINE_UPLOAD_FAIL", "ENGINE_DOWNLOAD_FAIL", "ENGINE_UNKNOWN_FAIL", "ENGINE_APPLY_FAIL", "ENGINE_BATCH_INTERRUPTED", "kSyncMasterPasswordLocked", "kSyncWeaveDisabled", "kSyncNetworkOffline", "kSyncBackoffNotMet", "kFirstSyncChoiceNotMade", "kSyncNotConfigured", "kFirefoxShuttingDown", "DEVICE_TYPE_DESKTOP", "DEVICE_TYPE_MOBILE", "SQLITE_MAX_VARIABLE_NUMBER"],
|
||||
"Constants.jsm": ["Roles", "Events", "Relations", "Filters", "States", "Prefilters"],
|
||||
"ContactDB.jsm": ["ContactDB", "DB_NAME", "STORE_NAME", "SAVED_GETALL_STORE_NAME", "REVISION_STORE", "DB_VERSION"],
|
||||
"content-server.jsm": ["init"],
|
||||
|
Loading…
Reference in New Issue
Block a user