mobile/android/base/sync/setup/activities/AccountActivity.java

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 package org.mozilla.gecko.sync.setup.activities;
michael@0 6
michael@0 7 import java.util.Locale;
michael@0 8
michael@0 9 import org.mozilla.gecko.R;
michael@0 10 import org.mozilla.gecko.background.common.log.Logger;
michael@0 11 import org.mozilla.gecko.sync.SyncConstants;
michael@0 12 import org.mozilla.gecko.sync.ThreadPool;
michael@0 13 import org.mozilla.gecko.sync.setup.Constants;
michael@0 14 import org.mozilla.gecko.sync.setup.InvalidSyncKeyException;
michael@0 15 import org.mozilla.gecko.sync.setup.SyncAccounts;
michael@0 16 import org.mozilla.gecko.sync.setup.SyncAccounts.SyncAccountParameters;
michael@0 17 import org.mozilla.gecko.sync.setup.auth.AccountAuthenticator;
michael@0 18 import org.mozilla.gecko.sync.setup.auth.AuthenticationResult;
michael@0 19
michael@0 20 import android.accounts.Account;
michael@0 21 import android.accounts.AccountAuthenticatorActivity;
michael@0 22 import android.accounts.AccountManager;
michael@0 23 import android.app.ProgressDialog;
michael@0 24 import android.content.Context;
michael@0 25 import android.content.Intent;
michael@0 26 import android.os.Bundle;
michael@0 27 import android.text.Editable;
michael@0 28 import android.text.TextWatcher;
michael@0 29 import android.view.View;
michael@0 30 import android.view.View.OnClickListener;
michael@0 31 import android.view.Window;
michael@0 32 import android.view.WindowManager;
michael@0 33 import android.widget.Button;
michael@0 34 import android.widget.CheckBox;
michael@0 35 import android.widget.CompoundButton;
michael@0 36 import android.widget.CompoundButton.OnCheckedChangeListener;
michael@0 37 import android.widget.EditText;
michael@0 38 import android.widget.Toast;
michael@0 39
michael@0 40 public class AccountActivity extends AccountAuthenticatorActivity {
michael@0 41 private final static String LOG_TAG = "AccountActivity";
michael@0 42
michael@0 43 private AccountManager mAccountManager;
michael@0 44 private Context mContext;
michael@0 45 private String username;
michael@0 46 private String password;
michael@0 47 private String key;
michael@0 48 private String server = SyncConstants.DEFAULT_AUTH_SERVER;
michael@0 49
michael@0 50 // UI elements.
michael@0 51 private EditText serverInput;
michael@0 52 private EditText usernameInput;
michael@0 53 private EditText passwordInput;
michael@0 54 private EditText synckeyInput;
michael@0 55 private CheckBox serverCheckbox;
michael@0 56 private Button connectButton;
michael@0 57 private Button cancelButton;
michael@0 58 private ProgressDialog progressDialog;
michael@0 59
michael@0 60 private AccountAuthenticator accountAuthenticator;
michael@0 61
michael@0 62 @Override
michael@0 63 public void onCreate(Bundle savedInstanceState) {
michael@0 64 super.onCreate(savedInstanceState);
michael@0 65 setContentView(R.layout.sync_account);
michael@0 66
michael@0 67 ActivityUtils.prepareLogging();
michael@0 68 mContext = getApplicationContext();
michael@0 69 Logger.debug(LOG_TAG, "AccountManager.get(" + mContext + ")");
michael@0 70 mAccountManager = AccountManager.get(mContext);
michael@0 71
michael@0 72 // Set "screen on" flag.
michael@0 73 Logger.debug(LOG_TAG, "Setting screen-on flag.");
michael@0 74 Window w = getWindow();
michael@0 75 w.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
michael@0 76
michael@0 77 // Find UI elements.
michael@0 78 usernameInput = (EditText) findViewById(R.id.usernameInput);
michael@0 79 passwordInput = (EditText) findViewById(R.id.passwordInput);
michael@0 80 synckeyInput = (EditText) findViewById(R.id.keyInput);
michael@0 81 serverInput = (EditText) findViewById(R.id.serverInput);
michael@0 82
michael@0 83 TextWatcher inputValidator = makeInputValidator();
michael@0 84
michael@0 85 usernameInput.addTextChangedListener(inputValidator);
michael@0 86 passwordInput.addTextChangedListener(inputValidator);
michael@0 87 synckeyInput.addTextChangedListener(inputValidator);
michael@0 88 serverInput.addTextChangedListener(inputValidator);
michael@0 89
michael@0 90 connectButton = (Button) findViewById(R.id.accountConnectButton);
michael@0 91 cancelButton = (Button) findViewById(R.id.accountCancelButton);
michael@0 92 serverCheckbox = (CheckBox) findViewById(R.id.checkbox_server);
michael@0 93
michael@0 94 serverCheckbox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
michael@0 95 @Override
michael@0 96 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
michael@0 97 Logger.info(LOG_TAG, "Toggling checkbox: " + isChecked);
michael@0 98 if (!isChecked) { // Clear server input.
michael@0 99 serverInput.setVisibility(View.GONE);
michael@0 100 findViewById(R.id.server_error).setVisibility(View.GONE);
michael@0 101 serverInput.setText("");
michael@0 102 } else {
michael@0 103 serverInput.setVisibility(View.VISIBLE);
michael@0 104 serverInput.setEnabled(true);
michael@0 105 }
michael@0 106 // Activate connectButton if necessary.
michael@0 107 activateView(connectButton, validateInputs());
michael@0 108 }
michael@0 109 });
michael@0 110 }
michael@0 111
michael@0 112 @Override
michael@0 113 public void onResume() {
michael@0 114 super.onResume();
michael@0 115 ActivityUtils.prepareLogging();
michael@0 116 clearCredentials();
michael@0 117 usernameInput.requestFocus();
michael@0 118 cancelButton.setOnClickListener(new OnClickListener() {
michael@0 119
michael@0 120 @Override
michael@0 121 public void onClick(View v) {
michael@0 122 cancelClickHandler(v);
michael@0 123 }
michael@0 124
michael@0 125 });
michael@0 126 }
michael@0 127
michael@0 128 public void cancelClickHandler(View target) {
michael@0 129 finish();
michael@0 130 }
michael@0 131
michael@0 132 public void cancelConnectHandler(View target) {
michael@0 133 if (accountAuthenticator != null) {
michael@0 134 accountAuthenticator.isCanceled = true;
michael@0 135 accountAuthenticator = null;
michael@0 136 }
michael@0 137 displayVerifying(false);
michael@0 138 activateView(connectButton, true);
michael@0 139 clearCredentials();
michael@0 140 usernameInput.requestFocus();
michael@0 141 }
michael@0 142
michael@0 143 private void clearCredentials() {
michael@0 144 // Only clear password. Re-typing the sync key or email is annoying.
michael@0 145 passwordInput.setText("");
michael@0 146 }
michael@0 147 /*
michael@0 148 * Get credentials on "Connect" and write to AccountManager, where it can be
michael@0 149 * accessed by Fennec and Sync Service.
michael@0 150 */
michael@0 151 public void connectClickHandler(View target) {
michael@0 152 Logger.debug(LOG_TAG, "connectClickHandler for view " + target);
michael@0 153 // Validate sync key format.
michael@0 154 try {
michael@0 155 key = ActivityUtils.validateSyncKey(synckeyInput.getText().toString());
michael@0 156 } catch (InvalidSyncKeyException e) {
michael@0 157 // Toast: invalid sync key format.
michael@0 158 Toast toast = Toast.makeText(mContext, R.string.sync_new_recoverykey_status_incorrect, Toast.LENGTH_LONG);
michael@0 159 toast.show();
michael@0 160 return;
michael@0 161 }
michael@0 162 username = usernameInput.getText().toString().toLowerCase(Locale.US);
michael@0 163 password = passwordInput.getText().toString();
michael@0 164 key = synckeyInput.getText().toString();
michael@0 165 server = SyncConstants.DEFAULT_AUTH_SERVER;
michael@0 166
michael@0 167 if (serverCheckbox.isChecked()) {
michael@0 168 String userServer = serverInput.getText().toString();
michael@0 169 if (userServer != null) {
michael@0 170 userServer = userServer.trim();
michael@0 171 if (userServer.length() != 0) {
michael@0 172 if (!userServer.startsWith("https://") &&
michael@0 173 !userServer.startsWith("http://")) {
michael@0 174 // Assume HTTPS if not specified.
michael@0 175 userServer = "https://" + userServer;
michael@0 176 serverInput.setText(userServer);
michael@0 177 }
michael@0 178 server = userServer;
michael@0 179 }
michael@0 180 }
michael@0 181 }
michael@0 182
michael@0 183 clearErrors();
michael@0 184 displayVerifying(true);
michael@0 185 cancelButton.setOnClickListener(new OnClickListener() {
michael@0 186 @Override
michael@0 187 public void onClick(View v) {
michael@0 188 cancelConnectHandler(v);
michael@0 189 // Set cancel click handler to leave account setup.
michael@0 190 cancelButton.setOnClickListener(new OnClickListener() {
michael@0 191 public void onClick(View v) {
michael@0 192 cancelClickHandler(v);
michael@0 193 }
michael@0 194 });
michael@0 195 }
michael@0 196 });
michael@0 197
michael@0 198 accountAuthenticator = new AccountAuthenticator(this);
michael@0 199 accountAuthenticator.authenticate(server, username, password);
michael@0 200 }
michael@0 201
michael@0 202 private TextWatcher makeInputValidator() {
michael@0 203 return new TextWatcher() {
michael@0 204
michael@0 205 @Override
michael@0 206 public void afterTextChanged(Editable s) {
michael@0 207 activateView(connectButton, validateInputs());
michael@0 208 }
michael@0 209
michael@0 210 @Override
michael@0 211 public void beforeTextChanged(CharSequence s, int start, int count,
michael@0 212 int after) {
michael@0 213 }
michael@0 214
michael@0 215 @Override
michael@0 216 public void onTextChanged(CharSequence s, int start, int before, int count) {
michael@0 217 }
michael@0 218 };
michael@0 219 }
michael@0 220
michael@0 221 private boolean validateInputs() {
michael@0 222 if (usernameInput.length() == 0 ||
michael@0 223 passwordInput.length() == 0 ||
michael@0 224 synckeyInput.length() == 0 ||
michael@0 225 (serverCheckbox.isChecked() &&
michael@0 226 serverInput.length() == 0)) {
michael@0 227 return false;
michael@0 228 }
michael@0 229 return true;
michael@0 230 }
michael@0 231
michael@0 232 /*
michael@0 233 * Callback that handles auth based on success/failure
michael@0 234 */
michael@0 235 public void authCallback(final AuthenticationResult result) {
michael@0 236 displayVerifying(false);
michael@0 237 if (result != AuthenticationResult.SUCCESS) {
michael@0 238 Logger.debug(LOG_TAG, "displayFailure()");
michael@0 239 displayFailure(result);
michael@0 240 return;
michael@0 241 }
michael@0 242 // Successful authentication. Create and add account to AccountManager.
michael@0 243 SyncAccountParameters syncAccount = new SyncAccountParameters(
michael@0 244 mContext, mAccountManager, username, key, password, server);
michael@0 245 createAccountOnThread(syncAccount);
michael@0 246 }
michael@0 247
michael@0 248 private void createAccountOnThread(final SyncAccountParameters syncAccount) {
michael@0 249 ThreadPool.run(new Runnable() {
michael@0 250 @Override
michael@0 251 public void run() {
michael@0 252 Account account = SyncAccounts.createSyncAccount(syncAccount);
michael@0 253 boolean isSuccess = (account != null);
michael@0 254 if (!isSuccess) {
michael@0 255 setResult(RESULT_CANCELED);
michael@0 256 runOnUiThread(new Runnable() {
michael@0 257 @Override
michael@0 258 public void run() {
michael@0 259 displayFailure(AuthenticationResult.FAILURE_ACCOUNT);
michael@0 260 }
michael@0 261 });
michael@0 262 return;
michael@0 263 }
michael@0 264
michael@0 265 // Account created successfully.
michael@0 266 clearErrors();
michael@0 267
michael@0 268 Bundle resultBundle = new Bundle();
michael@0 269 resultBundle.putString(AccountManager.KEY_ACCOUNT_NAME, syncAccount.username);
michael@0 270 resultBundle.putString(AccountManager.KEY_ACCOUNT_TYPE, SyncConstants.ACCOUNTTYPE_SYNC);
michael@0 271 resultBundle.putString(AccountManager.KEY_AUTHTOKEN, SyncConstants.ACCOUNTTYPE_SYNC);
michael@0 272 setAccountAuthenticatorResult(resultBundle);
michael@0 273
michael@0 274 setResult(RESULT_OK);
michael@0 275 runOnUiThread(new Runnable() {
michael@0 276 @Override
michael@0 277 public void run() {
michael@0 278 authSuccess();
michael@0 279 }
michael@0 280 });
michael@0 281 }
michael@0 282 });
michael@0 283 }
michael@0 284
michael@0 285 private void displayVerifying(final boolean isVerifying) {
michael@0 286 if (isVerifying) {
michael@0 287 progressDialog = ProgressDialog.show(AccountActivity.this, "", getString(R.string.sync_verifying_label), true);
michael@0 288 } else {
michael@0 289 progressDialog.dismiss();
michael@0 290 }
michael@0 291 }
michael@0 292
michael@0 293 private void displayFailure(final AuthenticationResult result) {
michael@0 294 runOnUiThread(new Runnable() {
michael@0 295 @Override
michael@0 296 public void run() {
michael@0 297 Intent intent;
michael@0 298 switch (result) {
michael@0 299 case FAILURE_USERNAME:
michael@0 300 // No such username. Don't leak whether the username exists.
michael@0 301 case FAILURE_PASSWORD:
michael@0 302 findViewById(R.id.cred_error).setVisibility(View.VISIBLE);
michael@0 303 usernameInput.requestFocus();
michael@0 304 break;
michael@0 305 case FAILURE_SERVER:
michael@0 306 findViewById(R.id.server_error).setVisibility(View.VISIBLE);
michael@0 307 serverInput.requestFocus();
michael@0 308 break;
michael@0 309 case FAILURE_ACCOUNT:
michael@0 310 intent = new Intent(mContext, SetupFailureActivity.class);
michael@0 311 intent.setFlags(Constants.FLAG_ACTIVITY_REORDER_TO_FRONT_NO_ANIMATION);
michael@0 312 intent.putExtra(Constants.INTENT_EXTRA_IS_ACCOUNTERROR, true);
michael@0 313 startActivity(intent);
michael@0 314 break;
michael@0 315 case FAILURE_OTHER:
michael@0 316 default:
michael@0 317 // Display default error screen.
michael@0 318 Logger.debug(LOG_TAG, "displaying default failure.");
michael@0 319 intent = new Intent(mContext, SetupFailureActivity.class);
michael@0 320 intent.setFlags(Constants.FLAG_ACTIVITY_REORDER_TO_FRONT_NO_ANIMATION);
michael@0 321 startActivity(intent);
michael@0 322 }
michael@0 323 }
michael@0 324 });
michael@0 325 }
michael@0 326
michael@0 327 /**
michael@0 328 * Feedback to user of account setup success.
michael@0 329 */
michael@0 330 public void authSuccess() {
michael@0 331 // Display feedback of successful account setup.
michael@0 332 Intent intent = new Intent(mContext, SetupSuccessActivity.class);
michael@0 333 intent.setFlags(Constants.FLAG_ACTIVITY_REORDER_TO_FRONT_NO_ANIMATION);
michael@0 334 startActivity(intent);
michael@0 335 finish();
michael@0 336 }
michael@0 337
michael@0 338 private void activateView(View view, boolean toActivate) {
michael@0 339 view.setEnabled(toActivate);
michael@0 340 view.setClickable(toActivate);
michael@0 341 }
michael@0 342
michael@0 343 private void clearErrors() {
michael@0 344 runOnUiThread(new Runnable() {
michael@0 345 @Override
michael@0 346 public void run() {
michael@0 347 findViewById(R.id.cred_error).setVisibility(View.GONE);
michael@0 348 findViewById(R.id.server_error).setVisibility(View.GONE);
michael@0 349 }
michael@0 350 });
michael@0 351 }
michael@0 352 }

mercurial