mirror of
https://github.com/roytam1/palemoon27.git
synced 2026-06-03 09:40:06 +00:00
690 lines
22 KiB
Java
690 lines
22 KiB
Java
/* 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.reading;
|
|
|
|
import java.io.IOException;
|
|
import java.net.URI;
|
|
import java.net.URISyntaxException;
|
|
import java.security.GeneralSecurityException;
|
|
import java.util.Queue;
|
|
import java.util.concurrent.Executor;
|
|
|
|
import org.mozilla.gecko.background.ReadingListConstants;
|
|
import org.mozilla.gecko.background.common.log.Logger;
|
|
import org.mozilla.gecko.reading.ReadingListResponse.ResponseFactory;
|
|
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
|
import org.mozilla.gecko.sync.net.AuthHeaderProvider;
|
|
import org.mozilla.gecko.sync.net.BaseResource;
|
|
import org.mozilla.gecko.sync.net.BaseResourceDelegate;
|
|
import org.mozilla.gecko.sync.net.BasicAuthHeaderProvider;
|
|
import org.mozilla.gecko.sync.net.MozResponse;
|
|
import org.mozilla.gecko.sync.net.Resource;
|
|
|
|
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;
|
|
|
|
/**
|
|
* This client exposes an API for the reading list service, documented at
|
|
* https://github.com/mozilla-services/readinglist/
|
|
*/
|
|
public class ReadingListClient {
|
|
static final String LOG_TAG = ReadingListClient.class.getSimpleName();
|
|
private final AuthHeaderProvider auth;
|
|
|
|
private final URI articlesURI; // .../articles
|
|
private final URI articlesBaseURI; // .../articles/
|
|
|
|
/**
|
|
* Use a {@link BasicAuthHeaderProvider} for testing, and an FxA OAuth provider for the real service.
|
|
*/
|
|
public ReadingListClient(final URI serviceURI, final AuthHeaderProvider auth) {
|
|
this.articlesURI = serviceURI.resolve("articles");
|
|
this.articlesBaseURI = serviceURI.resolve("articles/");
|
|
this.auth = auth;
|
|
}
|
|
|
|
private BaseResource getRelativeArticleResource(final String rel) {
|
|
return new BaseResource(this.articlesBaseURI.resolve(rel));
|
|
}
|
|
|
|
private static final class DelegatingUploadResourceDelegate extends UploadResourceDelegate<ReadingListRecordResponse> {
|
|
private final ClientReadingListRecord up;
|
|
private final ReadingListRecordUploadDelegate uploadDelegate;
|
|
|
|
DelegatingUploadResourceDelegate(Resource resource,
|
|
AuthHeaderProvider auth,
|
|
ResponseFactory<ReadingListRecordResponse> factory,
|
|
ClientReadingListRecord up,
|
|
ReadingListRecordUploadDelegate uploadDelegate) {
|
|
super(resource, auth, factory);
|
|
this.up = up;
|
|
this.uploadDelegate = uploadDelegate;
|
|
}
|
|
|
|
@Override
|
|
void onFailure(MozResponse response) {
|
|
Logger.warn(LOG_TAG, "Upload got failure response " + response.httpResponse().getStatusLine());
|
|
response.logResponseBody(LOG_TAG);
|
|
if (response.getStatusCode() == 400) {
|
|
// Error response.
|
|
uploadDelegate.onBadRequest(up, response);
|
|
} else {
|
|
uploadDelegate.onFailure(up, response);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
void onFailure(Exception ex) {
|
|
Logger.warn(LOG_TAG, "Upload failed.", ex);
|
|
uploadDelegate.onFailure(up, ex);
|
|
}
|
|
|
|
@Override
|
|
void onSuccess(ReadingListRecordResponse response) {
|
|
Logger.debug(LOG_TAG, "Upload: onSuccess: " + response.httpResponse().getStatusLine());
|
|
final ServerReadingListRecord down;
|
|
try {
|
|
down = response.getRecord();
|
|
Logger.debug(LOG_TAG, "Upload succeeded. Got GUID " + down.getGUID());
|
|
} catch (Exception e) {
|
|
uploadDelegate.onFailure(up, e);
|
|
return;
|
|
}
|
|
|
|
uploadDelegate.onSuccess(up, response, down);
|
|
}
|
|
|
|
@Override
|
|
void onSeeOther(ReadingListRecordResponse response) {
|
|
uploadDelegate.onConflict(up, response);
|
|
}
|
|
}
|
|
|
|
private static abstract class ReadingListResourceDelegate<T extends ReadingListResponse> extends BaseResourceDelegate {
|
|
private final ReadingListResponse.ResponseFactory<T> factory;
|
|
private final AuthHeaderProvider auth;
|
|
|
|
public ReadingListResourceDelegate(Resource resource, AuthHeaderProvider auth, ReadingListResponse.ResponseFactory<T> factory) {
|
|
super(resource);
|
|
this.auth = auth;
|
|
this.factory = factory;
|
|
}
|
|
|
|
abstract void onSuccess(T response);
|
|
abstract void onNonSuccess(T response);
|
|
abstract void onFailure(MozResponse response);
|
|
abstract void onFailure(Exception ex);
|
|
|
|
@Override
|
|
public void handleHttpResponse(HttpResponse response) {
|
|
final T resp = factory.getResponse(response);
|
|
if (resp.wasSuccessful()) {
|
|
onSuccess(resp);
|
|
} else {
|
|
onNonSuccess(resp);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void handleTransportException(GeneralSecurityException e) {
|
|
onFailure(e);
|
|
}
|
|
|
|
@Override
|
|
public void handleHttpProtocolException(ClientProtocolException e) {
|
|
onFailure(e);
|
|
}
|
|
|
|
@Override
|
|
public void handleHttpIOException(IOException e) {
|
|
onFailure(e);
|
|
}
|
|
|
|
@Override
|
|
public String getUserAgent() {
|
|
return ReadingListConstants.USER_AGENT;
|
|
}
|
|
|
|
@Override
|
|
public AuthHeaderProvider getAuthHeaderProvider() {
|
|
return auth;
|
|
}
|
|
|
|
@Override
|
|
public void addHeaders(HttpRequestBase request, DefaultHttpClient client) {
|
|
}
|
|
}
|
|
|
|
/**
|
|
* An intermediate delegate class that handles all of the shared storage behavior,
|
|
* such as handling If-Modified-Since.
|
|
*/
|
|
private static abstract class StorageResourceDelegate<T extends ReadingListResponse> extends ReadingListResourceDelegate<T> {
|
|
private final long ifModifiedSince;
|
|
|
|
public StorageResourceDelegate(Resource resource,
|
|
AuthHeaderProvider auth,
|
|
ReadingListResponse.ResponseFactory<T> factory,
|
|
long ifModifiedSince) {
|
|
super(resource, auth, factory);
|
|
this.ifModifiedSince = ifModifiedSince;
|
|
}
|
|
|
|
@Override
|
|
public void addHeaders(HttpRequestBase request, DefaultHttpClient client) {
|
|
if (ifModifiedSince != -1L) {
|
|
// TODO: format?
|
|
request.addHeader("If-Modified-Since", "" + ifModifiedSince);
|
|
}
|
|
super.addHeaders(request, client);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Wraps the @{link ReadingListRecordDelegate} interface to yield a {@link StorageResourceDelegate}.
|
|
*/
|
|
private static abstract class RecordResourceDelegate<T extends ReadingListResponse> extends StorageResourceDelegate<T> {
|
|
protected final ReadingListRecordDelegate recordDelegate;
|
|
|
|
public RecordResourceDelegate(Resource resource,
|
|
AuthHeaderProvider auth,
|
|
ReadingListRecordDelegate recordDelegate,
|
|
ReadingListResponse.ResponseFactory<T> factory,
|
|
long ifModifiedSince) {
|
|
super(resource, auth, factory, ifModifiedSince);
|
|
this.recordDelegate = recordDelegate;
|
|
}
|
|
|
|
abstract void onNotFound(ReadingListResponse resp);
|
|
|
|
@Override
|
|
void onNonSuccess(T resp) {
|
|
Logger.debug(LOG_TAG, "Got non-success record response " + resp.getStatusCode());
|
|
resp.logResponseBody(LOG_TAG);
|
|
|
|
switch (resp.getStatusCode()) {
|
|
case 304:
|
|
onNotModified(resp);
|
|
break;
|
|
case 404:
|
|
onNotFound(resp);
|
|
break;
|
|
default:
|
|
onFailure(resp);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
void onFailure(MozResponse response) {
|
|
recordDelegate.onFailure(response);
|
|
}
|
|
|
|
@Override
|
|
void onFailure(Exception ex) {
|
|
recordDelegate.onFailure(ex);
|
|
}
|
|
|
|
void onNotModified(T resp) {
|
|
recordDelegate.onComplete(resp);
|
|
}
|
|
}
|
|
|
|
private static final class SingleRecordResourceDelegate extends RecordResourceDelegate<ReadingListRecordResponse> {
|
|
private final String guid;
|
|
|
|
SingleRecordResourceDelegate(Resource resource,
|
|
AuthHeaderProvider auth,
|
|
ReadingListRecordDelegate recordDelegate,
|
|
ResponseFactory<ReadingListRecordResponse> factory,
|
|
long ifModifiedSince, String guid) {
|
|
super(resource, auth, recordDelegate, factory, ifModifiedSince);
|
|
this.guid = guid;
|
|
}
|
|
|
|
@Override
|
|
void onSuccess(ReadingListRecordResponse response) {
|
|
final ServerReadingListRecord record;
|
|
try {
|
|
record = response.getRecord();
|
|
} catch (Exception e) {
|
|
recordDelegate.onFailure(e);
|
|
return;
|
|
}
|
|
|
|
recordDelegate.onRecordReceived(record);
|
|
recordDelegate.onComplete(response);
|
|
}
|
|
|
|
@Override
|
|
void onNotFound(ReadingListResponse resp) {
|
|
recordDelegate.onRecordMissingOrDeleted(guid, resp);
|
|
}
|
|
}
|
|
|
|
private static final class MultipleRecordResourceDelegate extends RecordResourceDelegate<ReadingListStorageResponse> {
|
|
MultipleRecordResourceDelegate(Resource resource,
|
|
AuthHeaderProvider auth,
|
|
ReadingListRecordDelegate recordDelegate,
|
|
ResponseFactory<ReadingListStorageResponse> factory,
|
|
long ifModifiedSince) {
|
|
super(resource, auth, recordDelegate, factory, ifModifiedSince);
|
|
}
|
|
|
|
@Override
|
|
void onSuccess(ReadingListStorageResponse response) {
|
|
try {
|
|
final Iterable<ServerReadingListRecord> records = response.getRecords();
|
|
for (ServerReadingListRecord readingListRecord : records) {
|
|
recordDelegate.onRecordReceived(readingListRecord);
|
|
}
|
|
} catch (Exception e) {
|
|
recordDelegate.onFailure(e);
|
|
return;
|
|
}
|
|
|
|
recordDelegate.onComplete(response);
|
|
}
|
|
|
|
@Override
|
|
void onNotFound(ReadingListResponse resp) {
|
|
// Should not occur against articlesURI root.
|
|
recordDelegate.onFailure(resp);
|
|
}
|
|
}
|
|
|
|
private static abstract class UploadResourceDelegate<T extends ReadingListResponse> extends StorageResourceDelegate<T> {
|
|
public UploadResourceDelegate(Resource resource,
|
|
AuthHeaderProvider auth,
|
|
ReadingListResponse.ResponseFactory<T> factory,
|
|
long ifModifiedSince) {
|
|
super(resource, auth, factory, ifModifiedSince);
|
|
}
|
|
|
|
public UploadResourceDelegate(Resource resource,
|
|
AuthHeaderProvider auth,
|
|
ReadingListResponse.ResponseFactory<T> factory) {
|
|
this(resource, auth, factory, -1L);
|
|
}
|
|
|
|
@Override
|
|
void onNonSuccess(T resp) {
|
|
if (resp.getStatusCode() == 303) {
|
|
onSeeOther(resp);
|
|
return;
|
|
}
|
|
onFailure(resp);
|
|
}
|
|
|
|
abstract void onSeeOther(T resp);
|
|
}
|
|
|
|
|
|
/**
|
|
* Recursively calls `patch` with items from the queue, delivering callbacks
|
|
* to the provided delegate. Calls `onBatchDone` when the queue is exhausted.
|
|
*
|
|
* Uses the provided executor to flatten the recursive call stack.
|
|
*/
|
|
private abstract class BatchingUploadDelegate implements ReadingListRecordUploadDelegate {
|
|
private final Queue<ClientReadingListRecord> queue;
|
|
private final ReadingListRecordUploadDelegate batchUploadDelegate;
|
|
private final Executor executor;
|
|
|
|
BatchingUploadDelegate(Queue<ClientReadingListRecord> queue,
|
|
ReadingListRecordUploadDelegate batchUploadDelegate,
|
|
Executor executor) {
|
|
this.queue = queue;
|
|
this.batchUploadDelegate = batchUploadDelegate;
|
|
this.executor = executor;
|
|
}
|
|
|
|
abstract void again(ClientReadingListRecord record);
|
|
|
|
void next() {
|
|
final ClientReadingListRecord record = queue.poll();
|
|
executor.execute(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
if (record == null) {
|
|
batchUploadDelegate.onBatchDone();
|
|
return;
|
|
}
|
|
|
|
again(record);
|
|
}
|
|
});
|
|
}
|
|
|
|
@Override
|
|
public void onSuccess(ClientReadingListRecord up,
|
|
ReadingListRecordResponse response,
|
|
ServerReadingListRecord down) {
|
|
batchUploadDelegate.onSuccess(up, response, down);
|
|
next();
|
|
}
|
|
|
|
@Override
|
|
public void onInvalidUpload(ClientReadingListRecord up,
|
|
ReadingListResponse response) {
|
|
batchUploadDelegate.onInvalidUpload(up, response);
|
|
next();
|
|
}
|
|
|
|
@Override
|
|
public void onFailure(ClientReadingListRecord up, MozResponse response) {
|
|
batchUploadDelegate.onFailure(up, response);
|
|
next();
|
|
}
|
|
|
|
@Override
|
|
public void onFailure(ClientReadingListRecord up, Exception ex) {
|
|
batchUploadDelegate.onFailure(up, ex);
|
|
next();
|
|
}
|
|
|
|
@Override
|
|
public void onConflict(ClientReadingListRecord up,
|
|
ReadingListResponse response) {
|
|
batchUploadDelegate.onConflict(up, response);
|
|
next();
|
|
}
|
|
|
|
@Override
|
|
public void onBadRequest(ClientReadingListRecord up, MozResponse response) {
|
|
batchUploadDelegate.onBadRequest(up, response);
|
|
next();
|
|
}
|
|
|
|
@Override
|
|
public void onBatchDone() {
|
|
// This should never occur, but if it does, pass through.
|
|
batchUploadDelegate.onBatchDone();
|
|
}
|
|
}
|
|
|
|
private class PostBatchingUploadDelegate extends BatchingUploadDelegate {
|
|
PostBatchingUploadDelegate(Queue<ClientReadingListRecord> queue,
|
|
ReadingListRecordUploadDelegate batchUploadDelegate,
|
|
Executor executor) {
|
|
super(queue, batchUploadDelegate, executor);
|
|
}
|
|
|
|
@Override
|
|
void again(ClientReadingListRecord record) {
|
|
add(record, PostBatchingUploadDelegate.this);
|
|
}
|
|
}
|
|
|
|
private class PatchBatchingUploadDelegate extends BatchingUploadDelegate {
|
|
PatchBatchingUploadDelegate(Queue<ClientReadingListRecord> queue,
|
|
ReadingListRecordUploadDelegate batchUploadDelegate,
|
|
Executor executor) {
|
|
super(queue, batchUploadDelegate, executor);
|
|
}
|
|
|
|
@Override
|
|
void again(ClientReadingListRecord record) {
|
|
patch(record, PatchBatchingUploadDelegate.this);
|
|
}
|
|
}
|
|
|
|
private class DeleteBatchingDelegate implements ReadingListDeleteDelegate {
|
|
private final Queue<String> queue;
|
|
private final ReadingListDeleteDelegate batchDeleteDelegate;
|
|
private final Executor executor;
|
|
|
|
DeleteBatchingDelegate(Queue<String> guids,
|
|
ReadingListDeleteDelegate batchDeleteDelegate,
|
|
Executor executor) {
|
|
this.queue = guids;
|
|
this.batchDeleteDelegate = batchDeleteDelegate;
|
|
this.executor = executor;
|
|
}
|
|
|
|
void next() {
|
|
final String guid = queue.poll();
|
|
executor.execute(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
if (guid == null) {
|
|
batchDeleteDelegate.onBatchDone();
|
|
return;
|
|
}
|
|
|
|
again(guid);
|
|
}
|
|
});
|
|
}
|
|
|
|
void again(String guid) {
|
|
delete(guid, DeleteBatchingDelegate.this, -1L);
|
|
}
|
|
|
|
@Override
|
|
public void onSuccess(ReadingListRecordResponse response,
|
|
ReadingListRecord record) {
|
|
batchDeleteDelegate.onSuccess(response, record);
|
|
next();
|
|
}
|
|
|
|
@Override
|
|
public void onPreconditionFailed(String guid, MozResponse response) {
|
|
batchDeleteDelegate.onPreconditionFailed(guid, response);
|
|
next();
|
|
}
|
|
|
|
@Override
|
|
public void onRecordMissingOrDeleted(String guid, MozResponse response) {
|
|
batchDeleteDelegate.onRecordMissingOrDeleted(guid, response);
|
|
next();
|
|
}
|
|
|
|
@Override
|
|
public void onFailure(Exception e) {
|
|
batchDeleteDelegate.onFailure(e);
|
|
next();
|
|
}
|
|
|
|
@Override
|
|
public void onFailure(MozResponse response) {
|
|
batchDeleteDelegate.onFailure(response);
|
|
next();
|
|
}
|
|
|
|
@Override
|
|
public void onBatchDone() {
|
|
// This should never occur, but if it does, pass through.
|
|
batchDeleteDelegate.onBatchDone();
|
|
}
|
|
}
|
|
|
|
// Deliberately declare `delegate` non-final so we can't capture it below. We prefer
|
|
// to use `recordDelegate` explicitly.
|
|
public void getOne(final String guid, ReadingListRecordDelegate delegate, final long ifModifiedSince) {
|
|
final BaseResource r = getRelativeArticleResource(guid);
|
|
r.delegate = new SingleRecordResourceDelegate(r, auth, delegate, ReadingListRecordResponse.FACTORY, ifModifiedSince, guid);
|
|
if (ReadingListConstants.DEBUG) {
|
|
Logger.info(LOG_TAG, "Getting record " + guid);
|
|
}
|
|
r.get();
|
|
}
|
|
|
|
// Deliberately declare `delegate` non-final so we can't capture it below. We prefer
|
|
// to use `recordDelegate` explicitly.
|
|
public void getAll(final FetchSpec spec, ReadingListRecordDelegate delegate, final long ifModifiedSince) throws URISyntaxException {
|
|
final BaseResource r = new BaseResource(spec.getURI(this.articlesURI));
|
|
r.delegate = new MultipleRecordResourceDelegate(r, auth, delegate, ReadingListStorageResponse.FACTORY, ifModifiedSince);
|
|
if (ReadingListConstants.DEBUG) {
|
|
Logger.info(LOG_TAG, "Getting all records from " + r.getURIString());
|
|
}
|
|
r.get();
|
|
}
|
|
|
|
/**
|
|
* Mutates the provided queue.
|
|
*/
|
|
public void patch(final Queue<ClientReadingListRecord> queue, final Executor executor, final ReadingListRecordUploadDelegate batchUploadDelegate) {
|
|
if (queue.isEmpty()) {
|
|
batchUploadDelegate.onBatchDone();
|
|
return;
|
|
}
|
|
|
|
final ReadingListRecordUploadDelegate uploadDelegate = new PatchBatchingUploadDelegate(queue, batchUploadDelegate, executor);
|
|
|
|
patch(queue.poll(), uploadDelegate);
|
|
}
|
|
|
|
public void patch(final ClientReadingListRecord up, final ReadingListRecordUploadDelegate uploadDelegate) {
|
|
final String guid = up.getGUID();
|
|
if (guid == null) {
|
|
uploadDelegate.onFailure(up, new IllegalArgumentException("Supplied record must have a GUID."));
|
|
return;
|
|
}
|
|
|
|
final BaseResource r = getRelativeArticleResource(guid);
|
|
r.delegate = new DelegatingUploadResourceDelegate(r, auth, ReadingListRecordResponse.FACTORY, up,
|
|
uploadDelegate);
|
|
|
|
final ExtendedJSONObject body = up.toJSON();
|
|
if (ReadingListConstants.DEBUG) {
|
|
Logger.info(LOG_TAG, "Patching record " + guid + ": " + body.toJSONString());
|
|
}
|
|
r.patch(body);
|
|
}
|
|
|
|
/**
|
|
* Mutates the provided queue.
|
|
*/
|
|
public void add(final Queue<ClientReadingListRecord> queue, final Executor executor, final ReadingListRecordUploadDelegate batchUploadDelegate) {
|
|
if (queue.isEmpty()) {
|
|
batchUploadDelegate.onBatchDone();
|
|
return;
|
|
}
|
|
|
|
final ReadingListRecordUploadDelegate uploadDelegate = new PostBatchingUploadDelegate(queue, batchUploadDelegate, executor);
|
|
|
|
add(queue.poll(), uploadDelegate);
|
|
}
|
|
|
|
public void add(final ClientReadingListRecord up, final ReadingListRecordUploadDelegate uploadDelegate) {
|
|
final BaseResource r = new BaseResource(this.articlesURI);
|
|
r.delegate = new DelegatingUploadResourceDelegate(r, auth, ReadingListRecordResponse.FACTORY, up,
|
|
uploadDelegate);
|
|
|
|
final ExtendedJSONObject body = up.toJSON();
|
|
if (ReadingListConstants.DEBUG) {
|
|
Logger.info(LOG_TAG, "Uploading new record: " + body.toJSONString());
|
|
}
|
|
r.post(body);
|
|
}
|
|
|
|
public void delete(final Queue<String> guids, final Executor executor, final ReadingListDeleteDelegate batchDeleteDelegate) {
|
|
if (guids.isEmpty()) {
|
|
batchDeleteDelegate.onBatchDone();
|
|
return;
|
|
}
|
|
|
|
final ReadingListDeleteDelegate deleteDelegate = new DeleteBatchingDelegate(guids, batchDeleteDelegate, executor);
|
|
|
|
delete(guids.poll(), deleteDelegate, -1L);
|
|
}
|
|
|
|
public void delete(final String guid, final ReadingListDeleteDelegate delegate, final long ifUnmodifiedSince) {
|
|
final BaseResource r = getRelativeArticleResource(guid);
|
|
|
|
// If If-Unmodified-Since is provided, and the record has been modified,
|
|
// we'll receive a 412 Precondition Failed.
|
|
// If the record is missing or already deleted, a 404 will be returned.
|
|
// Otherwise, the response will be the deleted record.
|
|
r.delegate = new ReadingListResourceDelegate<ReadingListRecordResponse>(r, auth, ReadingListRecordResponse.FACTORY) {
|
|
@Override
|
|
public void addHeaders(HttpRequestBase request, DefaultHttpClient client) {
|
|
if (ifUnmodifiedSince != -1) {
|
|
request.addHeader("If-Unmodified-Since", "" + ifUnmodifiedSince);
|
|
}
|
|
super.addHeaders(request, client);
|
|
}
|
|
|
|
@Override
|
|
void onFailure(MozResponse response) {
|
|
switch (response.getStatusCode()) {
|
|
case 412:
|
|
delegate.onPreconditionFailed(guid, response);
|
|
return;
|
|
}
|
|
delegate.onFailure(response);
|
|
}
|
|
|
|
@Override
|
|
void onSuccess(ReadingListRecordResponse response) {
|
|
final ReadingListRecord record;
|
|
try {
|
|
record = response.getRecord();
|
|
} catch (Exception e) {
|
|
delegate.onFailure(e);
|
|
return;
|
|
}
|
|
|
|
delegate.onSuccess(response, record);
|
|
}
|
|
|
|
@Override
|
|
void onFailure(Exception ex) {
|
|
delegate.onFailure(ex);
|
|
}
|
|
|
|
@Override
|
|
void onNonSuccess(ReadingListRecordResponse response) {
|
|
if (response.getStatusCode() == 404) {
|
|
// Already deleted!
|
|
delegate.onRecordMissingOrDeleted(guid, response);
|
|
}
|
|
}
|
|
};
|
|
|
|
if (ReadingListConstants.DEBUG) {
|
|
Logger.debug(LOG_TAG, "Deleting " + r.getURIString());
|
|
}
|
|
r.delete();
|
|
}
|
|
|
|
// TODO: modified times etc.
|
|
public void wipe(final ReadingListWipeDelegate delegate) {
|
|
Logger.info(LOG_TAG, "Wiping server.");
|
|
final BaseResource r = new BaseResource(this.articlesURI);
|
|
|
|
r.delegate = new ReadingListResourceDelegate<ReadingListStorageResponse>(r, auth, ReadingListStorageResponse.FACTORY) {
|
|
|
|
@Override
|
|
void onSuccess(ReadingListStorageResponse response) {
|
|
Logger.info(LOG_TAG, "Wipe succeded.");
|
|
delegate.onSuccess(response);
|
|
}
|
|
|
|
@Override
|
|
void onNonSuccess(ReadingListStorageResponse response) {
|
|
Logger.warn(LOG_TAG, "Wipe failed: " + response.getStatusCode());
|
|
onFailure(response);
|
|
}
|
|
|
|
@Override
|
|
void onFailure(MozResponse response) {
|
|
Logger.warn(LOG_TAG, "Wipe failed: " + response.getStatusCode());
|
|
delegate.onFailure(response);
|
|
}
|
|
|
|
@Override
|
|
void onFailure(Exception ex) {
|
|
Logger.warn(LOG_TAG, "Wipe failed.", ex);
|
|
delegate.onFailure(ex);
|
|
}
|
|
};
|
|
|
|
r.delete();
|
|
}
|
|
}
|