mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1220892 - Part 2: Remove Activity sub-classes. r=mcomella
This commit is contained in:
parent
bf6bf4b0d2
commit
6b79b8e6f4
@ -853,22 +853,12 @@ sync_java_files = [TOPSRCDIR + '/mobile/android/services/src/main/java/org/mozil
|
||||
'fxa/activities/CustomColorPreference.java',
|
||||
'fxa/activities/FxAccountAbstractActivity.java',
|
||||
'fxa/activities/FxAccountAbstractSetupActivity.java',
|
||||
'fxa/activities/FxAccountAbstractUpdateCredentialsActivity.java',
|
||||
'fxa/activities/FxAccountConfirmAccountActivity.java',
|
||||
'fxa/activities/FxAccountConfirmAccountActivityWeb.java',
|
||||
'fxa/activities/FxAccountCreateAccountActivity.java',
|
||||
'fxa/activities/FxAccountCreateAccountNotAllowedActivity.java',
|
||||
'fxa/activities/FxAccountFinishMigratingActivity.java',
|
||||
'fxa/activities/FxAccountFinishMigratingActivityWeb.java',
|
||||
'fxa/activities/FxAccountGetStartedActivity.java',
|
||||
'fxa/activities/FxAccountGetStartedActivityWeb.java',
|
||||
'fxa/activities/FxAccountMigrationFinishedActivity.java',
|
||||
'fxa/activities/FxAccountSignInActivity.java',
|
||||
'fxa/activities/FxAccountStatusActivity.java',
|
||||
'fxa/activities/FxAccountStatusFragment.java',
|
||||
'fxa/activities/FxAccountUpdateCredentialsActivity.java',
|
||||
'fxa/activities/FxAccountUpdateCredentialsActivityWeb.java',
|
||||
'fxa/activities/FxAccountVerifiedAccountActivity.java',
|
||||
'fxa/activities/FxAccountWebFlowActivity.java',
|
||||
'fxa/activities/PicassoPreferenceIconTarget.java',
|
||||
'fxa/authenticator/AccountPickler.java',
|
||||
|
@ -18,82 +18,6 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:theme="@style/FxAccountTheme"
|
||||
android:label="@string/sync_app_name"
|
||||
android:clearTaskOnLaunch="true"
|
||||
android:taskAffinity="@ANDROID_PACKAGE_NAME@.FXA"
|
||||
android:name="org.mozilla.gecko.fxa.activities.FxAccountGetStartedActivity"
|
||||
android:configChanges="locale|layoutDirection"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<!-- Adding a launcher will make this activity appear on the
|
||||
Apps screen, which we only want when testing. -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<!-- <category android:name="android.intent.category.LAUNCHER" /> -->
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:theme="@style/FxAccountTheme"
|
||||
android:name="org.mozilla.gecko.fxa.activities.FxAccountCreateAccountActivity"
|
||||
android:configChanges="locale|layoutDirection"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:theme="@style/FxAccountTheme"
|
||||
android:name="org.mozilla.gecko.fxa.activities.FxAccountConfirmAccountActivity"
|
||||
android:configChanges="locale|layoutDirection"
|
||||
android:noHistory="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:theme="@style/FxAccountTheme"
|
||||
android:name="org.mozilla.gecko.fxa.activities.FxAccountSignInActivity"
|
||||
android:configChanges="locale|layoutDirection"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:theme="@style/FxAccountTheme"
|
||||
android:name="org.mozilla.gecko.fxa.activities.FxAccountVerifiedAccountActivity"
|
||||
android:configChanges="locale|layoutDirection"
|
||||
android:noHistory="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:theme="@style/FxAccountTheme"
|
||||
android:name="org.mozilla.gecko.fxa.activities.FxAccountUpdateCredentialsActivity"
|
||||
android:configChanges="locale|layoutDirection"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:theme="@style/FxAccountTheme"
|
||||
android:name="org.mozilla.gecko.fxa.activities.FxAccountFinishMigratingActivity"
|
||||
android:configChanges="locale|layoutDirection"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:theme="@style/FxAccountTheme"
|
||||
android:name="org.mozilla.gecko.fxa.activities.FxAccountMigrationFinishedActivity"
|
||||
android:configChanges="locale|layoutDirection"
|
||||
android:noHistory="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:theme="@style/FxAccountTheme"
|
||||
android:name="org.mozilla.gecko.fxa.activities.FxAccountCreateAccountNotAllowedActivity"
|
||||
android:configChanges="locale|layoutDirection"
|
||||
android:noHistory="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
</activity>
|
||||
|
||||
<receiver
|
||||
android:name="org.mozilla.gecko.fxa.receivers.FxAccountDeletedReceiver"
|
||||
android:permission="@MOZ_ANDROID_SHARED_FXACCOUNT_TYPE@.permission.PER_ACCOUNT_TYPE">
|
||||
|
@ -24,25 +24,20 @@ public abstract class FxAccountAbstractActivity extends LocaleAwareActivity {
|
||||
|
||||
protected final boolean cannotResumeWhenAccountsExist;
|
||||
protected final boolean cannotResumeWhenNoAccountsExist;
|
||||
protected final boolean cannotResumeWhenLockedOut;
|
||||
|
||||
public static final int CAN_ALWAYS_RESUME = 0;
|
||||
public static final int CANNOT_RESUME_WHEN_ACCOUNTS_EXIST = 1 << 0;
|
||||
public static final int CANNOT_RESUME_WHEN_NO_ACCOUNTS_EXIST = 1 << 1;
|
||||
public static final int CANNOT_RESUME_WHEN_LOCKED_OUT = 1 << 2;
|
||||
|
||||
public FxAccountAbstractActivity(int resume) {
|
||||
super();
|
||||
this.cannotResumeWhenAccountsExist = 0 != (resume & CANNOT_RESUME_WHEN_ACCOUNTS_EXIST);
|
||||
this.cannotResumeWhenNoAccountsExist = 0 != (resume & CANNOT_RESUME_WHEN_NO_ACCOUNTS_EXIST);
|
||||
this.cannotResumeWhenLockedOut = 0 != (resume & CANNOT_RESUME_WHEN_LOCKED_OUT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Many Firefox Accounts activities shouldn't display if an account already
|
||||
* exists or if account creation is locked out due to an age verification
|
||||
* check failing (getting started, create account, sign in). This function
|
||||
* redirects as appropriate.
|
||||
* exists. This function redirects as appropriate.
|
||||
*
|
||||
* @return true if redirected.
|
||||
*/
|
||||
@ -58,14 +53,6 @@ public abstract class FxAccountAbstractActivity extends LocaleAwareActivity {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (cannotResumeWhenLockedOut) {
|
||||
if (FxAccountAgeLockoutHelper.isLockedOut(SystemClock.elapsedRealtime())) {
|
||||
this.setResult(RESULT_CANCELED);
|
||||
launchActivity(FxAccountCreateAccountNotAllowedActivity.class);
|
||||
finish();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,7 @@ abstract public class FxAccountAbstractSetupActivity extends FxAccountAbstractAc
|
||||
public static final String JSON_KEY_PROFILE = "profile";
|
||||
|
||||
public FxAccountAbstractSetupActivity() {
|
||||
super(CANNOT_RESUME_WHEN_ACCOUNTS_EXIST | CANNOT_RESUME_WHEN_LOCKED_OUT);
|
||||
super(CANNOT_RESUME_WHEN_ACCOUNTS_EXIST);
|
||||
}
|
||||
|
||||
protected FxAccountAbstractSetupActivity(int resume) {
|
||||
@ -86,535 +86,4 @@ abstract public class FxAccountAbstractSetupActivity extends FxAccountAbstractAc
|
||||
}
|
||||
|
||||
private static final String LOG_TAG = FxAccountAbstractSetupActivity.class.getSimpleName();
|
||||
|
||||
// By default, any custom server configuration is only shown when the account
|
||||
// is configured to use a custom server.
|
||||
private static final boolean ALWAYS_SHOW_CUSTOM_SERVER_LAYOUT = false;
|
||||
|
||||
protected int minimumPasswordLength = 8;
|
||||
|
||||
protected AutoCompleteTextView emailEdit;
|
||||
protected EditText passwordEdit;
|
||||
protected Button showPasswordButton;
|
||||
protected TextView remoteErrorTextView;
|
||||
protected Button button;
|
||||
protected ProgressBar progressBar;
|
||||
|
||||
private String authServerEndpoint;
|
||||
private String syncServerEndpoint;
|
||||
private String profileServerEndpoint;
|
||||
|
||||
protected String getAuthServerEndpoint() {
|
||||
return authServerEndpoint;
|
||||
}
|
||||
|
||||
protected String getTokenServerEndpoint() {
|
||||
return syncServerEndpoint;
|
||||
}
|
||||
|
||||
protected String getProfileServerEndpoint() {
|
||||
return profileServerEndpoint;
|
||||
}
|
||||
|
||||
protected void createShowPasswordButton() {
|
||||
showPasswordButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
boolean isShown = passwordEdit.getTransformationMethod() instanceof SingleLineTransformationMethod;
|
||||
setPasswordButtonShown(!isShown);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
protected void setPasswordButtonShown(boolean shouldShow) {
|
||||
// Changing input type loses position in edit text; let's try to maintain it.
|
||||
int start = passwordEdit.getSelectionStart();
|
||||
int stop = passwordEdit.getSelectionEnd();
|
||||
|
||||
if (!shouldShow) {
|
||||
passwordEdit.setTransformationMethod(PasswordTransformationMethod.getInstance());
|
||||
showPasswordButton.setText(R.string.fxaccount_password_show);
|
||||
showPasswordButton.setBackgroundDrawable(getResources().getDrawable(R.drawable.fxaccount_password_button_show_background));
|
||||
showPasswordButton.setTextColor(ColorUtils.getColor(this, R.color.fxaccount_password_show_textcolor));
|
||||
} else {
|
||||
passwordEdit.setTransformationMethod(SingleLineTransformationMethod.getInstance());
|
||||
showPasswordButton.setText(R.string.fxaccount_password_hide);
|
||||
showPasswordButton.setBackgroundDrawable(getResources().getDrawable(R.drawable.fxaccount_password_button_hide_background));
|
||||
showPasswordButton.setTextColor(ColorUtils.getColor(this, R.color.fxaccount_password_hide_textcolor));
|
||||
}
|
||||
passwordEdit.setSelection(start, stop);
|
||||
}
|
||||
|
||||
protected void linkifyPolicy() {
|
||||
TextView policyView = (TextView) ensureFindViewById(null, R.id.policy, "policy links");
|
||||
final String linkTerms = getString(R.string.fxaccount_link_tos);
|
||||
final String linkPrivacy = getString(R.string.fxaccount_link_pn);
|
||||
final String linkedTOS = "<a href=\"" + linkTerms + "\">" + getString(R.string.fxaccount_policy_linktos) + "</a>";
|
||||
final String linkedPN = "<a href=\"" + linkPrivacy + "\">" + getString(R.string.fxaccount_policy_linkprivacy) + "</a>";
|
||||
policyView.setText(getString(R.string.fxaccount_create_account_policy_text, linkedTOS, linkedPN));
|
||||
final boolean underlineLinks = true;
|
||||
ActivityUtils.linkifyTextView(policyView, underlineLinks);
|
||||
}
|
||||
|
||||
protected void hideRemoteError() {
|
||||
if (AppConstants.Versions.feature11Plus) {
|
||||
// On v11+, we remove the view entirely, which triggers a smooth
|
||||
// animation.
|
||||
remoteErrorTextView.setVisibility(View.GONE);
|
||||
} else {
|
||||
// On earlier versions, we just hide the error.
|
||||
remoteErrorTextView.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
protected void showRemoteError(Exception e, int defaultResourceId) {
|
||||
if (e instanceof IOException) {
|
||||
remoteErrorTextView.setText(R.string.fxaccount_remote_error_COULD_NOT_CONNECT);
|
||||
} else if (e instanceof FxAccountClientRemoteException) {
|
||||
showClientRemoteException((FxAccountClientRemoteException) e);
|
||||
} else {
|
||||
remoteErrorTextView.setText(defaultResourceId);
|
||||
}
|
||||
Logger.warn(LOG_TAG, "Got exception; showing error message: " + remoteErrorTextView.getText().toString(), e);
|
||||
remoteErrorTextView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
protected void showClientRemoteException(final FxAccountClientRemoteException e) {
|
||||
if (!e.isAccountLocked()) {
|
||||
remoteErrorTextView.setText(e.getErrorMessageStringResource());
|
||||
return;
|
||||
}
|
||||
|
||||
// This horrible bit of special-casing is because we want this error message
|
||||
// to contain a clickable, extra chunk of text, but we don't want to pollute
|
||||
// the exception class with Android specifics.
|
||||
final int messageId = e.getErrorMessageStringResource();
|
||||
final int clickableId = R.string.fxaccount_resend_unlock_code_button_label;
|
||||
final Spannable span = Utils.interpolateClickableSpan(this, messageId, clickableId, new ClickableSpan() {
|
||||
@Override
|
||||
public void onClick(View widget) {
|
||||
// It would be best to capture the email address sent to the server
|
||||
// and use it here, but this will do for now. If the user modifies
|
||||
// the email address entered, the error text is hidden, so sending a
|
||||
// changed email address would be the result of an unusual race.
|
||||
final String email = emailEdit.getText().toString();
|
||||
byte[] emailUTF8 = null;
|
||||
try {
|
||||
emailUTF8 = email.getBytes("UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
// It's okay, we'll fail in the code resender.
|
||||
}
|
||||
FxAccountUnlockCodeResender.resendUnlockCode(FxAccountAbstractSetupActivity.this, getAuthServerEndpoint(), emailUTF8);
|
||||
}
|
||||
});
|
||||
remoteErrorTextView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
remoteErrorTextView.setText(span);
|
||||
}
|
||||
|
||||
protected void addListeners() {
|
||||
TextChangedListener textChangedListener = new TextChangedListener();
|
||||
EditorActionListener editorActionListener = new EditorActionListener();
|
||||
FocusChangeListener focusChangeListener = new FocusChangeListener();
|
||||
|
||||
emailEdit.addTextChangedListener(textChangedListener);
|
||||
emailEdit.setOnEditorActionListener(editorActionListener);
|
||||
emailEdit.setOnFocusChangeListener(focusChangeListener);
|
||||
passwordEdit.addTextChangedListener(textChangedListener);
|
||||
passwordEdit.setOnEditorActionListener(editorActionListener);
|
||||
passwordEdit.setOnFocusChangeListener(focusChangeListener);
|
||||
}
|
||||
|
||||
protected class FocusChangeListener implements OnFocusChangeListener {
|
||||
@Override
|
||||
public void onFocusChange(View v, boolean hasFocus) {
|
||||
if (hasFocus) {
|
||||
return;
|
||||
}
|
||||
updateButtonState();
|
||||
}
|
||||
}
|
||||
|
||||
protected class EditorActionListener implements OnEditorActionListener {
|
||||
@Override
|
||||
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
|
||||
updateButtonState();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected class TextChangedListener implements TextWatcher {
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
updateButtonState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence s, int start, int before, int count) {
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean shouldButtonBeEnabled() {
|
||||
final String email = emailEdit.getText().toString();
|
||||
final String password = passwordEdit.getText().toString();
|
||||
|
||||
boolean enabled =
|
||||
(email.length() > 0) &&
|
||||
Patterns.EMAIL_ADDRESS.matcher(email).matches() &&
|
||||
(password.length() >= minimumPasswordLength);
|
||||
return enabled;
|
||||
}
|
||||
|
||||
protected boolean updateButtonState() {
|
||||
boolean enabled = shouldButtonBeEnabled();
|
||||
if (!enabled) {
|
||||
// The user needs to do something before you can interact with the button;
|
||||
// presumably that interaction will fix whatever error is shown.
|
||||
hideRemoteError();
|
||||
}
|
||||
if (enabled != button.isEnabled()) {
|
||||
Logger.debug(LOG_TAG, (enabled ? "En" : "Dis") + "abling button.");
|
||||
button.setEnabled(enabled);
|
||||
}
|
||||
return enabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showProgress() {
|
||||
progressBar.setVisibility(View.VISIBLE);
|
||||
button.setVisibility(View.INVISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dismissProgress() {
|
||||
progressBar.setVisibility(View.INVISIBLE);
|
||||
button.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
public Intent makeSuccessIntent(String email, LoginResponse result) {
|
||||
Intent successIntent;
|
||||
if (result.verified) {
|
||||
successIntent = new Intent(this, FxAccountVerifiedAccountActivity.class);
|
||||
} else {
|
||||
successIntent = new Intent(this, FxAccountConfirmAccountActivity.class);
|
||||
}
|
||||
// Per http://stackoverflow.com/a/8992365, this triggers a known bug with
|
||||
// the soft keyboard not being shown for the started activity. Why, Android, why?
|
||||
successIntent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||
return successIntent;
|
||||
}
|
||||
|
||||
protected abstract class AddAccountDelegate implements RequestDelegate<LoginResponse> {
|
||||
public final String email;
|
||||
public final PasswordStretcher passwordStretcher;
|
||||
public final String serverURI;
|
||||
public final Map<String, Boolean> selectedEngines;
|
||||
public final Map<String, Boolean> authoritiesToSyncAutomaticallyMap;
|
||||
|
||||
public AddAccountDelegate(String email, PasswordStretcher passwordStretcher, String serverURI) {
|
||||
this(email, passwordStretcher, serverURI, null, AndroidFxAccount.DEFAULT_AUTHORITIES_TO_SYNC_AUTOMATICALLY_MAP);
|
||||
}
|
||||
|
||||
public AddAccountDelegate(String email, PasswordStretcher passwordStretcher, String serverURI, Map<String, Boolean> selectedEngines, Map<String, Boolean> authoritiesToSyncAutomaticallyMap) {
|
||||
if (email == null) {
|
||||
throw new IllegalArgumentException("email must not be null");
|
||||
}
|
||||
if (passwordStretcher == null) {
|
||||
throw new IllegalArgumentException("passwordStretcher must not be null");
|
||||
}
|
||||
if (serverURI == null) {
|
||||
throw new IllegalArgumentException("serverURI must not be null");
|
||||
}
|
||||
if (authoritiesToSyncAutomaticallyMap == null) {
|
||||
throw new IllegalArgumentException("authoritiesToSyncAutomaticallyMap must not be null");
|
||||
}
|
||||
this.email = email;
|
||||
this.passwordStretcher = passwordStretcher;
|
||||
this.serverURI = serverURI;
|
||||
// selectedEngines can be null, which means don't write
|
||||
// userSelectedEngines to prefs. This makes any created meta/global record
|
||||
// have the default set of engines to sync.
|
||||
this.selectedEngines = selectedEngines;
|
||||
// authoritiesToSyncAutomaticallymap cannot be null.
|
||||
this.authoritiesToSyncAutomaticallyMap = authoritiesToSyncAutomaticallyMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSuccess(LoginResponse result) {
|
||||
Logger.info(LOG_TAG, "Got success response; adding Android account.");
|
||||
|
||||
// We're on the UI thread, but it's okay to create the account here.
|
||||
AndroidFxAccount fxAccount;
|
||||
try {
|
||||
final String profile = Constants.DEFAULT_PROFILE;
|
||||
final String tokenServerURI = getTokenServerEndpoint();
|
||||
final String profileServerURI = getProfileServerEndpoint();
|
||||
// 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, so we create the Android account
|
||||
// with their entered email address, etc.
|
||||
// The passwordStretcher should have seen this email address before, so
|
||||
// we shouldn't be calculating the expensive stretch twice.
|
||||
byte[] quickStretchedPW = passwordStretcher.getQuickStretchedPW(result.remoteEmail.getBytes("UTF-8"));
|
||||
byte[] unwrapkB = FxAccountUtils.generateUnwrapBKey(quickStretchedPW);
|
||||
State state = new Engaged(email, result.uid, result.verified, unwrapkB, result.sessionToken, result.keyFetchToken);
|
||||
fxAccount = AndroidFxAccount.addAndroidAccount(getApplicationContext(),
|
||||
email,
|
||||
profile,
|
||||
serverURI,
|
||||
tokenServerURI,
|
||||
profileServerURI,
|
||||
state,
|
||||
this.authoritiesToSyncAutomaticallyMap);
|
||||
if (fxAccount == null) {
|
||||
throw new RuntimeException("Could not add Android account.");
|
||||
}
|
||||
|
||||
if (selectedEngines != null) {
|
||||
Logger.info(LOG_TAG, "User has selected engines; storing to prefs.");
|
||||
SyncConfiguration.storeSelectedEnginesToPrefs(fxAccount.getSyncPrefs(), selectedEngines);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
handleError(e);
|
||||
return;
|
||||
}
|
||||
|
||||
// For great debugging.
|
||||
if (FxAccountUtils.LOG_PERSONAL_INFORMATION) {
|
||||
fxAccount.dump();
|
||||
}
|
||||
|
||||
// The GetStarted activity has called us and needs to return a result to the authenticator.
|
||||
final Intent intent = new Intent();
|
||||
intent.putExtra(AccountManager.KEY_ACCOUNT_NAME, email);
|
||||
intent.putExtra(AccountManager.KEY_ACCOUNT_TYPE, FxAccountConstants.ACCOUNT_TYPE);
|
||||
// intent.putExtra(AccountManager.KEY_AUTHTOKEN, accountType);
|
||||
setResult(RESULT_OK, intent);
|
||||
|
||||
// Show success activity depending on verification status.
|
||||
Intent successIntent = makeSuccessIntent(email, result);
|
||||
startActivity(successIntent);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory function that produces a new PasswordStretcher instance.
|
||||
*
|
||||
* @return PasswordStretcher instance.
|
||||
*/
|
||||
protected PasswordStretcher makePasswordStretcher(String password) {
|
||||
return new QuickPasswordStretcher(password);
|
||||
}
|
||||
|
||||
protected abstract static class GetAccountsAsyncTask extends AsyncTask<Void, Void, Account[]> {
|
||||
protected final Context context;
|
||||
|
||||
public GetAccountsAsyncTask(Context context) {
|
||||
super();
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Account[] doInBackground(Void... params) {
|
||||
return AccountManager.get(context).getAccounts();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This updates UI, so needs to be done on the foreground thread.
|
||||
*/
|
||||
protected void populateEmailAddressAutocomplete(Account[] accounts) {
|
||||
// First a set, since we don't want repeats.
|
||||
final Set<String> emails = new HashSet<String>();
|
||||
for (Account account : accounts) {
|
||||
if (!Patterns.EMAIL_ADDRESS.matcher(account.name).matches()) {
|
||||
continue;
|
||||
}
|
||||
emails.add(account.name);
|
||||
}
|
||||
|
||||
// And then sorted in alphabetical order.
|
||||
final String[] sortedEmails = emails.toArray(new String[emails.size()]);
|
||||
Arrays.sort(sortedEmails);
|
||||
|
||||
final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_dropdown_item_1line, sortedEmails);
|
||||
emailEdit.setAdapter(adapter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
||||
@SuppressLint("NewApi")
|
||||
protected void maybeEnableAnimations() {
|
||||
// On v11+, we animate the error display being added and removed. This saves
|
||||
// us some vertical space when we start the activity.
|
||||
if (AppConstants.Versions.feature11Plus) {
|
||||
final ViewGroup container = (ViewGroup) remoteErrorTextView.getParent();
|
||||
container.setLayoutTransition(new LayoutTransition());
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateFromIntentExtras() {
|
||||
// Only set email/password in onCreate; we don't want to overwrite edited values onResume.
|
||||
if (getIntent() != null && getIntent().getExtras() != null) {
|
||||
Bundle bundle = getIntent().getExtras();
|
||||
emailEdit.setText(bundle.getString(EXTRA_EMAIL));
|
||||
passwordEdit.setText(bundle.getString(EXTRA_PASSWORD));
|
||||
setPasswordButtonShown(bundle.getBoolean(EXTRA_PASSWORD_SHOWN, false));
|
||||
}
|
||||
|
||||
// This sets defaults as well as extracting from extras, so it's not conditional.
|
||||
updateServersFromIntentExtras(getIntent());
|
||||
|
||||
if (FxAccountUtils.LOG_PERSONAL_INFORMATION) {
|
||||
FxAccountUtils.pii(LOG_TAG, "Using auth server: " + authServerEndpoint);
|
||||
FxAccountUtils.pii(LOG_TAG, "Using sync server: " + syncServerEndpoint);
|
||||
FxAccountUtils.pii(LOG_TAG, "Using profile server: " + profileServerEndpoint);
|
||||
}
|
||||
|
||||
updateCustomServerView();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
// Getting Accounts accesses databases on disk, so needs to be done on a
|
||||
// background thread.
|
||||
final GetAccountsAsyncTask task = new GetAccountsAsyncTask(this) {
|
||||
@Override
|
||||
public void onPostExecute(Account[] accounts) {
|
||||
populateEmailAddressAutocomplete(accounts);
|
||||
}
|
||||
};
|
||||
task.execute();
|
||||
}
|
||||
|
||||
protected Bundle makeExtrasBundle(String email, String password) {
|
||||
final Bundle bundle = new Bundle();
|
||||
|
||||
// Pass through any extras that we were started with.
|
||||
if (getIntent() != null && getIntent().getExtras() != null) {
|
||||
bundle.putAll(getIntent().getExtras());
|
||||
}
|
||||
|
||||
// Overwrite with current settings.
|
||||
if (email == null) {
|
||||
email = emailEdit.getText().toString();
|
||||
}
|
||||
if (password == null) {
|
||||
password = passwordEdit.getText().toString();
|
||||
}
|
||||
bundle.putString(EXTRA_EMAIL, email);
|
||||
bundle.putString(EXTRA_PASSWORD, password);
|
||||
|
||||
boolean isPasswordShown = passwordEdit.getTransformationMethod() instanceof SingleLineTransformationMethod;
|
||||
bundle.putBoolean(EXTRA_PASSWORD_SHOWN, isPasswordShown);
|
||||
|
||||
return bundle;
|
||||
}
|
||||
|
||||
protected void startActivityInstead(Class<?> cls, int requestCode, Bundle extras) {
|
||||
Intent intent = new Intent(this, cls);
|
||||
if (extras != null) {
|
||||
intent.putExtras(extras);
|
||||
}
|
||||
// Per http://stackoverflow.com/a/8992365, this triggers a known bug with
|
||||
// the soft keyboard not being shown for the started activity. Why, Android, why?
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||
startActivityForResult(intent, requestCode);
|
||||
}
|
||||
|
||||
protected void updateServersFromIntentExtras(Intent intent) {
|
||||
// Start with defaults.
|
||||
this.authServerEndpoint = FxAccountConstants.DEFAULT_AUTH_SERVER_ENDPOINT;
|
||||
this.syncServerEndpoint = FxAccountConstants.DEFAULT_TOKEN_SERVER_ENDPOINT;
|
||||
this.profileServerEndpoint = FxAccountConstants.DEFAULT_PROFILE_SERVER_ENDPOINT;
|
||||
|
||||
if (intent == null) {
|
||||
Logger.warn(LOG_TAG, "Intent is null; ignoring and using default servers.");
|
||||
return;
|
||||
}
|
||||
|
||||
final String extrasString = intent.getStringExtra(EXTRA_EXTRAS);
|
||||
|
||||
if (extrasString == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final ExtendedJSONObject extras;
|
||||
final ExtendedJSONObject services;
|
||||
try {
|
||||
extras = new ExtendedJSONObject(extrasString);
|
||||
services = extras.getObject(JSON_KEY_SERVICES);
|
||||
} catch (Exception e) {
|
||||
Logger.warn(LOG_TAG, "Got exception parsing extras; ignoring and using default servers.");
|
||||
return;
|
||||
}
|
||||
|
||||
String authServer = extras.getString(JSON_KEY_AUTH);
|
||||
String syncServer = services == null ? null : services.getString(JSON_KEY_SYNC);
|
||||
String profileServer = services == null ? null : services.getString(JSON_KEY_PROFILE);
|
||||
|
||||
if (authServer != null) {
|
||||
this.authServerEndpoint = authServer;
|
||||
}
|
||||
if (syncServer != null) {
|
||||
this.syncServerEndpoint = syncServer;
|
||||
}
|
||||
if (profileServer != null) {
|
||||
this.profileServerEndpoint = profileServer;
|
||||
}
|
||||
|
||||
if (FxAccountConstants.DEFAULT_TOKEN_SERVER_ENDPOINT.equals(syncServerEndpoint) &&
|
||||
!FxAccountConstants.DEFAULT_AUTH_SERVER_ENDPOINT.equals(authServerEndpoint)) {
|
||||
// We really don't want to hard-code assumptions about server
|
||||
// configurations into client code in such a way that if and when the
|
||||
// situation is relaxed, the client code stops valid usage. Instead, we
|
||||
// warn. This configuration should present itself as an auth exception at
|
||||
// Sync time.
|
||||
Logger.warn(LOG_TAG, "Mozilla's Sync token servers only works with Mozilla's auth servers. Sync will likely be mis-configured.");
|
||||
}
|
||||
}
|
||||
|
||||
protected void updateCustomServerView() {
|
||||
final boolean shouldShow =
|
||||
ALWAYS_SHOW_CUSTOM_SERVER_LAYOUT ||
|
||||
!FxAccountConstants.DEFAULT_AUTH_SERVER_ENDPOINT.equals(authServerEndpoint) ||
|
||||
!FxAccountConstants.DEFAULT_TOKEN_SERVER_ENDPOINT.equals(syncServerEndpoint);
|
||||
|
||||
if (!shouldShow) {
|
||||
setCustomServerViewVisibility(View.GONE);
|
||||
return;
|
||||
}
|
||||
|
||||
final TextView authServerView = (TextView) ensureFindViewById(null, R.id.account_server_summary, "account server");
|
||||
final TextView syncServerView = (TextView) ensureFindViewById(null, R.id.sync_server_summary, "Sync server");
|
||||
authServerView.setText(authServerEndpoint);
|
||||
syncServerView.setText(syncServerEndpoint);
|
||||
|
||||
setCustomServerViewVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
protected void setCustomServerViewVisibility(int visibility) {
|
||||
ensureFindViewById(null, R.id.account_server_layout, "account server layout").setVisibility(visibility);
|
||||
ensureFindViewById(null, R.id.sync_server_layout, "sync server layout").setVisibility(visibility);
|
||||
}
|
||||
|
||||
protected Map<String, String> getQueryParameters() {
|
||||
final Map<String, String> queryParameters = new HashMap<>();
|
||||
queryParameters.put("service", "sync");
|
||||
return queryParameters;
|
||||
}
|
||||
}
|
||||
|
@ -1,186 +0,0 @@
|
||||
/* 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.fxa.activities;
|
||||
|
||||
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;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.background.common.telemetry.TelemetryWrapper;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClient;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClient10.RequestDelegate;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClient20;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClient20.LoginResponse;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClientException.FxAccountClientRemoteException;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountUtils;
|
||||
import org.mozilla.gecko.background.fxa.PasswordStretcher;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.fxa.login.Engaged;
|
||||
import org.mozilla.gecko.fxa.login.State;
|
||||
import org.mozilla.gecko.fxa.tasks.FxAccountSignInTask;
|
||||
import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
|
||||
import org.mozilla.gecko.sync.telemetry.TelemetryContract;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
/**
|
||||
* 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.
|
||||
redirectToAction(FxAccountConstants.ACTION_FXA_STATUS);
|
||||
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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,172 +0,0 @@
|
||||
/* 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.fxa.activities;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.TextView;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||
import org.mozilla.gecko.fxa.SyncStatusListener;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.fxa.login.Engaged;
|
||||
import org.mozilla.gecko.fxa.login.State;
|
||||
import org.mozilla.gecko.fxa.login.State.Action;
|
||||
import org.mozilla.gecko.fxa.sync.FxAccountSyncStatusHelper;
|
||||
import org.mozilla.gecko.fxa.tasks.FxAccountCodeResender;
|
||||
import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
|
||||
|
||||
/**
|
||||
* Activity which displays account created successfully screen to the user, and
|
||||
* starts them on the email verification path.
|
||||
*/
|
||||
public class FxAccountConfirmAccountActivity extends FxAccountAbstractActivity implements OnClickListener {
|
||||
private static final String LOG_TAG = FxAccountConfirmAccountActivity.class.getSimpleName();
|
||||
|
||||
// Set in onCreate.
|
||||
protected TextView verificationLinkTextView;
|
||||
protected View resendLink;
|
||||
protected View changeEmail;
|
||||
|
||||
// Set in onResume.
|
||||
protected AndroidFxAccount fxAccount;
|
||||
|
||||
protected final InnerSyncStatusDelegate syncStatusDelegate = new InnerSyncStatusDelegate();
|
||||
|
||||
public FxAccountConfirmAccountActivity() {
|
||||
super(CANNOT_RESUME_WHEN_NO_ACCOUNTS_EXIST);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
Logger.debug(LOG_TAG, "onCreate(" + icicle + ")");
|
||||
|
||||
super.onCreate(icicle);
|
||||
setContentView(R.layout.fxaccount_confirm_account);
|
||||
|
||||
verificationLinkTextView = (TextView) ensureFindViewById(null, R.id.verification_link_text, "verification link text");
|
||||
resendLink = ensureFindViewById(null, R.id.resend_confirmation_email_link, "resend confirmation email link");
|
||||
resendLink.setOnClickListener(this);
|
||||
changeEmail = ensureFindViewById(null, R.id.change_confirmation_email_link, "change confirmation email address");
|
||||
changeEmail.setOnClickListener(this);
|
||||
|
||||
View backToBrowsingButton = ensureFindViewById(null, R.id.button, "back to browsing button");
|
||||
backToBrowsingButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
ActivityUtils.openURLInFennec(v.getContext(), null);
|
||||
setResult(Activity.RESULT_OK);
|
||||
finish();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
this.fxAccount = getAndroidFxAccount();
|
||||
if (fxAccount == null) {
|
||||
Logger.warn(LOG_TAG, "Could not get Firefox Account.");
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
FxAccountSyncStatusHelper.getInstance().startObserving(syncStatusDelegate);
|
||||
|
||||
refresh();
|
||||
|
||||
fxAccount.requestSync(FirefoxAccounts.NOW);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
FxAccountSyncStatusHelper.getInstance().stopObserving(syncStatusDelegate);
|
||||
|
||||
if (fxAccount != null) {
|
||||
fxAccount.requestSync(FirefoxAccounts.SOON);
|
||||
}
|
||||
}
|
||||
|
||||
protected class InnerSyncStatusDelegate implements SyncStatusListener {
|
||||
protected final Runnable refreshRunnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
refresh();
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public Context getContext() {
|
||||
return FxAccountConfirmAccountActivity.this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Account getAccount() {
|
||||
return fxAccount.getAndroidAccount();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSyncStarted() {
|
||||
Logger.info(LOG_TAG, "Got sync started message; ignoring.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSyncFinished() {
|
||||
if (fxAccount == null) {
|
||||
return;
|
||||
}
|
||||
Logger.info(LOG_TAG, "Got sync finished message; refreshing.");
|
||||
runOnUiThread(refreshRunnable);
|
||||
}
|
||||
}
|
||||
|
||||
protected void refresh() {
|
||||
final State state = fxAccount.getState();
|
||||
final Action neededAction = state.getNeededAction();
|
||||
switch (neededAction) {
|
||||
case NeedsVerification:
|
||||
// This is what we're here to handle.
|
||||
break;
|
||||
default:
|
||||
// We're not in the right place! Redirect to status.
|
||||
Logger.warn(LOG_TAG, "No need to verify Firefox Account that needs action " + neededAction.toString() +
|
||||
" (in state " + state.getStateLabel() + ").");
|
||||
setResult(RESULT_CANCELED);
|
||||
redirectToAction(FxAccountConstants.ACTION_FXA_STATUS);
|
||||
return;
|
||||
}
|
||||
|
||||
final String email = fxAccount.getEmail();
|
||||
final String text = getResources().getString(R.string.fxaccount_confirm_account_verification_link, email);
|
||||
verificationLinkTextView.setText(text);
|
||||
|
||||
boolean resendLinkShouldBeEnabled = ((Engaged) state).getSessionToken() != null;
|
||||
resendLink.setEnabled(resendLinkShouldBeEnabled);
|
||||
resendLink.setClickable(resendLinkShouldBeEnabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (v.equals(resendLink)) {
|
||||
FxAccountCodeResender.resendCode(this, fxAccount);
|
||||
} else if (v.equals(changeEmail)) {
|
||||
final Account account = fxAccount.getAndroidAccount();
|
||||
Intent intent = new Intent(this, FxAccountGetStartedActivity.class);
|
||||
FxAccountStatusActivity.maybeDeleteAndroidAccount(this, account, intent);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,538 +0,0 @@
|
||||
/* 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.fxa.activities;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountAgeLockoutHelper;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClient;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClient10.RequestDelegate;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClient20;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClient20.LoginResponse;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClientException.FxAccountClientRemoteException;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountUtils;
|
||||
import org.mozilla.gecko.background.fxa.PasswordStretcher;
|
||||
import org.mozilla.gecko.db.BrowserContract;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.fxa.tasks.FxAccountCreateAccountTask;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemClock;
|
||||
import android.text.Spannable;
|
||||
import android.text.method.LinkMovementMethod;
|
||||
import android.text.style.ClickableSpan;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
import android.widget.Button;
|
||||
import android.widget.CheckBox;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ListView;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* Activity which displays create account screen to the user.
|
||||
*/
|
||||
public class FxAccountCreateAccountActivity extends FxAccountAbstractSetupActivity {
|
||||
protected static final String LOG_TAG = FxAccountCreateAccountActivity.class.getSimpleName();
|
||||
|
||||
private static final int CHILD_REQUEST_CODE = 2;
|
||||
|
||||
protected String[] yearItems;
|
||||
protected String[] monthItems;
|
||||
protected String[] dayItems;
|
||||
protected EditText yearEdit;
|
||||
protected EditText monthEdit;
|
||||
protected EditText dayEdit;
|
||||
protected CheckBox chooseCheckBox;
|
||||
protected View monthDaycombo;
|
||||
|
||||
protected Map<String, Boolean> selectedEngines;
|
||||
protected final Map<String, Boolean> authoritiesToSyncAutomaticallyMap =
|
||||
new HashMap<String, Boolean>(AndroidFxAccount.DEFAULT_AUTHORITIES_TO_SYNC_AUTOMATICALLY_MAP);
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
Logger.debug(LOG_TAG, "onCreate(" + icicle + ")");
|
||||
|
||||
super.onCreate(icicle);
|
||||
setContentView(R.layout.fxaccount_create_account);
|
||||
|
||||
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");
|
||||
yearEdit = (EditText) ensureFindViewById(null, R.id.year_edit, "year edit");
|
||||
monthEdit = (EditText) ensureFindViewById(null, R.id.month_edit, "month edit");
|
||||
dayEdit = (EditText) ensureFindViewById(null, R.id.day_edit, "day edit");
|
||||
monthDaycombo = ensureFindViewById(null, R.id.month_day_combo, "month day combo");
|
||||
remoteErrorTextView = (TextView) ensureFindViewById(null, R.id.remote_error, "remote error text view");
|
||||
button = (Button) ensureFindViewById(null, R.id.button, "create account button");
|
||||
progressBar = (ProgressBar) ensureFindViewById(null, R.id.progress, "progress bar");
|
||||
chooseCheckBox = (CheckBox) ensureFindViewById(null, R.id.choose_what_to_sync_checkbox, "choose what to sync check box");
|
||||
selectedEngines = new HashMap<String, Boolean>();
|
||||
|
||||
createCreateAccountButton();
|
||||
createYearEdit();
|
||||
addListeners();
|
||||
updateButtonState();
|
||||
createShowPasswordButton();
|
||||
linkifyPolicy();
|
||||
createChooseCheckBox();
|
||||
initializeMonthAndDayValues();
|
||||
|
||||
View signInInsteadLink = ensureFindViewById(null, R.id.sign_in_instead_link, "sign in instead link");
|
||||
signInInsteadLink.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final Bundle extras = makeExtrasBundle(null, null);
|
||||
startActivityInstead(FxAccountSignInActivity.class, CHILD_REQUEST_CODE, extras);
|
||||
}
|
||||
});
|
||||
|
||||
updateFromIntentExtras();
|
||||
maybeEnableAnimations();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRestoreInstanceState(Bundle savedInstanceState) {
|
||||
super.onRestoreInstanceState(savedInstanceState);
|
||||
updateMonthAndDayFromBundle(savedInstanceState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
updateBundleWithMonthAndDay(outState);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Bundle makeExtrasBundle(String email, String password) {
|
||||
final Bundle extras = super.makeExtrasBundle(email, password);
|
||||
extras.putString(EXTRA_YEAR, yearEdit.getText().toString());
|
||||
updateBundleWithMonthAndDay(extras);
|
||||
return extras;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void updateFromIntentExtras() {
|
||||
super.updateFromIntentExtras();
|
||||
|
||||
if (getIntent() != null) {
|
||||
yearEdit.setText(getIntent().getStringExtra(EXTRA_YEAR));
|
||||
updateMonthAndDayFromBundle(getIntent().getExtras() != null ? getIntent().getExtras() : new Bundle());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateBundleWithMonthAndDay(final Bundle bundle) {
|
||||
if (monthEdit.getTag() != null) {
|
||||
bundle.putInt(EXTRA_MONTH, (Integer) monthEdit.getTag());
|
||||
}
|
||||
if (dayEdit.getTag() != null) {
|
||||
bundle.putInt(EXTRA_DAY, (Integer) dayEdit.getTag());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateMonthAndDayFromBundle(final Bundle extras) {
|
||||
final Integer zeroBasedMonthIndex = (Integer) extras.get(EXTRA_MONTH);
|
||||
final Integer oneBasedDayIndex = (Integer) extras.get(EXTRA_DAY);
|
||||
maybeEnableMonthAndDayButtons();
|
||||
|
||||
if (zeroBasedMonthIndex != null) {
|
||||
monthEdit.setText(monthItems[zeroBasedMonthIndex]);
|
||||
monthEdit.setTag(Integer.valueOf(zeroBasedMonthIndex));
|
||||
createDayEdit(zeroBasedMonthIndex);
|
||||
|
||||
if (oneBasedDayIndex != null && dayItems != null) {
|
||||
dayEdit.setText(dayItems[oneBasedDayIndex - 1]);
|
||||
dayEdit.setTag(Integer.valueOf(oneBasedDayIndex));
|
||||
}
|
||||
} else {
|
||||
monthEdit.setText("");
|
||||
dayEdit.setText("");
|
||||
}
|
||||
updateButtonState();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void showClientRemoteException(final FxAccountClientRemoteException e) {
|
||||
if (!e.isAccountAlreadyExists()) {
|
||||
super.showClientRemoteException(e);
|
||||
return;
|
||||
}
|
||||
|
||||
// This horrible bit of special-casing is because we want this error message to
|
||||
// contain a clickable, extra chunk of text, but we don't want to pollute
|
||||
// the exception class with Android specifics.
|
||||
final int messageId = e.getErrorMessageStringResource();
|
||||
final int clickableId = R.string.fxaccount_sign_in_button_label;
|
||||
|
||||
final Spannable span = Utils.interpolateClickableSpan(this, messageId, clickableId, new ClickableSpan() {
|
||||
@Override
|
||||
public void onClick(View widget) {
|
||||
// Pass through the email address that already existed.
|
||||
String email = e.body.getString("email");
|
||||
if (email == null) {
|
||||
email = emailEdit.getText().toString();
|
||||
}
|
||||
final String password = passwordEdit.getText().toString();
|
||||
|
||||
final Bundle extras = makeExtrasBundle(email, password);
|
||||
startActivityInstead(FxAccountSignInActivity.class, CHILD_REQUEST_CODE, extras);
|
||||
}
|
||||
});
|
||||
remoteErrorTextView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
remoteErrorTextView.setText(span);
|
||||
}
|
||||
|
||||
/**
|
||||
* We might have switched to the SignIn activity; if that activity
|
||||
* succeeds, feed its result back to the authenticator.
|
||||
*/
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
Logger.debug(LOG_TAG, "onActivityResult: " + requestCode);
|
||||
if (requestCode != CHILD_REQUEST_CODE || resultCode != RESULT_OK) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
return;
|
||||
}
|
||||
this.setResult(resultCode, data);
|
||||
this.finish();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return years to display in picker.
|
||||
*
|
||||
* @return 1990 or earlier, 1991, 1992, up to five years before current year.
|
||||
* (So, if it is currently 2014, up to 2009.)
|
||||
*/
|
||||
protected String[] getYearItems() {
|
||||
int year = Calendar.getInstance().get(Calendar.YEAR);
|
||||
LinkedList<String> years = new LinkedList<String>();
|
||||
years.add(getResources().getString(R.string.fxaccount_create_account_1990_or_earlier));
|
||||
for (int i = 1991; i <= year - 5; i++) {
|
||||
years.add(Integer.toString(i));
|
||||
}
|
||||
return years.toArray(new String[years.size()]);
|
||||
}
|
||||
|
||||
protected void createYearEdit() {
|
||||
yearItems = getYearItems();
|
||||
|
||||
yearEdit.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
android.content.DialogInterface.OnClickListener listener = new Dialog.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
yearEdit.setText(yearItems[which]);
|
||||
maybeEnableMonthAndDayButtons();
|
||||
updateButtonState();
|
||||
}
|
||||
};
|
||||
final AlertDialog dialog = new AlertDialog.Builder(FxAccountCreateAccountActivity.this)
|
||||
.setTitle(R.string.fxaccount_create_account_year_of_birth)
|
||||
.setItems(yearItems, listener)
|
||||
.setIcon(R.drawable.icon)
|
||||
.create();
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void initializeMonthAndDayValues() {
|
||||
// Hide Month and day pickers
|
||||
monthDaycombo.setVisibility(View.GONE);
|
||||
dayEdit.setEnabled(false);
|
||||
|
||||
// Populate month names.
|
||||
final Calendar calendar = Calendar.getInstance();
|
||||
final Map<String, Integer> monthNamesMap = calendar.getDisplayNames(Calendar.MONTH, Calendar.LONG, Locale.getDefault());
|
||||
monthItems = new String[monthNamesMap.size()];
|
||||
for (Map.Entry<String, Integer> entry : monthNamesMap.entrySet()) {
|
||||
monthItems[entry.getValue()] = entry.getKey();
|
||||
}
|
||||
createMonthEdit();
|
||||
}
|
||||
|
||||
protected void createMonthEdit() {
|
||||
monthEdit.setText("");
|
||||
monthEdit.setTag(null);
|
||||
monthEdit.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
android.content.DialogInterface.OnClickListener listener = new Dialog.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
monthEdit.setText(monthItems[which]);
|
||||
monthEdit.setTag(Integer.valueOf(which));
|
||||
createDayEdit(which);
|
||||
updateButtonState();
|
||||
}
|
||||
};
|
||||
final AlertDialog dialog = new AlertDialog.Builder(FxAccountCreateAccountActivity.this)
|
||||
.setTitle(R.string.fxaccount_create_account_month_of_birth)
|
||||
.setItems(monthItems, listener)
|
||||
.setIcon(R.drawable.icon)
|
||||
.create();
|
||||
dialog.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void createDayEdit(final int monthIndex) {
|
||||
dayEdit.setText("");
|
||||
dayEdit.setTag(null);
|
||||
dayEdit.setEnabled(true);
|
||||
|
||||
String yearText = yearEdit.getText().toString();
|
||||
Integer birthYear;
|
||||
try {
|
||||
birthYear = Integer.parseInt(yearText);
|
||||
} catch (NumberFormatException e) {
|
||||
// Ideal this should never happen.
|
||||
Logger.debug(LOG_TAG, "Exception while parsing year value" + e);
|
||||
return;
|
||||
}
|
||||
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.set(birthYear, monthIndex, 1);
|
||||
LinkedList<String> days = new LinkedList<String>();
|
||||
for (int i = c.getActualMinimum(Calendar.DAY_OF_MONTH); i <= c.getActualMaximum(Calendar.DAY_OF_MONTH); i++) {
|
||||
days.add(Integer.toString(i));
|
||||
}
|
||||
dayItems = days.toArray(new String[days.size()]);
|
||||
|
||||
dayEdit.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
android.content.DialogInterface.OnClickListener listener = new Dialog.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
dayEdit.setText(dayItems[which]);
|
||||
dayEdit.setTag(Integer.valueOf(which + 1)); // Days are 1-based.
|
||||
updateButtonState();
|
||||
}
|
||||
};
|
||||
final AlertDialog dialog = new AlertDialog.Builder(FxAccountCreateAccountActivity.this)
|
||||
.setTitle(R.string.fxaccount_create_account_day_of_birth)
|
||||
.setItems(dayItems, listener)
|
||||
.setIcon(R.drawable.icon)
|
||||
.create();
|
||||
dialog.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void maybeEnableMonthAndDayButtons() {
|
||||
Integer yearOfBirth = null;
|
||||
try {
|
||||
yearOfBirth = Integer.valueOf(yearEdit.getText().toString(), 10);
|
||||
} catch (NumberFormatException e) {
|
||||
Logger.debug(LOG_TAG, "Year text is not a number; assuming year is a range and that user is old enough.");
|
||||
}
|
||||
|
||||
// Check if the selected year is the magic year.
|
||||
if (yearOfBirth == null || !FxAccountAgeLockoutHelper.isMagicYear(yearOfBirth)) {
|
||||
// Year/Dec/31 is the latest birthday in the selected year, corresponding
|
||||
// to the youngest person.
|
||||
monthEdit.setTag(Integer.valueOf(11));
|
||||
dayEdit.setTag(Integer.valueOf(31));
|
||||
return;
|
||||
}
|
||||
|
||||
// Show month and date field.
|
||||
yearEdit.setVisibility(View.GONE);
|
||||
monthDaycombo.setVisibility(View.VISIBLE);
|
||||
monthEdit.setTag(null);
|
||||
dayEdit.setTag(null);
|
||||
}
|
||||
|
||||
public void createAccount(String email, String password, Map<String, Boolean> engines, Map<String, Boolean> authoritiesToSyncAutomaticallyMap) {
|
||||
String serverURI = getAuthServerEndpoint();
|
||||
PasswordStretcher passwordStretcher = makePasswordStretcher(password);
|
||||
// This delegate creates a new Android account on success, opens the
|
||||
// appropriate "success!" activity, and finishes this activity.
|
||||
RequestDelegate<LoginResponse> delegate = new AddAccountDelegate(email, passwordStretcher, serverURI, engines, authoritiesToSyncAutomaticallyMap) {
|
||||
@Override
|
||||
public void handleError(Exception e) {
|
||||
showRemoteError(e, R.string.fxaccount_create_account_unknown_error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleFailure(FxAccountClientRemoteException e) {
|
||||
showRemoteError(e, R.string.fxaccount_create_account_unknown_error);
|
||||
}
|
||||
};
|
||||
|
||||
Executor executor = Executors.newSingleThreadExecutor();
|
||||
FxAccountClient client = new FxAccountClient20(serverURI, executor);
|
||||
try {
|
||||
hideRemoteError();
|
||||
new FxAccountCreateAccountTask(this, this, email, passwordStretcher, client, getQueryParameters(), delegate).execute();
|
||||
} catch (Exception e) {
|
||||
showRemoteError(e, R.string.fxaccount_create_account_unknown_error);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldButtonBeEnabled() {
|
||||
return super.shouldButtonBeEnabled() &&
|
||||
(yearEdit.length() > 0) &&
|
||||
(monthEdit.getTag() != null) &&
|
||||
(dayEdit.getTag() != null);
|
||||
}
|
||||
|
||||
protected void createCreateAccountButton() {
|
||||
button.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
if (!updateButtonState()) {
|
||||
return;
|
||||
}
|
||||
final String email = emailEdit.getText().toString();
|
||||
final String password = passwordEdit.getText().toString();
|
||||
final int dayOfBirth = (Integer) dayEdit.getTag();
|
||||
final int zeroBasedMonthOfBirth = (Integer) monthEdit.getTag();
|
||||
// Only include selected engines if the user currently has the option checked.
|
||||
final Map<String, Boolean> engines = chooseCheckBox.isChecked()
|
||||
? selectedEngines
|
||||
: null;
|
||||
// Only include authorities if the user currently has the option checked.
|
||||
final Map<String, Boolean> authoritiesMap = chooseCheckBox.isChecked()
|
||||
? authoritiesToSyncAutomaticallyMap
|
||||
: AndroidFxAccount.DEFAULT_AUTHORITIES_TO_SYNC_AUTOMATICALLY_MAP;
|
||||
if (FxAccountAgeLockoutHelper.passesAgeCheck(dayOfBirth, zeroBasedMonthOfBirth, yearEdit.getText().toString(), yearItems)) {
|
||||
FxAccountUtils.pii(LOG_TAG, "Passed age check.");
|
||||
createAccount(email, password, engines, authoritiesMap);
|
||||
} else {
|
||||
FxAccountUtils.pii(LOG_TAG, "Failed age check!");
|
||||
FxAccountAgeLockoutHelper.lockOut(SystemClock.elapsedRealtime());
|
||||
setResult(RESULT_CANCELED);
|
||||
launchActivity(FxAccountCreateAccountNotAllowedActivity.class);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The "Choose what to sync" checkbox pops up a multi-choice dialog when it is
|
||||
* unchecked. It toggles to unchecked from checked.
|
||||
*/
|
||||
protected void createChooseCheckBox() {
|
||||
final int INDEX_BOOKMARKS = 0;
|
||||
final int INDEX_HISTORY = 1;
|
||||
final int INDEX_TABS = 2;
|
||||
final int INDEX_PASSWORDS = 3;
|
||||
final int INDEX_READING_LIST = 4; // Only valid if reading list is enabled.
|
||||
final int NUMBER_OF_ENGINES;
|
||||
if (AppConstants.MOZ_ANDROID_READING_LIST_SERVICE) {
|
||||
NUMBER_OF_ENGINES = 5;
|
||||
} else {
|
||||
NUMBER_OF_ENGINES = 4;
|
||||
}
|
||||
|
||||
final String items[] = new String[NUMBER_OF_ENGINES];
|
||||
final boolean checkedItems[] = new boolean[NUMBER_OF_ENGINES];
|
||||
items[INDEX_BOOKMARKS] = getResources().getString(R.string.fxaccount_status_bookmarks);
|
||||
items[INDEX_HISTORY] = getResources().getString(R.string.fxaccount_status_history);
|
||||
items[INDEX_TABS] = getResources().getString(R.string.fxaccount_status_tabs);
|
||||
items[INDEX_PASSWORDS] = getResources().getString(R.string.fxaccount_status_passwords);
|
||||
if (AppConstants.MOZ_ANDROID_READING_LIST_SERVICE) {
|
||||
items[INDEX_READING_LIST] = getResources().getString(R.string.fxaccount_status_reading_list);
|
||||
}
|
||||
// Default to everything checked.
|
||||
for (int i = 0; i < NUMBER_OF_ENGINES; i++) {
|
||||
checkedItems[i] = true;
|
||||
}
|
||||
|
||||
final DialogInterface.OnClickListener clickListener = new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
if (which != DialogInterface.BUTTON_POSITIVE) {
|
||||
Logger.debug(LOG_TAG, "onClick: not button positive, unchecking.");
|
||||
chooseCheckBox.setChecked(false);
|
||||
return;
|
||||
}
|
||||
// We only check the box on success.
|
||||
Logger.debug(LOG_TAG, "onClick: button positive, checking.");
|
||||
chooseCheckBox.setChecked(true);
|
||||
// And then remember for future use.
|
||||
ListView selectionsList = ((AlertDialog) dialog).getListView();
|
||||
for (int i = 0; i < NUMBER_OF_ENGINES; i++) {
|
||||
checkedItems[i] = selectionsList.isItemChecked(i);
|
||||
}
|
||||
selectedEngines.put("bookmarks", checkedItems[INDEX_BOOKMARKS]);
|
||||
selectedEngines.put("history", checkedItems[INDEX_HISTORY]);
|
||||
selectedEngines.put("tabs", checkedItems[INDEX_TABS]);
|
||||
selectedEngines.put("passwords", checkedItems[INDEX_PASSWORDS]);
|
||||
if (AppConstants.MOZ_ANDROID_READING_LIST_SERVICE) {
|
||||
authoritiesToSyncAutomaticallyMap.put(BrowserContract.READING_LIST_AUTHORITY, checkedItems[INDEX_READING_LIST]);
|
||||
}
|
||||
FxAccountUtils.pii(LOG_TAG, "Updating selectedEngines: " + selectedEngines.toString());
|
||||
FxAccountUtils.pii(LOG_TAG, "Updating authorities: " + authoritiesToSyncAutomaticallyMap.toString());
|
||||
}
|
||||
};
|
||||
|
||||
final DialogInterface.OnMultiChoiceClickListener multiChoiceClickListener = new DialogInterface.OnMultiChoiceClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which, boolean isChecked) {
|
||||
// Display multi-selection clicks in UI.
|
||||
ListView selectionsList = ((AlertDialog) dialog).getListView();
|
||||
selectionsList.setItemChecked(which, isChecked);
|
||||
}
|
||||
};
|
||||
|
||||
final AlertDialog dialog = new AlertDialog.Builder(this)
|
||||
.setTitle(R.string.fxaccount_create_account_choose_what_to_sync)
|
||||
.setIcon(R.drawable.icon)
|
||||
.setMultiChoiceItems(items, checkedItems, multiChoiceClickListener)
|
||||
.setPositiveButton(android.R.string.ok, clickListener)
|
||||
.setNegativeButton(android.R.string.cancel, clickListener)
|
||||
.create();
|
||||
|
||||
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
Logger.debug(LOG_TAG, "onCancel: unchecking.");
|
||||
chooseCheckBox.setChecked(false);
|
||||
}
|
||||
});
|
||||
|
||||
chooseCheckBox.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
// There appears to be no way to stop Android interpreting the click
|
||||
// first. So, if the user clicked on an unchecked box, it's checked by
|
||||
// the time we get here.
|
||||
if (!chooseCheckBox.isChecked()) {
|
||||
Logger.debug(LOG_TAG, "onClick: was checked, not showing dialog.");
|
||||
return;
|
||||
}
|
||||
Logger.debug(LOG_TAG, "onClick: was unchecked, showing dialog.");
|
||||
dialog.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
/* 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.fxa.activities;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* Activity which displays sign up/sign in screen to the user.
|
||||
*/
|
||||
public class FxAccountCreateAccountNotAllowedActivity extends FxAccountAbstractActivity {
|
||||
protected static final String LOG_TAG = FxAccountCreateAccountNotAllowedActivity.class.getSimpleName();
|
||||
|
||||
public FxAccountCreateAccountNotAllowedActivity() {
|
||||
super(CANNOT_RESUME_WHEN_ACCOUNTS_EXIST);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
Logger.debug(LOG_TAG, "onCreate(" + icicle + ")");
|
||||
|
||||
super.onCreate(icicle);
|
||||
setContentView(R.layout.fxaccount_create_account_not_allowed);
|
||||
TextView view = (TextView) findViewById(R.id.learn_more_link);
|
||||
ActivityUtils.linkTextView(view, R.string.fxaccount_account_create_not_allowed_learn_more, R.string.fxaccount_link_create_not_allowed);
|
||||
}
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
/* 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.fxa.activities;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClient20.LoginResponse;
|
||||
import org.mozilla.gecko.fxa.login.State;
|
||||
import org.mozilla.gecko.fxa.login.State.StateLabel;
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
/**
|
||||
* Activity which displays a screen for inputting the password and finishing
|
||||
* migrating to Firefox Accounts / Sync 1.5.
|
||||
*/
|
||||
public class FxAccountFinishMigratingActivity extends FxAccountAbstractUpdateCredentialsActivity {
|
||||
protected static final String LOG_TAG = FxAccountFinishMigratingActivity.class.getSimpleName();
|
||||
|
||||
public FxAccountFinishMigratingActivity() {
|
||||
super(R.layout.fxaccount_finish_migrating);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
this.fxAccount = getAndroidFxAccount();
|
||||
if (fxAccount == null) {
|
||||
Logger.warn(LOG_TAG, "Could not get Firefox Account.");
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
final State state = fxAccount.getState();
|
||||
if (state.getStateLabel() != StateLabel.MigratedFromSync11) {
|
||||
Logger.warn(LOG_TAG, "Cannot finish migrating from Firefox Account in state: " + state.getStateLabel());
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
emailEdit.setText(fxAccount.getEmail());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent makeSuccessIntent(String email, LoginResponse result) {
|
||||
final Intent successIntent = new Intent(this, FxAccountMigrationFinishedActivity.class);
|
||||
// Per http://stackoverflow.com/a/8992365, this triggers a known bug with
|
||||
// the soft keyboard not being shown for the started activity. Why, Android, why?
|
||||
successIntent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||
return successIntent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, String> getQueryParameters() {
|
||||
final Map<String, String> queryParameters = super.getQueryParameters();
|
||||
queryParameters.put("migration", "sync11");
|
||||
return queryParameters;
|
||||
}
|
||||
}
|
@ -1,171 +0,0 @@
|
||||
/* 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.fxa.activities;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
import org.mozilla.gecko.Locales;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountAgeLockoutHelper;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountUtils;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
import org.mozilla.gecko.fxa.FxAccountConstants;
|
||||
import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
|
||||
|
||||
import android.accounts.AccountAuthenticatorActivity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemClock;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.animation.AlphaAnimation;
|
||||
import android.view.animation.Animation;
|
||||
import android.view.animation.AnimationSet;
|
||||
import android.view.animation.TranslateAnimation;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* Activity which displays sign up/sign in screen to the user.
|
||||
*/
|
||||
public class FxAccountGetStartedActivity extends AccountAuthenticatorActivity {
|
||||
protected static final String LOG_TAG = FxAccountGetStartedActivity.class.getSimpleName();
|
||||
|
||||
private static final int CHILD_REQUEST_CODE = 1;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
Logger.setThreadLogTag(FxAccountConstants.GLOBAL_LOG_TAG);
|
||||
Logger.debug(LOG_TAG, "onCreate(" + icicle + ")");
|
||||
|
||||
Locales.initializeLocale(getApplicationContext());
|
||||
|
||||
super.onCreate(icicle);
|
||||
|
||||
setContentView(R.layout.fxaccount_get_started);
|
||||
|
||||
linkifyOldFirefoxLink();
|
||||
|
||||
View button = findViewById(R.id.get_started_button);
|
||||
button.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Bundle extras = null; // startFlow accepts null.
|
||||
if (getIntent() != null) {
|
||||
extras = getIntent().getExtras();
|
||||
}
|
||||
startFlow(extras);
|
||||
}
|
||||
});
|
||||
|
||||
animateIconIn();
|
||||
}
|
||||
|
||||
/**
|
||||
* Float the icon up, starting from below and moving up to its final layout
|
||||
* position. Also, fade the icon in.
|
||||
* <p>
|
||||
* We animate relative to the size of the icon rather than from the bottom of
|
||||
* the containing view for two reasons: first, the distance from bottom could
|
||||
* be large on tablets; two, animating with absolute values requires that
|
||||
* measurement has happened first, which requires a (sometimes buggy)
|
||||
* onPreDrawListener.
|
||||
*/
|
||||
protected void animateIconIn() {
|
||||
final AlphaAnimation a = new AlphaAnimation(0.0f, 1.0f);
|
||||
final TranslateAnimation t = new TranslateAnimation(
|
||||
Animation.RELATIVE_TO_SELF, 0.0f, Animation.RELATIVE_TO_SELF, 0.0f,
|
||||
Animation.RELATIVE_TO_SELF, 2.0f, Animation.RELATIVE_TO_SELF, 0.0f);
|
||||
|
||||
final AnimationSet animationSet = new AnimationSet(true);
|
||||
animationSet.setDuration(150 * 7); // Straight outta... fxa-content-server.
|
||||
animationSet.addAnimation(a);
|
||||
animationSet.addAnimation(t);
|
||||
|
||||
final View iconView = findViewById(R.id.icon);
|
||||
iconView.startAnimation(animationSet);
|
||||
}
|
||||
|
||||
protected void startFlow(Bundle extras) {
|
||||
final Intent intent = new Intent(this, FxAccountCreateAccountActivity.class);
|
||||
// Per http://stackoverflow.com/a/8992365, this triggers a known bug with
|
||||
// the soft keyboard not being shown for the started activity. Why, Android, why?
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||
if (extras != null) {
|
||||
intent.putExtras(extras);
|
||||
}
|
||||
startActivityForResult(intent, CHILD_REQUEST_CODE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
|
||||
Intent intent = null;
|
||||
if (FxAccountAgeLockoutHelper.isLockedOut(SystemClock.elapsedRealtime())) {
|
||||
intent = new Intent(this, FxAccountCreateAccountNotAllowedActivity.class);
|
||||
} else if (FirefoxAccounts.firefoxAccountsExist(this)) {
|
||||
intent = new Intent(this, FxAccountStatusActivity.class);
|
||||
}
|
||||
|
||||
if (intent != null) {
|
||||
this.setAccountAuthenticatorResult(null);
|
||||
setResult(RESULT_CANCELED);
|
||||
// Per http://stackoverflow.com/a/8992365, this triggers a known bug with
|
||||
// the soft keyboard not being shown for the started activity. Why, Android, why?
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
|
||||
this.startActivity(intent);
|
||||
this.finish();
|
||||
}
|
||||
|
||||
// If we've been launched with extras (namely custom server URLs), continue
|
||||
// past go and collect 200 dollars. If we ever get back here (for example,
|
||||
// if the user hits the back button), forget that we had extras entirely, so
|
||||
// that we don't enter a loop.
|
||||
Bundle extras = null;
|
||||
if (getIntent() != null) {
|
||||
extras = getIntent().getExtras();
|
||||
}
|
||||
if (extras != null && extras.containsKey(FxAccountAbstractSetupActivity.EXTRA_EXTRAS)) {
|
||||
getIntent().replaceExtras(Bundle.EMPTY);
|
||||
startFlow((Bundle) extras.clone());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We started the CreateAccount activity for a result; this returns it to the
|
||||
* authenticator.
|
||||
*/
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
Logger.debug(LOG_TAG, "onActivityResult: " + requestCode + ", " + resultCode);
|
||||
if (requestCode != CHILD_REQUEST_CODE) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
return;
|
||||
}
|
||||
|
||||
this.setResult(requestCode, data);
|
||||
if (data != null) {
|
||||
this.setAccountAuthenticatorResult(data.getExtras());
|
||||
|
||||
// We want to drop ourselves off the back stack if the user successfully
|
||||
// created or signed in to an account. We can easily determine this by
|
||||
// checking for the presence of response data.
|
||||
this.finish();
|
||||
}
|
||||
}
|
||||
|
||||
protected void linkifyOldFirefoxLink() {
|
||||
TextView oldFirefox = (TextView) findViewById(R.id.old_firefox);
|
||||
String text = getResources().getString(R.string.fxaccount_getting_started_old_firefox);
|
||||
final String url = FirefoxAccounts.getOldSyncUpgradeURL(getResources(), Locale.getDefault());
|
||||
FxAccountUtils.pii(LOG_TAG, "Old Firefox url is: " + url); // Don't want to leak locale in particular.
|
||||
ActivityUtils.linkTextView(oldFirefox, text, url);
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
/* 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.fxa.activities;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.fxa.login.State;
|
||||
import org.mozilla.gecko.fxa.login.State.Action;
|
||||
import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
|
||||
/**
|
||||
* Activity which displays "Upgrade finished" success screen.
|
||||
*/
|
||||
public class FxAccountMigrationFinishedActivity extends FxAccountAbstractActivity {
|
||||
private static final String LOG_TAG = FxAccountMigrationFinishedActivity.class.getSimpleName();
|
||||
|
||||
protected AndroidFxAccount fxAccount;
|
||||
|
||||
public FxAccountMigrationFinishedActivity() {
|
||||
super(CANNOT_RESUME_WHEN_NO_ACCOUNTS_EXIST);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
Logger.debug(LOG_TAG, "onCreate(" + icicle + ")");
|
||||
|
||||
super.onCreate(icicle);
|
||||
setContentView(R.layout.fxaccount_migration_finished);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
this.fxAccount = getAndroidFxAccount();
|
||||
if (fxAccount == null) {
|
||||
Logger.warn(LOG_TAG, "Could not get Firefox Account.");
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
final State state = fxAccount.getState();
|
||||
if (state.getNeededAction() == Action.NeedsFinishMigrating) {
|
||||
Logger.warn(LOG_TAG, "Firefox Account needs to finish migrating; not displaying migration finished activity.");
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
final View backToBrowsingButton = ensureFindViewById(null, R.id.button, "back to browsing button");
|
||||
backToBrowsingButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
ActivityUtils.openURLInFennec(v.getContext(), null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,131 +0,0 @@
|
||||
/* 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.fxa.activities;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClient;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClient10.RequestDelegate;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClient20;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClient20.LoginResponse;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClientException.FxAccountClientRemoteException;
|
||||
import org.mozilla.gecko.background.fxa.PasswordStretcher;
|
||||
import org.mozilla.gecko.fxa.tasks.FxAccountSignInTask;
|
||||
import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
* Activity which displays sign in screen to the user.
|
||||
*/
|
||||
public class FxAccountSignInActivity extends FxAccountAbstractSetupActivity {
|
||||
protected static final String LOG_TAG = FxAccountSignInActivity.class.getSimpleName();
|
||||
|
||||
private static final int CHILD_REQUEST_CODE = 3;
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
Logger.debug(LOG_TAG, "onCreate(" + icicle + ")");
|
||||
|
||||
super.onCreate(icicle);
|
||||
setContentView(R.layout.fxaccount_sign_in);
|
||||
|
||||
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, "sign in button");
|
||||
progressBar = (ProgressBar) ensureFindViewById(null, R.id.progress, "progress bar");
|
||||
|
||||
minimumPasswordLength = 1; // Minimal restriction on passwords entered to sign in.
|
||||
createSignInButton();
|
||||
addListeners();
|
||||
updateButtonState();
|
||||
createShowPasswordButton();
|
||||
linkifyPolicy();
|
||||
|
||||
View createAccountInsteadLink = ensureFindViewById(null, R.id.create_account_link, "create account instead link");
|
||||
createAccountInsteadLink.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final Bundle extras = makeExtrasBundle(null, null);
|
||||
startActivityInstead(FxAccountCreateAccountActivity.class, CHILD_REQUEST_CODE, extras);
|
||||
}
|
||||
});
|
||||
|
||||
updateFromIntentExtras();
|
||||
maybeEnableAnimations();
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* We might have switched to the CreateAccount activity; if that activity
|
||||
* succeeds, feed its result back to the authenticator.
|
||||
*/
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
Logger.debug(LOG_TAG, "onActivityResult: " + requestCode);
|
||||
if (requestCode != CHILD_REQUEST_CODE || resultCode != RESULT_OK) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
return;
|
||||
}
|
||||
this.setResult(resultCode, data);
|
||||
this.finish();
|
||||
}
|
||||
|
||||
public void signIn(String email, String password) {
|
||||
String serverURI = getAuthServerEndpoint();
|
||||
PasswordStretcher passwordStretcher = makePasswordStretcher(password);
|
||||
// This delegate creates a new Android account on success, opens the
|
||||
// appropriate "success!" activity, and finishes this activity.
|
||||
RequestDelegate<LoginResponse> delegate = new AddAccountDelegate(email, passwordStretcher, serverURI) {
|
||||
@Override
|
||||
public void handleError(Exception e) {
|
||||
showRemoteError(e, R.string.fxaccount_sign_in_unknown_error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleFailure(FxAccountClientRemoteException e) {
|
||||
showRemoteError(e, R.string.fxaccount_sign_in_unknown_error);
|
||||
}
|
||||
};
|
||||
|
||||
Executor executor = Executors.newSingleThreadExecutor();
|
||||
FxAccountClient client = new FxAccountClient20(serverURI, executor);
|
||||
try {
|
||||
hideRemoteError();
|
||||
new FxAccountSignInTask(this, this, email, passwordStretcher, client, getQueryParameters(), delegate).execute();
|
||||
} catch (Exception e) {
|
||||
showRemoteError(e, R.string.fxaccount_sign_in_unknown_error);
|
||||
}
|
||||
}
|
||||
|
||||
protected void createSignInButton() {
|
||||
button.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final String email = emailEdit.getText().toString();
|
||||
final String password = passwordEdit.getText().toString();
|
||||
signIn(email, password);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
/* 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.fxa.activities;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountClient20.LoginResponse;
|
||||
import org.mozilla.gecko.fxa.login.State;
|
||||
import org.mozilla.gecko.fxa.login.State.StateLabel;
|
||||
|
||||
import android.content.Intent;
|
||||
|
||||
/**
|
||||
* Activity which displays a screen for updating the local password.
|
||||
*/
|
||||
public class FxAccountUpdateCredentialsActivity extends FxAccountAbstractUpdateCredentialsActivity {
|
||||
protected static final String LOG_TAG = FxAccountUpdateCredentialsActivity.class.getSimpleName();
|
||||
|
||||
public FxAccountUpdateCredentialsActivity() {
|
||||
super(R.layout.fxaccount_update_credentials);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
this.fxAccount = getAndroidFxAccount();
|
||||
if (fxAccount == null) {
|
||||
Logger.warn(LOG_TAG, "Could not get Firefox Account.");
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
final State state = fxAccount.getState();
|
||||
if (state.getStateLabel() != StateLabel.Separated) {
|
||||
Logger.warn(LOG_TAG, "Cannot update credentials from Firefox Account in state: " + state.getStateLabel());
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
emailEdit.setText(fxAccount.getEmail());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent makeSuccessIntent(String email, LoginResponse result) {
|
||||
// We don't show anything after updating credentials. The updating Activity
|
||||
// sets its result to OK and the user is returned to the previous task,
|
||||
// which is often the Status Activity.
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
/* 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.fxa.activities;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.fxa.login.State;
|
||||
import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
|
||||
/**
|
||||
* Activity which displays "Account verified" success screen.
|
||||
*/
|
||||
public class FxAccountVerifiedAccountActivity extends FxAccountAbstractActivity {
|
||||
private static final String LOG_TAG = FxAccountVerifiedAccountActivity.class.getSimpleName();
|
||||
|
||||
protected AndroidFxAccount fxAccount;
|
||||
|
||||
public FxAccountVerifiedAccountActivity() {
|
||||
super(CANNOT_RESUME_WHEN_NO_ACCOUNTS_EXIST);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
Logger.debug(LOG_TAG, "onCreate(" + icicle + ")");
|
||||
|
||||
super.onCreate(icicle);
|
||||
setContentView(R.layout.fxaccount_account_verified);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
this.fxAccount = getAndroidFxAccount();
|
||||
if (fxAccount == null) {
|
||||
Logger.warn(LOG_TAG, "Could not get Firefox Account.");
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
State state = fxAccount.getState();
|
||||
if (!state.verified) {
|
||||
Logger.warn(LOG_TAG, "Firefox Account is not verified; not displaying verified account activity.");
|
||||
setResult(RESULT_CANCELED);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
View backToBrowsingButton = ensureFindViewById(null, R.id.button, "back to browsing button");
|
||||
backToBrowsingButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
ActivityUtils.openURLInFennec(v.getContext(), null);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user