Files
palemoon27/mobile/android/base/fxa/activities/FxAccountAbstractUpdateCredentialsActivity.java
T
2018-07-24 23:11:02 +08:00

187 lines
7.4 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.goanna.fxa.activities;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import org.mozilla.goanna.R;
import org.mozilla.goanna.background.common.log.Logger;
import org.mozilla.goanna.background.common.telemetry.TelemetryWrapper;
import org.mozilla.goanna.background.fxa.FxAccountClient;
import org.mozilla.goanna.background.fxa.FxAccountClient10.RequestDelegate;
import org.mozilla.goanna.background.fxa.FxAccountClient20;
import org.mozilla.goanna.background.fxa.FxAccountClient20.LoginResponse;
import org.mozilla.goanna.background.fxa.FxAccountClientException.FxAccountClientRemoteException;
import org.mozilla.goanna.background.fxa.FxAccountUtils;
import org.mozilla.goanna.background.fxa.PasswordStretcher;
import org.mozilla.goanna.fxa.FirefoxAccounts;
import org.mozilla.goanna.fxa.authenticator.AndroidFxAccount;
import org.mozilla.goanna.fxa.login.Engaged;
import org.mozilla.goanna.fxa.login.State;
import org.mozilla.goanna.fxa.tasks.FxAccountSignInTask;
import org.mozilla.goanna.sync.setup.activities.ActivityUtils;
import org.mozilla.goanna.sync.telemetry.TelemetryContract;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AutoCompleteTextView;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.TextView;
/**
* Abstract activity which displays a screen for updating the local password.
*/
public abstract class FxAccountAbstractUpdateCredentialsActivity extends FxAccountAbstractSetupActivity {
protected static final String LOG_TAG = FxAccountAbstractUpdateCredentialsActivity.class.getSimpleName();
protected AndroidFxAccount fxAccount;
protected final int layoutResourceId;
public FxAccountAbstractUpdateCredentialsActivity(int layoutResourceId) {
// We want to share code with the other setup activities, but this activity
// doesn't create a new Android Account, it modifies an existing one. If you
// manage to get an account, and somehow be locked out too, we'll let you
// update it.
super(CANNOT_RESUME_WHEN_NO_ACCOUNTS_EXIST);
this.layoutResourceId = layoutResourceId;
}
/**
* {@inheritDoc}
*/
@Override
public void onCreate(Bundle icicle) {
Logger.debug(LOG_TAG, "onCreate(" + icicle + ")");
super.onCreate(icicle);
setContentView(layoutResourceId);
emailEdit = (AutoCompleteTextView) ensureFindViewById(null, R.id.email, "email edit");
passwordEdit = (EditText) ensureFindViewById(null, R.id.password, "password edit");
showPasswordButton = (Button) ensureFindViewById(null, R.id.show_password, "show password button");
remoteErrorTextView = (TextView) ensureFindViewById(null, R.id.remote_error, "remote error text view");
button = (Button) ensureFindViewById(null, R.id.button, "update credentials");
progressBar = (ProgressBar) ensureFindViewById(null, R.id.progress, "progress bar");
minimumPasswordLength = 1; // Minimal restriction on passwords entered to sign in.
createButton();
addListeners();
updateButtonState();
createShowPasswordButton();
emailEdit.setEnabled(false);
TextView view = (TextView) findViewById(R.id.forgot_password_link);
ActivityUtils.linkTextView(view, R.string.fxaccount_sign_in_forgot_password, R.string.fxaccount_link_forgot_password);
updateFromIntentExtras();
maybeEnableAnimations();
}
protected class UpdateCredentialsDelegate implements RequestDelegate<LoginResponse> {
public final String email;
public final String serverURI;
public final PasswordStretcher passwordStretcher;
public UpdateCredentialsDelegate(String email, PasswordStretcher passwordStretcher, String serverURI) {
this.email = email;
this.serverURI = serverURI;
this.passwordStretcher = passwordStretcher;
}
@Override
public void handleError(Exception e) {
showRemoteError(e, R.string.fxaccount_update_credentials_unknown_error);
}
@Override
public void handleFailure(FxAccountClientRemoteException e) {
if (e.isUpgradeRequired()) {
Logger.error(LOG_TAG, "Got upgrade required from remote server; transitioning Firefox Account to Doghouse state.");
final State state = fxAccount.getState();
fxAccount.setState(state.makeDoghouseState());
// The status activity will say that the user needs to upgrade.
redirectToActivity(FxAccountStatusActivity.class);
return;
}
showRemoteError(e, R.string.fxaccount_update_credentials_unknown_error);
}
@Override
public void handleSuccess(LoginResponse result) {
Logger.info(LOG_TAG, "Got success signing in.");
if (fxAccount == null) {
this.handleError(new IllegalStateException("fxAccount must not be null"));
return;
}
byte[] unwrapkB;
try {
// It is crucial that we use the email address provided by the server
// (rather than whatever the user entered), because the user's keys are
// wrapped and salted with the initial email they provided to
// /create/account. Of course, we want to pass through what the user
// entered locally as much as possible.
byte[] quickStretchedPW = passwordStretcher.getQuickStretchedPW(result.remoteEmail.getBytes("UTF-8"));
unwrapkB = FxAccountUtils.generateUnwrapBKey(quickStretchedPW);
} catch (Exception e) {
this.handleError(e);
return;
}
fxAccount.setState(new Engaged(email, result.uid, result.verified, unwrapkB, result.sessionToken, result.keyFetchToken));
fxAccount.requestSync(FirefoxAccounts.FORCE);
// For great debugging.
if (FxAccountUtils.LOG_PERSONAL_INFORMATION) {
fxAccount.dump();
}
setResult(RESULT_OK);
// Maybe show success activity.
final Intent successIntent = makeSuccessIntent(email, result);
if (successIntent != null) {
startActivity(successIntent);
}
finish();
TelemetryWrapper.addToHistogram(TelemetryContract.SYNC11_MIGRATIONS_COMPLETED, 1);
}
}
public void updateCredentials(String email, String password) {
String serverURI = fxAccount.getAccountServerURI();
Executor executor = Executors.newSingleThreadExecutor();
FxAccountClient client = new FxAccountClient20(serverURI, executor);
PasswordStretcher passwordStretcher = makePasswordStretcher(password);
try {
hideRemoteError();
RequestDelegate<LoginResponse> delegate = new UpdateCredentialsDelegate(email, passwordStretcher, serverURI);
new FxAccountSignInTask(this, this, email, passwordStretcher, client, getQueryParameters(), delegate).execute();
} catch (Exception e) {
Logger.warn(LOG_TAG, "Got exception updating credentials for account.", e);
showRemoteError(e, R.string.fxaccount_update_credentials_unknown_error);
}
}
protected void createButton() {
button.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
final String email = emailEdit.getText().toString();
final String password = passwordEdit.getText().toString();
updateCredentials(email, password);
}
});
}
}