Wed, 31 Dec 2014 07:22:50 +0100
Correct previous dual key logic pending first delivery installment.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 package org.mozilla.gecko.fxa.activities;
7 import java.util.concurrent.Executor;
8 import java.util.concurrent.Executors;
10 import org.mozilla.gecko.R;
11 import org.mozilla.gecko.background.common.log.Logger;
12 import org.mozilla.gecko.background.fxa.FxAccountClient;
13 import org.mozilla.gecko.background.fxa.FxAccountClient10.RequestDelegate;
14 import org.mozilla.gecko.background.fxa.FxAccountClient20;
15 import org.mozilla.gecko.background.fxa.FxAccountClientException.FxAccountClientRemoteException;
16 import org.mozilla.gecko.fxa.FirefoxAccounts;
17 import org.mozilla.gecko.fxa.authenticator.AndroidFxAccount;
18 import org.mozilla.gecko.fxa.login.Engaged;
19 import org.mozilla.gecko.fxa.login.State;
20 import org.mozilla.gecko.fxa.login.State.Action;
21 import org.mozilla.gecko.fxa.sync.FxAccountSyncStatusHelper;
22 import org.mozilla.gecko.sync.setup.activities.ActivityUtils;
24 import android.accounts.Account;
25 import android.app.Activity;
26 import android.content.Context;
27 import android.os.Bundle;
28 import android.view.View;
29 import android.view.View.OnClickListener;
30 import android.widget.TextView;
31 import android.widget.Toast;
33 /**
34 * Activity which displays account created successfully screen to the user, and
35 * starts them on the email verification path.
36 */
37 public class FxAccountConfirmAccountActivity extends FxAccountAbstractActivity implements OnClickListener {
38 private static final String LOG_TAG = FxAccountConfirmAccountActivity.class.getSimpleName();
40 // Set in onCreate.
41 protected TextView verificationLinkTextView;
42 protected View resendLink;
44 // Set in onResume.
45 protected AndroidFxAccount fxAccount;
47 protected final InnerSyncStatusDelegate syncStatusDelegate = new InnerSyncStatusDelegate();
49 public FxAccountConfirmAccountActivity() {
50 super(CANNOT_RESUME_WHEN_NO_ACCOUNTS_EXIST);
51 }
53 /**
54 * {@inheritDoc}
55 */
56 @Override
57 public void onCreate(Bundle icicle) {
58 Logger.debug(LOG_TAG, "onCreate(" + icicle + ")");
60 super.onCreate(icicle);
61 setContentView(R.layout.fxaccount_confirm_account);
63 verificationLinkTextView = (TextView) ensureFindViewById(null, R.id.verification_link_text, "verification link text");
64 resendLink = ensureFindViewById(null, R.id.resend_confirmation_email_link, "resend confirmation email link");
65 resendLink.setOnClickListener(this);
67 View backToBrowsingButton = ensureFindViewById(null, R.id.button, "back to browsing button");
68 backToBrowsingButton.setOnClickListener(new OnClickListener() {
69 @Override
70 public void onClick(View v) {
71 ActivityUtils.openURLInFennec(v.getContext(), null);
72 setResult(Activity.RESULT_OK);
73 finish();
74 }
75 });
76 }
78 @Override
79 public void onResume() {
80 super.onResume();
81 this.fxAccount = getAndroidFxAccount();
82 if (fxAccount == null) {
83 Logger.warn(LOG_TAG, "Could not get Firefox Account.");
84 setResult(RESULT_CANCELED);
85 finish();
86 return;
87 }
89 FxAccountSyncStatusHelper.getInstance().startObserving(syncStatusDelegate);
91 refresh();
93 fxAccount.requestSync(FirefoxAccounts.NOW);
94 }
96 @Override
97 public void onPause() {
98 super.onPause();
99 FxAccountSyncStatusHelper.getInstance().stopObserving(syncStatusDelegate);
101 if (fxAccount != null) {
102 fxAccount.requestSync(FirefoxAccounts.SOON);
103 }
104 }
106 protected class InnerSyncStatusDelegate implements FirefoxAccounts.SyncStatusListener {
107 protected final Runnable refreshRunnable = new Runnable() {
108 @Override
109 public void run() {
110 refresh();
111 }
112 };
114 @Override
115 public Context getContext() {
116 return FxAccountConfirmAccountActivity.this;
117 }
119 @Override
120 public Account getAccount() {
121 return fxAccount.getAndroidAccount();
122 }
124 @Override
125 public void onSyncStarted() {
126 Logger.info(LOG_TAG, "Got sync started message; ignoring.");
127 }
129 @Override
130 public void onSyncFinished() {
131 if (fxAccount == null) {
132 return;
133 }
134 Logger.info(LOG_TAG, "Got sync finished message; refreshing.");
135 runOnUiThread(refreshRunnable);
136 }
137 }
139 protected void refresh() {
140 final State state = fxAccount.getState();
141 final Action neededAction = state.getNeededAction();
142 switch (neededAction) {
143 case NeedsVerification:
144 // This is what we're here to handle.
145 break;
146 case NeedsPassword:
147 case NeedsUpgrade:
148 case None:
149 default:
150 // We're not in the right place! Redirect to status.
151 Logger.warn(LOG_TAG, "No need to verifiy Firefox Account that needs action " + neededAction.toString() +
152 " (in state " + state.getStateLabel() + ").");
153 setResult(RESULT_CANCELED);
154 this.redirectToActivity(FxAccountStatusActivity.class);
155 return;
156 }
158 final String email = fxAccount.getEmail();
159 final String text = getResources().getString(R.string.fxaccount_confirm_account_verification_link, email);
160 verificationLinkTextView.setText(text);
162 boolean resendLinkShouldBeEnabled = ((Engaged) state).getSessionToken() != null;
163 resendLink.setEnabled(resendLinkShouldBeEnabled);
164 resendLink.setClickable(resendLinkShouldBeEnabled);
165 }
167 public static class FxAccountResendCodeTask extends FxAccountSetupTask<Void> {
168 protected static final String LOG_TAG = FxAccountResendCodeTask.class.getSimpleName();
170 protected final byte[] sessionToken;
172 public FxAccountResendCodeTask(Context context, byte[] sessionToken, FxAccountClient client, RequestDelegate<Void> delegate) {
173 super(context, null, client, delegate);
174 this.sessionToken = sessionToken;
175 }
177 @Override
178 protected InnerRequestDelegate<Void> doInBackground(Void... arg0) {
179 try {
180 client.resendCode(sessionToken, innerDelegate);
181 latch.await();
182 return innerDelegate;
183 } catch (Exception e) {
184 Logger.error(LOG_TAG, "Got exception signing in.", e);
185 delegate.handleError(e);
186 }
187 return null;
188 }
189 }
191 protected static class ResendCodeDelegate implements RequestDelegate<Void> {
192 public final Context context;
194 public ResendCodeDelegate(Context context) {
195 this.context = context;
196 }
198 @Override
199 public void handleError(Exception e) {
200 Logger.warn(LOG_TAG, "Got exception requesting fresh confirmation link; ignoring.", e);
201 Toast.makeText(context, R.string.fxaccount_confirm_account_verification_link_not_sent, Toast.LENGTH_LONG).show();
202 }
204 @Override
205 public void handleFailure(FxAccountClientRemoteException e) {
206 handleError(e);
207 }
209 @Override
210 public void handleSuccess(Void result) {
211 Toast.makeText(context, R.string.fxaccount_confirm_account_verification_link_sent, Toast.LENGTH_SHORT).show();
212 }
213 }
215 public static void resendCode(Context context, AndroidFxAccount fxAccount) {
216 RequestDelegate<Void> delegate = new ResendCodeDelegate(context);
218 byte[] sessionToken;
219 try {
220 sessionToken = ((Engaged) fxAccount.getState()).getSessionToken();
221 } catch (Exception e) {
222 delegate.handleError(e);
223 return;
224 }
225 if (sessionToken == null) {
226 delegate.handleError(new IllegalStateException("sessionToken should not be null"));
227 return;
228 }
230 Executor executor = Executors.newSingleThreadExecutor();
231 FxAccountClient client = new FxAccountClient20(fxAccount.getAccountServerURI(), executor);
232 new FxAccountResendCodeTask(context, sessionToken, client, delegate).execute();
233 }
235 @Override
236 public void onClick(View v) {
237 resendCode(this, fxAccount);
238 }
239 }