mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-02 18:08:58 +00:00
Bug 1098667 - Part 1: Import from android-sync. r=rnewman
--HG-- extra : rebase_source : afa367b0bb0002a6cfda4a1531bc7c47a5f0effa extra : source : 705b1be87804d5e3427eb433f6445ef055857a89
This commit is contained in:
parent
87fc4f13ec
commit
fa93f00372
@ -838,10 +838,13 @@ sync_java_files = [
|
||||
'fxa/AccountLoader.java',
|
||||
'fxa/activities/FxAccountAbstractActivity.java',
|
||||
'fxa/activities/FxAccountAbstractSetupActivity.java',
|
||||
'fxa/activities/FxAccountAbstractUpdateCredentialsActivity.java',
|
||||
'fxa/activities/FxAccountConfirmAccountActivity.java',
|
||||
'fxa/activities/FxAccountCreateAccountActivity.java',
|
||||
'fxa/activities/FxAccountCreateAccountNotAllowedActivity.java',
|
||||
'fxa/activities/FxAccountFinishMigratingActivity.java',
|
||||
'fxa/activities/FxAccountGetStartedActivity.java',
|
||||
'fxa/activities/FxAccountMigrationFinishedActivity.java',
|
||||
'fxa/activities/FxAccountSignInActivity.java',
|
||||
'fxa/activities/FxAccountStatusActivity.java',
|
||||
'fxa/activities/FxAccountStatusFragment.java',
|
||||
@ -861,6 +864,7 @@ sync_java_files = [
|
||||
'fxa/login/FxAccountLoginStateMachine.java',
|
||||
'fxa/login/FxAccountLoginTransition.java',
|
||||
'fxa/login/Married.java',
|
||||
'fxa/login/MigratedFromSync11.java',
|
||||
'fxa/login/Separated.java',
|
||||
'fxa/login/State.java',
|
||||
'fxa/login/StateFactory.java',
|
||||
|
@ -0,0 +1,181 @@
|
||||
/* 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.FxAccountUtils;
|
||||
import org.mozilla.gecko.background.fxa.PasswordStretcher;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
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 android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.AutoCompleteTextView;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
/**
|
||||
* Abstract activity which displays a screen for updating the local password.
|
||||
*/
|
||||
public abstract class FxAccountAbstractUpdateCredentialsActivity extends FxAccountAbstractSetupActivity {
|
||||
protected static final String LOG_TAG = FxAccountAbstractUpdateCredentialsActivity.class.getSimpleName();
|
||||
|
||||
protected AndroidFxAccount fxAccount;
|
||||
|
||||
protected final int layoutResourceId;
|
||||
|
||||
public FxAccountAbstractUpdateCredentialsActivity(int layoutResourceId) {
|
||||
// We want to share code with the other setup activities, but this activity
|
||||
// doesn't create a new Android Account, it modifies an existing one. If you
|
||||
// manage to get an account, and somehow be locked out too, we'll let you
|
||||
// update it.
|
||||
super(CANNOT_RESUME_WHEN_NO_ACCOUNTS_EXIST);
|
||||
this.layoutResourceId = layoutResourceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
Logger.debug(LOG_TAG, "onCreate(" + icicle + ")");
|
||||
|
||||
super.onCreate(icicle);
|
||||
setContentView(layoutResourceId);
|
||||
|
||||
emailEdit = (AutoCompleteTextView) ensureFindViewById(null, R.id.email, "email edit");
|
||||
passwordEdit = (EditText) ensureFindViewById(null, R.id.password, "password edit");
|
||||
showPasswordButton = (Button) ensureFindViewById(null, R.id.show_password, "show password button");
|
||||
remoteErrorTextView = (TextView) ensureFindViewById(null, R.id.remote_error, "remote error text view");
|
||||
button = (Button) ensureFindViewById(null, R.id.button, "update credentials");
|
||||
progressBar = (ProgressBar) ensureFindViewById(null, R.id.progress, "progress bar");
|
||||
|
||||
minimumPasswordLength = 1; // Minimal restriction on passwords entered to sign in.
|
||||
createButton();
|
||||
addListeners();
|
||||
updateButtonState();
|
||||
createShowPasswordButton();
|
||||
|
||||
emailEdit.setEnabled(false);
|
||||
|
||||
TextView view = (TextView) findViewById(R.id.forgot_password_link);
|
||||
ActivityUtils.linkTextView(view, R.string.fxaccount_sign_in_forgot_password, R.string.fxaccount_link_forgot_password);
|
||||
|
||||
updateFromIntentExtras();
|
||||
}
|
||||
|
||||
protected class UpdateCredentialsDelegate implements RequestDelegate<LoginResponse> {
|
||||
public final String email;
|
||||
public final String serverURI;
|
||||
public final PasswordStretcher passwordStretcher;
|
||||
|
||||
public UpdateCredentialsDelegate(String email, PasswordStretcher passwordStretcher, String serverURI) {
|
||||
this.email = email;
|
||||
this.serverURI = serverURI;
|
||||
this.passwordStretcher = passwordStretcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleError(Exception e) {
|
||||
showRemoteError(e, R.string.fxaccount_update_credentials_unknown_error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleFailure(FxAccountClientRemoteException e) {
|
||||
if (e.isUpgradeRequired()) {
|
||||
Logger.error(LOG_TAG, "Got upgrade required from remote server; transitioning Firefox Account to Doghouse state.");
|
||||
final State state = fxAccount.getState();
|
||||
fxAccount.setState(state.makeDoghouseState());
|
||||
// The status activity will say that the user needs to upgrade.
|
||||
redirectToActivity(FxAccountStatusActivity.class);
|
||||
return;
|
||||
}
|
||||
showRemoteError(e, R.string.fxaccount_update_credentials_unknown_error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSuccess(LoginResponse result) {
|
||||
Logger.info(LOG_TAG, "Got success signing in.");
|
||||
|
||||
if (fxAccount == null) {
|
||||
this.handleError(new IllegalStateException("fxAccount must not be null"));
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] unwrapkB;
|
||||
try {
|
||||
// It is crucial that we use the email address provided by the server
|
||||
// (rather than whatever the user entered), because the user's keys are
|
||||
// wrapped and salted with the initial email they provided to
|
||||
// /create/account. Of course, we want to pass through what the user
|
||||
// entered locally as much as possible.
|
||||
byte[] quickStretchedPW = passwordStretcher.getQuickStretchedPW(result.remoteEmail.getBytes("UTF-8"));
|
||||
unwrapkB = FxAccountUtils.generateUnwrapBKey(quickStretchedPW);
|
||||
} catch (Exception e) {
|
||||
this.handleError(e);
|
||||
return;
|
||||
}
|
||||
fxAccount.setState(new Engaged(email, result.uid, result.verified, unwrapkB, result.sessionToken, result.keyFetchToken));
|
||||
fxAccount.requestSync(FirefoxAccounts.FORCE);
|
||||
|
||||
// For great debugging.
|
||||
if (FxAccountUtils.LOG_PERSONAL_INFORMATION) {
|
||||
fxAccount.dump();
|
||||
}
|
||||
|
||||
setResult(RESULT_OK);
|
||||
|
||||
// Maybe show success activity.
|
||||
final Intent successIntent = makeSuccessIntent(email, result);
|
||||
if (successIntent != null) {
|
||||
startActivity(successIntent);
|
||||
}
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
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, 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -7,7 +7,6 @@ package org.mozilla.gecko.fxa.activities;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
import org.mozilla.gecko.fxa.activities.FxAccountGetStartedActivity;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.fxa.login.Engaged;
|
||||
import org.mozilla.gecko.fxa.login.State;
|
||||
@ -141,9 +140,6 @@ public class FxAccountConfirmAccountActivity extends FxAccountAbstractActivity i
|
||||
case NeedsVerification:
|
||||
// This is what we're here to handle.
|
||||
break;
|
||||
case NeedsPassword:
|
||||
case NeedsUpgrade:
|
||||
case None:
|
||||
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() +
|
||||
|
@ -0,0 +1,54 @@
|
||||
/* 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 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;
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/* 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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
@ -5,13 +5,12 @@
|
||||
package org.mozilla.gecko.fxa.activities;
|
||||
|
||||
import org.mozilla.gecko.AppConstants;
|
||||
import org.mozilla.gecko.LocaleAware.LocaleAwareFragmentActivity;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
import org.mozilla.gecko.LocaleAware.LocaleAwareActivity;
|
||||
import org.mozilla.gecko.LocaleAware.LocaleAwareFragmentActivity;
|
||||
|
||||
import android.accounts.Account;
|
||||
import android.accounts.AccountManager;
|
||||
|
@ -77,6 +77,7 @@ public class FxAccountStatusFragment
|
||||
protected Preference needsVerificationPreference;
|
||||
protected Preference needsMasterSyncAutomaticallyEnabledPreference;
|
||||
protected Preference needsAccountEnabledPreference;
|
||||
protected Preference needsFinishMigratingPreference;
|
||||
|
||||
protected PreferenceCategory syncCategory;
|
||||
|
||||
@ -138,6 +139,7 @@ public class FxAccountStatusFragment
|
||||
needsVerificationPreference = ensureFindPreference("needs_verification");
|
||||
needsMasterSyncAutomaticallyEnabledPreference = ensureFindPreference("needs_master_sync_automatically_enabled");
|
||||
needsAccountEnabledPreference = ensureFindPreference("needs_account_enabled");
|
||||
needsFinishMigratingPreference = ensureFindPreference("needs_finish_migrating");
|
||||
|
||||
syncCategory = (PreferenceCategory) ensureFindPreference("sync_category");
|
||||
|
||||
@ -157,6 +159,7 @@ public class FxAccountStatusFragment
|
||||
needsPasswordPreference.setOnPreferenceClickListener(this);
|
||||
needsVerificationPreference.setOnPreferenceClickListener(this);
|
||||
needsAccountEnabledPreference.setOnPreferenceClickListener(this);
|
||||
needsFinishMigratingPreference.setOnPreferenceClickListener(this);
|
||||
|
||||
bookmarksPreference.setOnPreferenceClickListener(this);
|
||||
historyPreference.setOnPreferenceClickListener(this);
|
||||
@ -204,6 +207,20 @@ public class FxAccountStatusFragment
|
||||
return true;
|
||||
}
|
||||
|
||||
if (preference == needsFinishMigratingPreference) {
|
||||
final Intent intent = new Intent(getActivity(), FxAccountFinishMigratingActivity.class);
|
||||
final Bundle extras = getExtrasForAccount();
|
||||
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);
|
||||
startActivity(intent);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if (preference == needsVerificationPreference) {
|
||||
FxAccountCodeResender.resendCode(getActivity().getApplicationContext(), fxAccount);
|
||||
|
||||
@ -280,6 +297,7 @@ public class FxAccountStatusFragment
|
||||
this.needsVerificationPreference,
|
||||
this.needsMasterSyncAutomaticallyEnabledPreference,
|
||||
this.needsAccountEnabledPreference,
|
||||
this.needsFinishMigratingPreference,
|
||||
};
|
||||
for (Preference errorPreference : errorPreferences) {
|
||||
final boolean currentlyShown = null != findPreference(errorPreference.getKey());
|
||||
@ -325,6 +343,12 @@ public class FxAccountStatusFragment
|
||||
setCheckboxesEnabled(false);
|
||||
}
|
||||
|
||||
protected void showNeedsFinishMigrating() {
|
||||
syncCategory.setTitle(R.string.fxaccount_status_sync);
|
||||
showOnlyOneErrorPreference(needsFinishMigratingPreference);
|
||||
setCheckboxesEnabled(false);
|
||||
}
|
||||
|
||||
protected void showConnected() {
|
||||
syncCategory.setTitle(R.string.fxaccount_status_sync_enabled);
|
||||
showOnlyOneErrorPreference(null);
|
||||
@ -464,8 +488,12 @@ public class FxAccountStatusFragment
|
||||
case NeedsVerification:
|
||||
showNeedsVerification();
|
||||
break;
|
||||
default:
|
||||
case NeedsFinishMigrating:
|
||||
showNeedsFinishMigrating();
|
||||
break;
|
||||
case None:
|
||||
showConnected();
|
||||
break;
|
||||
}
|
||||
|
||||
// We check for the master setting last, since it is not strictly
|
||||
@ -703,6 +731,11 @@ public class FxAccountStatusFragment
|
||||
State state = fxAccount.getState();
|
||||
fxAccount.setState(state.makeDoghouseState());
|
||||
refresh();
|
||||
} else if ("debug_migrated_from_sync11".equals(key)) {
|
||||
Logger.info(LOG_TAG, "Moving to MigratedFromSync11 state: Requiring password.");
|
||||
State state = fxAccount.getState();
|
||||
fxAccount.setState(state.makeMigratedFromSync11State(null));
|
||||
refresh();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@ -729,7 +762,8 @@ public class FxAccountStatusFragment
|
||||
"debug_force_sync",
|
||||
"debug_forget_certificate",
|
||||
"debug_require_password",
|
||||
"debug_require_upgrade" };
|
||||
"debug_require_upgrade",
|
||||
"debug_migrated_from_sync11" };
|
||||
for (String debugKey : debugKeys) {
|
||||
final Preference button = ensureFindPreference(debugKey);
|
||||
button.setTitle(debugKey); // Not very friendly, but this is for debugging only!
|
||||
|
@ -4,80 +4,22 @@
|
||||
|
||||
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.FxAccountUtils;
|
||||
import org.mozilla.gecko.background.fxa.PasswordStretcher;
|
||||
import org.mozilla.gecko.fxa.FirefoxAccounts;
|
||||
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.StateLabel;
|
||||
import org.mozilla.gecko.fxa.tasks.FxAccountSignInTask;
|
||||
import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
|
||||
|
||||
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 android.content.Intent;
|
||||
|
||||
/**
|
||||
* Activity which displays a screen for updating the local password.
|
||||
*/
|
||||
public class FxAccountUpdateCredentialsActivity extends FxAccountAbstractSetupActivity {
|
||||
public class FxAccountUpdateCredentialsActivity extends FxAccountAbstractUpdateCredentialsActivity {
|
||||
protected static final String LOG_TAG = FxAccountUpdateCredentialsActivity.class.getSimpleName();
|
||||
|
||||
protected AndroidFxAccount fxAccount;
|
||||
|
||||
public FxAccountUpdateCredentialsActivity() {
|
||||
// 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public void onCreate(Bundle icicle) {
|
||||
Logger.debug(LOG_TAG, "onCreate(" + icicle + ")");
|
||||
|
||||
super.onCreate(icicle);
|
||||
setContentView(R.layout.fxaccount_update_credentials);
|
||||
|
||||
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();
|
||||
super(R.layout.fxaccount_update_credentials);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -90,7 +32,7 @@ public class FxAccountUpdateCredentialsActivity extends FxAccountAbstractSetupAc
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
State state = fxAccount.getState();
|
||||
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);
|
||||
@ -100,93 +42,11 @@ public class FxAccountUpdateCredentialsActivity extends FxAccountAbstractSetupAc
|
||||
emailEdit.setText(fxAccount.getEmail());
|
||||
}
|
||||
|
||||
protected class UpdateCredentialsDelegate implements RequestDelegate<LoginResponse> {
|
||||
public final String email;
|
||||
public final String serverURI;
|
||||
public final PasswordStretcher passwordStretcher;
|
||||
|
||||
public UpdateCredentialsDelegate(String email, PasswordStretcher passwordStretcher, String serverURI) {
|
||||
this.email = email;
|
||||
this.serverURI = serverURI;
|
||||
this.passwordStretcher = passwordStretcher;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleError(Exception e) {
|
||||
showRemoteError(e, R.string.fxaccount_update_credentials_unknown_error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleFailure(FxAccountClientRemoteException e) {
|
||||
if (e.isUpgradeRequired()) {
|
||||
Logger.error(LOG_TAG, "Got upgrade required from remote server; transitioning Firefox Account to Doghouse state.");
|
||||
final State state = fxAccount.getState();
|
||||
fxAccount.setState(state.makeDoghouseState());
|
||||
// The status activity will say that the user needs to upgrade.
|
||||
redirectToActivity(FxAccountStatusActivity.class);
|
||||
return;
|
||||
}
|
||||
showRemoteError(e, R.string.fxaccount_update_credentials_unknown_error);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleSuccess(LoginResponse result) {
|
||||
Logger.info(LOG_TAG, "Got success signing in.");
|
||||
|
||||
if (fxAccount == null) {
|
||||
this.handleError(new IllegalStateException("fxAccount must not be null"));
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] unwrapkB;
|
||||
try {
|
||||
// It is crucial that we use the email address provided by the server
|
||||
// (rather than whatever the user entered), because the user's keys are
|
||||
// wrapped and salted with the initial email they provided to
|
||||
// /create/account. Of course, we want to pass through what the user
|
||||
// entered locally as much as possible.
|
||||
byte[] quickStretchedPW = passwordStretcher.getQuickStretchedPW(result.remoteEmail.getBytes("UTF-8"));
|
||||
unwrapkB = FxAccountUtils.generateUnwrapBKey(quickStretchedPW);
|
||||
} catch (Exception e) {
|
||||
this.handleError(e);
|
||||
return;
|
||||
}
|
||||
fxAccount.setState(new Engaged(email, result.uid, result.verified, unwrapkB, result.sessionToken, result.keyFetchToken));
|
||||
fxAccount.requestSync(FirefoxAccounts.FORCE);
|
||||
|
||||
// For great debugging.
|
||||
if (FxAccountUtils.LOG_PERSONAL_INFORMATION) {
|
||||
fxAccount.dump();
|
||||
}
|
||||
|
||||
setResult(RESULT_OK);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
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, 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);
|
||||
}
|
||||
});
|
||||
@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;
|
||||
}
|
||||
}
|
||||
|
28
mobile/android/base/fxa/login/MigratedFromSync11.java
Normal file
28
mobile/android/base/fxa/login/MigratedFromSync11.java
Normal file
@ -0,0 +1,28 @@
|
||||
/* 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.login;
|
||||
|
||||
import org.mozilla.gecko.fxa.login.FxAccountLoginStateMachine.ExecuteDelegate;
|
||||
import org.mozilla.gecko.fxa.login.FxAccountLoginTransition.PasswordRequired;
|
||||
|
||||
public class MigratedFromSync11 extends State {
|
||||
public final String password;
|
||||
|
||||
public MigratedFromSync11(String email, String uid, boolean verified, String password) {
|
||||
super(StateLabel.MigratedFromSync11, email, uid, verified);
|
||||
// Null password is allowed.
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(final ExecuteDelegate delegate) {
|
||||
delegate.handleTransition(new PasswordRequired(), this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Action getNeededAction() {
|
||||
return Action.NeedsFinishMigrating;
|
||||
}
|
||||
}
|
@ -9,7 +9,7 @@ import org.mozilla.gecko.sync.ExtendedJSONObject;
|
||||
import org.mozilla.gecko.sync.Utils;
|
||||
|
||||
public abstract class State {
|
||||
public static final long CURRENT_VERSION = 2L;
|
||||
public static final long CURRENT_VERSION = 3L;
|
||||
|
||||
public enum StateLabel {
|
||||
Engaged,
|
||||
@ -17,12 +17,14 @@ public abstract class State {
|
||||
Married,
|
||||
Separated,
|
||||
Doghouse,
|
||||
MigratedFromSync11,
|
||||
}
|
||||
|
||||
public enum Action {
|
||||
NeedsUpgrade,
|
||||
NeedsPassword,
|
||||
NeedsVerification,
|
||||
NeedsFinishMigrating,
|
||||
None,
|
||||
}
|
||||
|
||||
@ -60,6 +62,10 @@ public abstract class State {
|
||||
return new Doghouse(email, uid, verified);
|
||||
}
|
||||
|
||||
public State makeMigratedFromSync11State(String password) {
|
||||
return new MigratedFromSync11(email, uid, verified, password);
|
||||
}
|
||||
|
||||
public abstract void execute(ExecuteDelegate delegate);
|
||||
|
||||
public abstract Action getNeededAction();
|
||||
|
@ -54,8 +54,11 @@ public class StateFactory {
|
||||
}
|
||||
|
||||
final int v = version.intValue();
|
||||
if (v == 2) {
|
||||
if (v == 3) {
|
||||
// The most common case is the most recent version.
|
||||
return fromJSONObjectV3(stateLabel, o);
|
||||
}
|
||||
if (v == 2) {
|
||||
return fromJSONObjectV2(stateLabel, o);
|
||||
}
|
||||
if (v == 1) {
|
||||
@ -134,6 +137,23 @@ public class StateFactory {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exactly the same as {@link fromJSONObjectV2}, except that there's a new
|
||||
* MigratedFromSyncV11 state.
|
||||
*/
|
||||
protected static State fromJSONObjectV3(StateLabel stateLabel, ExtendedJSONObject o) throws InvalidKeySpecException, NoSuchAlgorithmException, NonObjectJSONException {
|
||||
switch (stateLabel) {
|
||||
case MigratedFromSync11:
|
||||
return new MigratedFromSync11(
|
||||
o.getString("email"),
|
||||
o.getString("uid"),
|
||||
o.getBoolean("verified"),
|
||||
o.getString("password"));
|
||||
default:
|
||||
return fromJSONObjectV2(stateLabel, o);
|
||||
}
|
||||
}
|
||||
|
||||
protected static void logMigration(State from, State to) {
|
||||
if (!FxAccountUtils.LOG_PERSONAL_INFORMATION) {
|
||||
return;
|
||||
|
@ -8,6 +8,7 @@ import org.mozilla.gecko.BrowserLocaleManager;
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.background.common.log.Logger;
|
||||
import org.mozilla.gecko.background.fxa.FxAccountUtils;
|
||||
import org.mozilla.gecko.fxa.activities.FxAccountFinishMigratingActivity;
|
||||
import org.mozilla.gecko.fxa.activities.FxAccountStatusActivity;
|
||||
import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
|
||||
import org.mozilla.gecko.fxa.login.State;
|
||||
@ -67,12 +68,21 @@ public class FxAccountNotificationManager {
|
||||
BrowserLocaleManager.getInstance().getAndApplyPersistedLocale(context);
|
||||
}
|
||||
|
||||
final String title = context.getResources().getString(R.string.fxaccount_sync_sign_in_error_notification_title);
|
||||
final String text = context.getResources().getString(R.string.fxaccount_sync_sign_in_error_notification_text, state.email);
|
||||
final String title;
|
||||
final String text;
|
||||
final Intent notificationIntent;
|
||||
if (action == Action.NeedsFinishMigrating) {
|
||||
title = context.getResources().getString(R.string.fxaccount_sync_finish_migrating_notification_title);
|
||||
text = context.getResources().getString(R.string.fxaccount_sync_finish_migrating_notification_text, state.email);
|
||||
notificationIntent = new Intent(context, FxAccountFinishMigratingActivity.class);
|
||||
} else {
|
||||
title = context.getResources().getString(R.string.fxaccount_sync_sign_in_error_notification_title);
|
||||
text = context.getResources().getString(R.string.fxaccount_sync_sign_in_error_notification_text, state.email);
|
||||
notificationIntent = new Intent(context, FxAccountStatusActivity.class);
|
||||
}
|
||||
Logger.info(LOG_TAG, "State " + state.getStateLabel() + " needs action; offering notification with title: " + title);
|
||||
FxAccountUtils.pii(LOG_TAG, "And text: " + text);
|
||||
|
||||
final Intent notificationIntent = new Intent(context, FxAccountStatusActivity.class);
|
||||
final PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, notificationIntent, 0);
|
||||
|
||||
final Builder builder = new NotificationCompat.Builder(context);
|
||||
|
@ -118,6 +118,7 @@ public class FxAccountSchedulePolicy implements SchedulePolicy {
|
||||
switch (needed) {
|
||||
case NeedsPassword:
|
||||
case NeedsUpgrade:
|
||||
case NeedsFinishMigrating:
|
||||
requestPeriodicSync(POLL_INTERVAL_ERROR_STATE_SEC);
|
||||
break;
|
||||
case NeedsVerification:
|
||||
|
@ -180,10 +180,16 @@
|
||||
<!ENTITY fxaccount_account_verified_sub_header 'Account verified'>
|
||||
<!ENTITY fxaccount_account_verified_description2 'Your data will begin syncing momentarily.'>
|
||||
|
||||
<!ENTITY fxaccount_migration_finished_header 'Upgrade finished'>
|
||||
|
||||
<!ENTITY fxaccount_update_credentials_header 'Sign in'>
|
||||
<!ENTITY fxaccount_update_credentials_button_label 'Sign in'>
|
||||
<!ENTITY fxaccount_update_credentials_unknown_error 'Could not sign in'>
|
||||
|
||||
<!ENTITY fxaccount_finish_migrating_header 'Sign in to finish upgrading'>
|
||||
<!ENTITY fxaccount_finish_migrating_button_label 'Finish upgrading'>
|
||||
<!ENTITY fxaccount_finish_migrating_description 'Upgrading can transfer a lot of data. It\'s best to be on a WiFi network.'>
|
||||
|
||||
<!ENTITY fxaccount_status_header2 'Firefox Account'>
|
||||
<!ENTITY fxaccount_status_signed_in_as 'Signed in as'>
|
||||
<!ENTITY fxaccount_status_auth_server 'Account server'>
|
||||
@ -198,6 +204,7 @@
|
||||
<!ENTITY fxaccount_status_needs_upgrade 'You need to upgrade &brandShortName; to sign in.'>
|
||||
<!ENTITY fxaccount_status_needs_master_sync_automatically_enabled '&syncBrand.shortName.label; is set up, but not syncing automatically. Toggle “Auto-sync data” in Android Settings > Data Usage.'>
|
||||
<!ENTITY fxaccount_status_needs_account_enabled '&syncBrand.shortName.label; is set up, but not syncing automatically. Tap to start syncing.'>
|
||||
<!ENTITY fxaccount_status_needs_finish_migrating 'Tap to sign in to your new Firefox Account.'>
|
||||
<!ENTITY fxaccount_status_bookmarks 'Bookmarks'>
|
||||
<!ENTITY fxaccount_status_history 'History'>
|
||||
<!ENTITY fxaccount_status_passwords 'Passwords'>
|
||||
@ -250,3 +257,8 @@
|
||||
<!-- Localization note: the format string below will be replaced
|
||||
with the Firefox Account's email address. -->
|
||||
<!ENTITY fxaccount_sync_sign_in_error_notification_text2 'Tap to sign in as &formatS;'>
|
||||
|
||||
<!ENTITY fxaccount_sync_finish_migrating_notification_title 'Finish upgrading &syncBrand.shortName.label;?'>
|
||||
<!-- Localization note: the format string below will be replaced
|
||||
with the Firefox Account's email address. -->
|
||||
<!ENTITY fxaccount_sync_finish_migrating_notification_text 'Tap to sign in as &formatS;'>
|
||||
|
@ -0,0 +1,61 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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/.
|
||||
-->
|
||||
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:fillViewport="true" >
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/update_credentials_view"
|
||||
style="@style/FxAccountMiddle" >
|
||||
|
||||
<LinearLayout style="@style/FxAccountSpacer" />
|
||||
|
||||
<TextView
|
||||
style="@style/FxAccountHeaderItem"
|
||||
android:text="@string/fxaccount_finish_migrating_header" />
|
||||
|
||||
<include layout="@layout/fxaccount_custom_server_view" />
|
||||
|
||||
<include layout="@layout/fxaccount_email_password_view" />
|
||||
|
||||
<TextView
|
||||
style="@style/FxAccountTextItem"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/fxaccount_finish_migrating_description" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/remote_error"
|
||||
style="@style/FxAccountErrorItem" />
|
||||
|
||||
<RelativeLayout style="@style/FxAccountButtonLayout" >
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress"
|
||||
style="@style/FxAccountProgress" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button"
|
||||
style="@style/FxAccountButton"
|
||||
android:text="@string/fxaccount_finish_migrating_button_label" />
|
||||
</RelativeLayout>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/forgot_password_link"
|
||||
style="@style/FxAccountLinkifiedItem"
|
||||
android:layout_marginTop="10dp"
|
||||
android:text="@string/fxaccount_sign_in_forgot_password" />
|
||||
|
||||
<LinearLayout style="@style/FxAccountSpacer" />
|
||||
|
||||
<ImageView
|
||||
style="@style/FxAccountIcon"
|
||||
android:contentDescription="@string/fxaccount_empty_contentDescription" />
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
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/.
|
||||
-->
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="fill_parent"
|
||||
android:fillViewport="true" >
|
||||
|
||||
<LinearLayout style="@style/FxAccountMiddle" >
|
||||
|
||||
<TextView
|
||||
style="@style/FxAccountHeaderItem"
|
||||
android:text="@string/fxaccount_migration_finished_header" >
|
||||
</TextView>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_horizontal"
|
||||
android:layout_marginBottom="45dp"
|
||||
android:contentDescription="@string/fxaccount_empty_contentDescription"
|
||||
android:src="@drawable/fxaccount_checkbox" >
|
||||
</ImageView>
|
||||
|
||||
<TextView
|
||||
style="@style/FxAccountTextItem"
|
||||
android:layout_marginBottom="40dp"
|
||||
android:text="@string/fxaccount_migration_finished_description"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/button"
|
||||
style="@style/FxAccountButton"
|
||||
android:text="@string/fxaccount_back_to_browsing" />
|
||||
|
||||
<LinearLayout style="@style/FxAccountSpacer" />
|
||||
|
||||
<ImageView
|
||||
style="@style/FxAccountIcon"
|
||||
android:contentDescription="@string/fxaccount_empty_contentDescription" />
|
||||
</LinearLayout>
|
||||
|
||||
</ScrollView>
|
@ -54,6 +54,13 @@
|
||||
android:layout="@layout/fxaccount_status_error_preference"
|
||||
android:persistent="false"
|
||||
android:title="@string/fxaccount_status_needs_account_enabled" />
|
||||
<Preference
|
||||
android:editable="false"
|
||||
android:icon="@drawable/fxaccount_sync_error"
|
||||
android:key="needs_finish_migrating"
|
||||
android:layout="@layout/fxaccount_status_error_preference"
|
||||
android:persistent="false"
|
||||
android:title="@string/fxaccount_status_needs_finish_migrating" />
|
||||
|
||||
<Preference
|
||||
android:editable="false"
|
||||
@ -125,6 +132,7 @@
|
||||
<Preference android:key="debug_forget_certificate" />
|
||||
<Preference android:key="debug_require_password" />
|
||||
<Preference android:key="debug_require_upgrade" />
|
||||
<Preference android:key="debug_migrated_from_sync11" />
|
||||
</PreferenceCategory>
|
||||
|
||||
</PreferenceScreen>
|
||||
|
@ -67,6 +67,21 @@
|
||||
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"
|
||||
|
@ -167,10 +167,17 @@
|
||||
<string name="fxaccount_account_verified_sub_header">&fxaccount_account_verified_sub_header;</string>
|
||||
<string name="fxaccount_account_verified_description">&fxaccount_account_verified_description2;</string>
|
||||
|
||||
<string name="fxaccount_migration_finished_header">&fxaccount_migration_finished_header;</string>
|
||||
<string name="fxaccount_migration_finished_description">&fxaccount_account_verified_description2;</string>
|
||||
|
||||
<string name="fxaccount_update_credentials_header">&fxaccount_update_credentials_header;</string>
|
||||
<string name="fxaccount_update_credentials_button_label">&fxaccount_update_credentials_button_label;</string>
|
||||
<string name="fxaccount_update_credentials_unknown_error">&fxaccount_update_credentials_unknown_error;</string>
|
||||
|
||||
<string name="fxaccount_finish_migrating_header">&fxaccount_finish_migrating_header;</string>
|
||||
<string name="fxaccount_finish_migrating_button_label">&fxaccount_finish_migrating_button_label;</string>
|
||||
<string name="fxaccount_finish_migrating_description">&fxaccount_finish_migrating_description;</string>
|
||||
|
||||
<string name="fxaccount_status_activity_label">&syncBrand.shortName.label;</string>
|
||||
<string name="fxaccount_status_header">&fxaccount_status_header2;</string>
|
||||
<string name="fxaccount_status_signed_in_as">&fxaccount_status_signed_in_as;</string>
|
||||
@ -187,6 +194,7 @@
|
||||
<string name="fxaccount_status_needs_upgrade">&fxaccount_status_needs_upgrade;</string>
|
||||
<string name="fxaccount_status_needs_master_sync_automatically_enabled">&fxaccount_status_needs_master_sync_automatically_enabled;</string>
|
||||
<string name="fxaccount_status_needs_account_enabled">&fxaccount_status_needs_account_enabled;</string>
|
||||
<string name="fxaccount_status_needs_finish_migrating">&fxaccount_status_needs_finish_migrating;</string>
|
||||
<string name="fxaccount_status_bookmarks">&fxaccount_status_bookmarks;</string>
|
||||
<string name="fxaccount_status_history">&fxaccount_status_history;</string>
|
||||
<string name="fxaccount_status_passwords">&fxaccount_status_passwords;</string>
|
||||
@ -219,3 +227,6 @@
|
||||
<string name="fxaccount_remove_account_dialog_message">&fxaccount_remove_account_dialog_message;</string>
|
||||
<string name="fxaccount_remove_account_toast">&fxaccount_remove_account_toast;</string>
|
||||
<string name="fxaccount_remove_account_menu_item">&fxaccount_remove_account_menu_item;</string>
|
||||
|
||||
<string name="fxaccount_sync_finish_migrating_notification_title">&fxaccount_sync_finish_migrating_notification_title;</string>
|
||||
<string name="fxaccount_sync_finish_migrating_notification_text">&fxaccount_sync_finish_migrating_notification_text;</string>
|
||||
|
Loading…
Reference in New Issue
Block a user