diff options
Diffstat (limited to 'mobile/android/services/src/main/java/org/mozilla/gecko/sync/MetaGlobal.java')
-rw-r--r-- | mobile/android/services/src/main/java/org/mozilla/gecko/sync/MetaGlobal.java | 372 |
1 files changed, 0 insertions, 372 deletions
diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/MetaGlobal.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/MetaGlobal.java deleted file mode 100644 index a90c0fee8..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/MetaGlobal.java +++ /dev/null @@ -1,372 +0,0 @@ -/* 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; - -import java.io.IOException; -import java.net.URISyntaxException; -import java.util.Collection; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -import org.json.simple.JSONArray; -import org.mozilla.gecko.background.common.log.Logger; -import org.mozilla.gecko.sync.MetaGlobalException.MetaGlobalMalformedSyncIDException; -import org.mozilla.gecko.sync.MetaGlobalException.MetaGlobalMalformedVersionException; -import org.mozilla.gecko.sync.delegates.MetaGlobalDelegate; -import org.mozilla.gecko.sync.net.AuthHeaderProvider; -import org.mozilla.gecko.sync.net.SyncStorageRecordRequest; -import org.mozilla.gecko.sync.net.SyncStorageRequestDelegate; -import org.mozilla.gecko.sync.net.SyncStorageResponse; - -public class MetaGlobal implements SyncStorageRequestDelegate { - private static final String LOG_TAG = "MetaGlobal"; - protected String metaURL; - - // Fields. - protected ExtendedJSONObject engines; - protected JSONArray declined; - protected Long storageVersion; - protected String syncID; - - // Lookup tables. - protected Map<String, String> syncIDs; - protected Map<String, Integer> versions; - protected Map<String, MetaGlobalException> exceptions; - - // Temporary location to store our callback. - private MetaGlobalDelegate callback; - - // A little hack so we can use the same delegate implementation for upload and download. - private boolean isUploading; - protected final AuthHeaderProvider authHeaderProvider; - - public MetaGlobal(String metaURL, AuthHeaderProvider authHeaderProvider) { - this.metaURL = metaURL; - this.authHeaderProvider = authHeaderProvider; - } - - public void fetch(MetaGlobalDelegate delegate) { - this.callback = delegate; - try { - this.isUploading = false; - SyncStorageRecordRequest r = new SyncStorageRecordRequest(this.metaURL); - r.delegate = this; - r.get(); - } catch (URISyntaxException e) { - this.callback.handleError(e); - } - } - - public void upload(MetaGlobalDelegate callback) { - try { - this.isUploading = true; - SyncStorageRecordRequest r = new SyncStorageRecordRequest(this.metaURL); - - r.delegate = this; - this.callback = callback; - r.put(this.asCryptoRecord()); - } catch (Exception e) { - callback.handleError(e); - } - } - - protected ExtendedJSONObject asRecordContents() { - ExtendedJSONObject json = new ExtendedJSONObject(); - json.put("storageVersion", storageVersion); - json.put("engines", engines); - json.put("syncID", syncID); - json.put("declined", declined); - return json; - } - - /** - * Return a copy ready for upload. - * @return an unencrypted <code>CryptoRecord</code>. - */ - public CryptoRecord asCryptoRecord() { - ExtendedJSONObject payload = this.asRecordContents(); - CryptoRecord record = new CryptoRecord(payload); - record.collection = "meta"; - record.guid = "global"; - record.deleted = false; - return record; - } - - public void setFromRecord(CryptoRecord record) throws IllegalStateException, IOException, NonObjectJSONException, NonArrayJSONException { - if (record == null) { - throw new IllegalArgumentException("Cannot set meta/global from null record"); - } - Logger.debug(LOG_TAG, "meta/global is " + record.payload.toJSONString()); - this.storageVersion = (Long) record.payload.get("storageVersion"); - this.syncID = (String) record.payload.get("syncID"); - - setEngines(record.payload.getObject("engines")); - - // Accepts null -- declined can be missing. - setDeclinedEngineNames(record.payload.getArray("declined")); - } - - public Long getStorageVersion() { - return this.storageVersion; - } - - public void setStorageVersion(Long version) { - this.storageVersion = version; - } - - public ExtendedJSONObject getEngines() { - return engines; - } - - @SuppressWarnings("unchecked") - public void declineEngine(String engine) { - if (this.declined == null) { - JSONArray replacement = new JSONArray(); - replacement.add(engine); - setDeclinedEngineNames(replacement); - return; - } - - this.declined.add(engine); - } - - @SuppressWarnings("unchecked") - public void declineEngineNames(Collection<String> additional) { - if (this.declined == null) { - JSONArray replacement = new JSONArray(); - replacement.addAll(additional); - setDeclinedEngineNames(replacement); - return; - } - - for (String engine : additional) { - if (!this.declined.contains(engine)) { - this.declined.add(engine); - } - } - } - - public void setDeclinedEngineNames(JSONArray declined) { - if (declined == null) { - this.declined = new JSONArray(); - return; - } - this.declined = declined; - } - - /** - * Return the set of engines that we support (given as an argument) - * but the user hasn't explicitly declined on another device. - * - * Can return the input if the user hasn't declined any engines. - */ - public Set<String> getNonDeclinedEngineNames(Set<String> supported) { - if (this.declined == null || - this.declined.isEmpty()) { - return supported; - } - - final Set<String> result = new HashSet<String>(supported); - result.removeAll(this.declined); - return result; - } - - 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); - syncIDs = new HashMap<String, String>(count); - exceptions = new HashMap<String, MetaGlobalException>(count); - for (String engineName : engines.keySet()) { - try { - ExtendedJSONObject engineEntry = engines.getObject(engineName); - 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. - } - } - } - - /** - * Take a JSON object corresponding to the 'engines' field for the provided engine name, - * updating {@link #syncIDs} and {@link #versions} accordingly. - * - * If the record is malformed, an entry is added to {@link #exceptions}, to be rethrown - * during validation. - */ - protected void recordEngineState(String engineName, ExtendedJSONObject engineEntry) { - 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); - if (version == null || - version == 0) { - // Invalid version. Wipe the server. - Logger.warn(LOG_TAG, "Malformed version " + version + - " for " + engineName + ". Recording exception."); - exceptions.put(engineName, new MetaGlobalMalformedVersionException()); - return; - } - versions.put(engineName, version); - } catch (NumberFormatException e) { - // Invalid version. Wipe the server. - Logger.warn(LOG_TAG, "Malformed version " + engineEntry.get("version") + - " for " + engineName + ". Recording exception."); - exceptions.put(engineName, new MetaGlobalMalformedVersionException()); - return; - } - } - - /** - * Get enabled engine names. - * - * @return a collection of engine names or <code>null</code> if meta/global - * was malformed. - */ - public Set<String> getEnabledEngineNames() { - if (engines == null) { - return null; - } - return new HashSet<String>(engines.keySet()); - } - - @SuppressWarnings("unchecked") - public Set<String> getDeclinedEngineNames() { - if (declined == null) { - return null; - } - return new HashSet<String>(declined); - } - - /** - * Returns if the server settings and local settings match. - * Throws a specific MetaGlobalException if that's not the case. - */ - public void verifyEngineSettings(String engineName, EngineSettings engineSettings) - throws MetaGlobalException { - - // We use syncIDs as our canary. - if (syncIDs == null) { - throw new IllegalStateException("No meta/global record yet processed."); - } - - if (engineSettings == null) { - throw new IllegalArgumentException("engineSettings cannot be null."); - } - - // First, see if we had a parsing problem. - final MetaGlobalException exception = exceptions.get(engineName); - if (exception != null) { - throw exception; - } - - 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); - } - - if (!syncID.equals(engineSettings.syncID)) { - // Our syncID is wrong. Reset client and take the server syncID. - throw new MetaGlobalException.MetaGlobalStaleClientSyncIDException(syncID); - } - } - - public String getSyncID() { - return syncID; - } - - public void setSyncID(String syncID) { - this.syncID = syncID; - } - - // SyncStorageRequestDelegate methods for fetching. - public String credentials() { - return null; - } - - @Override - public AuthHeaderProvider getAuthHeaderProvider() { - return authHeaderProvider; - } - - @Override - public String ifUnmodifiedSince() { - return null; - } - - @Override - public void handleRequestSuccess(SyncStorageResponse response) { - if (this.isUploading) { - this.handleUploadSuccess(response); - } else { - this.handleDownloadSuccess(response); - } - } - - private void handleUploadSuccess(SyncStorageResponse response) { - this.callback.handleSuccess(this, response); - } - - private void handleDownloadSuccess(SyncStorageResponse response) { - if (response.wasSuccessful()) { - try { - CryptoRecord record = CryptoRecord.fromJSONRecord(response.jsonObjectBody()); - this.setFromRecord(record); - this.callback.handleSuccess(this, response); - } catch (Exception e) { - this.callback.handleError(e); - } - return; - } - this.callback.handleFailure(response); - } - - @Override - public void handleRequestFailure(SyncStorageResponse response) { - if (response.getStatusCode() == 404) { - this.callback.handleMissing(this, response); - return; - } - this.callback.handleFailure(response); - } - - @Override - public void handleRequestError(Exception e) { - this.callback.handleError(e); - } -} |