diff options
author | wolfbeast <mcwerewolf@wolfbeast.com> | 2019-04-19 02:02:56 +0200 |
---|---|---|
committer | wolfbeast <mcwerewolf@wolfbeast.com> | 2019-04-19 02:02:56 +0200 |
commit | de75f133a7ec654d2a7c5bf628b3aee9fc109730 (patch) | |
tree | 4771e6d114249bf48d1e843167bcf393de2b98a2 /mobile/android/services/src/main/java/org/mozilla/gecko/sync/net | |
parent | cdc962dca59f2d68b82bec99beb5d67ae163f24a (diff) | |
download | UXP-de75f133a7ec654d2a7c5bf628b3aee9fc109730.tar UXP-de75f133a7ec654d2a7c5bf628b3aee9fc109730.tar.gz UXP-de75f133a7ec654d2a7c5bf628b3aee9fc109730.tar.lz UXP-de75f133a7ec654d2a7c5bf628b3aee9fc109730.tar.xz UXP-de75f133a7ec654d2a7c5bf628b3aee9fc109730.zip |
Remove Firefox Accounts service and tie-ins.
See previous commit for removal of browser identity module.
Diffstat (limited to 'mobile/android/services/src/main/java/org/mozilla/gecko/sync/net')
28 files changed, 0 insertions, 2927 deletions
diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/AbstractBearerTokenAuthHeaderProvider.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/AbstractBearerTokenAuthHeaderProvider.java deleted file mode 100644 index e3b4f25b1..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/AbstractBearerTokenAuthHeaderProvider.java +++ /dev/null @@ -1,34 +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.net; - -import ch.boye.httpclientandroidlib.Header; -import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase; -import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient; -import ch.boye.httpclientandroidlib.message.BasicHeader; -import ch.boye.httpclientandroidlib.protocol.BasicHttpContext; - -/** - * An <code>AuthHeaderProvider</code> that returns an Authorization header for - * bearer tokens, adding a simple prefix. - */ -public abstract class AbstractBearerTokenAuthHeaderProvider implements AuthHeaderProvider { - protected final String header; - - public AbstractBearerTokenAuthHeaderProvider(String token) { - if (token == null) { - throw new IllegalArgumentException("token must not be null."); - } - - this.header = getPrefix() + " " + token; - } - - protected abstract String getPrefix(); - - @Override - public Header getAuthHeader(HttpRequestBase request, BasicHttpContext context, DefaultHttpClient client) { - return new BasicHeader("Authorization", header); - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/AuthHeaderProvider.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/AuthHeaderProvider.java deleted file mode 100644 index 7be6fef3d..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/AuthHeaderProvider.java +++ /dev/null @@ -1,30 +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.net; - -import java.security.GeneralSecurityException; - -import ch.boye.httpclientandroidlib.Header; -import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase; -import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient; -import ch.boye.httpclientandroidlib.protocol.BasicHttpContext; - -/** - * An <code>AuthHeaderProvider</code> generates HTTP Authorization headers for - * HTTP requests. - */ -public interface AuthHeaderProvider { - /** - * Generate an HTTP Authorization header. - * - * @param request HTTP request. - * @param context HTTP context. - * @param client HTTP client. - * @return HTTP Authorization header. - * @throws GeneralSecurityException usually wrapping a more specific exception. - */ - Header getAuthHeader(HttpRequestBase request, BasicHttpContext context, DefaultHttpClient client) - throws GeneralSecurityException; -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/BaseResource.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/BaseResource.java deleted file mode 100644 index 60bbc86bb..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/BaseResource.java +++ /dev/null @@ -1,565 +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.net; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.lang.ref.WeakReference; -import java.net.URI; -import java.net.URISyntaxException; -import java.security.GeneralSecurityException; -import java.security.KeyManagementException; -import java.security.NoSuchAlgorithmException; -import java.security.SecureRandom; -import java.util.concurrent.CopyOnWriteArrayList; - -import javax.net.ssl.SSLContext; - -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.mozilla.gecko.background.common.GlobalConstants; -import org.mozilla.gecko.background.common.log.Logger; -import org.mozilla.gecko.sync.ExtendedJSONObject; - -import ch.boye.httpclientandroidlib.Header; -import ch.boye.httpclientandroidlib.HttpEntity; -import ch.boye.httpclientandroidlib.HttpResponse; -import ch.boye.httpclientandroidlib.HttpVersion; -import ch.boye.httpclientandroidlib.client.AuthCache; -import ch.boye.httpclientandroidlib.client.ClientProtocolException; -import ch.boye.httpclientandroidlib.client.entity.GzipCompressingEntity; -import ch.boye.httpclientandroidlib.client.methods.HttpDelete; -import ch.boye.httpclientandroidlib.client.methods.HttpGet; -import ch.boye.httpclientandroidlib.client.methods.HttpPatch; -import ch.boye.httpclientandroidlib.client.methods.HttpPost; -import ch.boye.httpclientandroidlib.client.methods.HttpPut; -import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase; -import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest; -import ch.boye.httpclientandroidlib.client.protocol.ClientContext; -import ch.boye.httpclientandroidlib.conn.ClientConnectionManager; -import ch.boye.httpclientandroidlib.conn.scheme.PlainSocketFactory; -import ch.boye.httpclientandroidlib.conn.scheme.Scheme; -import ch.boye.httpclientandroidlib.conn.scheme.SchemeRegistry; -import ch.boye.httpclientandroidlib.conn.ssl.SSLSocketFactory; -import ch.boye.httpclientandroidlib.entity.StringEntity; -import ch.boye.httpclientandroidlib.impl.client.BasicAuthCache; -import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient; -import ch.boye.httpclientandroidlib.impl.conn.tsccm.ThreadSafeClientConnManager; -import ch.boye.httpclientandroidlib.params.HttpConnectionParams; -import ch.boye.httpclientandroidlib.params.HttpParams; -import ch.boye.httpclientandroidlib.params.HttpProtocolParams; -import ch.boye.httpclientandroidlib.protocol.BasicHttpContext; -import ch.boye.httpclientandroidlib.protocol.HttpContext; -import ch.boye.httpclientandroidlib.util.EntityUtils; - -/** - * Provide simple HTTP access to a Sync server or similar. - * Implements Basic Auth by asking its delegate for credentials. - * Communicates with a ResourceDelegate to asynchronously return responses and errors. - * Exposes simple get/post/put/delete methods. - */ -@SuppressWarnings("deprecation") -public class BaseResource implements Resource { - private static final String ANDROID_LOOPBACK_IP = "10.0.2.2"; - - private static final int MAX_TOTAL_CONNECTIONS = 20; - private static final int MAX_CONNECTIONS_PER_ROUTE = 10; - - private boolean retryOnFailedRequest = true; - - public static boolean rewriteLocalhost = true; - - private static final String LOG_TAG = "BaseResource"; - - protected final URI uri; - protected BasicHttpContext context; - protected DefaultHttpClient client; - public ResourceDelegate delegate; - protected HttpRequestBase request; - public final String charset = "utf-8"; - - private boolean shouldGzipCompress = false; - // A hint whether uploaded payloads are chunked. Default true to use GzipCompressingEntity, which is built-in functionality. - private boolean shouldChunkUploadsHint = true; - - /** - * We have very few writes (observers tend to be installed around sync - * sessions) and many iterations (every HTTP request iterates observers), so - * CopyOnWriteArrayList is a reasonable choice. - */ - protected static final CopyOnWriteArrayList<WeakReference<HttpResponseObserver>> - httpResponseObservers = new CopyOnWriteArrayList<>(); - - public BaseResource(String uri) throws URISyntaxException { - this(uri, rewriteLocalhost); - } - - public BaseResource(URI uri) { - this(uri, rewriteLocalhost); - } - - public BaseResource(String uri, boolean rewrite) throws URISyntaxException { - this(new URI(uri), rewrite); - } - - public BaseResource(URI uri, boolean rewrite) { - if (uri == null) { - throw new IllegalArgumentException("uri must not be null"); - } - if (rewrite && "localhost".equals(uri.getHost())) { - // Rewrite localhost URIs to refer to the special Android emulator loopback passthrough interface. - Logger.debug(LOG_TAG, "Rewriting " + uri + " to point to " + ANDROID_LOOPBACK_IP + "."); - try { - this.uri = new URI(uri.getScheme(), uri.getUserInfo(), ANDROID_LOOPBACK_IP, uri.getPort(), uri.getPath(), uri.getQuery(), uri.getFragment()); - } catch (URISyntaxException e) { - Logger.error(LOG_TAG, "Got error rewriting URI for Android emulator.", e); - throw new IllegalArgumentException("Invalid URI", e); - } - } else { - this.uri = uri; - } - } - - public static void addHttpResponseObserver(HttpResponseObserver newHttpResponseObserver) { - if (newHttpResponseObserver == null) { - return; - } - httpResponseObservers.add(new WeakReference<HttpResponseObserver>(newHttpResponseObserver)); - } - - public static boolean isHttpResponseObserver(HttpResponseObserver httpResponseObserver) { - for (WeakReference<HttpResponseObserver> weakReference : httpResponseObservers) { - HttpResponseObserver innerHttpResponseObserver = weakReference.get(); - if (innerHttpResponseObserver == httpResponseObserver) { - return true; - } - } - return false; - } - - public static boolean removeHttpResponseObserver(HttpResponseObserver httpResponseObserver) { - for (WeakReference<HttpResponseObserver> weakReference : httpResponseObservers) { - HttpResponseObserver innerHttpResponseObserver = weakReference.get(); - if (innerHttpResponseObserver == httpResponseObserver) { - // It's safe to mutate the observers while iterating. - httpResponseObservers.remove(weakReference); - return true; - } - } - return false; - } - - @Override - public URI getURI() { - return this.uri; - } - - @Override - public String getURIString() { - return this.uri.toString(); - } - - @Override - public String getHostname() { - return this.getURI().getHost(); - } - - /** - * Causes the Resource to compress the uploaded entity payload in requests with payloads (e.g. post, put) - * @param shouldCompress true if the entity should be compressed, false otherwise - */ - public void setShouldCompressUploadedEntity(final boolean shouldCompress) { - shouldGzipCompress = shouldCompress; - } - - /** - * Causes the Resource to chunk the uploaded entity payload in requests with payloads (e.g. post, put). - * Note: this flag is only a hint - chunking is not guaranteed. - * - * Chunking is currently supported with gzip compression. - * - * @param shouldChunk true if the transfer should be chunked, false otherwise - */ - public void setShouldChunkUploadsHint(final boolean shouldChunk) { - shouldChunkUploadsHint = shouldChunk; - } - - private HttpEntity getMaybeCompressedEntity(final HttpEntity entity) { - if (!shouldGzipCompress) { - return entity; - } - - return shouldChunkUploadsHint ? new GzipCompressingEntity(entity) : new GzipNonChunkedCompressingEntity(entity); - } - - /** - * This shuts up HttpClient, which will otherwise debug log about there - * being no auth cache in the context. - */ - private static void addAuthCacheToContext(HttpUriRequest request, HttpContext context) { - AuthCache authCache = new BasicAuthCache(); // Not thread safe. - context.setAttribute(ClientContext.AUTH_CACHE, authCache); - } - - /** - * Invoke this after delegate and request have been set. - * @throws NoSuchAlgorithmException - * @throws KeyManagementException - */ - protected void prepareClient() throws KeyManagementException, NoSuchAlgorithmException, GeneralSecurityException { - context = new BasicHttpContext(); - - // We could reuse these client instances, except that we mess around - // with their parameters… so we'd need a pool of some kind. - client = new DefaultHttpClient(getConnectionManager()); - - // TODO: Eventually we should use Apache HttpAsyncClient. It's not out of alpha yet. - // Until then, we synchronously make the request, then invoke our delegate's callback. - AuthHeaderProvider authHeaderProvider = delegate.getAuthHeaderProvider(); - if (authHeaderProvider != null) { - Header authHeader = authHeaderProvider.getAuthHeader(request, context, client); - if (authHeader != null) { - request.addHeader(authHeader); - Logger.debug(LOG_TAG, "Added auth header."); - } - } - - addAuthCacheToContext(request, context); - - HttpParams params = client.getParams(); - HttpConnectionParams.setConnectionTimeout(params, delegate.connectionTimeout()); - HttpConnectionParams.setSoTimeout(params, delegate.socketTimeout()); - HttpConnectionParams.setStaleCheckingEnabled(params, false); - HttpProtocolParams.setContentCharset(params, charset); - HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); - final String userAgent = delegate.getUserAgent(); - if (userAgent != null) { - HttpProtocolParams.setUserAgent(params, userAgent); - } - delegate.addHeaders(request, client); - } - - private static final Object connManagerMonitor = new Object(); - private static ClientConnectionManager connManager; - - // Call within a synchronized block on connManagerMonitor. - private static ClientConnectionManager enableTLSConnectionManager() throws KeyManagementException, NoSuchAlgorithmException { - SSLContext sslContext = SSLContext.getInstance("TLS"); - sslContext.init(null, null, new SecureRandom()); - - Logger.debug(LOG_TAG, "Using protocols and cipher suites for Android API " + android.os.Build.VERSION.SDK_INT); - SSLSocketFactory sf = new SSLSocketFactory(sslContext, GlobalConstants.DEFAULT_PROTOCOLS, GlobalConstants.DEFAULT_CIPHER_SUITES, null); - SchemeRegistry schemeRegistry = new SchemeRegistry(); - schemeRegistry.register(new Scheme("https", 443, sf)); - schemeRegistry.register(new Scheme("http", 80, new PlainSocketFactory())); - ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(schemeRegistry); - - cm.setMaxTotal(MAX_TOTAL_CONNECTIONS); - cm.setDefaultMaxPerRoute(MAX_CONNECTIONS_PER_ROUTE); - connManager = cm; - return cm; - } - - public static ClientConnectionManager getConnectionManager() throws KeyManagementException, NoSuchAlgorithmException - { - // TODO: shutdown. - synchronized (connManagerMonitor) { - if (connManager != null) { - return connManager; - } - return enableTLSConnectionManager(); - } - } - - /** - * Do some cleanup, so we don't need the stale connection check. - */ - public static void closeExpiredConnections() { - ClientConnectionManager connectionManager; - synchronized (connManagerMonitor) { - connectionManager = connManager; - } - if (connectionManager == null) { - return; - } - Logger.trace(LOG_TAG, "Closing expired connections."); - connectionManager.closeExpiredConnections(); - } - - public static void shutdownConnectionManager() { - ClientConnectionManager connectionManager; - synchronized (connManagerMonitor) { - connectionManager = connManager; - connManager = null; - } - if (connectionManager == null) { - return; - } - Logger.debug(LOG_TAG, "Shutting down connection manager."); - connectionManager.shutdown(); - } - - private void execute() { - HttpResponse response; - try { - response = client.execute(request, context); - Logger.debug(LOG_TAG, "Response: " + response.getStatusLine().toString()); - } catch (ClientProtocolException e) { - delegate.handleHttpProtocolException(e); - return; - } catch (IOException e) { - Logger.debug(LOG_TAG, "I/O exception returned from execute."); - if (!retryOnFailedRequest) { - delegate.handleHttpIOException(e); - } else { - retryRequest(); - } - return; - } catch (Exception e) { - // Bug 740731: Don't let an exception fall through. Wrapping isn't - // optimal, but often the exception is treated as an Exception anyway. - if (!retryOnFailedRequest) { - // Bug 769671: IOException(Throwable cause) was added only in API level 9. - final IOException ex = new IOException(); - ex.initCause(e); - delegate.handleHttpIOException(ex); - } else { - retryRequest(); - } - return; - } - - // Don't retry if the observer or delegate throws! - for (WeakReference<HttpResponseObserver> weakReference : httpResponseObservers) { - HttpResponseObserver observer = weakReference.get(); - if (observer != null) { - observer.observeHttpResponse(request, response); - } - } - delegate.handleHttpResponse(response); - } - - private void retryRequest() { - // Only retry once. - retryOnFailedRequest = false; - Logger.debug(LOG_TAG, "Retrying request..."); - this.execute(); - } - - private void go(HttpRequestBase request) { - if (delegate == null) { - throw new IllegalArgumentException("No delegate provided."); - } - this.request = request; - try { - this.prepareClient(); - } catch (KeyManagementException e) { - Logger.error(LOG_TAG, "Couldn't prepare client.", e); - delegate.handleTransportException(e); - return; - } catch (GeneralSecurityException e) { - Logger.error(LOG_TAG, "Couldn't prepare client.", e); - delegate.handleTransportException(e); - return; - } catch (Exception e) { - // Bug 740731: Don't let an exception fall through. Wrapping isn't - // optimal, but often the exception is treated as an Exception anyway. - delegate.handleTransportException(new GeneralSecurityException(e)); - return; - } - this.execute(); - } - - @Override - public void get() { - Logger.debug(LOG_TAG, "HTTP GET " + this.uri.toASCIIString()); - this.go(new HttpGet(this.uri)); - } - - /** - * Perform an HTTP GET as with {@link BaseResource#get()}, returning only - * after callbacks have been invoked. - */ - public void getBlocking() { - // Until we use the asynchronous Apache HttpClient, we can simply call - // through. - this.get(); - } - - @Override - public void delete() { - Logger.debug(LOG_TAG, "HTTP DELETE " + this.uri.toASCIIString()); - this.go(new HttpDelete(this.uri)); - } - - @Override - public void post(HttpEntity body) { - Logger.debug(LOG_TAG, "HTTP POST " + this.uri.toASCIIString()); - body = getMaybeCompressedEntity(body); - HttpPost request = new HttpPost(this.uri); - request.setEntity(body); - this.go(request); - } - - @Override - public void patch(HttpEntity body) { - Logger.debug(LOG_TAG, "HTTP PATCH " + this.uri.toASCIIString()); - body = getMaybeCompressedEntity(body); - HttpPatch request = new HttpPatch(this.uri); - request.setEntity(body); - this.go(request); - } - - @Override - public void put(HttpEntity body) { - Logger.debug(LOG_TAG, "HTTP PUT " + this.uri.toASCIIString()); - body = getMaybeCompressedEntity(body); - HttpPut request = new HttpPut(this.uri); - request.setEntity(body); - this.go(request); - } - - protected static StringEntity stringEntityWithContentTypeApplicationJSON(String s) { - StringEntity e = new StringEntity(s, "UTF-8"); - e.setContentType("application/json"); - return e; - } - - /** - * Helper for turning a JSON object into a payload. - * @throws UnsupportedEncodingException - */ - protected static StringEntity jsonEntity(JSONObject body) { - return stringEntityWithContentTypeApplicationJSON(body.toJSONString()); - } - - /** - * Helper for turning an extended JSON object into a payload. - * @throws UnsupportedEncodingException - */ - protected static StringEntity jsonEntity(ExtendedJSONObject body) { - return stringEntityWithContentTypeApplicationJSON(body.toJSONString()); - } - - /** - * Helper for turning a JSON array into a payload. - * @throws UnsupportedEncodingException - */ - protected static HttpEntity jsonEntity(JSONArray toPOST) throws UnsupportedEncodingException { - return stringEntityWithContentTypeApplicationJSON(toPOST.toJSONString()); - } - - /** - * Best-effort attempt to ensure that the entity has been fully consumed and - * that the underlying stream has been closed. - * - * This releases the connection back to the connection pool. - * - * @param entity The HttpEntity to be consumed. - */ - public static void consumeEntity(HttpEntity entity) { - try { - EntityUtils.consume(entity); - } catch (IOException e) { - // Doesn't matter. - } - } - - /** - * Best-effort attempt to ensure that the entity corresponding to the given - * HTTP response has been fully consumed and that the underlying stream has - * been closed. - * - * This releases the connection back to the connection pool. - * - * @param response - * The HttpResponse to be consumed. - */ - public static void consumeEntity(HttpResponse response) { - if (response == null) { - return; - } - try { - EntityUtils.consume(response.getEntity()); - } catch (IOException e) { - } - } - - /** - * Best-effort attempt to ensure that the entity corresponding to the given - * Sync storage response has been fully consumed and that the underlying - * stream has been closed. - * - * This releases the connection back to the connection pool. - * - * @param response - * The SyncStorageResponse to be consumed. - */ - public static void consumeEntity(SyncStorageResponse response) { - if (response.httpResponse() == null) { - return; - } - consumeEntity(response.httpResponse()); - } - - /** - * Best-effort attempt to ensure that the reader has been fully consumed, so - * that the underlying stream will be closed. - * - * This should allow the connection to be released back to the connection pool. - * - * @param reader The BufferedReader to be consumed. - */ - public static void consumeReader(BufferedReader reader) { - try { - reader.close(); - } catch (IOException e) { - // Do nothing. - } - } - - public void post(JSONArray jsonArray) throws UnsupportedEncodingException { - post(jsonEntity(jsonArray)); - } - - public void put(JSONObject jsonObject) throws UnsupportedEncodingException { - put(jsonEntity(jsonObject)); - } - - public void put(ExtendedJSONObject o) { - put(jsonEntity(o)); - } - - public void post(ExtendedJSONObject o) { - post(jsonEntity(o)); - } - - /** - * Perform an HTTP POST as with {@link BaseResource#post(ExtendedJSONObject)}, returning only - * after callbacks have been invoked. - */ - public void postBlocking(final ExtendedJSONObject o) { - // Until we use the asynchronous Apache HttpClient, we can simply call - // through. - post(jsonEntity(o)); - } - - public void post(JSONObject jsonObject) throws UnsupportedEncodingException { - post(jsonEntity(jsonObject)); - } - - public void patch(JSONArray jsonArray) throws UnsupportedEncodingException { - patch(jsonEntity(jsonArray)); - } - - public void patch(ExtendedJSONObject o) { - patch(jsonEntity(o)); - } - - public void patch(JSONObject jsonObject) throws UnsupportedEncodingException { - patch(jsonEntity(jsonObject)); - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/BaseResourceDelegate.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/BaseResourceDelegate.java deleted file mode 100644 index 84ae7a3d5..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/BaseResourceDelegate.java +++ /dev/null @@ -1,44 +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.net; - -import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase; -import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient; - -/** - * Shared abstract class for resource delegate that use the same timeouts - * and no credentials. - * - * @author rnewman - * - */ -public abstract class BaseResourceDelegate implements ResourceDelegate { - public static int connectionTimeoutInMillis = 1000 * 30; // Wait 30s for a connection to open. - public static int socketTimeoutInMillis = 1000 * 2 * 60; // Wait 2 minutes for data. - - protected Resource resource; - public BaseResourceDelegate(Resource resource) { - this.resource = resource; - } - - @Override - public int connectionTimeout() { - return connectionTimeoutInMillis; - } - - @Override - public int socketTimeout() { - return socketTimeoutInMillis; - } - - @Override - public AuthHeaderProvider getAuthHeaderProvider() { - return null; - } - - @Override - public void addHeaders(HttpRequestBase request, DefaultHttpClient client) { - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/BasicAuthHeaderProvider.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/BasicAuthHeaderProvider.java deleted file mode 100644 index d8a371ddc..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/BasicAuthHeaderProvider.java +++ /dev/null @@ -1,51 +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.net; - -import ch.boye.httpclientandroidlib.Header; -import ch.boye.httpclientandroidlib.auth.Credentials; -import ch.boye.httpclientandroidlib.auth.UsernamePasswordCredentials; -import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase; -import ch.boye.httpclientandroidlib.impl.auth.BasicScheme; -import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient; -import ch.boye.httpclientandroidlib.protocol.BasicHttpContext; - -/** - * An <code>AuthHeaderProvider</code> that returns an HTTP Basic auth header. - */ -public class BasicAuthHeaderProvider implements AuthHeaderProvider { - protected final String credentials; - - /** - * Constructor. - * - * @param credentials string in form "user:pass". - */ - public BasicAuthHeaderProvider(String credentials) { - this.credentials = credentials; - } - - /** - * Constructor. - * - * @param user username. - * @param pass password. - */ - public BasicAuthHeaderProvider(String user, String pass) { - this(user + ":" + pass); - } - - /** - * Return a Header object representing an Authentication header for HTTP - * Basic. - */ - @Override - public Header getAuthHeader(HttpRequestBase request, BasicHttpContext context, DefaultHttpClient client) { - Credentials creds = new UsernamePasswordCredentials(credentials); - - // This must be UTF-8 to generate the same Basic Auth headers as desktop for non-ASCII passwords. - return BasicScheme.authenticate(creds, "UTF-8", false); - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/BearerAuthHeaderProvider.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/BearerAuthHeaderProvider.java deleted file mode 100644 index d142d50d9..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/BearerAuthHeaderProvider.java +++ /dev/null @@ -1,22 +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.net; - -/** - * An <code>AuthHeaderProvider</code> that returns an Authorization header for - * Bearer tokens in the format expected by a Mozilla Firefox Accounts Profile Server. - * <p> - * See <a href="https://github.com/mozilla/fxa-profile-server/blob/master/docs/API.md">https://github.com/mozilla/fxa-profile-server/blob/master/docs/API.md</a>. - */ -public class BearerAuthHeaderProvider extends AbstractBearerTokenAuthHeaderProvider { - public BearerAuthHeaderProvider(String token) { - super(token); - } - - @Override - protected String getPrefix() { - return "Bearer"; - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/BrowserIDAuthHeaderProvider.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/BrowserIDAuthHeaderProvider.java deleted file mode 100644 index 5004673b3..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/BrowserIDAuthHeaderProvider.java +++ /dev/null @@ -1,23 +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.net; - -/** - * An <code>AuthHeaderProvider</code> that returns an Authorization header for - * BrowserID assertions in the format expected by a Mozilla Services Token - * Server. - * <p> - * See <a href="http://docs.services.mozilla.com/token/apis.html">http://docs.services.mozilla.com/token/apis.html</a>. - */ -public class BrowserIDAuthHeaderProvider extends AbstractBearerTokenAuthHeaderProvider { - public BrowserIDAuthHeaderProvider(String assertion) { - super(assertion); - } - - @Override - protected String getPrefix() { - return "BrowserID"; - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/ConnectionMonitorThread.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/ConnectionMonitorThread.java deleted file mode 100644 index 1a2011771..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/ConnectionMonitorThread.java +++ /dev/null @@ -1,44 +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.net; - -import org.mozilla.gecko.background.common.log.Logger; - -/** - * Every <code>REAP_INTERVAL</code> milliseconds, wake up - * and expire any connections that need cleaning up. - * - * When we're told to shut down, take the connection manager - * with us. - */ -public class ConnectionMonitorThread extends Thread { - private static final long REAP_INTERVAL = 5000; // 5 seconds. - private static final String LOG_TAG = "ConnectionMonitorThread"; - - private volatile boolean stopping; - - @Override - public void run() { - try { - while (!stopping) { - synchronized (this) { - wait(REAP_INTERVAL); - BaseResource.closeExpiredConnections(); - } - } - } catch (InterruptedException e) { - Logger.trace(LOG_TAG, "Interrupted."); - } - BaseResource.shutdownConnectionManager(); - } - - public void shutdown() { - Logger.debug(LOG_TAG, "ConnectionMonitorThread told to shut down."); - stopping = true; - synchronized (this) { - notifyAll(); - } - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/GzipNonChunkedCompressingEntity.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/GzipNonChunkedCompressingEntity.java deleted file mode 100644 index 1e238c022..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/GzipNonChunkedCompressingEntity.java +++ /dev/null @@ -1,92 +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.net; - -import ch.boye.httpclientandroidlib.HttpEntity; -import ch.boye.httpclientandroidlib.client.entity.GzipCompressingEntity; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; - -/** - * Wrapping entity that compresses content when {@link #writeTo writing}. - * - * This differs from {@link GzipCompressingEntity} in that it does not chunk - * the sent data, therefore replacing the "Transfer-Encoding" HTTP header with - * the "Content-Length" header required by some servers. - * - * However, to measure the content length, the gzipped content will be temporarily - * stored in memory so be careful what content you send! - */ -public class GzipNonChunkedCompressingEntity extends GzipCompressingEntity { - final int MAX_BUFFER_SIZE_BYTES = 10 * 1000 * 1000; // 10 MB. - - private byte[] gzippedContent; - - public GzipNonChunkedCompressingEntity(final HttpEntity entity) { - super(entity); - } - - /** - * @return content length for gzipped content or -1 if there is an error - */ - @Override - public long getContentLength() { - try { - initBuffer(); - } catch (final IOException e) { - // GzipCompressingEntity always returns -1 in which case a 'Content-Length' header is omitted. - // Presumably, without it the request will fail (either client-side or server-side). - return -1; - } - return gzippedContent.length; - } - - @Override - public boolean isChunked() { - // "Content-Length" & chunked encoding are mutually exclusive: - // https://en.wikipedia.org/wiki/Chunked_transfer_encoding - return false; - } - - @Override - public InputStream getContent() throws IOException { - initBuffer(); - return new ByteArrayInputStream(gzippedContent); - } - - @Override - public void writeTo(final OutputStream outstream) throws IOException { - initBuffer(); - outstream.write(gzippedContent); - } - - private void initBuffer() throws IOException { - if (gzippedContent != null) { - return; - } - - final long unzippedContentLength = wrappedEntity.getContentLength(); - if (unzippedContentLength > MAX_BUFFER_SIZE_BYTES) { - throw new IOException( - "Wrapped entity content length, " + unzippedContentLength + " bytes, exceeds max: " + MAX_BUFFER_SIZE_BYTES); - } - - // The buffer size needed by the gzipped content should be smaller than this, - // but it's more efficient just to allocate one larger buffer than allocate - // twice if the gzipped content is too large for the default buffer. - final ByteArrayOutputStream s = new ByteArrayOutputStream((int) unzippedContentLength); - try { - super.writeTo(s); - } finally { - s.close(); - } - - gzippedContent = s.toByteArray(); - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/HMACAuthHeaderProvider.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/HMACAuthHeaderProvider.java deleted file mode 100644 index 5314d345b..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/HMACAuthHeaderProvider.java +++ /dev/null @@ -1,257 +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.net; - -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.security.GeneralSecurityException; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; - -import org.mozilla.apache.commons.codec.binary.Base64; -import org.mozilla.gecko.background.common.log.Logger; -import org.mozilla.gecko.sync.Utils; - -import ch.boye.httpclientandroidlib.Header; -import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase; -import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest; -import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient; -import ch.boye.httpclientandroidlib.message.BasicHeader; -import ch.boye.httpclientandroidlib.protocol.BasicHttpContext; - -/** - * An <code>AuthHeaderProvider</code> that returns an Authorization header for - * HMAC-SHA1-signed requests in the format expected by Mozilla Services - * identity-attached services and specified by the MAC Authentication spec, available at - * <a href="https://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac">https://tools.ietf.org/html/draft-ietf-oauth-v2-http-mac</a>. - * <p> - * See <a href="https://wiki.mozilla.org/Services/Sagrada/ServiceClientFlow#Access">https://wiki.mozilla.org/Services/Sagrada/ServiceClientFlow#Access</a>. - */ -public class HMACAuthHeaderProvider implements AuthHeaderProvider { - public static final String LOG_TAG = "HMACAuthHeaderProvider"; - - public static final int NONCE_LENGTH_IN_BYTES = 8; - - public static final String HMAC_SHA1_ALGORITHM = "hmacSHA1"; - - public final String identifier; - public final String key; - - public HMACAuthHeaderProvider(String identifier, String key) { - // Validate identifier string. From the MAC Authentication spec: - // id = "id" "=" string-value - // string-value = ( <"> plain-string <"> ) / plain-string - // plain-string = 1*( %x20-21 / %x23-5B / %x5D-7E ) - // We add quotes around the id string, so input identifier must be a plain-string. - if (identifier == null) { - throw new IllegalArgumentException("identifier must not be null."); - } - if (!isPlainString(identifier)) { - throw new IllegalArgumentException("identifier must be a plain-string."); - } - - if (key == null) { - throw new IllegalArgumentException("key must not be null."); - } - - this.identifier = identifier; - this.key = key; - } - - @Override - public Header getAuthHeader(HttpRequestBase request, BasicHttpContext context, DefaultHttpClient client) throws GeneralSecurityException { - long timestamp = System.currentTimeMillis() / 1000; - String nonce = Base64.encodeBase64String(Utils.generateRandomBytes(NONCE_LENGTH_IN_BYTES)); - String extra = ""; - - try { - return getAuthHeader(request, context, client, timestamp, nonce, extra); - } catch (InvalidKeyException | NoSuchAlgorithmException | UnsupportedEncodingException e) { - // We lie a little and make every exception a GeneralSecurityException. - throw new GeneralSecurityException(e); - } - } - - /** - * Test if input is a <code>plain-string</code>. - * <p> - * A plain-string is defined by the MAC Authentication spec as - * <code>plain-string = 1*( %x20-21 / %x23-5B / %x5D-7E )</code>. - * - * @param input - * as a String of "US-ASCII" bytes. - * @return true if input is a <code>plain-string</code>; false otherwise. - * @throws UnsupportedEncodingException - */ - protected static boolean isPlainString(String input) { - if (input == null || input.length() == 0) { - return false; - } - - byte[] bytes; - try { - bytes = input.getBytes("US-ASCII"); - } catch (UnsupportedEncodingException e) { - // Should never happen. - Logger.warn(LOG_TAG, "Got exception in isPlainString; returning false.", e); - return false; - } - - for (byte b : bytes) { - if ((0x20 <= b && b <= 0x21) || (0x23 <= b && b <= 0x5B) || (0x5D <= b && b <= 0x7E)) { - continue; - } - return false; - } - - return true; - } - - /** - * Helper function that generates an HTTP Authorization header given - * additional MAC Authentication specific data. - * - * @throws UnsupportedEncodingException - * @throws NoSuchAlgorithmException - * @throws InvalidKeyException - */ - protected Header getAuthHeader(HttpRequestBase request, BasicHttpContext context, DefaultHttpClient client, - long timestamp, String nonce, String extra) - throws UnsupportedEncodingException, InvalidKeyException, NoSuchAlgorithmException { - // Validate timestamp. From the MAC Authentication spec: - // timestamp = 1*DIGIT - // This is equivalent to timestamp >= 0. - if (timestamp < 0) { - throw new IllegalArgumentException("timestamp must contain only [0-9]."); - } - - // Validate nonce string. From the MAC Authentication spec: - // nonce = "nonce" "=" string-value - // string-value = ( <"> plain-string <"> ) / plain-string - // plain-string = 1*( %x20-21 / %x23-5B / %x5D-7E ) - // We add quotes around the nonce string, so input nonce must be a plain-string. - if (nonce == null) { - throw new IllegalArgumentException("nonce must not be null."); - } - if (nonce.length() == 0) { - throw new IllegalArgumentException("nonce must not be empty."); - } - if (!isPlainString(nonce)) { - throw new IllegalArgumentException("nonce must be a plain-string."); - } - - // Validate extra string. From the MAC Authentication spec: - // ext = "ext" "=" string-value - // string-value = ( <"> plain-string <"> ) / plain-string - // plain-string = 1*( %x20-21 / %x23-5B / %x5D-7E ) - // We add quotes around the extra string, so input extra must be a plain-string. - // We break the spec by allowing ext to be an empty string, i.e. to match 0*(...). - if (extra == null) { - throw new IllegalArgumentException("extra must not be null."); - } - if (extra.length() > 0 && !isPlainString(extra)) { - throw new IllegalArgumentException("extra must be a plain-string."); - } - - String requestString = getRequestString(request, timestamp, nonce, extra); - String macString = getSignature(requestString, this.key); - - String h = "MAC id=\"" + this.identifier + "\", " + - "ts=\"" + timestamp + "\", " + - "nonce=\"" + nonce + "\", " + - "mac=\"" + macString + "\""; - - if (extra != null) { - h += ", ext=\"" + extra + "\""; - } - - Header header = new BasicHeader("Authorization", h); - - return header; - } - - protected static byte[] sha1(byte[] message, byte[] key) - throws NoSuchAlgorithmException, InvalidKeyException { - - SecretKeySpec keySpec = new SecretKeySpec(key, HMAC_SHA1_ALGORITHM); - - Mac hasher = Mac.getInstance(HMAC_SHA1_ALGORITHM); - hasher.init(keySpec); - hasher.update(message); - - byte[] hmac = hasher.doFinal(); - - return hmac; - } - - /** - * Sign an HMAC request string. - * - * @param requestString to sign. - * @param key as <code>String</code>. - * @return signature as base-64 encoded string. - * @throws InvalidKeyException - * @throws NoSuchAlgorithmException - * @throws UnsupportedEncodingException - */ - protected static String getSignature(String requestString, String key) - throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException { - String macString = Base64.encodeBase64String(sha1(requestString.getBytes("UTF-8"), key.getBytes("UTF-8"))); - - return macString; - } - - /** - * Generate an HMAC request string. - * <p> - * This method trusts its inputs to be valid as per the MAC Authentication spec. - * - * @param request HTTP request. - * @param timestamp to use. - * @param nonce to use. - * @param extra to use. - * @return request string. - */ - protected static String getRequestString(HttpUriRequest request, long timestamp, String nonce, String extra) { - String method = request.getMethod().toUpperCase(); - - URI uri = request.getURI(); - String host = uri.getHost(); - - String path = uri.getRawPath(); - if (uri.getRawQuery() != null) { - path += "?"; - path += uri.getRawQuery(); - } - if (uri.getRawFragment() != null) { - path += "#"; - path += uri.getRawFragment(); - } - - int port = uri.getPort(); - String scheme = uri.getScheme(); - if (port != -1) { - } else if ("http".equalsIgnoreCase(scheme)) { - port = 80; - } else if ("https".equalsIgnoreCase(scheme)) { - port = 443; - } else { - throw new IllegalArgumentException("Unsupported URI scheme: " + scheme + "."); - } - - String requestString = timestamp + "\n" + - nonce + "\n" + - method + "\n" + - path + "\n" + - host + "\n" + - port + "\n" + - extra + "\n"; - - return requestString; - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/HandleProgressException.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/HandleProgressException.java deleted file mode 100644 index 27ec74b66..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/HandleProgressException.java +++ /dev/null @@ -1,15 +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.net; - -import org.mozilla.gecko.sync.SyncException; - -public class HandleProgressException extends SyncException { - private static final long serialVersionUID = -4444933937013161059L; - - public HandleProgressException(Exception ex) { - super(ex); - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/HawkAuthHeaderProvider.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/HawkAuthHeaderProvider.java deleted file mode 100644 index 2bdd5604a..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/HawkAuthHeaderProvider.java +++ /dev/null @@ -1,403 +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.net; - -import java.io.IOException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.security.GeneralSecurityException; -import java.security.InvalidKeyException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.Locale; - -import javax.crypto.Mac; -import javax.crypto.spec.SecretKeySpec; - -import org.mozilla.apache.commons.codec.binary.Base64; -import org.mozilla.gecko.background.common.log.Logger; -import org.mozilla.gecko.sync.Utils; - -import ch.boye.httpclientandroidlib.Header; -import ch.boye.httpclientandroidlib.HttpEntity; -import ch.boye.httpclientandroidlib.HttpEntityEnclosingRequest; -import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase; -import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest; -import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient; -import ch.boye.httpclientandroidlib.message.BasicHeader; -import ch.boye.httpclientandroidlib.protocol.BasicHttpContext; - -/** - * An <code>AuthHeaderProvider</code> that returns an Authorization header for - * Hawk: <a href="https://github.com/hueniverse/hawk">https://github.com/hueniverse/hawk</a>. - * - * Hawk is an HTTP authentication scheme using a message authentication code - * (MAC) algorithm to provide partial HTTP request cryptographic verification. - * Hawk is the successor to the HMAC authentication scheme. - */ -public class HawkAuthHeaderProvider implements AuthHeaderProvider { - public static final String LOG_TAG = HawkAuthHeaderProvider.class.getSimpleName(); - - public static final int HAWK_HEADER_VERSION = 1; - - protected static final int NONCE_LENGTH_IN_BYTES = 8; - protected static final String HMAC_SHA256_ALGORITHM = "hmacSHA256"; - - protected final String id; - protected final byte[] key; - protected final boolean includePayloadHash; - protected final long skewSeconds; - - /** - * Create a Hawk Authorization header provider. - * <p> - * Hawk specifies no mechanism by which a client receives an - * identifier-and-key pair from the server. - * <p> - * Hawk requests can include a payload verification hash with requests that - * enclose an entity (PATCH, POST, and PUT requests). <b>You should default - * to including the payload verification hash<b> unless you have a good reason - * not to -- the server can always ignore payload verification hashes provided - * by the client. - * - * @param id - * to name requests with. - * @param key - * to sign request with. - * - * @param includePayloadHash - * true if payload verification hash should be included in signed - * request header. See <a href="https://github.com/hueniverse/hawk#payload-validation">https://github.com/hueniverse/hawk#payload-validation</a>. - * - * @param skewSeconds - * a number of seconds by which to skew the current time when - * computing a header. - */ - public HawkAuthHeaderProvider(String id, byte[] key, boolean includePayloadHash, long skewSeconds) { - if (id == null) { - throw new IllegalArgumentException("id must not be null"); - } - if (key == null) { - throw new IllegalArgumentException("key must not be null"); - } - this.id = id; - this.key = key; - this.includePayloadHash = includePayloadHash; - this.skewSeconds = skewSeconds; - } - - /** - * @return the current time in milliseconds. - */ - @SuppressWarnings("static-method") - protected long now() { - return System.currentTimeMillis(); - } - - /** - * @return the current time in seconds, adjusted for skew. This should - * approximate the server's timestamp. - */ - protected long getTimestampSeconds() { - return (now() / 1000) + skewSeconds; - } - - @Override - public Header getAuthHeader(HttpRequestBase request, BasicHttpContext context, DefaultHttpClient client) throws GeneralSecurityException { - long timestamp = getTimestampSeconds(); - String nonce = Base64.encodeBase64String(Utils.generateRandomBytes(NONCE_LENGTH_IN_BYTES)); - String extra = ""; - - try { - return getAuthHeader(request, context, client, timestamp, nonce, extra, this.includePayloadHash); - } catch (Exception e) { - // We lie a little and make every exception a GeneralSecurityException. - throw new GeneralSecurityException(e); - } - } - - /** - * Helper function that generates an HTTP Authorization: Hawk header given - * additional Hawk specific data. - * - * @throws NoSuchAlgorithmException - * @throws InvalidKeyException - * @throws IOException - */ - protected Header getAuthHeader(HttpRequestBase request, BasicHttpContext context, DefaultHttpClient client, - long timestamp, String nonce, String extra, boolean includePayloadHash) - throws InvalidKeyException, NoSuchAlgorithmException, IOException { - if (timestamp < 0) { - throw new IllegalArgumentException("timestamp must contain only [0-9]."); - } - - if (nonce == null) { - throw new IllegalArgumentException("nonce must not be null."); - } - if (nonce.length() == 0) { - throw new IllegalArgumentException("nonce must not be empty."); - } - - String payloadHash = null; - if (includePayloadHash) { - payloadHash = getPayloadHashString(request); - } else { - Logger.debug(LOG_TAG, "Configured to not include payload hash for this request."); - } - - String app = null; - String dlg = null; - String requestString = getRequestString(request, "header", timestamp, nonce, payloadHash, extra, app, dlg); - String macString = getSignature(requestString.getBytes("UTF-8"), this.key); - - StringBuilder sb = new StringBuilder(); - sb.append("Hawk id=\""); - sb.append(this.id); - sb.append("\", "); - sb.append("ts=\""); - sb.append(timestamp); - sb.append("\", "); - sb.append("nonce=\""); - sb.append(nonce); - sb.append("\", "); - if (payloadHash != null) { - sb.append("hash=\""); - sb.append(payloadHash); - sb.append("\", "); - } - if (extra != null && extra.length() > 0) { - sb.append("ext=\""); - sb.append(escapeExtraHeaderAttribute(extra)); - sb.append("\", "); - } - sb.append("mac=\""); - sb.append(macString); - sb.append("\""); - - return new BasicHeader("Authorization", sb.toString()); - } - - /** - * Get the payload verification hash for the given request, if possible. - * <p> - * Returns null if the request does not enclose an entity (is not an HTTP - * PATCH, POST, or PUT). Throws if the payload verification hash cannot be - * computed. - * - * @param request - * to compute hash for. - * @return verification hash, or null if the request does not enclose an entity. - * @throws IllegalArgumentException if the request does not enclose a valid non-null entity. - * @throws UnsupportedEncodingException - * @throws NoSuchAlgorithmException - * @throws IOException - */ - protected static String getPayloadHashString(HttpRequestBase request) - throws UnsupportedEncodingException, NoSuchAlgorithmException, IOException, IllegalArgumentException { - final boolean shouldComputePayloadHash = request instanceof HttpEntityEnclosingRequest; - if (!shouldComputePayloadHash) { - Logger.debug(LOG_TAG, "Not computing payload verification hash for non-enclosing request."); - return null; - } - if (!(request instanceof HttpEntityEnclosingRequest)) { - throw new IllegalArgumentException("Cannot compute payload verification hash for enclosing request without an entity"); - } - final HttpEntity entity = ((HttpEntityEnclosingRequest) request).getEntity(); - if (entity == null) { - throw new IllegalArgumentException("Cannot compute payload verification hash for enclosing request with a null entity"); - } - return Base64.encodeBase64String(getPayloadHash(entity)); - } - - /** - * Escape the user-provided extra string for the ext="" header attribute. - * <p> - * Hawk escapes the header ext="" attribute differently than it does the extra - * line in the normalized request string. - * <p> - * See <a href="https://github.com/hueniverse/hawk/blob/871cc597973110900467bd3dfb84a3c892f678fb/lib/browser.js#L385">https://github.com/hueniverse/hawk/blob/871cc597973110900467bd3dfb84a3c892f678fb/lib/browser.js#L385</a>. - * - * @param extra to escape. - * @return extra escaped for the ext="" header attribute. - */ - protected static String escapeExtraHeaderAttribute(String extra) { - return extra.replaceAll("\\\\", "\\\\").replaceAll("\"", "\\\""); - } - - /** - * Escape the user-provided extra string for inserting into the normalized - * request string. - * <p> - * Hawk escapes the header ext="" attribute differently than it does the extra - * line in the normalized request string. - * <p> - * See <a href="https://github.com/hueniverse/hawk/blob/871cc597973110900467bd3dfb84a3c892f678fb/lib/crypto.js#L67">https://github.com/hueniverse/hawk/blob/871cc597973110900467bd3dfb84a3c892f678fb/lib/crypto.js#L67</a>. - * - * @param extra to escape. - * @return extra escaped for the normalized request string. - */ - protected static String escapeExtraString(String extra) { - return extra.replaceAll("\\\\", "\\\\").replaceAll("\n", "\\n"); - } - - /** - * Return the content type with no parameters (pieces following ;). - * - * @param contentTypeHeader to interrogate. - * @return base content type. - */ - protected static String getBaseContentType(Header contentTypeHeader) { - if (contentTypeHeader == null) { - throw new IllegalArgumentException("contentTypeHeader must not be null."); - } - String contentType = contentTypeHeader.getValue(); - if (contentType == null) { - throw new IllegalArgumentException("contentTypeHeader value must not be null."); - } - int index = contentType.indexOf(";"); - if (index < 0) { - return contentType.trim(); - } - return contentType.substring(0, index).trim(); - } - - /** - * Generate the SHA-256 hash of a normalized Hawk payload generated from an - * HTTP entity. - * <p> - * <b>Warning:</b> the entity <b>must</b> be repeatable. If it is not, this - * code throws an <code>IllegalArgumentException</code>. - * <p> - * This is under-specified; the code here was reverse engineered from the code - * at - * <a href="https://github.com/hueniverse/hawk/blob/871cc597973110900467bd3dfb84a3c892f678fb/lib/crypto.js#L81">https://github.com/hueniverse/hawk/blob/871cc597973110900467bd3dfb84a3c892f678fb/lib/crypto.js#L81</a>. - * @param entity to normalize and hash. - * @return hash. - * @throws IllegalArgumentException if entity is not repeatable. - */ - protected static byte[] getPayloadHash(HttpEntity entity) throws UnsupportedEncodingException, IOException, NoSuchAlgorithmException { - if (!entity.isRepeatable()) { - throw new IllegalArgumentException("entity must be repeatable"); - } - final MessageDigest digest = MessageDigest.getInstance("SHA-256"); - digest.update(("hawk." + HAWK_HEADER_VERSION + ".payload\n").getBytes("UTF-8")); - digest.update(getBaseContentType(entity.getContentType()).getBytes("UTF-8")); - digest.update("\n".getBytes("UTF-8")); - InputStream stream = entity.getContent(); - try { - int numRead; - byte[] buffer = new byte[4096]; - while (-1 != (numRead = stream.read(buffer))) { - if (numRead > 0) { - digest.update(buffer, 0, numRead); - } - } - digest.update("\n".getBytes("UTF-8")); // Trailing newline is specified by Hawk. - return digest.digest(); - } finally { - stream.close(); - } - } - - /** - * Generate a normalized Hawk request string. This is under-specified; the - * code here was reverse engineered from the code at - * <a href="https://github.com/hueniverse/hawk/blob/871cc597973110900467bd3dfb84a3c892f678fb/lib/crypto.js#L55">https://github.com/hueniverse/hawk/blob/871cc597973110900467bd3dfb84a3c892f678fb/lib/crypto.js#L55</a>. - * <p> - * This method trusts its inputs to be valid. - */ - protected static String getRequestString(HttpUriRequest request, String type, long timestamp, String nonce, String hash, String extra, String app, String dlg) { - String method = request.getMethod().toUpperCase(Locale.US); - - URI uri = request.getURI(); - String host = uri.getHost(); - - String path = uri.getRawPath(); - if (uri.getRawQuery() != null) { - path += "?"; - path += uri.getRawQuery(); - } - if (uri.getRawFragment() != null) { - path += "#"; - path += uri.getRawFragment(); - } - - int port = uri.getPort(); - String scheme = uri.getScheme(); - if (port != -1) { - } else if ("http".equalsIgnoreCase(scheme)) { - port = 80; - } else if ("https".equalsIgnoreCase(scheme)) { - port = 443; - } else { - throw new IllegalArgumentException("Unsupported URI scheme: " + scheme + "."); - } - - StringBuilder sb = new StringBuilder(); - sb.append("hawk."); - sb.append(HAWK_HEADER_VERSION); - sb.append('.'); - sb.append(type); - sb.append('\n'); - sb.append(timestamp); - sb.append('\n'); - sb.append(nonce); - sb.append('\n'); - sb.append(method); - sb.append('\n'); - sb.append(path); - sb.append('\n'); - sb.append(host); - sb.append('\n'); - sb.append(port); - sb.append('\n'); - if (hash != null) { - sb.append(hash); - } - sb.append("\n"); - if (extra != null && extra.length() > 0) { - sb.append(escapeExtraString(extra)); - } - sb.append("\n"); - if (app != null) { - sb.append(app); - sb.append("\n"); - if (dlg != null) { - sb.append(dlg); - } - sb.append("\n"); - } - - return sb.toString(); - } - - protected static byte[] hmacSha256(byte[] message, byte[] key) - throws NoSuchAlgorithmException, InvalidKeyException { - - SecretKeySpec keySpec = new SecretKeySpec(key, HMAC_SHA256_ALGORITHM); - - Mac hasher = Mac.getInstance(HMAC_SHA256_ALGORITHM); - hasher.init(keySpec); - hasher.update(message); - - return hasher.doFinal(); - } - - /** - * Sign a Hawk request string. - * - * @param requestString to sign. - * @param key as <code>String</code>. - * @return signature as base-64 encoded string. - * @throws InvalidKeyException - * @throws NoSuchAlgorithmException - * @throws UnsupportedEncodingException - */ - protected static String getSignature(byte[] requestString, byte[] key) - throws InvalidKeyException, NoSuchAlgorithmException, UnsupportedEncodingException { - return Base64.encodeBase64String(hmacSha256(requestString, key)); - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/HttpResponseObserver.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/HttpResponseObserver.java deleted file mode 100644 index 24b37a0e6..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/HttpResponseObserver.java +++ /dev/null @@ -1,20 +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.net; - -import ch.boye.httpclientandroidlib.HttpResponse; -import ch.boye.httpclientandroidlib.client.methods.HttpUriRequest; - -public interface HttpResponseObserver { - /** - * Observe an HTTP response. - * @param request - * The <code>HttpUriRequest<code> that elicited the response. - * - * @param response - * The <code>HttpResponse</code> to observe. - */ - public void observeHttpResponse(HttpUriRequest request, HttpResponse response); -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/MozResponse.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/MozResponse.java deleted file mode 100644 index 3f76f929f..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/MozResponse.java +++ /dev/null @@ -1,225 +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.net; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.util.Scanner; - -import org.json.simple.JSONArray; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; -import org.mozilla.gecko.background.common.log.Logger; -import org.mozilla.gecko.sync.ExtendedJSONObject; -import org.mozilla.gecko.sync.NonArrayJSONException; -import org.mozilla.gecko.sync.NonObjectJSONException; - -import ch.boye.httpclientandroidlib.Header; -import ch.boye.httpclientandroidlib.HttpEntity; -import ch.boye.httpclientandroidlib.HttpResponse; -import ch.boye.httpclientandroidlib.HttpStatus; -import ch.boye.httpclientandroidlib.impl.cookie.DateParseException; -import ch.boye.httpclientandroidlib.impl.cookie.DateUtils; - -public class MozResponse { - private static final String LOG_TAG = "MozResponse"; - - private static final String HEADER_RETRY_AFTER = "retry-after"; - - protected HttpResponse response; - private String body = null; - - public HttpResponse httpResponse() { - return this.response; - } - - public int getStatusCode() { - return this.response.getStatusLine().getStatusCode(); - } - - public boolean wasSuccessful() { - return this.getStatusCode() == 200; - } - - public boolean isInvalidAuthentication() { - return this.getStatusCode() == HttpStatus.SC_UNAUTHORIZED; - } - - /** - * Fetch the content type of the HTTP response body. - * - * @return a <code>Header</code> instance, or <code>null</code> if there was - * no body or no valid Content-Type. - */ - public Header getContentType() { - HttpEntity entity = this.response.getEntity(); - if (entity == null) { - return null; - } - return entity.getContentType(); - } - - private static boolean missingHeader(String value) { - return value == null || - value.trim().length() == 0; - } - - public String body() throws IllegalStateException, IOException { - if (body != null) { - return body; - } - final HttpEntity entity = this.response.getEntity(); - if (entity == null) { - body = null; - return null; - } - - InputStreamReader is = new InputStreamReader(entity.getContent()); - // Oh, Java, you are so evil. - body = new Scanner(is).useDelimiter("\\A").next(); - return body; - } - - /** - * Return the body as a <b>non-null</b> <code>ExtendedJSONObject</code>. - * - * @return A non-null <code>ExtendedJSONObject</code>. - * - * @throws IllegalStateException - * @throws IOException - * @throws NonObjectJSONException - */ - public ExtendedJSONObject jsonObjectBody() throws IllegalStateException, IOException, NonObjectJSONException { - if (body != null) { - // Do it from the cached String. - return new ExtendedJSONObject(body); - } - - HttpEntity entity = this.response.getEntity(); - if (entity == null) { - throw new IOException("no entity"); - } - - InputStream content = entity.getContent(); - try { - Reader in = new BufferedReader(new InputStreamReader(content, "UTF-8")); - return new ExtendedJSONObject(in); - } finally { - content.close(); - } - } - - public JSONArray jsonArrayBody() throws NonArrayJSONException, IOException { - final JSONParser parser = new JSONParser(); - try { - if (body != null) { - // Do it from the cached String. - return (JSONArray) parser.parse(body); - } - - final HttpEntity entity = this.response.getEntity(); - if (entity == null) { - throw new IOException("no entity"); - } - - final InputStream content = entity.getContent(); - final Reader in = new BufferedReader(new InputStreamReader(content, "UTF-8")); - try { - return (JSONArray) parser.parse(in); - } finally { - in.close(); - } - } catch (ClassCastException | ParseException e) { - NonArrayJSONException exception = new NonArrayJSONException("value must be a json array"); - exception.initCause(e); - throw exception; - } - } - - protected boolean hasHeader(String h) { - return this.response.containsHeader(h); - } - - public MozResponse(HttpResponse res) { - response = res; - } - - protected String getNonMissingHeader(String h) { - if (!this.hasHeader(h)) { - return null; - } - - final Header header = this.response.getFirstHeader(h); - final String value = header.getValue(); - if (missingHeader(value)) { - Logger.warn(LOG_TAG, h + " header present but empty."); - return null; - } - return value; - } - - protected long getLongHeader(String h) throws NumberFormatException { - final String value = getNonMissingHeader(h); - if (value == null) { - return -1L; - } - return Long.parseLong(value, 10); - } - - protected int getIntegerHeader(String h) throws NumberFormatException { - final String value = getNonMissingHeader(h); - if (value == null) { - return -1; - } - return Integer.parseInt(value, 10); - } - - /** - * @return A number of seconds, or -1 if the 'Retry-After' header was not present. - */ - public int retryAfterInSeconds() throws NumberFormatException { - final String retryAfter = getNonMissingHeader(HEADER_RETRY_AFTER); - if (retryAfter == null) { - return -1; - } - - try { - return Integer.parseInt(retryAfter, 10); - } catch (NumberFormatException e) { - // Fall through to try date format. - } - - try { - final long then = DateUtils.parseDate(retryAfter).getTime(); - final long now = System.currentTimeMillis(); - return (int)((then - now) / 1000); // Convert milliseconds to seconds. - } catch (DateParseException e) { - Logger.warn(LOG_TAG, "Retry-After header neither integer nor date: " + retryAfter); - return -1; - } - } - - /** - * @return A number of seconds, or -1 if the 'Backoff' header was not - * present. - */ - public int backoffInSeconds() throws NumberFormatException { - return this.getIntegerHeader("backoff"); - } - - public void logResponseBody(final String logTag) { - if (!Logger.LOG_PERSONAL_INFORMATION) { - return; - } - try { - Logger.pii(logTag, "Response body: " + body()); - } catch (Throwable e) { - Logger.debug(logTag, "No response body."); - } - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/Resource.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/Resource.java deleted file mode 100644 index ab7b98aff..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/Resource.java +++ /dev/null @@ -1,20 +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.net; - -import java.net.URI; - -import ch.boye.httpclientandroidlib.HttpEntity; - -public interface Resource { - public abstract URI getURI(); - public abstract String getURIString(); - public abstract String getHostname(); - public abstract void get(); - public abstract void delete(); - public abstract void post(HttpEntity body); - public abstract void patch(HttpEntity body); - public abstract void put(HttpEntity body); -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/ResourceDelegate.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/ResourceDelegate.java deleted file mode 100644 index 0dea9432b..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/ResourceDelegate.java +++ /dev/null @@ -1,55 +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.net; - -import java.io.IOException; -import java.security.GeneralSecurityException; - -import ch.boye.httpclientandroidlib.HttpResponse; -import ch.boye.httpclientandroidlib.client.ClientProtocolException; -import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase; -import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient; - -/** - * ResourceDelegate implementers must ensure that HTTP responses - * are fully consumed to ensure that connections are returned to - * the pool: - * - * EntityUtils.consume(entity); - * @author rnewman - * - */ -public interface ResourceDelegate { - // Request augmentation. - AuthHeaderProvider getAuthHeaderProvider(); - void addHeaders(HttpRequestBase request, DefaultHttpClient client); - - /** - * The value of the User-Agent header to include with the request. - * - * @return User-Agent header value; null means do not set User-Agent header. - */ - public String getUserAgent(); - - // Response handling. - - /** - * Override this to handle an HttpResponse. - * - * ResourceDelegate implementers <b>must</b> ensure that HTTP responses are - * fully consumed to ensure that connections are returned to the pool, for - * example by calling <code>EntityUtils.consume(response.getEntity())</code>. - */ - void handleHttpResponse(HttpResponse response); - void handleHttpProtocolException(ClientProtocolException e); - void handleHttpIOException(IOException e); - - // During preparation. - void handleTransportException(GeneralSecurityException e); - - // Connection parameters. - int connectionTimeout(); - int socketTimeout(); -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SRPConstants.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SRPConstants.java deleted file mode 100644 index 5dfe660ef..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SRPConstants.java +++ /dev/null @@ -1,174 +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.net; - -import java.math.BigInteger; - -/** - * SRP Group Parameters from - * <a href="http://tools.ietf.org/html/rfc5054#appendix-A">Appendix A of RFC 5054</a>. - * - * The 1024-, 1536-, and 2048-bit groups are taken from software - * developed by Tom Wu and Eugene Jhong for the Stanford SRP - * distribution, and subsequently proven to be prime. The larger primes - * are taken from [MODP], but generators have been calculated that are - * primitive roots of N, unlike the generators in [MODP]. - * - * The 1024-bit and 1536-bit groups <b>MUST</b> be supported. - */ -public class SRPConstants { - public static class Parameters { - public final BigInteger N; - public final BigInteger g; - public final int bitLength; - public final int byteLength; - public final int hexLength; - - protected Parameters(String N, long g) { - if (N == null) { - throw new IllegalArgumentException("N must not be null"); - } - this.N = new BigInteger(N.replaceAll(" ", ""), 16); // Hex. - this.g = BigInteger.valueOf(g); - this.hexLength = this.N.toString(16).length(); - this.byteLength = hexLength / 2; - this.bitLength = this.byteLength * 8; - } - } - - public static final Parameters _1024 = new Parameters("" + - "EEAF0AB9 ADB38DD6 9C33F80A FA8FC5E8 60726187 75FF3C0B 9EA2314C" + - "9C256576 D674DF74 96EA81D3 383B4813 D692C6E0 E0D5D8E2 50B98BE4" + - "8E495C1D 6089DAD1 5DC7D7B4 6154D6B6 CE8EF4AD 69B15D49 82559B29" + - "7BCF1885 C529F566 660E57EC 68EDBC3C 05726CC0 2FD4CBF4 976EAA9A" + - "FD5138FE 8376435B 9FC61D2F C0EB06E3", 2L); - - public static final Parameters _1536 = new Parameters("" + - "9DEF3CAF B939277A B1F12A86 17A47BBB DBA51DF4 99AC4C80 BEEEA961" + - "4B19CC4D 5F4F5F55 6E27CBDE 51C6A94B E4607A29 1558903B A0D0F843" + - "80B655BB 9A22E8DC DF028A7C EC67F0D0 8134B1C8 B9798914 9B609E0B" + - "E3BAB63D 47548381 DBC5B1FC 764E3F4B 53DD9DA1 158BFD3E 2B9C8CF5" + - "6EDF0195 39349627 DB2FD53D 24B7C486 65772E43 7D6C7F8C E442734A" + - "F7CCB7AE 837C264A E3A9BEB8 7F8A2FE9 B8B5292E 5A021FFF 5E91479E" + - "8CE7A28C 2442C6F3 15180F93 499A234D CF76E3FE D135F9BB", 2L); - - public static final Parameters _2048 = new Parameters("" + - "AC6BDB41 324A9A9B F166DE5E 1389582F AF72B665 1987EE07 FC319294" + - "3DB56050 A37329CB B4A099ED 8193E075 7767A13D D52312AB 4B03310D" + - "CD7F48A9 DA04FD50 E8083969 EDB767B0 CF609517 9A163AB3 661A05FB" + - "D5FAAAE8 2918A996 2F0B93B8 55F97993 EC975EEA A80D740A DBF4FF74" + - "7359D041 D5C33EA7 1D281E44 6B14773B CA97B43A 23FB8016 76BD207A" + - "436C6481 F1D2B907 8717461A 5B9D32E6 88F87748 544523B5 24B0D57D" + - "5EA77A27 75D2ECFA 032CFBDB F52FB378 61602790 04E57AE6 AF874E73" + - "03CE5329 9CCC041C 7BC308D8 2A5698F3 A8D0C382 71AE35F8 E9DBFBB6" + - "94B5C803 D89F7AE4 35DE236D 525F5475 9B65E372 FCD68EF2 0FA7111F" + - "9E4AFF73", 2L); - - public static final Parameters _3072 = new Parameters("" + - "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08" + - "8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B" + - "302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9" + - "A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6" + - "49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8" + - "FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" + - "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C" + - "180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718" + - "3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D" + - "04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D" + - "B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226" + - "1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" + - "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC" + - "E0FD108E 4B82D120 A93AD2CA FFFFFFFF FFFFFFFF", 5L); - - public static final Parameters _4096 = new Parameters("" + - "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08" + - "8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B" + - "302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9" + - "A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6" + - "49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8" + - "FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" + - "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C" + - "180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718" + - "3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D" + - "04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D" + - "B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226" + - "1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" + - "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC" + - "E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 88719A10 BDBA5B26" + - "99C32718 6AF4E23C 1A946834 B6150BDA 2583E9CA 2AD44CE8 DBBBC2DB" + - "04DE8EF9 2E8EFC14 1FBECAA6 287C5947 4E6BC05D 99B2964F A090C3A2" + - "233BA186 515BE7ED 1F612970 CEE2D7AF B81BDD76 2170481C D0069127" + - "D5B05AA9 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34063199" + - "FFFFFFFF FFFFFFFF", 5L); - - public static final Parameters _6144 = new Parameters("" + - "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08" + - "8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B" + - "302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9" + - "A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6" + - "49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8" + - "FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" + - "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C" + - "180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718" + - "3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D" + - "04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D" + - "B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226" + - "1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" + - "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC" + - "E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 88719A10 BDBA5B26" + - "99C32718 6AF4E23C 1A946834 B6150BDA 2583E9CA 2AD44CE8 DBBBC2DB" + - "04DE8EF9 2E8EFC14 1FBECAA6 287C5947 4E6BC05D 99B2964F A090C3A2" + - "233BA186 515BE7ED 1F612970 CEE2D7AF B81BDD76 2170481C D0069127" + - "D5B05AA9 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492" + - "36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD F8FF9406" + - "AD9E530E E5DB382F 413001AE B06A53ED 9027D831 179727B0 865A8918" + - "DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B DB7F1447 E6CC254B 33205151" + - "2BD7AF42 6FB8F401 378CD2BF 5983CA01 C64B92EC F032EA15 D1721D03" + - "F482D7CE 6E74FEF6 D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F" + - "BEC7E8F3 23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA" + - "CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328 06A1D58B" + - "B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C DA56C9EC 2EF29632" + - "387FE8D7 6E3C0468 043E8F66 3F4860EE 12BF2D5B 0B7474D6 E694F91E" + - "6DCC4024 FFFFFFFF FFFFFFFF", 5L); - - public static final Parameters _8192 = new Parameters("" + - "FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1 29024E08" + - "8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD EF9519B3 CD3A431B" + - "302B0A6D F25F1437 4FE1356D 6D51C245 E485B576 625E7EC6 F44C42E9" + - "A637ED6B 0BFF5CB6 F406B7ED EE386BFB 5A899FA5 AE9F2411 7C4B1FE6" + - "49286651 ECE45B3D C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8" + - "FD24CF5F 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D" + - "670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B E39E772C" + - "180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9 DE2BCBF6 95581718" + - "3995497C EA956AE5 15D22618 98FA0510 15728E5A 8AAAC42D AD33170D" + - "04507A33 A85521AB DF1CBA64 ECFB8504 58DBEF0A 8AEA7157 5D060C7D" + - "B3970F85 A6E1E4C7 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226" + - "1AD2EE6B F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C" + - "BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31 43DB5BFC" + - "E0FD108E 4B82D120 A9210801 1A723C12 A787E6D7 88719A10 BDBA5B26" + - "99C32718 6AF4E23C 1A946834 B6150BDA 2583E9CA 2AD44CE8 DBBBC2DB" + - "04DE8EF9 2E8EFC14 1FBECAA6 287C5947 4E6BC05D 99B2964F A090C3A2" + - "233BA186 515BE7ED 1F612970 CEE2D7AF B81BDD76 2170481C D0069127" + - "D5B05AA9 93B4EA98 8D8FDDC1 86FFB7DC 90A6C08F 4DF435C9 34028492" + - "36C3FAB4 D27C7026 C1D4DCB2 602646DE C9751E76 3DBA37BD F8FF9406" + - "AD9E530E E5DB382F 413001AE B06A53ED 9027D831 179727B0 865A8918" + - "DA3EDBEB CF9B14ED 44CE6CBA CED4BB1B DB7F1447 E6CC254B 33205151" + - "2BD7AF42 6FB8F401 378CD2BF 5983CA01 C64B92EC F032EA15 D1721D03" + - "F482D7CE 6E74FEF6 D55E702F 46980C82 B5A84031 900B1C9E 59E7C97F" + - "BEC7E8F3 23A97A7E 36CC88BE 0F1D45B7 FF585AC5 4BD407B2 2B4154AA" + - "CC8F6D7E BF48E1D8 14CC5ED2 0F8037E0 A79715EE F29BE328 06A1D58B" + - "B7C5DA76 F550AA3D 8A1FBFF0 EB19CCB1 A313D55C DA56C9EC 2EF29632" + - "387FE8D7 6E3C0468 043E8F66 3F4860EE 12BF2D5B 0B7474D6 E694F91E" + - "6DBE1159 74A3926F 12FEE5E4 38777CB6 A932DF8C D8BEC4D0 73B931BA" + - "3BC832B6 8D9DD300 741FA7BF 8AFC47ED 2576F693 6BA42466 3AAB639C" + - "5AE4F568 3423B474 2BF1C978 238F16CB E39D652D E3FDB8BE FC848AD9" + - "22222E04 A4037C07 13EB57A8 1A23F0C7 3473FC64 6CEA306B 4BCBC886" + - "2F8385DD FA9D4B7F A2C087E8 79683303 ED5BDD3A 062B3CF5 B3A278A6" + - "6D2A13F8 3F44F82D DF310EE0 74AB6A36 4597E899 A0255DC1 64F31CC5" + - "0846851D F9AB4819 5DED7EA1 B1D510BD 7EE74D73 FAF36BC3 1ECFA268" + - "359046F4 EB879F92 4009438B 481C6CD7 889A002E D5EE382B C9190DA6" + - "FC026E47 9558E447 5677E9AA 9E3050E2 765694DF C81F56E8 80B96E71" + - "60C980DD 98EDD3DF FFFFFFFF FFFFFFFF", 19L); -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncResponse.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncResponse.java deleted file mode 100644 index 177d7aaba..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncResponse.java +++ /dev/null @@ -1,157 +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.net; - -import android.support.annotation.Nullable; - -import org.mozilla.gecko.sync.Utils; - -import ch.boye.httpclientandroidlib.HttpResponse; - -public class SyncResponse extends MozResponse { - public static final String X_WEAVE_BACKOFF = "x-weave-backoff"; - public static final String X_BACKOFF = "x-backoff"; - public static final String X_LAST_MODIFIED = "x-last-modified"; - public static final String X_WEAVE_TIMESTAMP = "x-weave-timestamp"; - public static final String X_WEAVE_RECORDS = "x-weave-records"; - public static final String X_WEAVE_QUOTA_REMAINING = "x-weave-quota-remaining"; - public static final String X_WEAVE_ALERT = "x-weave-alert"; - public static final String X_WEAVE_NEXT_OFFSET = "x-weave-next-offset"; - - public SyncResponse(HttpResponse res) { - super(res); - } - - /** - * @return A number of seconds, or -1 if the 'X-Weave-Backoff' header was not - * present. - */ - public int weaveBackoffInSeconds() throws NumberFormatException { - return this.getIntegerHeader(X_WEAVE_BACKOFF); - } - - /** - * @return A number of seconds, or -1 if the 'X-Backoff' header was not - * present. - */ - public int xBackoffInSeconds() throws NumberFormatException { - return this.getIntegerHeader(X_BACKOFF); - } - - /** - * Extract a number of seconds, or -1 if none of the specified headers were present. - * - * @param includeRetryAfter - * if <code>true</code>, the Retry-After header is excluded. This is - * useful for processing non-error responses where a Retry-After - * header would be unexpected. - * @return the maximum of the three possible backoff headers, in seconds. - */ - public int totalBackoffInSeconds(boolean includeRetryAfter) { - int retryAfterInSeconds = -1; - if (includeRetryAfter) { - try { - retryAfterInSeconds = retryAfterInSeconds(); - } catch (NumberFormatException e) { - } - } - - int weaveBackoffInSeconds = -1; - try { - weaveBackoffInSeconds = weaveBackoffInSeconds(); - } catch (NumberFormatException e) { - } - - int backoffInSeconds = -1; - try { - backoffInSeconds = xBackoffInSeconds(); - } catch (NumberFormatException e) { - } - - int totalBackoff = Math.max(retryAfterInSeconds, Math.max(backoffInSeconds, weaveBackoffInSeconds)); - if (totalBackoff < 0) { - return -1; - } else { - return totalBackoff; - } - } - - /** - * @return A number of milliseconds, or -1 if neither the 'Retry-After', - * 'X-Backoff', or 'X-Weave-Backoff' header were present. - */ - public long totalBackoffInMilliseconds() { - long totalBackoff = totalBackoffInSeconds(true); - if (totalBackoff < 0) { - return -1; - } else { - return 1000 * totalBackoff; - } - } - - public long normalizedWeaveTimestamp() { - return normalizedTimestampForHeader(X_WEAVE_TIMESTAMP); - } - - /** - * Timestamps returned from a Sync server are decimal numbers of seconds, - * e.g., 1323393518.04. - * - * We want milliseconds since epoch. - * - * @return milliseconds since the epoch, as a long, or -1 if the header - * was missing or invalid. - */ - public long normalizedTimestampForHeader(String header) { - if (!this.hasHeader(header)) { - return -1; - } - - return Utils.decimalSecondsToMilliseconds( - this.response.getFirstHeader(header).getValue() - ); - } - - public int weaveRecords() throws NumberFormatException { - return this.getIntegerHeader(X_WEAVE_RECORDS); - } - - public int weaveQuotaRemaining() throws NumberFormatException { - return this.getIntegerHeader(X_WEAVE_QUOTA_REMAINING); - } - - public String weaveAlert() { - return this.getNonMissingHeader(X_WEAVE_ALERT); - } - - /** - * This header may be sent back with multi-record responses where the request included a limit parameter. - * Its presence indicates that the number of available records exceeded the given limit. - * The value from this header can be passed back in the offset parameter to retrieve additional records. - * The value of this header will always be a string of characters from the urlsafe-base64 alphabet. - * The specific contents of the string are an implementation detail of the server, - * so clients should treat it as an opaque token. - * - * @return the offset header - */ - public String weaveOffset() { - return this.getNonMissingHeader(X_WEAVE_NEXT_OFFSET); - } - - /** - * This header gives the last-modified time of the target resource as seen during processing of the request, - * and will be included in all success responses (200, 201, 204). - * When given in response to a write request, this will be equal to the server’s current time and - * to the new last-modified time of any BSOs created or changed by the request. - * It is similar to the standard HTTP Last-Modified header, - * but the value is a decimal timestamp rather than a HTTP-format date. - * - * @return the last modified header - */ - @Nullable - public String lastModified() { - return this.getNonMissingHeader(X_LAST_MODIFIED); - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageCollectionRequest.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageCollectionRequest.java deleted file mode 100644 index 3ae672f21..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageCollectionRequest.java +++ /dev/null @@ -1,145 +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.net; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URI; - -import org.mozilla.gecko.background.common.log.Logger; - -import ch.boye.httpclientandroidlib.Header; -import ch.boye.httpclientandroidlib.HttpEntity; -import ch.boye.httpclientandroidlib.HttpResponse; -import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase; -import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient; - -/** - * A request class that handles line-by-line responses. Eventually this will - * handle real stream processing; for now, just parse the returned body - * line-by-line. - * - * @author rnewman - * - */ -public class SyncStorageCollectionRequest extends SyncStorageRequest { - private static final String LOG_TAG = "CollectionRequest"; - - public SyncStorageCollectionRequest(URI uri) { - super(uri); - } - - protected volatile boolean aborting = false; - - /** - * Instruct the request that it should process no more records, - * and decline to notify any more delegate callbacks. - */ - public void abort() { - aborting = true; - try { - this.resource.request.abort(); - } catch (Exception e) { - // Just in case. - Logger.warn(LOG_TAG, "Got exception in abort: " + e); - } - } - - @Override - protected BaseResourceDelegate makeResourceDelegate(SyncStorageRequest request) { - return new SyncCollectionResourceDelegate((SyncStorageCollectionRequest) request); - } - - // TODO: this is awful. - public class SyncCollectionResourceDelegate extends - SyncStorageResourceDelegate { - - private static final String CONTENT_TYPE_INCREMENTAL = "application/newlines"; - private static final int FETCH_BUFFER_SIZE = 16 * 1024; // 16K chars. - - SyncCollectionResourceDelegate(SyncStorageCollectionRequest request) { - super(request); - } - - @Override - public void addHeaders(HttpRequestBase request, DefaultHttpClient client) { - super.addHeaders(request, client); - request.setHeader("Accept", CONTENT_TYPE_INCREMENTAL); - // Caller is responsible for setting full=1. - } - - @Override - public void handleHttpResponse(HttpResponse response) { - if (aborting) { - return; - } - - if (response.getStatusLine().getStatusCode() != 200) { - super.handleHttpResponse(response); - return; - } - - HttpEntity entity = response.getEntity(); - Header contentType = entity.getContentType(); - if (!contentType.getValue().startsWith(CONTENT_TYPE_INCREMENTAL)) { - // Not incremental! - super.handleHttpResponse(response); - return; - } - - // TODO: at this point we can access X-Weave-Timestamp, compare - // that to our local timestamp, and compute an estimate of clock - // skew. We can provide this to the incremental delegate, which - // will allow it to seamlessly correct timestamps on the records - // it processes. Bug 721887. - - // Line-by-line processing, then invoke success. - SyncStorageCollectionRequestDelegate delegate = (SyncStorageCollectionRequestDelegate) this.request.delegate; - InputStream content = null; - BufferedReader br = null; - try { - content = entity.getContent(); - br = new BufferedReader(new InputStreamReader(content), FETCH_BUFFER_SIZE); - String line; - - // This relies on connection timeouts at the HTTP layer. - while (!aborting && - null != (line = br.readLine())) { - try { - delegate.handleRequestProgress(line); - } catch (Exception ex) { - delegate.handleRequestError(new HandleProgressException(ex)); - BaseResource.consumeEntity(entity); - return; - } - } - if (aborting) { - // So we don't hit the success case below. - return; - } - } catch (IOException ex) { - if (!aborting) { - delegate.handleRequestError(ex); - } - BaseResource.consumeEntity(entity); - return; - } finally { - // Attempt to close the stream and reader. - if (br != null) { - try { - br.close(); - } catch (IOException e) { - // We don't care if this fails. - } - } - } - // We're done processing the entity. Don't let fetching the body succeed! - BaseResource.consumeEntity(entity); - delegate.handleRequestSuccess(new SyncStorageResponse(response)); - } - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageCollectionRequestDelegate.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageCollectionRequestDelegate.java deleted file mode 100644 index ddf52007b..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageCollectionRequestDelegate.java +++ /dev/null @@ -1,9 +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.net; - -public abstract class SyncStorageCollectionRequestDelegate implements - SyncStorageRequestIncrementalDelegate, SyncStorageRequestDelegate { -}
\ No newline at end of file diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageRecordRequest.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageRecordRequest.java deleted file mode 100644 index c18c4fe15..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageRecordRequest.java +++ /dev/null @@ -1,95 +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.net; - -import org.json.simple.JSONArray; -import org.json.simple.JSONObject; -import org.mozilla.gecko.sync.CryptoRecord; - -import java.io.UnsupportedEncodingException; -import java.net.URI; -import java.net.URISyntaxException; - -/** - * Resource class that implements expected headers and processing for Sync. - * Accepts a simplified delegate. - * - * Includes: - * * Basic Auth headers (via Resource) - * * Error responses: - * * 401 - * * 503 - * * Headers: - * * Retry-After - * * X-Weave-Backoff - * * X-Backoff - * * X-Weave-Records? - * * ... - * * Timeouts - * * Network errors - * * application/newlines - * * JSON parsing - * * Content-Type and Content-Length validation. - */ -public class SyncStorageRecordRequest extends SyncStorageRequest { - - public class SyncStorageRecordResourceDelegate extends SyncStorageResourceDelegate { - SyncStorageRecordResourceDelegate(SyncStorageRequest request) { - super(request); - } - } - - public SyncStorageRecordRequest(URI uri) { - super(uri); - } - - public SyncStorageRecordRequest(String url) throws URISyntaxException { - this(new URI(url)); - } - - @Override - protected BaseResourceDelegate makeResourceDelegate(SyncStorageRequest request) { - return new SyncStorageRecordResourceDelegate(request); - } - - @SuppressWarnings("unchecked") - public void post(JSONObject body) { - // Let's do this the trivial way for now. - // Note that POSTs should be an array, so we wrap here. - final JSONArray toPOST = new JSONArray(); - toPOST.add(body); - try { - this.resource.post(toPOST); - } catch (UnsupportedEncodingException e) { - this.delegate.handleRequestError(e); - } - } - - public void post(JSONArray body) { - // Let's do this the trivial way for now. - try { - this.resource.post(body); - } catch (UnsupportedEncodingException e) { - this.delegate.handleRequestError(e); - } - } - - public void put(JSONObject body) { - // Let's do this the trivial way for now. - try { - this.resource.put(body); - } catch (UnsupportedEncodingException e) { - this.delegate.handleRequestError(e); - } - } - - public void post(CryptoRecord record) { - this.post(record.toJSONObject()); - } - - public void put(CryptoRecord record) { - this.put(record.toJSONObject()); - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageRequest.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageRequest.java deleted file mode 100644 index 3ede9cded..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageRequest.java +++ /dev/null @@ -1,204 +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.net; - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.security.GeneralSecurityException; -import java.util.HashMap; - -import org.mozilla.gecko.background.common.log.Logger; -import org.mozilla.gecko.sync.SyncConstants; - -import ch.boye.httpclientandroidlib.HttpEntity; -import ch.boye.httpclientandroidlib.HttpResponse; -import ch.boye.httpclientandroidlib.client.ClientProtocolException; -import ch.boye.httpclientandroidlib.client.methods.HttpRequestBase; -import ch.boye.httpclientandroidlib.impl.client.DefaultHttpClient; - -public class SyncStorageRequest implements Resource { - public static HashMap<String, String> SERVER_ERROR_MESSAGES; - static { - HashMap<String, String> errors = new HashMap<String, String>(); - - // Sync protocol errors. - errors.put("1", "Illegal method/protocol"); - errors.put("2", "Incorrect/missing CAPTCHA"); - errors.put("3", "Invalid/missing username"); - errors.put("4", "Attempt to overwrite data that can't be overwritten (such as creating a user ID that already exists)"); - errors.put("5", "User ID does not match account in path"); - errors.put("6", "JSON parse failure"); - errors.put("7", "Missing password field"); - errors.put("8", "Invalid Weave Basic Object"); - errors.put("9", "Requested password not strong enough"); - errors.put("10", "Invalid/missing password reset code"); - errors.put("11", "Unsupported function"); - errors.put("12", "No email address on file"); - errors.put("13", "Invalid collection"); - errors.put("14", "User over quota"); - errors.put("15", "The email does not match the username"); - errors.put("16", "Client upgrade required"); - errors.put("255", "An unexpected server error occurred: pool is empty."); - - // Infrastructure-generated errors. - errors.put("\"server issue: getVS failed\"", "server issue: getVS failed"); - errors.put("\"server issue: prefix not set\"", "server issue: prefix not set"); - errors.put("\"server issue: host header not received from client\"", "server issue: host header not received from client"); - errors.put("\"server issue: database lookup failed\"", "server issue: database lookup failed"); - errors.put("\"server issue: database is not healthy\"", "server issue: database is not healthy"); - errors.put("\"server issue: database not in pool\"", "server issue: database not in pool"); - errors.put("\"server issue: database marked as down\"", "server issue: database marked as down"); - SERVER_ERROR_MESSAGES = errors; - } - public static String getServerErrorMessage(String body) { - if (SERVER_ERROR_MESSAGES.containsKey(body)) { - return SERVER_ERROR_MESSAGES.get(body); - } - return body; - } - - /** - * @param uri - * @throws URISyntaxException - */ - public SyncStorageRequest(String uri) throws URISyntaxException { - this(new URI(uri)); - } - - /** - * @param uri - */ - public SyncStorageRequest(URI uri) { - this.resource = new BaseResource(uri); - this.resourceDelegate = this.makeResourceDelegate(this); - this.resource.delegate = this.resourceDelegate; - } - - @Override - public URI getURI() { - return this.resource.getURI(); - } - - @Override - public String getURIString() { - return this.resource.getURIString(); - } - - @Override - public String getHostname() { - return this.resource.getHostname(); - } - - /** - * A ResourceDelegate that mediates between Resource-level notifications and the SyncStorageRequest. - */ - public class SyncStorageResourceDelegate extends BaseResourceDelegate { - private static final String LOG_TAG = "SSResourceDelegate"; - protected SyncStorageRequest request; - - SyncStorageResourceDelegate(SyncStorageRequest request) { - super(request); - this.request = request; - } - - @Override - public AuthHeaderProvider getAuthHeaderProvider() { - return request.delegate.getAuthHeaderProvider(); - } - - @Override - public String getUserAgent() { - return SyncConstants.USER_AGENT; - } - - @Override - public void handleHttpResponse(HttpResponse response) { - Logger.debug(LOG_TAG, "SyncStorageResourceDelegate handling response: " + response.getStatusLine() + "."); - SyncStorageRequestDelegate d = this.request.delegate; - SyncStorageResponse res = new SyncStorageResponse(response); - // It is the responsibility of the delegate handlers to completely consume the response. - // In context of a Sync storage response, success is either a 200 OK or 202 Accepted. - // 202 is returned during uploads of data in a batching mode, indicating that more is expected. - if (res.getStatusCode() == 200 || res.getStatusCode() == 202) { - d.handleRequestSuccess(res); - } else { - Logger.warn(LOG_TAG, "HTTP request failed."); - try { - Logger.warn(LOG_TAG, "HTTP response body: " + res.getErrorMessage()); - } catch (Exception e) { - Logger.error(LOG_TAG, "Can't fetch HTTP response body.", e); - } - d.handleRequestFailure(res); - } - } - - @Override - public void handleHttpProtocolException(ClientProtocolException e) { - this.request.delegate.handleRequestError(e); - } - - @Override - public void handleHttpIOException(IOException e) { - this.request.delegate.handleRequestError(e); - } - - @Override - public void handleTransportException(GeneralSecurityException e) { - this.request.delegate.handleRequestError(e); - } - - @Override - public void addHeaders(HttpRequestBase request, DefaultHttpClient client) { - // Clients can use their delegate interface to specify X-If-Unmodified-Since. - String ifUnmodifiedSince = this.request.delegate.ifUnmodifiedSince(); - if (ifUnmodifiedSince != null) { - Logger.debug(LOG_TAG, "Making request with X-If-Unmodified-Since = " + ifUnmodifiedSince); - request.setHeader("x-if-unmodified-since", ifUnmodifiedSince); - } - if (request.getMethod().equalsIgnoreCase("DELETE")) { - request.addHeader("x-confirm-delete", "1"); - } - } - } - - protected BaseResourceDelegate resourceDelegate; - public SyncStorageRequestDelegate delegate; - protected BaseResource resource; - - public SyncStorageRequest() { - super(); - } - - // Default implementation. Override this. - protected BaseResourceDelegate makeResourceDelegate(SyncStorageRequest request) { - return new SyncStorageResourceDelegate(request); - } - - @Override - public void get() { - this.resource.get(); - } - - @Override - public void delete() { - this.resource.delete(); - } - - @Override - public void post(HttpEntity body) { - this.resource.post(body); - } - - @Override - public void patch(HttpEntity body) { - this.resource.patch(body); - } - - @Override - public void put(HttpEntity body) { - this.resource.put(body); - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageRequestDelegate.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageRequestDelegate.java deleted file mode 100644 index 29f42cc28..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageRequestDelegate.java +++ /dev/null @@ -1,38 +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.net; - -public interface SyncStorageRequestDelegate { - public AuthHeaderProvider getAuthHeaderProvider(); - - String ifUnmodifiedSince(); - - // TODO: at this point we can access X-Weave-Timestamp, compare - // that to our local timestamp, and compute an estimate of clock - // skew. Bug 721887. - - /** - * Override this to handle a successful SyncStorageRequest. - * - * SyncStorageResourceDelegate implementers <b>must</b> ensure that the HTTP - * responses underlying SyncStorageResponses are fully consumed to ensure that - * connections are returned to the pool, for example by calling - * <code>BaseResource.consumeEntity(response)</code>. - */ - void handleRequestSuccess(SyncStorageResponse response); - - /** - * Override this to handle a failed SyncStorageRequest. - * - * - * SyncStorageResourceDelegate implementers <b>must</b> ensure that the HTTP - * responses underlying SyncStorageResponses are fully consumed to ensure that - * connections are returned to the pool, for example by calling - * <code>BaseResource.consumeEntity(response)</code>. - */ - void handleRequestFailure(SyncStorageResponse response); - - void handleRequestError(Exception ex); -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageRequestIncrementalDelegate.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageRequestIncrementalDelegate.java deleted file mode 100644 index aa5d735bf..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageRequestIncrementalDelegate.java +++ /dev/null @@ -1,9 +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.net; - -public interface SyncStorageRequestIncrementalDelegate { - void handleRequestProgress(String progress); // For line-by-line. -}
\ No newline at end of file diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageResponse.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageResponse.java deleted file mode 100644 index 644df314c..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/SyncStorageResponse.java +++ /dev/null @@ -1,85 +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.net; - -import java.io.IOException; -import java.util.HashMap; - -import org.mozilla.gecko.background.common.log.Logger; - -import ch.boye.httpclientandroidlib.HttpResponse; - -public class SyncStorageResponse extends SyncResponse { - private static final String LOG_TAG = "SyncStorageResponse"; - - // Responses that are actionable get constant status codes. - public static final String RESPONSE_CLIENT_UPGRADE_REQUIRED = "16"; - - public static HashMap<String, String> SERVER_ERROR_MESSAGES; - static { - HashMap<String, String> errors = new HashMap<String, String>(); - - // Sync protocol errors. - errors.put("1", "Illegal method/protocol"); - errors.put("2", "Incorrect/missing CAPTCHA"); - errors.put("3", "Invalid/missing username"); - errors.put("4", "Attempt to overwrite data that can't be overwritten (such as creating a user ID that already exists)"); - errors.put("5", "User ID does not match account in path"); - errors.put("6", "JSON parse failure"); - errors.put("7", "Missing password field"); - errors.put("8", "Invalid Weave Basic Object"); - errors.put("9", "Requested password not strong enough"); - errors.put("10", "Invalid/missing password reset code"); - errors.put("11", "Unsupported function"); - errors.put("12", "No email address on file"); - errors.put("13", "Invalid collection"); - errors.put("14", "User over quota"); - errors.put("15", "The email does not match the username"); - errors.put(RESPONSE_CLIENT_UPGRADE_REQUIRED, "Client upgrade required"); - errors.put("255", "An unexpected server error occurred: pool is empty."); - - // Infrastructure-generated errors. - errors.put("\"server issue: getVS failed\"", "server issue: getVS failed"); - errors.put("\"server issue: prefix not set\"", "server issue: prefix not set"); - errors.put("\"server issue: host header not received from client\"", "server issue: host header not received from client"); - errors.put("\"server issue: database lookup failed\"", "server issue: database lookup failed"); - errors.put("\"server issue: database is not healthy\"", "server issue: database is not healthy"); - errors.put("\"server issue: database not in pool\"", "server issue: database not in pool"); - errors.put("\"server issue: database marked as down\"", "server issue: database marked as down"); - SERVER_ERROR_MESSAGES = errors; - } - public static String getServerErrorMessage(String body) { - Logger.debug(LOG_TAG, "Looking up message for body \"" + body + "\""); - if (SERVER_ERROR_MESSAGES.containsKey(body)) { - return SERVER_ERROR_MESSAGES.get(body); - } - return body; - } - - - public SyncStorageResponse(HttpResponse res) { - super(res); - } - - public String getErrorMessage() throws IllegalStateException, IOException { - return SyncStorageResponse.getServerErrorMessage(this.body().trim()); - } - - /** - * This header gives the last-modified time of the target resource as seen during processing of - * the request, and will be included in all success responses (200, 201, 204). - * When given in response to a write request, this will be equal to the server’s current time and - * to the new last-modified time of any BSOs created or changed by the request. - */ - public String getLastModified() { - if (!response.containsHeader(X_LAST_MODIFIED)) { - return null; - } - return response.getFirstHeader(X_LAST_MODIFIED).getValue(); - } - - // TODO: Content-Type and Content-Length validation. - -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/TLSSocketFactory.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/TLSSocketFactory.java deleted file mode 100644 index dd68c0515..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/TLSSocketFactory.java +++ /dev/null @@ -1,62 +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.net; - -import java.io.IOException; -import java.net.Socket; - -import javax.net.ssl.SSLContext; -import javax.net.ssl.SSLSocket; - -import org.mozilla.gecko.background.common.GlobalConstants; -import org.mozilla.gecko.background.common.log.Logger; - -import ch.boye.httpclientandroidlib.conn.ssl.SSLSocketFactory; -import ch.boye.httpclientandroidlib.params.HttpParams; - -public class TLSSocketFactory extends SSLSocketFactory { - private static final String LOG_TAG = "TLSSocketFactory"; - - // Guarded by `this`. - private static String[] cipherSuites = GlobalConstants.DEFAULT_CIPHER_SUITES; - - public TLSSocketFactory(SSLContext sslContext) { - super(sslContext); - } - - /** - * Attempt to specify the cipher suites to use for a connection. If - * setting fails (as it will on Android 2.2, because the wrong names - * are in use to specify ciphers), attempt to set the defaults. - * - * We store the list of cipher suites in `cipherSuites`, which - * avoids this fallback handling having to be executed more than once. - * - * This method is synchronized to ensure correct use of that member. - * - * See Bug 717691 for more details. - * - * @param socket - * The SSLSocket on which to operate. - */ - public static synchronized void setEnabledCipherSuites(SSLSocket socket) { - try { - socket.setEnabledCipherSuites(cipherSuites); - } catch (IllegalArgumentException e) { - cipherSuites = socket.getSupportedCipherSuites(); - Logger.warn(LOG_TAG, "Setting enabled cipher suites failed: " + e.getMessage()); - Logger.warn(LOG_TAG, "Using " + cipherSuites.length + " supported suites."); - socket.setEnabledCipherSuites(cipherSuites); - } - } - - @Override - public Socket createSocket(HttpParams params) throws IOException { - SSLSocket socket = (SSLSocket) super.createSocket(params); - socket.setEnabledProtocols(GlobalConstants.DEFAULT_PROTOCOLS); - setEnabledCipherSuites(socket); - return socket; - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/WBOCollectionRequestDelegate.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/WBOCollectionRequestDelegate.java deleted file mode 100644 index 2e26f041b..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/WBOCollectionRequestDelegate.java +++ /dev/null @@ -1,35 +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.net; - -import org.mozilla.gecko.sync.crypto.KeyBundle; -import org.mozilla.gecko.sync.CryptoRecord; -import org.mozilla.gecko.sync.KeyBundleProvider; - -/** - * Subclass this to handle collection fetches. - * @author rnewman - * - */ -public abstract class WBOCollectionRequestDelegate -extends SyncStorageCollectionRequestDelegate -implements KeyBundleProvider { - - @Override - public abstract KeyBundle keyBundle(); - public abstract void handleWBO(CryptoRecord record); - - @Override - public void handleRequestProgress(String progress) { - try { - CryptoRecord record = CryptoRecord.fromJSONRecord(progress); - record.keyBundle = this.keyBundle(); - this.handleWBO(record); - } catch (Exception e) { - this.handleRequestError(e); - // TODO: abort?! Allow exception to propagate to fail? - } - } -} diff --git a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/WBORequestDelegate.java b/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/WBORequestDelegate.java deleted file mode 100644 index 8a09e0c7f..000000000 --- a/mobile/android/services/src/main/java/org/mozilla/gecko/sync/net/WBORequestDelegate.java +++ /dev/null @@ -1,14 +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.net; - -import org.mozilla.gecko.sync.KeyBundleProvider; -import org.mozilla.gecko.sync.crypto.KeyBundle; - -public abstract class WBORequestDelegate -implements SyncStorageRequestDelegate, KeyBundleProvider { - @Override - public abstract KeyBundle keyBundle(); -} |