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.login;
7 import java.security.NoSuchAlgorithmException;
8 import java.util.HashSet;
9 import java.util.Set;
11 import org.mozilla.gecko.background.fxa.FxAccountClient;
12 import org.mozilla.gecko.browserid.BrowserIDKeyPair;
13 import org.mozilla.gecko.fxa.login.FxAccountLoginTransition.Transition;
14 import org.mozilla.gecko.fxa.login.State.StateLabel;
16 public class FxAccountLoginStateMachine {
17 public static final String LOG_TAG = FxAccountLoginStateMachine.class.getSimpleName();
19 public interface LoginStateMachineDelegate {
20 public FxAccountClient getClient();
21 public long getCertificateDurationInMilliseconds();
22 public long getAssertionDurationInMilliseconds();
23 public void handleTransition(Transition transition, State state);
24 public void handleFinal(State state);
25 public BrowserIDKeyPair generateKeyPair() throws NoSuchAlgorithmException;
26 }
28 public static class ExecuteDelegate {
29 protected final LoginStateMachineDelegate delegate;
30 protected final StateLabel desiredStateLabel;
31 // It's as difficult to detect arbitrary cycles as repeated states.
32 protected final Set<StateLabel> stateLabelsSeen = new HashSet<StateLabel>();
34 protected ExecuteDelegate(StateLabel initialStateLabel, StateLabel desiredStateLabel, LoginStateMachineDelegate delegate) {
35 this.delegate = delegate;
36 this.desiredStateLabel = desiredStateLabel;
37 this.stateLabelsSeen.add(initialStateLabel);
38 }
40 public FxAccountClient getClient() {
41 return delegate.getClient();
42 }
44 public long getCertificateDurationInMilliseconds() {
45 return delegate.getCertificateDurationInMilliseconds();
46 }
48 public long getAssertionDurationInMilliseconds() {
49 return delegate.getAssertionDurationInMilliseconds();
50 }
52 public BrowserIDKeyPair generateKeyPair() throws NoSuchAlgorithmException {
53 return delegate.generateKeyPair();
54 }
56 public void handleTransition(Transition transition, State state) {
57 // Always trigger the transition callback.
58 delegate.handleTransition(transition, state);
60 // Possibly trigger the final callback. We trigger if we're at our desired
61 // state, or if we've seen this state before.
62 StateLabel stateLabel = state.getStateLabel();
63 if (stateLabel == desiredStateLabel || stateLabelsSeen.contains(stateLabel)) {
64 delegate.handleFinal(state);
65 return;
66 }
68 // If this wasn't the last state, leave a bread crumb and move on to the
69 // next state.
70 stateLabelsSeen.add(stateLabel);
71 state.execute(this);
72 }
73 }
75 public void advance(State initialState, final StateLabel desiredStateLabel, final LoginStateMachineDelegate delegate) {
76 if (initialState.getStateLabel() == desiredStateLabel) {
77 // We're already where we want to be!
78 delegate.handleFinal(initialState);
79 return;
80 }
81 ExecuteDelegate executeDelegate = new ExecuteDelegate(initialState.getStateLabel(), desiredStateLabel, delegate);
82 initialState.execute(executeDelegate);
83 }
84 }