зеркало из https://github.com/mozilla/gecko-dev.git
Bug 709311 - Handle changed meta/global. r=rnewman, a=blocking-fennec
This commit is contained in:
Родитель
9a9d84392f
Коммит
e1a6551162
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
|
@ -14,6 +14,7 @@ import java.util.HashMap;
|
|||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
|
@ -49,6 +50,7 @@ import org.mozilla.gecko.sync.stage.GlobalSyncStage.Stage;
|
|||
import org.mozilla.gecko.sync.stage.NoSuchStageException;
|
||||
import org.mozilla.gecko.sync.stage.PasswordsServerSyncStage;
|
||||
import org.mozilla.gecko.sync.stage.SyncClientsEngineStage;
|
||||
import org.mozilla.gecko.sync.stage.UploadMetaGlobalStage;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
|
@ -70,6 +72,11 @@ public class GlobalSession implements CredentialsSource, PrefsSource, HttpRespon
|
|||
private Context context;
|
||||
private ClientsDataDelegate clientsDelegate;
|
||||
|
||||
/**
|
||||
* Map from engine name to new settings for an updated meta/global record.
|
||||
*/
|
||||
public final Map<String, EngineSettings> enginesToUpdate = new HashMap<String, EngineSettings>();
|
||||
|
||||
/*
|
||||
* Key accessors.
|
||||
*/
|
||||
|
@ -218,6 +225,7 @@ public class GlobalSession implements CredentialsSource, PrefsSource, HttpRespon
|
|||
stages.put(Stage.syncHistory, new AndroidBrowserHistoryServerSyncStage(this));
|
||||
stages.put(Stage.syncFormHistory, new FormHistoryServerSyncStage(this));
|
||||
|
||||
stages.put(Stage.uploadMetaGlobal, new UploadMetaGlobalStage(this));
|
||||
stages.put(Stage.completed, new CompletedStage(this));
|
||||
|
||||
this.stages = Collections.unmodifiableMap(stages);
|
||||
|
@ -355,6 +363,102 @@ public class GlobalSession implements CredentialsSource, PrefsSource, HttpRespon
|
|||
this.callback.handleSuccess(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Record that an updated meta/global record should be uploaded with the given
|
||||
* settings for the given engine.
|
||||
*
|
||||
* @param engineName engine to update.
|
||||
* @param engineSettings new syncID and version.
|
||||
*/
|
||||
public void updateMetaGlobalWith(String engineName, EngineSettings engineSettings) {
|
||||
enginesToUpdate.put(engineName, engineSettings);
|
||||
}
|
||||
|
||||
public boolean hasUpdatedMetaGlobal() {
|
||||
if (enginesToUpdate.isEmpty()) {
|
||||
Logger.info(LOG_TAG, "Not uploading updated meta/global record since there are no engines requesting upload.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Logger.logVerbose(LOG_TAG)) {
|
||||
Logger.trace(LOG_TAG, "Uploading updated meta/global record since there are engines requesting upload: " +
|
||||
Utils.toCommaSeparatedString(enginesToUpdate.keySet()));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void updateMetaGlobalInPlace() {
|
||||
ExtendedJSONObject engines = config.metaGlobal.getEngines();
|
||||
for (Entry<String, EngineSettings> pair : enginesToUpdate.entrySet()) {
|
||||
engines.put(pair.getKey(), pair.getValue().toJSONObject());
|
||||
}
|
||||
enginesToUpdate.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronously upload an updated meta/global.
|
||||
* <p>
|
||||
* All problems are logged and ignored.
|
||||
*/
|
||||
public void uploadUpdatedMetaGlobal() {
|
||||
updateMetaGlobalInPlace();
|
||||
|
||||
Logger.debug(LOG_TAG, "Uploading updated meta/global record.");
|
||||
final Object monitor = new Object();
|
||||
|
||||
Runnable doUpload = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
config.metaGlobal.upload(new MetaGlobalDelegate() {
|
||||
@Override
|
||||
public void handleSuccess(MetaGlobal global, SyncStorageResponse response) {
|
||||
Logger.info(LOG_TAG, "Successfully uploaded updated meta/global record.");
|
||||
synchronized (monitor) {
|
||||
monitor.notify();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMissing(MetaGlobal global, SyncStorageResponse response) {
|
||||
Logger.warn(LOG_TAG, "Got 404 missing uploading updated meta/global record; shouldn't happen. Ignoring.");
|
||||
synchronized (monitor) {
|
||||
monitor.notify();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleFailure(SyncStorageResponse response) {
|
||||
Logger.warn(LOG_TAG, "Failed to upload updated meta/global record; ignoring.");
|
||||
synchronized (monitor) {
|
||||
monitor.notify();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleError(Exception e) {
|
||||
Logger.warn(LOG_TAG, "Got exception trying to upload updated meta/global record; ignoring.", e);
|
||||
synchronized (monitor) {
|
||||
monitor.notify();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
final Thread upload = new Thread(doUpload);
|
||||
synchronized (monitor) {
|
||||
try {
|
||||
upload.start();
|
||||
monitor.wait();
|
||||
Logger.debug(LOG_TAG, "Uploaded updated meta/global record.");
|
||||
} catch (InterruptedException e) {
|
||||
Logger.error(LOG_TAG, "Uploading updated meta/global interrupted; continuing.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void abort(Exception e, String reason) {
|
||||
Logger.warn(LOG_TAG, "Aborting sync: " + reason, e);
|
||||
uninstallAsHttpResponseObserver();
|
||||
|
@ -362,6 +466,12 @@ public class GlobalSession implements CredentialsSource, PrefsSource, HttpRespon
|
|||
if (existingBackoff > 0) {
|
||||
callback.requestBackoff(existingBackoff);
|
||||
}
|
||||
if (!(e instanceof HTTPFailureException)) {
|
||||
// e is null, or we aborted for a non-HTTP reason; okay to upload new meta/global record.
|
||||
if (this.hasUpdatedMetaGlobal()) {
|
||||
this.uploadUpdatedMetaGlobal(); // Only logs errors; does not call abort.
|
||||
}
|
||||
}
|
||||
this.callback.handleError(this, e);
|
||||
}
|
||||
|
||||
|
|
|
@ -94,8 +94,8 @@ public class MetaGlobal implements SyncStorageRequestDelegate {
|
|||
public void setFromRecord(CryptoRecord record) throws IllegalStateException, IOException, ParseException, NonObjectJSONException {
|
||||
Logger.info(LOG_TAG, "meta/global is " + record.payload.toJSONString());
|
||||
this.storageVersion = (Long) record.payload.get("storageVersion");
|
||||
this.engines = record.payload.getObject("engines");
|
||||
this.syncID = (String) record.payload.get("syncID");
|
||||
setEngines(record.payload.getObject("engines"));
|
||||
}
|
||||
|
||||
public Long getStorageVersion() {
|
||||
|
@ -111,6 +111,9 @@ public class MetaGlobal implements SyncStorageRequestDelegate {
|
|||
}
|
||||
|
||||
public void setEngines(ExtendedJSONObject engines) {
|
||||
if (engines == null) {
|
||||
engines = new ExtendedJSONObject();
|
||||
}
|
||||
this.engines = engines;
|
||||
final int count = engines.size();
|
||||
versions = new HashMap<String, Integer>(count);
|
||||
|
@ -122,6 +125,7 @@ public class MetaGlobal implements SyncStorageRequestDelegate {
|
|||
recordEngineState(engineName, engineEntry);
|
||||
} catch (NonObjectJSONException e) {
|
||||
Logger.error(LOG_TAG, "Engine field for " + engineName + " in meta/global is not an object.");
|
||||
recordEngineState(engineName, new ExtendedJSONObject()); // Doesn't have a version or syncID, for example, so will be server wiped.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -137,6 +141,22 @@ public class MetaGlobal implements SyncStorageRequestDelegate {
|
|||
if (engineEntry == null) {
|
||||
throw new IllegalArgumentException("engineEntry cannot be null.");
|
||||
}
|
||||
|
||||
// Record syncID first, so that engines with bad versions are recorded.
|
||||
try {
|
||||
String syncID = engineEntry.getString("syncID");
|
||||
if (syncID == null) {
|
||||
Logger.warn(LOG_TAG, "No syncID for " + engineName + ". Recording exception.");
|
||||
exceptions.put(engineName, new MetaGlobalMalformedSyncIDException());
|
||||
}
|
||||
syncIDs.put(engineName, syncID);
|
||||
} catch (ClassCastException e) {
|
||||
// Malformed syncID on the server. Wipe the server.
|
||||
Logger.warn(LOG_TAG, "Malformed syncID " + engineEntry.get("syncID") +
|
||||
" for " + engineName + ". Recording exception.");
|
||||
exceptions.put(engineName, new MetaGlobalMalformedSyncIDException());
|
||||
}
|
||||
|
||||
try {
|
||||
Integer version = engineEntry.getIntegerSafely("version");
|
||||
Logger.trace(LOG_TAG, "Engine " + engineName + " has server version " + version);
|
||||
|
@ -156,20 +176,6 @@ public class MetaGlobal implements SyncStorageRequestDelegate {
|
|||
exceptions.put(engineName, new MetaGlobalMalformedVersionException());
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
String syncID = engineEntry.getString("syncID");
|
||||
if (syncID == null) {
|
||||
Logger.warn(LOG_TAG, "No syncID for " + engineName + ". Recording exception.");
|
||||
exceptions.put(engineName, new MetaGlobalMalformedSyncIDException());
|
||||
}
|
||||
syncIDs.put(engineName, syncID);
|
||||
} catch (ClassCastException e) {
|
||||
// Malformed syncID on the server. Wipe the server.
|
||||
Logger.warn(LOG_TAG, "Malformed syncID " + engineEntry.get("syncID") +
|
||||
" for " + engineName + ". Recording exception.");
|
||||
exceptions.put(engineName, new MetaGlobalException.MetaGlobalMalformedSyncIDException());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -201,18 +207,21 @@ public class MetaGlobal implements SyncStorageRequestDelegate {
|
|||
throw new IllegalArgumentException("engineSettings cannot be null.");
|
||||
}
|
||||
|
||||
final String syncID = syncIDs.get(engineName);
|
||||
if (syncID == null) {
|
||||
throw new IllegalArgumentException("Unknown engine " + engineName);
|
||||
}
|
||||
|
||||
// First, see if we had a parsing problem.
|
||||
final MetaGlobalException exception = exceptions.get(engineName);
|
||||
if (exception != null) {
|
||||
throw exception;
|
||||
}
|
||||
|
||||
final Integer version = versions.get(engineName);
|
||||
final String syncID = syncIDs.get(engineName);
|
||||
if (syncID == null) {
|
||||
// We have checked engineName against enabled engine names before this, so
|
||||
// we should either have a syncID or an exception for this engine already.
|
||||
throw new IllegalArgumentException("Unknown engine " + engineName);
|
||||
}
|
||||
|
||||
// Since we don't have an exception, and we do have a syncID, we should have a version.
|
||||
final Integer version = versions.get(engineName);
|
||||
if (version > engineSettings.version) {
|
||||
// We're out of date.
|
||||
throw new MetaGlobalException.MetaGlobalStaleClientVersionException(version);
|
||||
|
|
|
@ -44,7 +44,6 @@ import org.mozilla.gecko.sync.SyncConfiguration.ConfigurationBranch;
|
|||
import org.mozilla.gecko.sync.repositories.RepositorySessionBundle;
|
||||
|
||||
import android.content.SharedPreferences.Editor;
|
||||
import android.util.Log;
|
||||
|
||||
public class SynchronizerConfiguration {
|
||||
private static final String LOG_TAG = "SynczrConfiguration";
|
||||
|
@ -63,14 +62,6 @@ public class SynchronizerConfiguration {
|
|||
this.localBundle = localBundle;
|
||||
}
|
||||
|
||||
public String[] toStringValues() {
|
||||
String[] out = new String[3];
|
||||
out[0] = syncID;
|
||||
out[1] = remoteBundle.toJSONString();
|
||||
out[2] = localBundle.toJSONString();
|
||||
return out;
|
||||
}
|
||||
|
||||
// This should get partly shuffled back into SyncConfiguration, I think.
|
||||
public void load(ConfigurationBranch config) throws NonObjectJSONException, IOException, ParseException {
|
||||
if (config == null) {
|
||||
|
@ -89,7 +80,7 @@ public class SynchronizerConfiguration {
|
|||
syncID = config.getString("syncID", null);
|
||||
remoteBundle = rB;
|
||||
localBundle = lB;
|
||||
Log.i(LOG_TAG, "Initialized SynchronizerConfiguration. syncID: " + syncID + ", remoteBundle: " + remoteBundle + ", localBundle: " + localBundle);
|
||||
Logger.debug(LOG_TAG, "Loaded SynchronizerConfiguration. syncID: " + syncID + ", remoteBundle: " + remoteBundle + ", localBundle: " + localBundle);
|
||||
}
|
||||
|
||||
public void persist(ConfigurationBranch config) {
|
||||
|
@ -105,5 +96,6 @@ public class SynchronizerConfiguration {
|
|||
|
||||
// Synchronous.
|
||||
editor.commit();
|
||||
Logger.debug(LOG_TAG, "Persisted SynchronizerConfiguration. syncID: " + syncID + ", remoteBundle: " + remoteBundle + ", localBundle: " + localBundle);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@ public interface GlobalSyncStage {
|
|||
syncBookmarks("bookmarks"),
|
||||
syncHistory("history"),
|
||||
syncFormHistory("forms"),
|
||||
|
||||
uploadMetaGlobal,
|
||||
completed;
|
||||
|
||||
// Maintain a mapping from names ("bookmarks") to Stage enumerations (syncBookmarks).
|
||||
|
|
|
@ -9,6 +9,8 @@ import java.net.URISyntaxException;
|
|||
import java.util.concurrent.ExecutorService;
|
||||
|
||||
import org.json.simple.parser.ParseException;
|
||||
import org.mozilla.gecko.sync.CredentialsSource;
|
||||
import org.mozilla.gecko.sync.EngineSettings;
|
||||
import org.mozilla.gecko.sync.GlobalSession;
|
||||
import org.mozilla.gecko.sync.HTTPFailureException;
|
||||
import org.mozilla.gecko.sync.Logger;
|
||||
|
@ -16,8 +18,14 @@ import org.mozilla.gecko.sync.MetaGlobalException;
|
|||
import org.mozilla.gecko.sync.NoCollectionKeysSetException;
|
||||
import org.mozilla.gecko.sync.NonObjectJSONException;
|
||||
import org.mozilla.gecko.sync.SynchronizerConfiguration;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.sync.crypto.KeyBundle;
|
||||
import org.mozilla.gecko.sync.delegates.WipeServerDelegate;
|
||||
import org.mozilla.gecko.sync.middleware.Crypto5MiddlewareRepository;
|
||||
import org.mozilla.gecko.sync.net.BaseResource;
|
||||
import org.mozilla.gecko.sync.net.SyncStorageRequest;
|
||||
import org.mozilla.gecko.sync.net.SyncStorageRequestDelegate;
|
||||
import org.mozilla.gecko.sync.net.SyncStorageResponse;
|
||||
import org.mozilla.gecko.sync.repositories.InactiveSessionException;
|
||||
import org.mozilla.gecko.sync.repositories.InvalidSessionTransitionException;
|
||||
import org.mozilla.gecko.sync.repositories.RecordFactory;
|
||||
|
@ -63,9 +71,30 @@ public abstract class ServerSyncStage implements
|
|||
* @throws MetaGlobalException
|
||||
*/
|
||||
protected boolean isEnabled() throws MetaGlobalException {
|
||||
// TODO: pass EngineSettings here to check syncID and storage version.
|
||||
// Catch the subclasses of MetaGlobalException to trigger various resets and wipes.
|
||||
return session.engineIsEnabled(this.getEngineName(), null);
|
||||
EngineSettings engineSettings = null;
|
||||
try {
|
||||
engineSettings = getEngineSettings();
|
||||
} catch (Exception e) {
|
||||
Logger.warn(LOG_TAG, "Unable to get engine settings for " + this + ": fetching config failed.", e);
|
||||
// Fall through; null engineSettings will pass below.
|
||||
}
|
||||
|
||||
// We catch the subclasses of MetaGlobalException to trigger various resets and wipes in execute().
|
||||
return session.engineIsEnabled(this.getEngineName(), engineSettings);
|
||||
}
|
||||
|
||||
protected EngineSettings getEngineSettings() throws NonObjectJSONException, IOException, ParseException {
|
||||
Integer version = getStorageVersion();
|
||||
if (version == null) {
|
||||
Logger.warn(LOG_TAG, "null storage version for " + this + "; using version 0.");
|
||||
version = new Integer(0);
|
||||
}
|
||||
|
||||
SynchronizerConfiguration config = this.getConfig();
|
||||
if (config == null) {
|
||||
return new EngineSettings(null, version.intValue());
|
||||
}
|
||||
return new EngineSettings(config.syncID, version.intValue());
|
||||
}
|
||||
|
||||
protected abstract String getCollection();
|
||||
|
@ -113,17 +142,24 @@ public abstract class ServerSyncStage implements
|
|||
Synchronizer synchronizer = new Synchronizer();
|
||||
synchronizer.repositoryA = remote;
|
||||
synchronizer.repositoryB = this.getLocalRepository();
|
||||
synchronizer.load(getConfig());
|
||||
|
||||
SynchronizerConfiguration config = this.getConfig();
|
||||
synchronizer.load(config);
|
||||
|
||||
// TODO: should wipe in either direction?
|
||||
// TODO: syncID?!
|
||||
return synchronizer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset timestamps.
|
||||
*/
|
||||
@Override
|
||||
public void resetLocal() {
|
||||
resetLocal(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset timestamps and possibly set syncID.
|
||||
* @param syncID if non-null, new syncID to persist.
|
||||
*/
|
||||
public void resetLocal(String syncID) {
|
||||
// Clear both timestamps.
|
||||
SynchronizerConfiguration config;
|
||||
try {
|
||||
|
@ -133,10 +169,14 @@ public abstract class ServerSyncStage implements
|
|||
return;
|
||||
}
|
||||
|
||||
if (syncID != null) {
|
||||
config.syncID = syncID;
|
||||
Logger.info(LOG_TAG, "Setting syncID for " + this + " to '" + syncID + "'.");
|
||||
}
|
||||
config.localBundle.setTimestamp(0L);
|
||||
config.remoteBundle.setTimestamp(0L);
|
||||
Logger.info(LOG_TAG, "Reset timestamps for " + this);
|
||||
persistConfig(config);
|
||||
Logger.info(LOG_TAG, "Reset timestamps for " + this);
|
||||
}
|
||||
|
||||
// Not thread-safe. Use with caution.
|
||||
|
@ -156,8 +196,8 @@ public abstract class ServerSyncStage implements
|
|||
/**
|
||||
* Synchronously wipe this stage by instantiating a local repository session
|
||||
* and wiping that.
|
||||
*
|
||||
* Logs and rethrows an exception on failure.
|
||||
* <p>
|
||||
* Logs and re-throws an exception on failure.
|
||||
*/
|
||||
@Override
|
||||
public void wipeLocal() throws Exception {
|
||||
|
@ -290,6 +330,105 @@ public abstract class ServerSyncStage implements
|
|||
Logger.info(LOG_TAG, "Wiping stage complete.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Asynchronously wipe collection on server.
|
||||
*/
|
||||
protected void wipeServer(final CredentialsSource credentials, final WipeServerDelegate wipeDelegate) {
|
||||
SyncStorageRequest request;
|
||||
|
||||
try {
|
||||
request = new SyncStorageRequest(session.config.collectionURI(getCollection()));
|
||||
} catch (URISyntaxException ex) {
|
||||
Logger.warn(LOG_TAG, "Invalid URI in wipeServer.");
|
||||
wipeDelegate.onWipeFailed(ex);
|
||||
return;
|
||||
}
|
||||
|
||||
request.delegate = new SyncStorageRequestDelegate() {
|
||||
|
||||
@Override
|
||||
public String ifUnmodifiedSince() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRequestSuccess(SyncStorageResponse response) {
|
||||
BaseResource.consumeEntity(response);
|
||||
resetLocal();
|
||||
wipeDelegate.onWiped(response.normalizedWeaveTimestamp());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRequestFailure(SyncStorageResponse response) {
|
||||
Logger.warn(LOG_TAG, "Got request failure " + response.getStatusCode() + " in wipeServer.");
|
||||
// Process HTTP failures here to pick up backoffs, etc.
|
||||
session.interpretHTTPFailure(response.httpResponse());
|
||||
BaseResource.consumeEntity(response); // The exception thrown should not need the body of the response.
|
||||
wipeDelegate.onWipeFailed(new HTTPFailureException(response));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleRequestError(Exception ex) {
|
||||
Logger.warn(LOG_TAG, "Got exception in wipeServer.", ex);
|
||||
wipeDelegate.onWipeFailed(ex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String credentials() {
|
||||
return credentials.credentials();
|
||||
}
|
||||
};
|
||||
|
||||
request.delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronously wipe the server.
|
||||
* <p>
|
||||
* Logs and re-throws an exception on failure.
|
||||
*/
|
||||
public void wipeServer() throws Exception {
|
||||
final WipeWaiter monitor = new WipeWaiter();
|
||||
|
||||
final Runnable doWipe = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
wipeServer(session, new WipeServerDelegate() {
|
||||
@Override
|
||||
public void onWiped(long timestamp) {
|
||||
synchronized (monitor) {
|
||||
monitor.notify();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWipeFailed(Exception e) {
|
||||
synchronized (monitor) {
|
||||
monitor.notify(e, false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
final Thread wiping = new Thread(doWipe);
|
||||
synchronized (monitor) {
|
||||
wiping.start();
|
||||
try {
|
||||
monitor.wait();
|
||||
} catch (InterruptedException e) {
|
||||
Logger.error(LOG_TAG, "Server wipe interrupted.");
|
||||
}
|
||||
}
|
||||
|
||||
if (!monitor.wipeSucceeded) {
|
||||
Logger.error(LOG_TAG, "Failed to wipe server.");
|
||||
throw monitor.error;
|
||||
}
|
||||
|
||||
Logger.info(LOG_TAG, "Wiping server complete.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws NoSuchStageException {
|
||||
final String name = getEngineName();
|
||||
|
@ -301,12 +440,36 @@ public abstract class ServerSyncStage implements
|
|||
session.advance();
|
||||
return;
|
||||
}
|
||||
} catch (MetaGlobalException.MetaGlobalMalformedSyncIDException e) {
|
||||
// Bad engine syncID. This should never happen. Wipe the server.
|
||||
try {
|
||||
session.updateMetaGlobalWith(name, new EngineSettings(Utils.generateGuid(), this.getStorageVersion()));
|
||||
Logger.info(LOG_TAG, "Wiping server because malformed engine sync ID was found in meta/global.");
|
||||
wipeServer();
|
||||
Logger.info(LOG_TAG, "Wiped server after malformed engine sync ID found in meta/global.");
|
||||
} catch (Exception ex) {
|
||||
session.abort(ex, "Failed to wipe server after malformed engine sync ID found in meta/global.");
|
||||
}
|
||||
} catch (MetaGlobalException.MetaGlobalMalformedVersionException e) {
|
||||
// Bad engine version. This should never happen. Wipe the server.
|
||||
try {
|
||||
session.updateMetaGlobalWith(name, new EngineSettings(Utils.generateGuid(), this.getStorageVersion()));
|
||||
Logger.info(LOG_TAG, "Wiping server because malformed engine version was found in meta/global.");
|
||||
wipeServer();
|
||||
Logger.info(LOG_TAG, "Wiped server after malformed engine version found in meta/global.");
|
||||
} catch (Exception ex) {
|
||||
session.abort(ex, "Failed to wipe server after malformed engine version found in meta/global.");
|
||||
}
|
||||
} catch (MetaGlobalException.MetaGlobalStaleClientSyncIDException e) {
|
||||
// Our syncID is wrong. Reset client and take the server syncID.
|
||||
Logger.warn(LOG_TAG, "Remote engine syncID different from local engine syncID:" +
|
||||
" resetting local engine and assuming remote engine syncID.");
|
||||
this.resetLocal(e.serverSyncID);
|
||||
} catch (MetaGlobalException e) {
|
||||
session.abort(e, "Inappropriate meta/global; refusing to execute " + name + " stage.");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Synchronizer synchronizer;
|
||||
try {
|
||||
synchronizer = this.getConfiguredSynchronizer(session);
|
||||
|
@ -336,11 +499,11 @@ public abstract class ServerSyncStage implements
|
|||
public void onSynchronized(Synchronizer synchronizer) {
|
||||
Logger.debug(LOG_TAG, "onSynchronized.");
|
||||
|
||||
SynchronizerConfiguration synchronizerConfiguration = synchronizer.save();
|
||||
if (synchronizerConfiguration != null) {
|
||||
persistConfig(synchronizerConfiguration);
|
||||
SynchronizerConfiguration newConfig = synchronizer.save();
|
||||
if (newConfig != null) {
|
||||
persistConfig(newConfig);
|
||||
} else {
|
||||
Logger.warn(LOG_TAG, "Didn't get configuration from synchronizer after success");
|
||||
Logger.warn(LOG_TAG, "Didn't get configuration from synchronizer after success.");
|
||||
}
|
||||
|
||||
Logger.info(LOG_TAG, "Advancing session.");
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
package org.mozilla.gecko.sync.stage;
|
||||
|
||||
import org.mozilla.gecko.sync.GlobalSession;
|
||||
|
||||
public class UploadMetaGlobalStage extends AbstractNonRepositorySyncStage {
|
||||
public static final String LOG_TAG = "UploadMGStage";
|
||||
|
||||
public UploadMetaGlobalStage(GlobalSession session) {
|
||||
super(session);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() throws NoSuchStageException {
|
||||
if (session.hasUpdatedMetaGlobal()) {
|
||||
session.uploadUpdatedMetaGlobal();
|
||||
}
|
||||
session.advance();
|
||||
}
|
||||
}
|
|
@ -28,6 +28,7 @@ import android.util.Log;
|
|||
* updated bundle information.
|
||||
*/
|
||||
public class Synchronizer {
|
||||
protected String configSyncID; // Used to pass syncID from load() back into save().
|
||||
|
||||
/**
|
||||
* I translate the fine-grained feedback of a SynchronizerSessionDelegate into
|
||||
|
@ -109,8 +110,7 @@ public class Synchronizer {
|
|||
}
|
||||
|
||||
public SynchronizerConfiguration save() {
|
||||
String syncID = null; // TODO: syncID.
|
||||
return new SynchronizerConfiguration(syncID, bundleA, bundleB);
|
||||
return new SynchronizerConfiguration(configSyncID, bundleA, bundleB);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -123,6 +123,6 @@ public class Synchronizer {
|
|||
public void load(SynchronizerConfiguration config) {
|
||||
bundleA = config.remoteBundle;
|
||||
bundleB = config.localBundle;
|
||||
// TODO: syncID.
|
||||
configSyncID = config.syncID;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -185,6 +185,7 @@ sync/stage/NoSyncIDException.java
|
|||
sync/stage/PasswordsServerSyncStage.java
|
||||
sync/stage/ServerSyncStage.java
|
||||
sync/stage/SyncClientsEngineStage.java
|
||||
sync/stage/UploadMetaGlobalStage.java
|
||||
sync/StubActivity.java
|
||||
sync/syncadapter/SyncAdapter.java
|
||||
sync/syncadapter/SyncService.java
|
||||
|
@ -205,7 +206,6 @@ sync/synchronizer/SynchronizerSessionDelegate.java
|
|||
sync/synchronizer/UnbundleError.java
|
||||
sync/synchronizer/UnexpectedSessionException.java
|
||||
sync/SynchronizerConfiguration.java
|
||||
sync/SynchronizerConfigurations.java
|
||||
sync/ThreadPool.java
|
||||
sync/UnexpectedJSONException.java
|
||||
sync/UnknownSynchronizerConfigurationVersionException.java
|
||||
|
|
Загрузка…
Ссылка в новой задаче