michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: package org.mozilla.gecko.fxa.activities; michael@0: michael@0: import java.util.concurrent.Executor; michael@0: import java.util.concurrent.Executors; michael@0: michael@0: import org.mozilla.gecko.R; michael@0: import org.mozilla.gecko.background.common.log.Logger; michael@0: import org.mozilla.gecko.background.fxa.FxAccountClient; michael@0: import org.mozilla.gecko.background.fxa.FxAccountClient10.RequestDelegate; michael@0: import org.mozilla.gecko.background.fxa.FxAccountClient20; michael@0: import org.mozilla.gecko.background.fxa.FxAccountClientException.FxAccountClientRemoteException; michael@0: import org.mozilla.gecko.fxa.FirefoxAccounts; michael@0: import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount; michael@0: import org.mozilla.gecko.fxa.login.Engaged; michael@0: import org.mozilla.gecko.fxa.login.State; michael@0: import org.mozilla.gecko.fxa.login.State.Action; michael@0: import org.mozilla.gecko.fxa.sync.FxAccountSyncStatusHelper; michael@0: import org.mozilla.gecko.sync.setup.activities.ActivityUtils; michael@0: michael@0: import android.accounts.Account; michael@0: import android.app.Activity; michael@0: import android.content.Context; michael@0: import android.os.Bundle; michael@0: import android.view.View; michael@0: import android.view.View.OnClickListener; michael@0: import android.widget.TextView; michael@0: import android.widget.Toast; michael@0: michael@0: /** michael@0: * Activity which displays account created successfully screen to the user, and michael@0: * starts them on the email verification path. michael@0: */ michael@0: public class FxAccountConfirmAccountActivity extends FxAccountAbstractActivity implements OnClickListener { michael@0: private static final String LOG_TAG = FxAccountConfirmAccountActivity.class.getSimpleName(); michael@0: michael@0: // Set in onCreate. michael@0: protected TextView verificationLinkTextView; michael@0: protected View resendLink; michael@0: michael@0: // Set in onResume. michael@0: protected AndroidFxAccount fxAccount; michael@0: michael@0: protected final InnerSyncStatusDelegate syncStatusDelegate = new InnerSyncStatusDelegate(); michael@0: michael@0: public FxAccountConfirmAccountActivity() { michael@0: super(CANNOT_RESUME_WHEN_NO_ACCOUNTS_EXIST); michael@0: } michael@0: michael@0: /** michael@0: * {@inheritDoc} michael@0: */ michael@0: @Override michael@0: public void onCreate(Bundle icicle) { michael@0: Logger.debug(LOG_TAG, "onCreate(" + icicle + ")"); michael@0: michael@0: super.onCreate(icicle); michael@0: setContentView(R.layout.fxaccount_confirm_account); michael@0: michael@0: verificationLinkTextView = (TextView) ensureFindViewById(null, R.id.verification_link_text, "verification link text"); michael@0: resendLink = ensureFindViewById(null, R.id.resend_confirmation_email_link, "resend confirmation email link"); michael@0: resendLink.setOnClickListener(this); michael@0: michael@0: View backToBrowsingButton = ensureFindViewById(null, R.id.button, "back to browsing button"); michael@0: backToBrowsingButton.setOnClickListener(new OnClickListener() { michael@0: @Override michael@0: public void onClick(View v) { michael@0: ActivityUtils.openURLInFennec(v.getContext(), null); michael@0: setResult(Activity.RESULT_OK); michael@0: finish(); michael@0: } michael@0: }); michael@0: } michael@0: michael@0: @Override michael@0: public void onResume() { michael@0: super.onResume(); michael@0: this.fxAccount = getAndroidFxAccount(); michael@0: if (fxAccount == null) { michael@0: Logger.warn(LOG_TAG, "Could not get Firefox Account."); michael@0: setResult(RESULT_CANCELED); michael@0: finish(); michael@0: return; michael@0: } michael@0: michael@0: FxAccountSyncStatusHelper.getInstance().startObserving(syncStatusDelegate); michael@0: michael@0: refresh(); michael@0: michael@0: fxAccount.requestSync(FirefoxAccounts.NOW); michael@0: } michael@0: michael@0: @Override michael@0: public void onPause() { michael@0: super.onPause(); michael@0: FxAccountSyncStatusHelper.getInstance().stopObserving(syncStatusDelegate); michael@0: michael@0: if (fxAccount != null) { michael@0: fxAccount.requestSync(FirefoxAccounts.SOON); michael@0: } michael@0: } michael@0: michael@0: protected class InnerSyncStatusDelegate implements FirefoxAccounts.SyncStatusListener { michael@0: protected final Runnable refreshRunnable = new Runnable() { michael@0: @Override michael@0: public void run() { michael@0: refresh(); michael@0: } michael@0: }; michael@0: michael@0: @Override michael@0: public Context getContext() { michael@0: return FxAccountConfirmAccountActivity.this; michael@0: } michael@0: michael@0: @Override michael@0: public Account getAccount() { michael@0: return fxAccount.getAndroidAccount(); michael@0: } michael@0: michael@0: @Override michael@0: public void onSyncStarted() { michael@0: Logger.info(LOG_TAG, "Got sync started message; ignoring."); michael@0: } michael@0: michael@0: @Override michael@0: public void onSyncFinished() { michael@0: if (fxAccount == null) { michael@0: return; michael@0: } michael@0: Logger.info(LOG_TAG, "Got sync finished message; refreshing."); michael@0: runOnUiThread(refreshRunnable); michael@0: } michael@0: } michael@0: michael@0: protected void refresh() { michael@0: final State state = fxAccount.getState(); michael@0: final Action neededAction = state.getNeededAction(); michael@0: switch (neededAction) { michael@0: case NeedsVerification: michael@0: // This is what we're here to handle. michael@0: break; michael@0: case NeedsPassword: michael@0: case NeedsUpgrade: michael@0: case None: michael@0: default: michael@0: // We're not in the right place! Redirect to status. michael@0: Logger.warn(LOG_TAG, "No need to verifiy Firefox Account that needs action " + neededAction.toString() + michael@0: " (in state " + state.getStateLabel() + ")."); michael@0: setResult(RESULT_CANCELED); michael@0: this.redirectToActivity(FxAccountStatusActivity.class); michael@0: return; michael@0: } michael@0: michael@0: final String email = fxAccount.getEmail(); michael@0: final String text = getResources().getString(R.string.fxaccount_confirm_account_verification_link, email); michael@0: verificationLinkTextView.setText(text); michael@0: michael@0: boolean resendLinkShouldBeEnabled = ((Engaged) state).getSessionToken() != null; michael@0: resendLink.setEnabled(resendLinkShouldBeEnabled); michael@0: resendLink.setClickable(resendLinkShouldBeEnabled); michael@0: } michael@0: michael@0: public static class FxAccountResendCodeTask extends FxAccountSetupTask { michael@0: protected static final String LOG_TAG = FxAccountResendCodeTask.class.getSimpleName(); michael@0: michael@0: protected final byte[] sessionToken; michael@0: michael@0: public FxAccountResendCodeTask(Context context, byte[] sessionToken, FxAccountClient client, RequestDelegate delegate) { michael@0: super(context, null, client, delegate); michael@0: this.sessionToken = sessionToken; michael@0: } michael@0: michael@0: @Override michael@0: protected InnerRequestDelegate doInBackground(Void... arg0) { michael@0: try { michael@0: client.resendCode(sessionToken, innerDelegate); michael@0: latch.await(); michael@0: return innerDelegate; michael@0: } catch (Exception e) { michael@0: Logger.error(LOG_TAG, "Got exception signing in.", e); michael@0: delegate.handleError(e); michael@0: } michael@0: return null; michael@0: } michael@0: } michael@0: michael@0: protected static class ResendCodeDelegate implements RequestDelegate { michael@0: public final Context context; michael@0: michael@0: public ResendCodeDelegate(Context context) { michael@0: this.context = context; michael@0: } michael@0: michael@0: @Override michael@0: public void handleError(Exception e) { michael@0: Logger.warn(LOG_TAG, "Got exception requesting fresh confirmation link; ignoring.", e); michael@0: Toast.makeText(context, R.string.fxaccount_confirm_account_verification_link_not_sent, Toast.LENGTH_LONG).show(); michael@0: } michael@0: michael@0: @Override michael@0: public void handleFailure(FxAccountClientRemoteException e) { michael@0: handleError(e); michael@0: } michael@0: michael@0: @Override michael@0: public void handleSuccess(Void result) { michael@0: Toast.makeText(context, R.string.fxaccount_confirm_account_verification_link_sent, Toast.LENGTH_SHORT).show(); michael@0: } michael@0: } michael@0: michael@0: public static void resendCode(Context context, AndroidFxAccount fxAccount) { michael@0: RequestDelegate delegate = new ResendCodeDelegate(context); michael@0: michael@0: byte[] sessionToken; michael@0: try { michael@0: sessionToken = ((Engaged) fxAccount.getState()).getSessionToken(); michael@0: } catch (Exception e) { michael@0: delegate.handleError(e); michael@0: return; michael@0: } michael@0: if (sessionToken == null) { michael@0: delegate.handleError(new IllegalStateException("sessionToken should not be null")); michael@0: return; michael@0: } michael@0: michael@0: Executor executor = Executors.newSingleThreadExecutor(); michael@0: FxAccountClient client = new FxAccountClient20(fxAccount.getAccountServerURI(), executor); michael@0: new FxAccountResendCodeTask(context, sessionToken, client, delegate).execute(); michael@0: } michael@0: michael@0: @Override michael@0: public void onClick(View v) { michael@0: resendCode(this, fxAccount); michael@0: } michael@0: }