summaryrefslogtreecommitdiffstats
path: root/mobile/android/services/src/main/java/org/mozilla/gecko/sync/MetaGlobal.java
diff options
context:
space:
mode:
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.java372
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);
- }
-}