зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1372655 - Notify other clients when uploading the local clients record for the first time. r=Grisha
MozReview-Commit-ID: HepBI6cbV3J --HG-- extra : rebase_source : 621fd761f51697605c16d16a38d2a77dd98ab6a6
This commit is contained in:
Родитель
f623d60510
Коммит
5beff3890e
|
@ -11,8 +11,6 @@ import org.mozilla.gecko.background.fxa.FxAccountClient20.TwoKeys;
|
||||||
import org.mozilla.gecko.fxa.devices.FxAccountDevice;
|
import org.mozilla.gecko.fxa.devices.FxAccountDevice;
|
||||||
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
import org.mozilla.gecko.sync.ExtendedJSONObject;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface FxAccountClient {
|
public interface FxAccountClient {
|
||||||
public void accountStatus(String uid, RequestDelegate<AccountStatusResponse> requestDelegate);
|
public void accountStatus(String uid, RequestDelegate<AccountStatusResponse> requestDelegate);
|
||||||
public void recoveryEmailStatus(byte[] sessionToken, RequestDelegate<RecoveryEmailStatusResponse> requestDelegate);
|
public void recoveryEmailStatus(byte[] sessionToken, RequestDelegate<RecoveryEmailStatusResponse> requestDelegate);
|
||||||
|
@ -21,5 +19,5 @@ public interface FxAccountClient {
|
||||||
public void registerOrUpdateDevice(byte[] sessionToken, FxAccountDevice device, RequestDelegate<FxAccountDevice> requestDelegate);
|
public void registerOrUpdateDevice(byte[] sessionToken, FxAccountDevice device, RequestDelegate<FxAccountDevice> requestDelegate);
|
||||||
public void destroyDevice(byte[] sessionToken, String deviceId, RequestDelegate<ExtendedJSONObject> requestDelegate);
|
public void destroyDevice(byte[] sessionToken, String deviceId, RequestDelegate<ExtendedJSONObject> requestDelegate);
|
||||||
public void deviceList(byte[] sessionToken, RequestDelegate<FxAccountDevice[]> requestDelegate);
|
public void deviceList(byte[] sessionToken, RequestDelegate<FxAccountDevice[]> requestDelegate);
|
||||||
public void notifyDevices(byte[] sessionToken, List<String> deviceIds, ExtendedJSONObject payload, Long TTL, RequestDelegate<ExtendedJSONObject> requestDelegate);
|
public void notifyDevices(byte[] sessionToken, ExtendedJSONObject body, RequestDelegate<ExtendedJSONObject> delegate);
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,7 +35,6 @@ import java.security.InvalidKeyException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
@ -898,7 +897,7 @@ public class FxAccountClient20 implements FxAccountClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyDevices(@NonNull byte[] sessionToken, @NonNull List<String> deviceIds, ExtendedJSONObject payload, Long TTL, RequestDelegate<ExtendedJSONObject> delegate) {
|
public void notifyDevices(@NonNull byte[] sessionToken, ExtendedJSONObject body, RequestDelegate<ExtendedJSONObject> delegate) {
|
||||||
final byte[] tokenId = new byte[32];
|
final byte[] tokenId = new byte[32];
|
||||||
final byte[] reqHMACKey = new byte[32];
|
final byte[] reqHMACKey = new byte[32];
|
||||||
final byte[] requestKey = new byte[32];
|
final byte[] requestKey = new byte[32];
|
||||||
|
@ -910,7 +909,6 @@ public class FxAccountClient20 implements FxAccountClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
final BaseResource resource;
|
final BaseResource resource;
|
||||||
final ExtendedJSONObject body = createNotifyDevicesBody(deviceIds, payload, TTL);
|
|
||||||
try {
|
try {
|
||||||
resource = getBaseResource("account/devices/notify");
|
resource = getBaseResource("account/devices/notify");
|
||||||
} catch (URISyntaxException | UnsupportedEncodingException e) {
|
} catch (URISyntaxException | UnsupportedEncodingException e) {
|
||||||
|
@ -931,20 +929,4 @@ public class FxAccountClient20 implements FxAccountClient {
|
||||||
|
|
||||||
post(resource, body);
|
post(resource, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private ExtendedJSONObject createNotifyDevicesBody(@NonNull List<String> deviceIds, ExtendedJSONObject payload, Long TTL) {
|
|
||||||
final ExtendedJSONObject body = new ExtendedJSONObject();
|
|
||||||
final JSONArray to = new JSONArray();
|
|
||||||
to.addAll(deviceIds);
|
|
||||||
body.put("to", to);
|
|
||||||
if (payload != null) {
|
|
||||||
body.put("payload", payload);
|
|
||||||
}
|
|
||||||
if (TTL != null) {
|
|
||||||
body.put("TTL", TTL);
|
|
||||||
}
|
|
||||||
return body;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,6 +128,9 @@ public class SyncClientsEngineStage extends AbstractSessionManagingSyncStage {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleRequestSuccess(SyncStorageResponse response) {
|
public void handleRequestSuccess(SyncStorageResponse response) {
|
||||||
|
final Context context = session.getContext();
|
||||||
|
final Account account = FirefoxAccounts.getFirefoxAccount(context);
|
||||||
|
final AndroidFxAccount fxAccount = new AndroidFxAccount(context, account);
|
||||||
|
|
||||||
// Hang onto the server's last modified timestamp to use
|
// Hang onto the server's last modified timestamp to use
|
||||||
// in X-If-Unmodified-Since for upload.
|
// in X-If-Unmodified-Since for upload.
|
||||||
|
@ -139,9 +142,11 @@ public class SyncClientsEngineStage extends AbstractSessionManagingSyncStage {
|
||||||
|
|
||||||
// If we successfully downloaded all records but ours was not one of them
|
// If we successfully downloaded all records but ours was not one of them
|
||||||
// then reset the timestamp.
|
// then reset the timestamp.
|
||||||
|
boolean isFirstLocalClientRecordUpload = false;
|
||||||
if (!localAccountGUIDDownloaded) {
|
if (!localAccountGUIDDownloaded) {
|
||||||
Logger.info(LOG_TAG, "Local client GUID does not exist on the server. Upload timestamp will be reset.");
|
Logger.info(LOG_TAG, "Local client GUID does not exist on the server. Upload timestamp will be reset.");
|
||||||
session.config.persistServerClientRecordTimestamp(0);
|
session.config.persistServerClientRecordTimestamp(0);
|
||||||
|
isFirstLocalClientRecordUpload = true;
|
||||||
}
|
}
|
||||||
localAccountGUIDDownloaded = false;
|
localAccountGUIDDownloaded = false;
|
||||||
|
|
||||||
|
@ -176,25 +181,31 @@ public class SyncClientsEngineStage extends AbstractSessionManagingSyncStage {
|
||||||
// before we actually uploaded the records
|
// before we actually uploaded the records
|
||||||
uploadRemoteRecords();
|
uploadRemoteRecords();
|
||||||
|
|
||||||
// Notify the clients who got their record written
|
// We will send a push notification later anyway.
|
||||||
notifyClients(devicesToNotify);
|
if (!isFirstLocalClientRecordUpload) {
|
||||||
|
// Notify the clients who got their record written
|
||||||
|
notifyClients(fxAccount, devicesToNotify);
|
||||||
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
checkAndUpload();
|
checkAndUpload();
|
||||||
|
if (isFirstLocalClientRecordUpload) {
|
||||||
|
notifyAllClients(fxAccount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifyClients(final List<String> devicesToNotify) {
|
private void notifyClients(@NonNull AndroidFxAccount fxAccount, @NonNull List<String> devicesToNotify) {
|
||||||
final ExecutorService executor = Executors.newSingleThreadExecutor();
|
final ExtendedJSONObject body = createNotifyClientsBody(devicesToNotify);
|
||||||
final Context context = session.getContext();
|
notifyClientsHelper(fxAccount, body);
|
||||||
final Account account = FirefoxAccounts.getFirefoxAccount(context);
|
}
|
||||||
if (account == null) {
|
|
||||||
Log.e(LOG_TAG, "Can't notify other clients: no account");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final AndroidFxAccount fxAccount = new AndroidFxAccount(context, account);
|
|
||||||
final ExtendedJSONObject payload = createNotifyDevicesPayload();
|
|
||||||
|
|
||||||
|
private void notifyAllClients(@NonNull AndroidFxAccount fxAccount) {
|
||||||
|
final ExtendedJSONObject body = createNotifyAllClientsBody(fxAccount.getDeviceId());
|
||||||
|
notifyClientsHelper(fxAccount, body);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyClientsHelper(@NonNull AndroidFxAccount fxAccount, @NonNull ExtendedJSONObject body) {
|
||||||
final byte[] sessionToken;
|
final byte[] sessionToken;
|
||||||
try {
|
try {
|
||||||
sessionToken = fxAccount.getState().getSessionToken();
|
sessionToken = fxAccount.getState().getSessionToken();
|
||||||
|
@ -205,9 +216,10 @@ public class SyncClientsEngineStage extends AbstractSessionManagingSyncStage {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final ExecutorService executor = Executors.newSingleThreadExecutor();
|
||||||
// API doc : https://github.com/mozilla/fxa-auth-server/blob/master/docs/api.md#post-v1accountdevicesnotify
|
// API doc : https://github.com/mozilla/fxa-auth-server/blob/master/docs/api.md#post-v1accountdevicesnotify
|
||||||
final FxAccountClient fxAccountClient = new FxAccountClient20(fxAccount.getAccountServerURI(), executor);
|
final FxAccountClient fxAccountClient = new FxAccountClient20(fxAccount.getAccountServerURI(), executor);
|
||||||
fxAccountClient.notifyDevices(sessionToken, devicesToNotify, payload, NOTIFY_TAB_SENT_TTL_SECS, new FxAccountClient20.RequestDelegate<ExtendedJSONObject>() {
|
fxAccountClient.notifyDevices(sessionToken, body, new FxAccountClient20.RequestDelegate<ExtendedJSONObject>() {
|
||||||
@Override
|
@Override
|
||||||
public void handleError(Exception e) {
|
public void handleError(Exception e) {
|
||||||
Log.e(LOG_TAG, "Error while notifying devices", e);
|
Log.e(LOG_TAG, "Error while notifying devices", e);
|
||||||
|
@ -220,11 +232,39 @@ public class SyncClientsEngineStage extends AbstractSessionManagingSyncStage {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleSuccess(ExtendedJSONObject result) {
|
public void handleSuccess(ExtendedJSONObject result) {
|
||||||
Log.i(LOG_TAG, devicesToNotify.size() + " devices notified");
|
Log.i(LOG_TAG, "Devices notified");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private ExtendedJSONObject createNotifyClientsBody(@NonNull List<String> devicesToNotify) {
|
||||||
|
final ExtendedJSONObject body = new ExtendedJSONObject();
|
||||||
|
final JSONArray to = new JSONArray();
|
||||||
|
to.addAll(devicesToNotify);
|
||||||
|
body.put("to", to);
|
||||||
|
createNotifyClientsHelper(body);
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private ExtendedJSONObject createNotifyAllClientsBody(@NonNull String localFxADeviceId) {
|
||||||
|
final ExtendedJSONObject body = new ExtendedJSONObject();
|
||||||
|
body.put("to", "all");
|
||||||
|
final JSONArray excluded = new JSONArray();
|
||||||
|
excluded.add(localFxADeviceId);
|
||||||
|
body.put("excluded", excluded);
|
||||||
|
createNotifyClientsHelper(body);
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createNotifyClientsHelper(ExtendedJSONObject body) {
|
||||||
|
body.put("payload", createNotifyDevicesPayload());
|
||||||
|
body.put("TTL", NOTIFY_TAB_SENT_TTL_SECS);
|
||||||
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private ExtendedJSONObject createNotifyDevicesPayload() {
|
private ExtendedJSONObject createNotifyDevicesPayload() {
|
||||||
|
|
|
@ -6,6 +6,7 @@ package org.mozilla.gecko.fxa.login;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import org.mozilla.gecko.background.fxa.FxAccountClient;
|
import org.mozilla.gecko.background.fxa.FxAccountClient;
|
||||||
|
import org.mozilla.gecko.background.fxa.FxAccountClient20;
|
||||||
import org.mozilla.gecko.background.fxa.FxAccountClient20.AccountStatusResponse;
|
import org.mozilla.gecko.background.fxa.FxAccountClient20.AccountStatusResponse;
|
||||||
import org.mozilla.gecko.background.fxa.FxAccountClient20.RequestDelegate;
|
import org.mozilla.gecko.background.fxa.FxAccountClient20.RequestDelegate;
|
||||||
import org.mozilla.gecko.background.fxa.FxAccountClient20.RecoveryEmailStatusResponse;
|
import org.mozilla.gecko.background.fxa.FxAccountClient20.RecoveryEmailStatusResponse;
|
||||||
|
@ -239,7 +240,7 @@ public class MockFxAccountClient implements FxAccountClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void notifyDevices(byte[] sessionToken, List<String> deviceIds, ExtendedJSONObject payload, Long TTL, RequestDelegate<ExtendedJSONObject> requestDelegate) {
|
public void notifyDevices(byte[] sessionToken, ExtendedJSONObject body, RequestDelegate<ExtendedJSONObject> requestDelegate) {
|
||||||
requestDelegate.handleSuccess(new ExtendedJSONObject());
|
requestDelegate.handleSuccess(new ExtendedJSONObject());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче