diff --git a/services/sync/modules/policies.js b/services/sync/modules/policies.js index b972c6db42a4..3a84ea00626e 100644 --- a/services/sync/modules/policies.js +++ b/services/sync/modules/policies.js @@ -177,6 +177,7 @@ SyncScheduler.prototype = { if (Status.checkSetup() == STATUS_OK) { Svc.Obs.add("wake_notification", this); Svc.Obs.add("captive-portal-login-success", this); + Svc.Obs.add("sleep_notification", this); IdleService.addIdleObserver(this, Svc.Prefs.get("scheduler.idleTime")); } }, @@ -328,6 +329,7 @@ SyncScheduler.prototype = { IdleService.addIdleObserver(this, Svc.Prefs.get("scheduler.idleTime")); Svc.Obs.add("wake_notification", this); Svc.Obs.add("captive-portal-login-success", this); + Svc.Obs.add("sleep_notification", this); break; case "weave:service:start-over": this.setDefaults(); @@ -389,6 +391,9 @@ SyncScheduler.prototype = { CommonUtils.nextTick(() => { this.scheduleNextSync(3000); }); + case "sleep_notification": + this._log.debug("Going to sleep, doing a quick sync."); + this.scheduleNextSync(0, ["tabs"], "sleep"); break; } }, @@ -490,7 +495,7 @@ SyncScheduler.prototype = { * * Otherwise, reschedule a sync for later. */ - syncIfMPUnlocked: function syncIfMPUnlocked() { + syncIfMPUnlocked(engines, why) { // No point if we got kicked out by the master password dialog. if (Status.login == MASTER_PASSWORD_LOCKED && Utils.mpLocked()) { @@ -506,13 +511,15 @@ SyncScheduler.prototype = { this._log.debug("Not initiating sync: app is shutting down"); return; } - CommonUtils.nextTick(this.service.sync, this.service); + Services.tm.dispatchToMainThread(() => { + this.service.sync({engines, why}); + }); }, /** * Set a timer for the next sync */ - scheduleNextSync: function scheduleNextSync(interval) { + scheduleNextSync(interval, engines = null, why = null) { // If no interval was specified, use the current sync interval. if (interval == null) { interval = this.syncInterval; @@ -543,12 +550,13 @@ SyncScheduler.prototype = { // Start the sync right away if we're already late. if (interval <= 0) { this._log.trace("Requested sync should happen right away."); - this.syncIfMPUnlocked(); + this.syncIfMPUnlocked(engines, why); return; } this._log.debug("Next sync in " + interval + " ms."); - CommonUtils.namedTimer(this.syncIfMPUnlocked, interval, this, "syncTimer"); + CommonUtils.namedTimer(() => { this.syncIfMPUnlocked(engines, why); }, + interval, this, "syncTimer"); // Save the next sync time in-case sync is disabled (logout/offline/etc.) this.nextSync = Date.now() + interval; diff --git a/services/sync/modules/service.js b/services/sync/modules/service.js index f1d03a385ac2..a40a43017327 100644 --- a/services/sync/modules/service.js +++ b/services/sync/modules/service.js @@ -908,8 +908,8 @@ Sync11Service.prototype = { // Stuff we need to do after login, before we can really do // anything (e.g. key setup). - async _remoteSetup(infoResponse) { - if (!(await this._fetchServerConfiguration())) { + async _remoteSetup(infoResponse, fetchConfig = true) { + if (fetchConfig && !(await this._fetchServerConfiguration())) { return false; } @@ -1112,7 +1112,7 @@ Sync11Service.prototype = { histogram.add(1); let synchronizer = new EngineSynchronizer(this); - await synchronizer.sync(engineNamesToSync); // Might throw! + await synchronizer.sync(engineNamesToSync, why); // Might throw! histogram = Services.telemetry.getHistogramById("WEAVE_COMPLETE_SUCCESS_COUNT"); histogram.add(1); diff --git a/services/sync/modules/stages/enginesync.js b/services/sync/modules/stages/enginesync.js index 3ae7ee9e943a..36fe76ee3939 100644 --- a/services/sync/modules/stages/enginesync.js +++ b/services/sync/modules/stages/enginesync.js @@ -31,7 +31,8 @@ this.EngineSynchronizer = function EngineSynchronizer(service) { }; EngineSynchronizer.prototype = { - async sync(engineNamesToSync) { + async sync(engineNamesToSync, why) { + let fastSync = why && why == "sleep"; let startTime = Date.now(); this.service.status.resetSync(); @@ -75,17 +76,19 @@ EngineSynchronizer.prototype = { engine.lastModified = info.obj[engine.name] || 0; } - if (!(await this.service._remoteSetup(info))) { + if (!(await this.service._remoteSetup(info, !fastSync))) { throw new Error("Aborting sync, remote setup failed"); } - // Make sure we have an up-to-date list of clients before sending commands - this._log.debug("Refreshing client list."); - if (!(await this._syncEngine(this.service.clientsEngine))) { - // Clients is an engine like any other; it can fail with a 401, - // and we can elect to abort the sync. - this._log.warn("Client engine sync failed. Aborting."); - return; + if (!fastSync) { + // Make sure we have an up-to-date list of clients before sending commands + this._log.debug("Refreshing client list."); + if (!(await this._syncEngine(this.service.clientsEngine))) { + // Clients is an engine like any other; it can fail with a 401, + // and we can elect to abort the sync. + this._log.warn("Client engine sync failed. Aborting."); + return; + } } // We only honor the "hint" of what engines to Sync if this isn't @@ -107,7 +110,7 @@ EngineSynchronizer.prototype = { break; } - if (this.service.clientsEngine.localCommands) { + if (!fastSync && this.service.clientsEngine.localCommands) { try { if (!(await this.service.clientsEngine.processIncomingCommands())) { this.service.status.sync = ABORT_SYNC_COMMAND; @@ -179,7 +182,9 @@ EngineSynchronizer.prototype = { } } - await Doctor.consult(enginesToValidate); + if (!fastSync) { + await Doctor.consult(enginesToValidate); + } // If there were no sync engine failures if (this.service.status.service != SYNC_FAILED_PARTIAL) {