mobile/android/base/fxa/activities/FxAccountUpdateCredentialsActivity.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 package org.mozilla.gecko.fxa.activities;
     7 import java.util.concurrent.Executor;
     8 import java.util.concurrent.Executors;
    10 import org.mozilla.gecko.R;
    11 import org.mozilla.gecko.background.common.log.Logger;
    12 import org.mozilla.gecko.background.fxa.FxAccountClient;
    13 import org.mozilla.gecko.background.fxa.FxAccountClient10.RequestDelegate;
    14 import org.mozilla.gecko.background.fxa.FxAccountClient20;
    15 import org.mozilla.gecko.background.fxa.FxAccountClient20.LoginResponse;
    16 import org.mozilla.gecko.background.fxa.FxAccountClientException.FxAccountClientRemoteException;
    17 import org.mozilla.gecko.background.fxa.FxAccountUtils;
    18 import org.mozilla.gecko.background.fxa.PasswordStretcher;
    19 import org.mozilla.gecko.fxa.FirefoxAccounts;
    20 import org.mozilla.gecko.fxa.FxAccountConstants;
    21 import org.mozilla.gecko.fxa.activities.FxAccountSetupTask.FxAccountSignInTask;
    22 import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
    23 import org.mozilla.gecko.fxa.login.Engaged;
    24 import org.mozilla.gecko.fxa.login.State;
    25 import org.mozilla.gecko.fxa.login.State.StateLabel;
    26 import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
    28 import android.os.Bundle;
    29 import android.view.View;
    30 import android.view.View.OnClickListener;
    31 import android.widget.AutoCompleteTextView;
    32 import android.widget.Button;
    33 import android.widget.EditText;
    34 import android.widget.ProgressBar;
    35 import android.widget.TextView;
    37 /**
    38  * Activity which displays a screen for updating the local password.
    39  */
    40 public class FxAccountUpdateCredentialsActivity extends FxAccountAbstractSetupActivity {
    41   protected static final String LOG_TAG = FxAccountUpdateCredentialsActivity.class.getSimpleName();
    43   protected AndroidFxAccount fxAccount;
    45   public FxAccountUpdateCredentialsActivity() {
    46     // We want to share code with the other setup activities, but this activity
    47     // doesn't create a new Android Account, it modifies an existing one. If you
    48     // manage to get an account, and somehow be locked out too, we'll let you
    49     // update it.
    50     super(CANNOT_RESUME_WHEN_NO_ACCOUNTS_EXIST);
    51   }
    53   /**
    54    * {@inheritDoc}
    55    */
    56   @Override
    57   public void onCreate(Bundle icicle) {
    58     Logger.debug(LOG_TAG, "onCreate(" + icicle + ")");
    60     super.onCreate(icicle);
    61     setContentView(R.layout.fxaccount_update_credentials);
    63     emailEdit = (AutoCompleteTextView) ensureFindViewById(null, R.id.email, "email edit");
    64     passwordEdit = (EditText) ensureFindViewById(null, R.id.password, "password edit");
    65     showPasswordButton = (Button) ensureFindViewById(null, R.id.show_password, "show password button");
    66     remoteErrorTextView = (TextView) ensureFindViewById(null, R.id.remote_error, "remote error text view");
    67     button = (Button) ensureFindViewById(null, R.id.button, "update credentials");
    68     progressBar = (ProgressBar) ensureFindViewById(null, R.id.progress, "progress bar");
    70     minimumPasswordLength = 1; // Minimal restriction on passwords entered to sign in.
    71     createButton();
    72     addListeners();
    73     updateButtonState();
    74     createShowPasswordButton();
    76     emailEdit.setEnabled(false);
    78     TextView view = (TextView) findViewById(R.id.forgot_password_link);
    79     ActivityUtils.linkTextView(view, R.string.fxaccount_sign_in_forgot_password, R.string.fxaccount_link_forgot_password);
    80   }
    82   @Override
    83   public void onResume() {
    84     super.onResume();
    85     this.fxAccount = getAndroidFxAccount();
    86     if (fxAccount == null) {
    87       Logger.warn(LOG_TAG, "Could not get Firefox Account.");
    88       setResult(RESULT_CANCELED);
    89       finish();
    90       return;
    91     }
    92     State state = fxAccount.getState();
    93     if (state.getStateLabel() != StateLabel.Separated) {
    94       Logger.warn(LOG_TAG, "Cannot update credentials from Firefox Account in state: " + state.getStateLabel());
    95       setResult(RESULT_CANCELED);
    96       finish();
    97       return;
    98     }
    99     emailEdit.setText(fxAccount.getEmail());
   100   }
   102   protected class UpdateCredentialsDelegate implements RequestDelegate<LoginResponse> {
   103     public final String email;
   104     public final String serverURI;
   105     public final PasswordStretcher passwordStretcher;
   107     public UpdateCredentialsDelegate(String email, PasswordStretcher passwordStretcher, String serverURI) {
   108       this.email = email;
   109       this.serverURI = serverURI;
   110       this.passwordStretcher = passwordStretcher;
   111     }
   113     @Override
   114     public void handleError(Exception e) {
   115       showRemoteError(e, R.string.fxaccount_update_credentials_unknown_error);
   116     }
   118     @Override
   119     public void handleFailure(FxAccountClientRemoteException e) {
   120       if (e.isUpgradeRequired()) {
   121         Logger.error(LOG_TAG, "Got upgrade required from remote server; transitioning Firefox Account to Doghouse state.");
   122         final State state = fxAccount.getState();
   123         fxAccount.setState(state.makeDoghouseState());
   124         // The status activity will say that the user needs to upgrade.
   125         redirectToActivity(FxAccountStatusActivity.class);
   126         return;
   127       }
   128       showRemoteError(e, R.string.fxaccount_update_credentials_unknown_error);
   129     }
   131     @Override
   132     public void handleSuccess(LoginResponse result) {
   133       Logger.info(LOG_TAG, "Got success signing in.");
   135       if (fxAccount == null) {
   136         this.handleError(new IllegalStateException("fxAccount must not be null"));
   137         return;
   138       }
   140       byte[] unwrapkB;
   141       try {
   142         // It is crucial that we use the email address provided by the server
   143         // (rather than whatever the user entered), because the user's keys are
   144         // wrapped and salted with the initial email they provided to
   145         // /create/account. Of course, we want to pass through what the user
   146         // entered locally as much as possible.
   147         byte[] quickStretchedPW = passwordStretcher.getQuickStretchedPW(result.remoteEmail.getBytes("UTF-8"));
   148         unwrapkB = FxAccountUtils.generateUnwrapBKey(quickStretchedPW);
   149       } catch (Exception e) {
   150         this.handleError(e);
   151         return;
   152       }
   153       fxAccount.setState(new Engaged(email, result.uid, result.verified, unwrapkB, result.sessionToken, result.keyFetchToken));
   154       fxAccount.requestSync(FirefoxAccounts.FORCE);
   156       // For great debugging.
   157       if (FxAccountConstants.LOG_PERSONAL_INFORMATION) {
   158         fxAccount.dump();
   159       }
   161       redirectToActivity(FxAccountStatusActivity.class);
   162     }
   163   }
   165   public void updateCredentials(String email, String password) {
   166     String serverURI = fxAccount.getAccountServerURI();
   167     Executor executor = Executors.newSingleThreadExecutor();
   168     FxAccountClient client = new FxAccountClient20(serverURI, executor);
   169     PasswordStretcher passwordStretcher = makePasswordStretcher(password);
   170     try {
   171       hideRemoteError();
   172       RequestDelegate<LoginResponse> delegate = new UpdateCredentialsDelegate(email, passwordStretcher, serverURI);
   173       new FxAccountSignInTask(this, this, email, passwordStretcher, client, delegate).execute();
   174     } catch (Exception e) {
   175       Logger.warn(LOG_TAG, "Got exception updating credentials for account.", e);
   176       showRemoteError(e, R.string.fxaccount_update_credentials_unknown_error);
   177     }
   178   }
   180   protected void createButton() {
   181     button.setOnClickListener(new OnClickListener() {
   182       @Override
   183       public void onClick(View v) {
   184         final String email = emailEdit.getText().toString();
   185         final String password = passwordEdit.getText().toString();
   186         updateCredentials(email, password);
   187       }
   188     });
   189   }
   190 }

mercurial