mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-26 14:22:01 +00:00
Bug 528278 - Remove remote commands and wait for user on wipeRemote/changePassphrase
Store the reason for starting fresh (new syncId) in meta/global and fail remoteSetup on certain reasons to let the UI show a notification to the user for a response (pick merge or change passphrase). Code paths (sync, prep, etc.) related to remote commands are removed.
This commit is contained in:
parent
9c4d31f028
commit
3be71460fc
@ -15,12 +15,13 @@ status.privateBrowsing = Disabled (Private Browsing)
|
||||
|
||||
error.login.title = Error While Signing In
|
||||
error.login.description = Weave encountered an error while signing you in: %1$S. Please try again.
|
||||
# should decide if we're going to show this
|
||||
error.logout.title = Error While Signing Out
|
||||
error.logout.description = Weave encountered an error while signing you out. It's probably ok, and you don't have to do anything about it.
|
||||
error.sync.title = Error While Syncing
|
||||
error.sync.description = Weave encountered an error while syncing: %1$S. Weave will automatically retry this action.
|
||||
error.sync.no_node_found = The Weave server is a little busy right now, but you don't need to do anything about it. We'll start syncing your data as soon as we can!
|
||||
error.sync.wipe_remote = You requested to replace the data here with your other client. Please choose how you want to merge your data for this client.
|
||||
error.sync.wipe_remote.label = Choose Merge
|
||||
error.sync.wipe_remote.accesskey = C
|
||||
error.sync.reset_passphrase = You changed the passphrase on another client, so please re-connect with the new passphrase.
|
||||
error.sync.no_node_found.title = Sync Delay
|
||||
error.sync.tryAgainButton.label = Sync Now
|
||||
error.sync.tryAgainButton.accesskey = S
|
||||
|
@ -106,7 +106,6 @@ KEYS_DOWNLOAD_FAIL: "error.sync.reason.keys_download_fail",
|
||||
NO_KEYS_NO_KEYGEN: "error.sync.reason.no_keys_no_keygen",
|
||||
KEYS_UPLOAD_FAIL: "error.sync.reason.keys_upload_fail",
|
||||
SETUP_FAILED_NO_PASSPHRASE: "error.sync.reason.setup_failed_no_passphrase",
|
||||
ABORT_SYNC_COMMAND: "aborting sync, process commands said so",
|
||||
NO_SYNC_NODE_FOUND: "error.sync.reason.no_node_found",
|
||||
|
||||
// engine failure status codes
|
||||
@ -115,6 +114,10 @@ ENGINE_DOWNLOAD_FAIL: "error.engine.reason.record_download_fail
|
||||
ENGINE_UNKNOWN_FAIL: "error.engine.reason.unknown_fail",
|
||||
ENGINE_METARECORD_UPLOAD_FAIL: "error.engine.reason.metarecord_upload_fail",
|
||||
|
||||
// reasons for changing the sync ID
|
||||
SYNCID_WIPE_REMOTE: "error.sync.wipe_remote",
|
||||
SYNCID_RESET_PASSPHRASE: "error.sync.reset_passphrase",
|
||||
|
||||
// Ways that a sync can be disabled (messages only to be printed in debug log)
|
||||
kSyncWeaveDisabled: "Weave is disabled",
|
||||
kSyncNotLoggedIn: "User is not logged in",
|
||||
|
@ -443,7 +443,7 @@ WeaveSvc.prototype = {
|
||||
this.syncOnIdle();
|
||||
}
|
||||
else if (!this._syncTimer) // start the clock if it isn't already
|
||||
this._scheduleNextSync();
|
||||
this._checkSyncStatus();
|
||||
},
|
||||
|
||||
// These are global (for all engines)
|
||||
@ -616,26 +616,13 @@ WeaveSvc.prototype = {
|
||||
|
||||
resetPassphrase: function WeaveSvc_resetPassphrase(newphrase)
|
||||
this._catch(this._notify("resetpph", "", function() {
|
||||
/* Make remote commands ready so we have a list of clients beforehand */
|
||||
this.prepCommand("logout", []);
|
||||
let clientsBackup = Clients._store.clients;
|
||||
|
||||
/* Wipe */
|
||||
this.wipeServer();
|
||||
PubKeys.clearCache();
|
||||
PrivKeys.clearCache();
|
||||
|
||||
/* Set remote commands before syncing */
|
||||
Clients._store.clients = clientsBackup;
|
||||
let username = this.username;
|
||||
let password = this.password;
|
||||
this.logout();
|
||||
|
||||
/* Set this so UI is updated on next run */
|
||||
// Save the new passphrase
|
||||
this.passphrase = newphrase;
|
||||
this.persistLogin();
|
||||
|
||||
/* Login in sync: this also generates new keys */
|
||||
this.login(username, password, newphrase);
|
||||
// Start over by wiping the server and reuploading
|
||||
this.login();
|
||||
this._freshStart(SYNCID_RESET_PASSPHRASE);
|
||||
this.sync(true);
|
||||
return true;
|
||||
}))(),
|
||||
@ -806,8 +793,6 @@ WeaveSvc.prototype = {
|
||||
// stuff we need to to after login, before we can really do
|
||||
// anything (e.g. key setup)
|
||||
_remoteSetup: function WeaveSvc__remoteSetup() {
|
||||
let reset = false;
|
||||
|
||||
this._log.debug("Fetching global metadata record");
|
||||
let meta = Records.import(this.metaURL);
|
||||
|
||||
@ -843,7 +828,6 @@ WeaveSvc.prototype = {
|
||||
Status.sync = DESKTOP_VERSION_OUT_OF_DATE;
|
||||
return false;
|
||||
}
|
||||
reset = true;
|
||||
this._log.info("Wiping server data");
|
||||
this._freshStart();
|
||||
|
||||
@ -861,13 +845,19 @@ WeaveSvc.prototype = {
|
||||
return false;
|
||||
|
||||
} else if (meta.payload.syncID != Clients.syncID) {
|
||||
this._log.warn("Meta.payload.syncID is " + meta.payload.syncID +
|
||||
", Clients.syncID is " + Clients.syncID);
|
||||
let reason = meta.payload.reason;
|
||||
this.resetClient();
|
||||
this._log.info("Reset client because of syncID mismatch.");
|
||||
this._log.debug("Reset client on syncID mismatch: " + reason);
|
||||
Clients.syncID = meta.payload.syncID;
|
||||
this._log.info("Reset the client after a server/client sync ID mismatch");
|
||||
this._updateRemoteVersion(meta);
|
||||
|
||||
// For some syncID changes, we might want to wait for the user
|
||||
switch (reason) {
|
||||
case SYNCID_WIPE_REMOTE:
|
||||
case SYNCID_RESET_PASSPHRASE:
|
||||
Status.sync = reason;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// We didn't wipe the server and we're not out of date, so update remote
|
||||
else
|
||||
@ -908,12 +898,6 @@ WeaveSvc.prototype = {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!reset) {
|
||||
this._log.warn("Calling freshStart from !reset case.");
|
||||
this._freshStart();
|
||||
this._log.info("Server data wiped to ensure consistency due to missing keys");
|
||||
}
|
||||
|
||||
let passphrase = ID.get("WeaveCryptoID");
|
||||
if (passphrase.password) {
|
||||
let keys = PubKeys.createKeypair(passphrase, PubKeys.defaultKeyUri,
|
||||
@ -1109,24 +1093,6 @@ WeaveSvc.prototype = {
|
||||
this._log.trace("Refreshing client list");
|
||||
Clients.sync();
|
||||
|
||||
// Process the incoming commands if we have any
|
||||
if (Clients.getClients()[Clients.clientID].commands) {
|
||||
try {
|
||||
if (!(this.processCommands())) {
|
||||
Status.sync = ABORT_SYNC_COMMAND;
|
||||
throw "aborting sync, process commands said so";
|
||||
}
|
||||
|
||||
// Repeat remoteSetup in-case the commands forced us to reset
|
||||
if (!(this._remoteSetup()))
|
||||
throw "aborting sync, remote setup failed after processing commands";
|
||||
}
|
||||
finally {
|
||||
// Always immediately push back the local client (now without commands)
|
||||
Clients.sync();
|
||||
}
|
||||
}
|
||||
|
||||
// Update the client mode now because it might change what we sync
|
||||
this._updateClientMode();
|
||||
|
||||
@ -1217,18 +1183,17 @@ WeaveSvc.prototype = {
|
||||
}
|
||||
},
|
||||
|
||||
_freshStart: function WeaveSvc__freshStart() {
|
||||
_freshStart: function WeaveSvc__freshStart(reason) {
|
||||
this.resetClient();
|
||||
this._log.info("Reset client data from freshStart.");
|
||||
this._log.info("Client metadata wiped, deleting server data");
|
||||
this._log.info("Resetting client and wiping server: " + reason);
|
||||
this.wipeServer();
|
||||
|
||||
// XXX Bug 504125 Wait a while after wiping so that the DELETEs replicate
|
||||
Sync.sleep(2000);
|
||||
|
||||
this._log.debug("Uploading new metadata record");
|
||||
let meta = new WBORecord(this.metaURL);
|
||||
meta.payload.syncID = Clients.syncID;
|
||||
meta.payload.reason = reason;
|
||||
this._updateRemoteVersion(meta);
|
||||
},
|
||||
|
||||
@ -1331,16 +1296,7 @@ WeaveSvc.prototype = {
|
||||
wipeRemote: function WeaveSvc_wipeRemote(engines)
|
||||
this._catch(this._notify("wipe-remote", "", function() {
|
||||
// Clear out any server data
|
||||
//this.wipeServer(engines);
|
||||
|
||||
// Only wipe the engines provided
|
||||
if (engines) {
|
||||
engines.forEach(function(e) this.prepCommand("wipeEngine", [e]), this);
|
||||
return;
|
||||
}
|
||||
|
||||
// Tell the remote machines to wipe themselves
|
||||
this.prepCommand("wipeAll", []);
|
||||
this._freshStart(SYNCID_WIPE_REMOTE);
|
||||
}))(),
|
||||
|
||||
/**
|
||||
@ -1394,126 +1350,4 @@ WeaveSvc.prototype = {
|
||||
this._log.debug("Could not remove old snapshots: " + Utils.exceptionStr(e));
|
||||
}
|
||||
}))(),
|
||||
|
||||
/**
|
||||
* A hash of valid commands that the client knows about. The key is a command
|
||||
* and the value is a hash containing information about the command such as
|
||||
* number of arguments and description.
|
||||
*/
|
||||
_commands: [
|
||||
["resetAll", 0, "Clear temporary local data for all engines"],
|
||||
["resetEngine", 1, "Clear temporary local data for engine"],
|
||||
["wipeAll", 0, "Delete all client data for all engines"],
|
||||
["wipeEngine", 1, "Delete all client data for engine"],
|
||||
["logout", 0, "Log out client"],
|
||||
].reduce(function WeaveSvc__commands(commands, entry) {
|
||||
commands[entry[0]] = {};
|
||||
for (let [i, attr] in Iterator(["args", "desc"]))
|
||||
commands[entry[0]][attr] = entry[i + 1];
|
||||
return commands;
|
||||
}, {}),
|
||||
|
||||
/**
|
||||
* Check if the local client has any remote commands and perform them.
|
||||
*
|
||||
* @return False to abort sync
|
||||
*/
|
||||
processCommands: function WeaveSvc_processCommands()
|
||||
this._notify("process-commands", "", function() {
|
||||
let info = Clients.getInfo(Clients.clientID);
|
||||
let commands = info.commands;
|
||||
|
||||
// Immediately clear out the commands as we've got them locally
|
||||
delete info.commands;
|
||||
Clients.setInfo(Clients.clientID, info);
|
||||
|
||||
// Process each command in order
|
||||
for each ({command: command, args: args} in commands) {
|
||||
this._log.debug("Processing command: " + command + "(" + args + ")");
|
||||
|
||||
let engines = [args[0]];
|
||||
switch (command) {
|
||||
case "resetAll":
|
||||
engines = null;
|
||||
// Fallthrough
|
||||
case "resetEngine":
|
||||
this.resetClient(engines);
|
||||
break;
|
||||
case "wipeAll":
|
||||
engines = null;
|
||||
// Fallthrough
|
||||
case "wipeEngine":
|
||||
this.wipeClient(engines);
|
||||
break;
|
||||
case "logout":
|
||||
this.logout();
|
||||
return false;
|
||||
default:
|
||||
this._log.debug("Received an unknown command: " + command);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
})(),
|
||||
|
||||
/**
|
||||
* Prepare to send a command to each remote client. Calling this doesn't
|
||||
* actually sync the command data to the server. If the client already has
|
||||
* the command/args pair, it won't get a duplicate action.
|
||||
*
|
||||
* @param command
|
||||
* Command to invoke on remote clients
|
||||
* @param args
|
||||
* Array of arguments to give to the command
|
||||
*/
|
||||
prepCommand: function WeaveSvc_prepCommand(command, args) {
|
||||
let commandData = this._commands[command];
|
||||
// Don't send commands that we don't know about
|
||||
if (commandData == null) {
|
||||
this._log.error("Unknown command to send: " + command);
|
||||
return;
|
||||
}
|
||||
// Don't send a command with the wrong number of arguments
|
||||
else if (args == null || args.length != commandData.args) {
|
||||
this._log.error("Expected " + commandData.args + " args for '" +
|
||||
command + "', but got " + args);
|
||||
return;
|
||||
}
|
||||
|
||||
// Package the command/args pair into an object
|
||||
let action = {
|
||||
command: command,
|
||||
args: args,
|
||||
};
|
||||
let actionStr = command + "(" + args + ")";
|
||||
|
||||
// Convert args into a string to simplify array comparisons
|
||||
let jsonArgs = JSON.stringify(args);
|
||||
let notDupe = function(action) action.command != command ||
|
||||
JSON.stringify(action.args) != jsonArgs;
|
||||
|
||||
this._log.info("Sending clients: " + actionStr + "; " + commandData.desc);
|
||||
|
||||
// Add the action to each remote client
|
||||
for (let guid in Clients.getClients()) {
|
||||
// Don't send commands to the local client
|
||||
if (guid == Clients.clientID)
|
||||
continue;
|
||||
|
||||
let info = Clients.getInfo(guid);
|
||||
// Set the action to be a new commands array if none exists
|
||||
if (info.commands == null)
|
||||
info.commands = [action];
|
||||
// Add the new action if there are no duplicates
|
||||
else if (info.commands.every(notDupe))
|
||||
info.commands.push(action);
|
||||
// Must have been a dupe.. skip!
|
||||
else
|
||||
continue;
|
||||
|
||||
Clients.setInfo(guid, info);
|
||||
this._log.trace("Client " + guid + " got a new action: " + actionStr);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user