Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
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 }