Bug 714304 - Handle 'Upgrade Required' error response. r=rnewman, a=blocking-fennec

This commit is contained in:
Richard Newman 2012-05-04 17:25:34 -07:00
Родитель 3db6dbbf82
Коммит a6f2573921
8 изменённых файлов: 110 добавлений и 8 удалений

Просмотреть файл

@ -393,13 +393,39 @@ public class GlobalSession implements CredentialsSource, PrefsSource, HttpRespon
callback.requestBackoff(responseBackoff);
}
if (response.getStatusLine() != null && response.getStatusLine().getStatusCode() == 401) {
/*
* Alert our callback we have a 401 on a cluster URL. This GlobalSession
* will fail, but the next one will fetch a new cluster URL and will
* distinguish between "node reassignment" and "user password changed".
*/
callback.informUnauthorizedResponse(this, config.getClusterURL());
if (response.getStatusLine() != null) {
final int statusCode = response.getStatusLine().getStatusCode();
switch(statusCode) {
case 400:
SyncStorageResponse storageResponse = new SyncStorageResponse(response);
this.interpretHTTPBadRequestBody(storageResponse);
break;
case 401:
/*
* Alert our callback we have a 401 on a cluster URL. This GlobalSession
* will fail, but the next one will fetch a new cluster URL and will
* distinguish between "node reassignment" and "user password changed".
*/
callback.informUnauthorizedResponse(this, config.getClusterURL());
break;
}
}
}
protected void interpretHTTPBadRequestBody(final SyncStorageResponse storageResponse) {
try {
final String body = storageResponse.body();
if (body == null) {
return;
}
if (SyncStorageResponse.RESPONSE_CLIENT_UPGRADE_REQUIRED.equals(body)) {
callback.informUpgradeRequiredResponse(this);
return;
}
} catch (Exception e) {
Logger.warn(LOG_TAG, "Exception parsing HTTP 400 body.", e);
}
}

Просмотреть файл

@ -51,10 +51,16 @@ public interface GlobalSessionCallback {
*/
void informNodeAuthenticationFailed(GlobalSession globalSession, URI failedClusterURL);
/**
* Called when an HTTP failure indicates that a software upgrade is required.
*/
void informUpgradeRequiredResponse(GlobalSession session);
void handleAborted(GlobalSession globalSession, String reason);
void handleError(GlobalSession globalSession, Exception ex);
void handleSuccess(GlobalSession globalSession);
void handleStageCompleted(Stage currentState, GlobalSession globalSession);
boolean shouldBackOff();
}

Просмотреть файл

@ -13,6 +13,9 @@ import ch.boye.httpclientandroidlib.HttpResponse;
public class SyncStorageResponse extends SyncResponse {
// Responses that are actionable get constant status codes.
public static final String RESPONSE_CLIENT_UPGRADE_REQUIRED = "16";
private static final String LOG_TAG = "SyncStorageResponse";
public static HashMap<String, String> SERVER_ERROR_MESSAGES;
static {
@ -34,6 +37,7 @@ public class SyncStorageResponse extends SyncResponse {
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.

Просмотреть файл

@ -0,0 +1,40 @@
/* 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.receivers;
import org.mozilla.gecko.sync.Logger;
import org.mozilla.gecko.sync.ThreadPool;
import org.mozilla.gecko.sync.setup.Constants;
import org.mozilla.gecko.sync.setup.SyncAccounts;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class UpgradeReceiver extends BroadcastReceiver {
private static final String LOG_TAG = "UpgradeReceiver";
@Override
public void onReceive(final Context context, Intent intent) {
Logger.debug(LOG_TAG, "Broadcast received.");
// Should filter for specific MY_PACKAGE_REPLACED intent, but Android does
// not expose it.
ThreadPool.run(new Runnable() {
@Override
public void run() {
AccountManager accountManager = AccountManager.get(context);
Account[] accounts = accountManager.getAccounts();
for (Account a : accounts) {
if ("1".equals(accountManager.getUserData(a, Constants.DATA_ENABLE_ON_UPGRADE))) {
SyncAccounts.setSyncAutomatically(a, true);
accountManager.setUserData(a, Constants.DATA_ENABLE_ON_UPGRADE, "0");
}
}
}
});
}
}

Просмотреть файл

@ -16,6 +16,7 @@ public class Constants {
public static final String ACCOUNT_GUID = "account.guid";
public static final String CLIENT_NAME = "account.clientName";
public static final String NUM_CLIENTS = "account.numClients";
public static final String DATA_ENABLE_ON_UPGRADE = "data.enableOnUpgrade";
// Constants for Activities.
public static final String INTENT_EXTRA_IS_SETUP = "isSetup";

Просмотреть файл

@ -18,6 +18,7 @@ import org.mozilla.gecko.sync.NonObjectJSONException;
import org.mozilla.gecko.sync.SyncConfiguration;
import org.mozilla.gecko.sync.SyncConfigurationException;
import org.mozilla.gecko.sync.SyncException;
import org.mozilla.gecko.sync.ThreadPool;
import org.mozilla.gecko.sync.Utils;
import org.mozilla.gecko.sync.crypto.KeyBundle;
import org.mozilla.gecko.sync.delegates.ClientsDataDelegate;
@ -532,4 +533,22 @@ public class SyncAdapter extends AbstractThreadedSyncAdapter implements GlobalSe
public void informUnauthorizedResponse(GlobalSession session, URI oldClusterURL) {
setClusterURLIsStale(true);
}
@Override
public void informUpgradeRequiredResponse(final GlobalSession session) {
final AccountManager manager = mAccountManager;
final Account toDisable = localAccount;
if (toDisable == null || manager == null) {
Logger.warn(LOG_TAG, "Attempting to disable account, but null found.");
return;
}
// Sync needs to be upgraded. Don't automatically sync anymore.
ThreadPool.run(new Runnable() {
@Override
public void run() {
manager.setUserData(toDisable, Constants.DATA_ENABLE_ON_UPGRADE, "1");
SyncAccounts.setSyncAutomatically(toDisable, false);
}
});
}
}

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -18,3 +18,9 @@
android:name="org.mozilla.gecko.sync.setup.activities.SetupFailureActivity" />
<activity
android:name="org.mozilla.gecko.sync.setup.activities.SetupSuccessActivity" />
<receiver
android:name="org.mozilla.gecko.sync.receivers.UpgradeReceiver">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>