From 5be41ac97d286cbbebbcf4bea7ab97c3274e0688 Mon Sep 17 00:00:00 2001 From: Richard Newman Date: Thu, 27 Oct 2011 22:25:00 -0700 Subject: [PATCH] Bug 684798 - Part 1: Catch server errors for crypto/keys. r=rnewman (reland) --- services/sync/modules/policies.js | 7 +- services/sync/modules/service.js | 7 +- services/sync/tests/unit/test_errorhandler.js | 113 +++++++++++++++++- 3 files changed, 119 insertions(+), 8 deletions(-) diff --git a/services/sync/modules/policies.js b/services/sync/modules/policies.js index 89655ecebb6..653420121bf 100644 --- a/services/sync/modules/policies.js +++ b/services/sync/modules/policies.js @@ -590,7 +590,12 @@ let ErrorHandler = { }, notifyOnNextTick: function notifyOnNextTick(topic) { - Utils.nextTick(function() Svc.Obs.notify(topic)); + Utils.nextTick(function() { + this._log.trace("Notifying " + topic + + ". Status.login is " + Status.login + + ". Status.sync is " + Status.sync); + Svc.Obs.notify(topic); + }, this); }, /** diff --git a/services/sync/modules/service.js b/services/sync/modules/service.js index e1c11577b82..2ee50e53064 100644 --- a/services/sync/modules/service.js +++ b/services/sync/modules/service.js @@ -702,8 +702,11 @@ WeaveSvc.prototype = { return true; } - } catch (e) { + } catch (ex) { // This means no keys are present, or there's a network error. + this._log.debug("Failed to fetch and verify keys: " + + Utils.exceptionStr(ex)); + ErrorHandler.checkServerError(ex); return false; } }, @@ -826,6 +829,7 @@ WeaveSvc.prototype = { let uploadRes = wbo.upload(this.cryptoKeysURL); if (uploadRes.status != 200) { this._log.warn("Got status " + uploadRes.status + " uploading new keys. What to do? Throw!"); + ErrorHandler.checkServerError(uploadRes); throw new Error("Unable to upload symmetric keys."); } this._log.info("Got status " + uploadRes.status + " uploading keys."); @@ -1678,7 +1682,6 @@ WeaveSvc.prototype = { // Pretend we've never synced to the server and drop cached data this.syncID = ""; - Svc.Prefs.reset("lastSync"); Records.clearCache(); }))(), diff --git a/services/sync/tests/unit/test_errorhandler.js b/services/sync/tests/unit/test_errorhandler.js index aa36bca0946..f22d2070d6b 100644 --- a/services/sync/tests/unit/test_errorhandler.js +++ b/services/sync/tests/unit/test_errorhandler.js @@ -20,8 +20,7 @@ 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()); + Svc.Prefs.set("lastSync", (new Date(Date.now() - lastSyncValue)).toString()); } function CatapultEngine() { @@ -937,7 +936,7 @@ add_test(function test_meta_global_login_prolonged_server_maintenance_error(){ Service.sync(); }); -add_test(function test_crypto_keys_login_prolonged_server_maintenance_error(){ +add_test(function test_download_crypto_keys_login_prolonged_server_maintenance_error(){ // Test crypto/keys prolonged server maintenance errors are reported. let server = sync_httpd_setup(); setUp(); @@ -971,6 +970,40 @@ add_test(function test_crypto_keys_login_prolonged_server_maintenance_error(){ Service.sync(); }); +add_test(function test_upload_crypto_keys_login_prolonged_server_maintenance_error(){ + // Test crypto/keys prolonged server maintenance errors are reported. + let server = sync_httpd_setup(); + + // Start off with an empty account, do not upload a key. + Service.username = "foo"; + Service.password = "ilovejane"; + Service.passphrase = "abcdeabcdeabcdeabcdeabcdea"; + Service.clusterURL = "http://localhost:8080/maintenance/"; + + let backoffInterval; + Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) { + Svc.Obs.remove("weave:service:backoff:interval", observe); + backoffInterval = subject; + }); + + Svc.Obs.add("weave:ui:login:error", function onUIUpdate() { + Svc.Obs.remove("weave:ui:login:error", onUIUpdate); + do_check_true(Status.enforceBackoff); + do_check_eq(backoffInterval, 42); + do_check_eq(Status.service, SYNC_FAILED); + do_check_eq(Status.sync, PROLONGED_SYNC_FAILURE); + + clean(); + server.stop(run_next_test); + }); + + do_check_false(Status.enforceBackoff); + do_check_eq(Status.service, STATUS_OK); + + setLastSync(PROLONGED_ERROR_DURATION); + Service.sync(); +}); + add_test(function test_sync_syncAndReportErrors_server_maintenance_error() { // Test server maintenance errors are reported // when calling syncAndReportErrors. @@ -1064,7 +1097,7 @@ add_test(function test_meta_global_login_syncAndReportErrors_server_maintenance_ ErrorHandler.syncAndReportErrors(); }); -add_test(function test_crypto_keys_login_syncAndReportErrors_server_maintenance_error() { +add_test(function test_download_crypto_keys_login_syncAndReportErrors_server_maintenance_error() { // Test crypto/keys server maintenance errors are reported // when calling syncAndReportErrors. let server = sync_httpd_setup(); @@ -1099,6 +1132,41 @@ add_test(function test_crypto_keys_login_syncAndReportErrors_server_maintenance_ ErrorHandler.syncAndReportErrors(); }); +add_test(function test_upload_crypto_keys_login_syncAndReportErrors_server_maintenance_error() { + // Test crypto/keys server maintenance errors are reported + // when calling syncAndReportErrors. + let server = sync_httpd_setup(); + + // Start off with an empty account, do not upload a key. + Service.username = "foo"; + Service.password = "ilovejane"; + Service.passphrase = "abcdeabcdeabcdeabcdeabcdea"; + Service.clusterURL = "http://localhost:8080/maintenance/"; + + let backoffInterval; + Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) { + Svc.Obs.remove("weave:service:backoff:interval", observe); + backoffInterval = subject; + }); + + Svc.Obs.add("weave:ui:login:error", function onUIUpdate() { + Svc.Obs.remove("weave:ui:login:error", onUIUpdate); + do_check_true(Status.enforceBackoff); + do_check_eq(backoffInterval, 42); + do_check_eq(Status.service, LOGIN_FAILED); + do_check_eq(Status.login, SERVER_MAINTENANCE); + + clean(); + server.stop(run_next_test); + }); + + do_check_false(Status.enforceBackoff); + do_check_eq(Status.service, STATUS_OK); + + setLastSync(NON_PROLONGED_ERROR_DURATION); + ErrorHandler.syncAndReportErrors(); +}); + add_test(function test_sync_syncAndReportErrors_prolonged_server_maintenance_error() { // Test prolonged server maintenance errors are // reported when calling syncAndReportErrors. @@ -1192,7 +1260,7 @@ add_test(function test_meta_global_login_syncAndReportErrors_prolonged_server_ma ErrorHandler.syncAndReportErrors(); }); -add_test(function test_crypto_keys_login_syncAndReportErrors_prolonged_server_maintenance_error() { +add_test(function test_download_crypto_keys_login_syncAndReportErrors_prolonged_server_maintenance_error() { // Test crypto/keys server maintenance errors are reported // when calling syncAndReportErrors. let server = sync_httpd_setup(); @@ -1227,6 +1295,41 @@ add_test(function test_crypto_keys_login_syncAndReportErrors_prolonged_server_ma ErrorHandler.syncAndReportErrors(); }); +add_test(function test_upload_crypto_keys_login_syncAndReportErrors_prolonged_server_maintenance_error() { + // Test crypto/keys server maintenance errors are reported + // when calling syncAndReportErrors. + let server = sync_httpd_setup(); + + // Start off with an empty account, do not upload a key. + Service.username = "foo"; + Service.password = "ilovejane"; + Service.passphrase = "abcdeabcdeabcdeabcdeabcdea"; + Service.clusterURL = "http://localhost:8080/maintenance/"; + + let backoffInterval; + Svc.Obs.add("weave:service:backoff:interval", function observe(subject, data) { + Svc.Obs.remove("weave:service:backoff:interval", observe); + backoffInterval = subject; + }); + + Svc.Obs.add("weave:ui:login:error", function onUIUpdate() { + Svc.Obs.remove("weave:ui:login:error", onUIUpdate); + do_check_true(Status.enforceBackoff); + do_check_eq(backoffInterval, 42); + do_check_eq(Status.service, LOGIN_FAILED); + do_check_eq(Status.login, SERVER_MAINTENANCE); + + clean(); + server.stop(run_next_test); + }); + + do_check_false(Status.enforceBackoff); + do_check_eq(Status.service, STATUS_OK); + + setLastSync(PROLONGED_ERROR_DURATION); + ErrorHandler.syncAndReportErrors(); +}); + add_test(function test_sync_engine_generic_fail() { let server = sync_httpd_setup();