/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
* 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.push;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.mozilla.gecko.push.RegisterUserAgentResponse;
import org.mozilla.gecko.push.SubscribeChannelResponse;
import org.mozilla.gecko.push.autopush.AutopushClient;
import org.mozilla.gecko.push.autopush.AutopushClientException;
import org.mozilla.gecko.sync.Utils;
import java.util.concurrent.Executor;
/**
* This class bridges the autopush client, which is written in callback style, with the Fennec
* push implementation, which is written in a linear style. It handles returning results and
* re-throwing exceptions passed as messages.
*
* TODO: fold this into the autopush client directly.
*/
public class PushClient {
public static class LocalException extends Exception {
private static final long serialVersionUID = 2387554736L;
public LocalException(Throwable throwable) {
super(throwable);
}
}
private final AutopushClient autopushClient;
public PushClient(String serverURI) {
this.autopushClient = new AutopushClient(serverURI, Utils.newSynchronousExecutor());
}
/**
* Each instance is single-use! Exactly one delegate method should be invoked once,
* but we take care to handle multiple invocations (favoring the earliest), just to be safe.
*/
protected static class Delegate implements AutopushClient.RequestDelegate {
Object result; // Oh, for an algebraic data type when you need one!
@SuppressWarnings("unchecked")
public T responseOrThrow() throws LocalException, AutopushClientException {
if (result instanceof LocalException) {
throw (LocalException) result;
}
if (result instanceof AutopushClientException) {
throw (AutopushClientException) result;
}
return (T) result;
}
@Override
public void handleError(Exception e) {
if (result == null) {
result = new LocalException(e);
}
}
@Override
public void handleFailure(AutopushClientException e) {
if (result == null) {
result = e;
}
}
@Override
public void handleSuccess(T response) {
if (result == null) {
result = response;
}
}
}
public RegisterUserAgentResponse registerUserAgent(@NonNull String token) throws LocalException, AutopushClientException {
final Delegate delegate = new Delegate<>();
autopushClient.registerUserAgent(token, delegate);
return delegate.responseOrThrow();
}
public void reregisterUserAgent(@NonNull String uaid, @NonNull String secret, @NonNull String token) throws LocalException, AutopushClientException {
final Delegate delegate = new Delegate<>();
autopushClient.reregisterUserAgent(uaid, secret, token, delegate);
delegate.responseOrThrow(); // For side-effects only.
}
public void unregisterUserAgent(@NonNull String uaid, @NonNull String secret) throws LocalException, AutopushClientException {
final Delegate delegate = new Delegate<>();
autopushClient.unregisterUserAgent(uaid, secret, delegate);
delegate.responseOrThrow(); // For side-effects only.
}
public SubscribeChannelResponse subscribeChannel(@NonNull String uaid, @NonNull String secret, @Nullable String appServerKey) throws LocalException, AutopushClientException {
final Delegate delegate = new Delegate<>();
autopushClient.subscribeChannel(uaid, secret, appServerKey, delegate);
return delegate.responseOrThrow();
}
public void unsubscribeChannel(@NonNull String uaid, @NonNull String secret, @NonNull String chid) throws LocalException, AutopushClientException {
final Delegate delegate = new Delegate<>();
autopushClient.unsubscribeChannel(uaid, secret, chid, delegate);
delegate.responseOrThrow(); // For side-effects only.
}
}