From a1c7ddad2ddee18fd76388413e212efe7ea2418e Mon Sep 17 00:00:00 2001 From: Alex Saveau Date: Thu, 15 Mar 2018 16:38:38 -0700 Subject: [PATCH 1/8] Prep for final refactors Signed-off-by: Alex Saveau --- .../data/model/IntentRequiredException.java | 29 +++++++++ .../model/PendingIntentRequiredException.java | 29 +++++++++ .../ui/auth/data/remote/ProfileMerger.java | 2 +- .../ui/auth/ui/TaskFailureLogger.java | 35 ----------- .../credentials/CredentialSaveActivity.java | 48 +++------------ .../ui/email/RecoverPasswordActivity.java | 2 +- .../auth/ui/email/RegisterEmailFragment.java | 2 +- .../ui/email/WelcomeBackPasswordPrompt.java | 2 +- .../auth/ui/idp/AuthMethodPickerActivity.java | 2 +- .../ui/auth/ui/idp/WelcomeBackIdpPrompt.java | 2 +- .../ui/auth/util/FirebaseAuthError.java | 2 +- .../ui/auth/util/data/TaskFailureLogger.java | 30 +++++++++ .../signincontainer/IdpSignInContainer.java | 2 +- .../util/signincontainer/SignInDelegate.java | 2 +- .../util/ui/BucketedTextChangeListener.java | 4 +- .../firebase/ui/auth/util/ui/FlowUtils.java | 42 +++++++++++++ .../ui/auth/viewmodel/AuthViewModelBase.java | 30 +++------ .../ui/auth/viewmodel/PendingResolution.java | 30 --------- .../ui/auth/viewmodel/SingleLiveEvent.java | 34 ++++------- .../ui/auth/viewmodel/ViewModelBase.java | 2 + .../email/RecoverPasswordHandler.java | 17 ++---- .../email/WelcomeBackPasswordHandler.java | 31 +++------- .../viewmodel/smartlock/SmartLockHandler.java | 61 ++++++------------- .../viewmodel/RecoverPasswordHandlerTest.java | 4 +- .../auth/viewmodel/SmartLockHandlerTest.java | 18 +++--- .../WelcomeBackPasswordHandlerTest.java | 4 +- 26 files changed, 216 insertions(+), 250 deletions(-) create mode 100644 auth/src/main/java/com/firebase/ui/auth/data/model/IntentRequiredException.java create mode 100644 auth/src/main/java/com/firebase/ui/auth/data/model/PendingIntentRequiredException.java delete mode 100644 auth/src/main/java/com/firebase/ui/auth/ui/TaskFailureLogger.java create mode 100644 auth/src/main/java/com/firebase/ui/auth/util/data/TaskFailureLogger.java create mode 100644 auth/src/main/java/com/firebase/ui/auth/util/ui/FlowUtils.java delete mode 100644 auth/src/main/java/com/firebase/ui/auth/viewmodel/PendingResolution.java diff --git a/auth/src/main/java/com/firebase/ui/auth/data/model/IntentRequiredException.java b/auth/src/main/java/com/firebase/ui/auth/data/model/IntentRequiredException.java new file mode 100644 index 000000000..191ab022f --- /dev/null +++ b/auth/src/main/java/com/firebase/ui/auth/data/model/IntentRequiredException.java @@ -0,0 +1,29 @@ +package com.firebase.ui.auth.data.model; + +import android.content.Intent; +import android.support.annotation.NonNull; +import android.support.annotation.RestrictTo; + +import com.firebase.ui.auth.ErrorCodes; +import com.firebase.ui.auth.FirebaseUiException; + +@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) +public class IntentRequiredException extends FirebaseUiException { + private final Intent mIntent; + private final int mRequestCode; + + public IntentRequiredException(@NonNull Intent intent, int requestCode) { + super(ErrorCodes.UNKNOWN_ERROR); + mIntent = intent; + mRequestCode = requestCode; + } + + @NonNull + public Intent getIntent() { + return mIntent; + } + + public int getRequestCode() { + return mRequestCode; + } +} diff --git a/auth/src/main/java/com/firebase/ui/auth/data/model/PendingIntentRequiredException.java b/auth/src/main/java/com/firebase/ui/auth/data/model/PendingIntentRequiredException.java new file mode 100644 index 000000000..0c6f17df2 --- /dev/null +++ b/auth/src/main/java/com/firebase/ui/auth/data/model/PendingIntentRequiredException.java @@ -0,0 +1,29 @@ +package com.firebase.ui.auth.data.model; + +import android.app.PendingIntent; +import android.support.annotation.NonNull; +import android.support.annotation.RestrictTo; + +import com.firebase.ui.auth.ErrorCodes; +import com.firebase.ui.auth.FirebaseUiException; + +@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) +public class PendingIntentRequiredException extends FirebaseUiException { + private final PendingIntent mPendingIntent; + private final int mRequestCode; + + public PendingIntentRequiredException(@NonNull PendingIntent pendingIntent, int requestCode) { + super(ErrorCodes.UNKNOWN_ERROR); + mPendingIntent = pendingIntent; + mRequestCode = requestCode; + } + + @NonNull + public PendingIntent getPendingIntent() { + return mPendingIntent; + } + + public int getRequestCode() { + return mRequestCode; + } +} diff --git a/auth/src/main/java/com/firebase/ui/auth/data/remote/ProfileMerger.java b/auth/src/main/java/com/firebase/ui/auth/data/remote/ProfileMerger.java index 6d4819450..ce83c9519 100644 --- a/auth/src/main/java/com/firebase/ui/auth/data/remote/ProfileMerger.java +++ b/auth/src/main/java/com/firebase/ui/auth/data/remote/ProfileMerger.java @@ -7,7 +7,7 @@ import com.firebase.ui.auth.IdpResponse; import com.firebase.ui.auth.data.model.User; -import com.firebase.ui.auth.ui.TaskFailureLogger; +import com.firebase.ui.auth.util.data.TaskFailureLogger; import com.google.android.gms.tasks.Continuation; import com.google.android.gms.tasks.Task; import com.google.android.gms.tasks.Tasks; diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/TaskFailureLogger.java b/auth/src/main/java/com/firebase/ui/auth/ui/TaskFailureLogger.java deleted file mode 100644 index 986f35d2d..000000000 --- a/auth/src/main/java/com/firebase/ui/auth/ui/TaskFailureLogger.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2016 Google Inc. All Rights Reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the - * License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either - * express or implied. See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.firebase.ui.auth.ui; - -import android.support.annotation.NonNull; -import android.util.Log; - -import com.google.android.gms.tasks.OnFailureListener; - -public class TaskFailureLogger implements OnFailureListener { - private String mTag; - private String mMessage; - - public TaskFailureLogger(@NonNull String tag, @NonNull String message) { - mTag = tag; - mMessage = message; - } - - @Override - public void onFailure(@NonNull Exception e) { - Log.w(mTag, mMessage, e); - } -} diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/credentials/CredentialSaveActivity.java b/auth/src/main/java/com/firebase/ui/auth/ui/credentials/CredentialSaveActivity.java index 215f83068..99152c68a 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/credentials/CredentialSaveActivity.java +++ b/auth/src/main/java/com/firebase/ui/auth/ui/credentials/CredentialSaveActivity.java @@ -4,7 +4,6 @@ import android.arch.lifecycle.ViewModelProviders; import android.content.Context; import android.content.Intent; -import android.content.IntentSender; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -15,8 +14,7 @@ import com.firebase.ui.auth.data.model.Resource; import com.firebase.ui.auth.ui.HelperActivityBase; import com.firebase.ui.auth.util.ExtraConstants; -import com.firebase.ui.auth.viewmodel.PendingResolution; -import com.firebase.ui.auth.viewmodel.ResolutionCodes; +import com.firebase.ui.auth.util.ui.FlowUtils; import com.firebase.ui.auth.viewmodel.smartlock.SmartLockHandler; import com.google.android.gms.auth.api.credentials.Credential; @@ -24,8 +22,7 @@ * Invisible Activity used for saving credentials to SmartLock. */ public class CredentialSaveActivity extends HelperActivityBase { - - private static final String TAG = "SmartlockSave"; + private static final String TAG = "CredentialSaveActivity"; private SmartLockHandler mHandler; private IdpResponse mIdpResponse; @@ -50,7 +47,7 @@ protected void onCreate(Bundle savedInstanceState) { Credential credential = getIntent().getParcelableExtra(ExtraConstants.EXTRA_CREDENTIAL); mIdpResponse = getIntent().getParcelableExtra(ExtraConstants.EXTRA_IDP_RESPONSE); - mHandler.getSaveOperation().observe(this, new Observer>() { + mHandler.getOperation().observe(this, new Observer>() { @Override public void onChanged(@Nullable Resource resource) { if (resource == null) { @@ -62,20 +59,8 @@ public void onChanged(@Nullable Resource resource) { } }); - mHandler.getPendingResolution().observe(this, new Observer() { - @Override - public void onChanged(@Nullable PendingResolution resolution) { - if (resolution == null) { - Log.w(TAG, "getPendingResolution:onChanged: null"); - return; - } - - onPendingResolution(resolution); - } - }); - // Avoid double-saving - Resource currentOp = mHandler.getSaveOperation().getValue(); + Resource currentOp = mHandler.getOperation().getValue(); if (currentOp == null) { Log.d(TAG, "Launching save operation."); mHandler.saveCredentials(credential); @@ -86,10 +71,8 @@ public void onChanged(@Nullable PendingResolution resolution) { @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { - // Forward activity results to the ViewModel - if (!mHandler.onActivityResult(requestCode, resultCode, data)) { - super.onActivityResult(requestCode, resultCode, data); - } + super.onActivityResult(requestCode, resultCode, data); + mHandler.onActivityResult(requestCode, resultCode); } private void onSaveOperation(@NonNull Resource resource) { @@ -99,23 +82,10 @@ private void onSaveOperation(@NonNull Resource resource) { break; case SUCCESS: case FAILURE: - finish(RESULT_OK, mIdpResponse.toIntent()); + if (!FlowUtils.handleError(this, resource.getException())) { + finish(RESULT_OK, mIdpResponse.toIntent()); + } break; } } - - private void onPendingResolution(@NonNull PendingResolution resolution) { - if (resolution.getRequestCode() == ResolutionCodes.RC_CRED_SAVE) { - try { - startIntentSenderForResult( - resolution.getPendingIntent().getIntentSender(), - resolution.getRequestCode(), - null, 0, 0, 0); - } catch (IntentSender.SendIntentException e) { - Log.e(TAG, "Failed to send resolution.", e); - finish(RESULT_OK, mIdpResponse.toIntent()); - }; - } - } - } diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/email/RecoverPasswordActivity.java b/auth/src/main/java/com/firebase/ui/auth/ui/email/RecoverPasswordActivity.java index 2fad5d490..febce9a50 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/email/RecoverPasswordActivity.java +++ b/auth/src/main/java/com/firebase/ui/auth/ui/email/RecoverPasswordActivity.java @@ -64,7 +64,7 @@ protected void onCreate(Bundle savedInstanceState) { mHandler = ViewModelProviders.of(this).get(RecoverPasswordHandler.class); mHandler.init(getFlowHolder().getArguments()); - mHandler.getProgressLiveData().observe(this, new Observer>() { + mHandler.getOperation().observe(this, new Observer>() { @Override public void onChanged(Resource resource) { if (resource.getState() == State.LOADING) { diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/email/RegisterEmailFragment.java b/auth/src/main/java/com/firebase/ui/auth/ui/email/RegisterEmailFragment.java index c5b8d9835..a2c6af730 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/email/RegisterEmailFragment.java +++ b/auth/src/main/java/com/firebase/ui/auth/ui/email/RegisterEmailFragment.java @@ -21,10 +21,10 @@ import com.firebase.ui.auth.data.model.User; import com.firebase.ui.auth.data.remote.ProfileMerger; import com.firebase.ui.auth.ui.FragmentBase; -import com.firebase.ui.auth.ui.TaskFailureLogger; import com.firebase.ui.auth.ui.idp.WelcomeBackIdpPrompt; import com.firebase.ui.auth.util.ExtraConstants; import com.firebase.ui.auth.util.data.ProviderUtils; +import com.firebase.ui.auth.util.data.TaskFailureLogger; import com.firebase.ui.auth.util.ui.ImeHelper; import com.firebase.ui.auth.util.ui.PreambleHandler; import com.firebase.ui.auth.util.ui.fieldvalidators.BaseValidator; diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/email/WelcomeBackPasswordPrompt.java b/auth/src/main/java/com/firebase/ui/auth/ui/email/WelcomeBackPasswordPrompt.java index dd0f5f787..e1004fb19 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/email/WelcomeBackPasswordPrompt.java +++ b/auth/src/main/java/com/firebase/ui/auth/ui/email/WelcomeBackPasswordPrompt.java @@ -110,7 +110,7 @@ protected void onCreate(Bundle savedInstanceState) { mHandler.init(getFlowHolder().getArguments()); // Observe the state of the main auth operation - mHandler.getSignInOperation().observe(this, new Observer>() { + mHandler.getOperation().observe(this, new Observer>() { @Override public void onChanged(@Nullable Resource resource) { onSignInOperation(resource); diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/idp/AuthMethodPickerActivity.java b/auth/src/main/java/com/firebase/ui/auth/ui/idp/AuthMethodPickerActivity.java index a4f9b52d9..33c07ac8f 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/idp/AuthMethodPickerActivity.java +++ b/auth/src/main/java/com/firebase/ui/auth/ui/idp/AuthMethodPickerActivity.java @@ -41,10 +41,10 @@ import com.firebase.ui.auth.provider.TwitterProvider; import com.firebase.ui.auth.ui.AppCompatBase; import com.firebase.ui.auth.ui.HelperActivityBase; -import com.firebase.ui.auth.ui.TaskFailureLogger; import com.firebase.ui.auth.ui.email.EmailActivity; import com.firebase.ui.auth.ui.phone.PhoneActivity; import com.firebase.ui.auth.util.data.ProviderUtils; +import com.firebase.ui.auth.util.data.TaskFailureLogger; import com.google.android.gms.tasks.OnSuccessListener; import com.google.firebase.auth.AuthCredential; import com.google.firebase.auth.AuthResult; diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/idp/WelcomeBackIdpPrompt.java b/auth/src/main/java/com/firebase/ui/auth/ui/idp/WelcomeBackIdpPrompt.java index 4c38144e7..f0888d11c 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/idp/WelcomeBackIdpPrompt.java +++ b/auth/src/main/java/com/firebase/ui/auth/ui/idp/WelcomeBackIdpPrompt.java @@ -39,9 +39,9 @@ import com.firebase.ui.auth.provider.TwitterProvider; import com.firebase.ui.auth.ui.AppCompatBase; import com.firebase.ui.auth.ui.HelperActivityBase; -import com.firebase.ui.auth.ui.TaskFailureLogger; import com.firebase.ui.auth.util.ExtraConstants; import com.firebase.ui.auth.util.data.ProviderUtils; +import com.firebase.ui.auth.util.data.TaskFailureLogger; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.OnFailureListener; import com.google.android.gms.tasks.OnSuccessListener; diff --git a/auth/src/main/java/com/firebase/ui/auth/util/FirebaseAuthError.java b/auth/src/main/java/com/firebase/ui/auth/util/FirebaseAuthError.java index 8d6e43100..14c1077b5 100644 --- a/auth/src/main/java/com/firebase/ui/auth/util/FirebaseAuthError.java +++ b/auth/src/main/java/com/firebase/ui/auth/util/FirebaseAuthError.java @@ -33,7 +33,7 @@ public enum FirebaseAuthError { ERROR_CREDENTIAL_ALREADY_IN_USE("This credential is already associated with a different user account."), - ERROR_USER_DISABLED( "The user account has been disabled by an administrator."), + ERROR_USER_DISABLED("The user account has been disabled by an administrator."), ERROR_USER_TOKEN_EXPIRED("The user's credential has expired. The user must sign in again."), diff --git a/auth/src/main/java/com/firebase/ui/auth/util/data/TaskFailureLogger.java b/auth/src/main/java/com/firebase/ui/auth/util/data/TaskFailureLogger.java new file mode 100644 index 000000000..8fb062d26 --- /dev/null +++ b/auth/src/main/java/com/firebase/ui/auth/util/data/TaskFailureLogger.java @@ -0,0 +1,30 @@ +package com.firebase.ui.auth.util.data; + +import android.support.annotation.NonNull; +import android.util.Log; + +import com.firebase.ui.auth.AuthUI; +import com.firebase.ui.auth.BuildConfig; +import com.google.android.gms.tasks.OnFailureListener; + +public class TaskFailureLogger implements OnFailureListener { + private String mTag; + private String mMessage; + + public TaskFailureLogger(@NonNull String tag, @NonNull String message) { + mTag = tag; + mMessage = message; + } + + @Override + public void onFailure(@NonNull Exception e) { + try { + Class buildConfigClass = Class.forName( + AuthUI.getApplicationContext().getPackageName() + "." + + BuildConfig.class.getSimpleName()); + if (buildConfigClass.getDeclaredField("DEBUG").getBoolean(null)) { + Log.w(mTag, mMessage, e); + } + } catch (Exception ignored) {} + } +} diff --git a/auth/src/main/java/com/firebase/ui/auth/util/signincontainer/IdpSignInContainer.java b/auth/src/main/java/com/firebase/ui/auth/util/signincontainer/IdpSignInContainer.java index 7497a70a5..9bfb0f183 100644 --- a/auth/src/main/java/com/firebase/ui/auth/util/signincontainer/IdpSignInContainer.java +++ b/auth/src/main/java/com/firebase/ui/auth/util/signincontainer/IdpSignInContainer.java @@ -37,10 +37,10 @@ import com.firebase.ui.auth.provider.TwitterProvider; import com.firebase.ui.auth.ui.FragmentBase; import com.firebase.ui.auth.ui.HelperActivityBase; -import com.firebase.ui.auth.ui.TaskFailureLogger; import com.firebase.ui.auth.ui.idp.CredentialSignInHandler; import com.firebase.ui.auth.util.ExtraConstants; import com.firebase.ui.auth.util.data.ProviderUtils; +import com.firebase.ui.auth.util.data.TaskFailureLogger; import com.google.android.gms.tasks.OnSuccessListener; import com.google.firebase.auth.AuthCredential; import com.google.firebase.auth.AuthResult; diff --git a/auth/src/main/java/com/firebase/ui/auth/util/signincontainer/SignInDelegate.java b/auth/src/main/java/com/firebase/ui/auth/util/signincontainer/SignInDelegate.java index afc9280fe..01a7bd977 100644 --- a/auth/src/main/java/com/firebase/ui/auth/util/signincontainer/SignInDelegate.java +++ b/auth/src/main/java/com/firebase/ui/auth/util/signincontainer/SignInDelegate.java @@ -19,13 +19,13 @@ import com.firebase.ui.auth.data.model.FlowParameters; import com.firebase.ui.auth.data.model.User; import com.firebase.ui.auth.ui.FragmentBase; -import com.firebase.ui.auth.ui.TaskFailureLogger; import com.firebase.ui.auth.ui.email.EmailActivity; import com.firebase.ui.auth.ui.idp.AuthMethodPickerActivity; import com.firebase.ui.auth.ui.phone.PhoneActivity; import com.firebase.ui.auth.util.ExtraConstants; import com.firebase.ui.auth.util.GoogleApiUtils; import com.firebase.ui.auth.util.data.ProviderUtils; +import com.firebase.ui.auth.util.data.TaskFailureLogger; import com.google.android.gms.auth.api.credentials.Credential; import com.google.android.gms.auth.api.credentials.CredentialRequest; import com.google.android.gms.auth.api.credentials.CredentialRequestResponse; diff --git a/auth/src/main/java/com/firebase/ui/auth/util/ui/BucketedTextChangeListener.java b/auth/src/main/java/com/firebase/ui/auth/util/ui/BucketedTextChangeListener.java index cd8af145d..9ff8e4067 100644 --- a/auth/src/main/java/com/firebase/ui/auth/util/ui/BucketedTextChangeListener.java +++ b/auth/src/main/java/com/firebase/ui/auth/util/ui/BucketedTextChangeListener.java @@ -71,8 +71,8 @@ public BucketedTextChangeListener(EditText editText, int expectedContentLength, } /** - * For example, passing in ("-", 6) would return the following result: {"", "-", "--", "---", - * "----", "-----", "------"} + * For example, passing in ("-", 6) would return the following result: + * {"", "-", "--", "---", "----", "-----", "------"} * * @param repeatableChar the char to repeat to the specified length * @param length the maximum length of repeated chars diff --git a/auth/src/main/java/com/firebase/ui/auth/util/ui/FlowUtils.java b/auth/src/main/java/com/firebase/ui/auth/util/ui/FlowUtils.java new file mode 100644 index 000000000..e22f0c809 --- /dev/null +++ b/auth/src/main/java/com/firebase/ui/auth/util/ui/FlowUtils.java @@ -0,0 +1,42 @@ +package com.firebase.ui.auth.util.ui; + +import android.app.Activity; +import android.app.PendingIntent; +import android.content.IntentSender; +import android.support.annotation.NonNull; + +import com.firebase.ui.auth.IdpResponse; +import com.firebase.ui.auth.data.model.IntentRequiredException; +import com.firebase.ui.auth.data.model.PendingIntentRequiredException; +import com.firebase.ui.auth.ui.HelperActivityBase; + +public final class FlowUtils { + private FlowUtils() { + throw new AssertionError("No instance for you!"); + } + + public static boolean handleError(@NonNull HelperActivityBase activity, @NonNull Exception e) { + if (e instanceof IntentRequiredException) { + IntentRequiredException typed = (IntentRequiredException) e; + activity.startActivityForResult(typed.getIntent(), typed.getRequestCode()); + return true; + } else if (e instanceof PendingIntentRequiredException) { + PendingIntentRequiredException typed = (PendingIntentRequiredException) e; + startIntentSenderForResult(activity, typed.getPendingIntent(), typed.getRequestCode()); + return true; + } else { + return false; + } + } + + private static void startIntentSenderForResult(HelperActivityBase activity, + PendingIntent intent, + int requestCode) { + try { + activity.startIntentSenderForResult( + intent.getIntentSender(), requestCode, null, 0, 0, 0); + } catch (IntentSender.SendIntentException e) { + activity.finish(Activity.RESULT_CANCELED, IdpResponse.getErrorIntent(e)); + } + } +} diff --git a/auth/src/main/java/com/firebase/ui/auth/viewmodel/AuthViewModelBase.java b/auth/src/main/java/com/firebase/ui/auth/viewmodel/AuthViewModelBase.java index 07d8598af..e38551547 100644 --- a/auth/src/main/java/com/firebase/ui/auth/viewmodel/AuthViewModelBase.java +++ b/auth/src/main/java/com/firebase/ui/auth/viewmodel/AuthViewModelBase.java @@ -1,13 +1,13 @@ package com.firebase.ui.auth.viewmodel; import android.app.Application; -import android.app.PendingIntent; import android.arch.lifecycle.LiveData; -import android.content.Intent; +import android.arch.lifecycle.MutableLiveData; import android.support.annotation.RestrictTo; import android.support.annotation.VisibleForTesting; import com.firebase.ui.auth.data.model.FlowParameters; +import com.firebase.ui.auth.data.model.Resource; import com.firebase.ui.auth.util.GoogleApiUtils; import com.google.android.gms.auth.api.credentials.CredentialsClient; import com.google.firebase.FirebaseApp; @@ -15,13 +15,12 @@ import com.google.firebase.auth.PhoneAuthProvider; @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) -public class AuthViewModelBase extends ViewModelBase { - +public abstract class AuthViewModelBase extends ViewModelBase { private CredentialsClient mCredentialsClient; private FirebaseAuth mAuth; private PhoneAuthProvider mPhoneAuth; - private SingleLiveEvent mPendingResolution = new SingleLiveEvent<>(); + private MutableLiveData> mOperation = new MutableLiveData<>(); protected AuthViewModelBase(Application application) { super(application); @@ -48,25 +47,14 @@ protected CredentialsClient getCredentialsClient() { } /** - * Get an observable stream of {@link PendingIntent} resolutions requested by the ViewModel. - * - * Make sure to call {@link #onActivityResult(int, int, Intent)} for all activity results - * after firing these pending intents. + * Get the observable state of the sign in operation. */ - public LiveData getPendingResolution() { - return mPendingResolution; - } - - protected void setPendingResolution(PendingResolution resolution) { - mPendingResolution.setValue(resolution); + public LiveData> getOperation() { + return mOperation; } - /** - * Delegate activity result handling to the ViewModel. Returns {@code true} if the result was - * handled. - */ - public boolean onActivityResult(int requestCode, int resultCode, Intent data) { - return false; + protected void setResult(Resource result) { + mOperation.setValue(result); } @VisibleForTesting diff --git a/auth/src/main/java/com/firebase/ui/auth/viewmodel/PendingResolution.java b/auth/src/main/java/com/firebase/ui/auth/viewmodel/PendingResolution.java deleted file mode 100644 index 5d34a4652..000000000 --- a/auth/src/main/java/com/firebase/ui/auth/viewmodel/PendingResolution.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.firebase.ui.auth.viewmodel; - -import android.app.PendingIntent; -import android.support.annotation.NonNull; -import android.support.annotation.RestrictTo; - -/** - * POJO holding the data for a resolution that some Activity needs to fire. - */ -@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) -public class PendingResolution { - - private PendingIntent mPendingIntent; - private int mRequestCode; - - public PendingResolution(@NonNull PendingIntent pendingIntent, int requestCode) { - this.mPendingIntent = pendingIntent; - this.mRequestCode = requestCode; - } - - @NonNull - public PendingIntent getPendingIntent() { - return mPendingIntent; - } - - public int getRequestCode() { - return mRequestCode; - } - -} diff --git a/auth/src/main/java/com/firebase/ui/auth/viewmodel/SingleLiveEvent.java b/auth/src/main/java/com/firebase/ui/auth/viewmodel/SingleLiveEvent.java index e1fb133ee..74c73a08d 100644 --- a/auth/src/main/java/com/firebase/ui/auth/viewmodel/SingleLiveEvent.java +++ b/auth/src/main/java/com/firebase/ui/auth/viewmodel/SingleLiveEvent.java @@ -12,7 +12,7 @@ /** * A lifecycle-aware observable that sends only new updates after subscription, used for events like - * navigation and Snackbar messages. + * navigation and SnackBar messages. *

* This avoids a common problem with events: on configuration change (like rotation) an update * can be emitted if the observer is active. This LiveData only calls the observable if there's an @@ -26,14 +26,12 @@ * googlesamples/android-architecture */ public class SingleLiveEvent extends MutableLiveData { - private static final String TAG = "SingleLiveEvent"; private final AtomicBoolean mPending = new AtomicBoolean(false); @MainThread - public void observe(LifecycleOwner owner, final Observer observer) { - + public void observe(@NonNull LifecycleOwner owner, @NonNull final Observer observer) { if (hasActiveObservers()) { Log.w(TAG, "Multiple observers registered but only one will be notified of changes."); } @@ -49,10 +47,10 @@ public void onChanged(@Nullable T t) { }); } - @Deprecated - @Override - public void removeObserver(@NonNull Observer observer) { - super.removeObserver(observer); + @MainThread + public void setValue(@Nullable T t) { + mPending.set(true); + super.setValue(t); } @Deprecated @@ -63,21 +61,13 @@ public void observeForever(@NonNull Observer observer) { @Deprecated @Override - public void removeObservers(@NonNull LifecycleOwner owner) { - super.removeObservers(owner); - } - - @MainThread - public void setValue(@Nullable T t) { - mPending.set(true); - super.setValue(t); + public void removeObserver(@NonNull Observer observer) { + super.removeObserver(observer); } - /** - * Used for cases where T is Void, to make calls cleaner. - */ - @MainThread - public void call() { - setValue(null); + @Deprecated + @Override + public void removeObservers(@NonNull LifecycleOwner owner) { + super.removeObservers(owner); } } diff --git a/auth/src/main/java/com/firebase/ui/auth/viewmodel/ViewModelBase.java b/auth/src/main/java/com/firebase/ui/auth/viewmodel/ViewModelBase.java index 9441e63ee..73ab859ca 100644 --- a/auth/src/main/java/com/firebase/ui/auth/viewmodel/ViewModelBase.java +++ b/auth/src/main/java/com/firebase/ui/auth/viewmodel/ViewModelBase.java @@ -2,6 +2,7 @@ import android.app.Application; import android.arch.lifecycle.AndroidViewModel; +import android.support.annotation.CallSuper; import android.support.annotation.RestrictTo; import java.util.concurrent.atomic.AtomicBoolean; @@ -34,6 +35,7 @@ protected void setArguments(T arguments) { mArguments = arguments; } + @CallSuper @Override protected void onCleared() { mIsInitialized.set(false); diff --git a/auth/src/main/java/com/firebase/ui/auth/viewmodel/email/RecoverPasswordHandler.java b/auth/src/main/java/com/firebase/ui/auth/viewmodel/email/RecoverPasswordHandler.java index 17d19f8b4..fc9d007ad 100644 --- a/auth/src/main/java/com/firebase/ui/auth/viewmodel/email/RecoverPasswordHandler.java +++ b/auth/src/main/java/com/firebase/ui/auth/viewmodel/email/RecoverPasswordHandler.java @@ -1,8 +1,6 @@ package com.firebase.ui.auth.viewmodel.email; import android.app.Application; -import android.arch.lifecycle.LiveData; -import android.arch.lifecycle.MutableLiveData; import android.support.annotation.NonNull; import android.support.annotation.RestrictTo; @@ -12,28 +10,21 @@ import com.google.android.gms.tasks.Task; @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) -public class RecoverPasswordHandler extends AuthViewModelBase { - private final MutableLiveData> mProgressLiveData = - new MutableLiveData<>(); - +public class RecoverPasswordHandler extends AuthViewModelBase { public RecoverPasswordHandler(Application application) { super(application); } - public LiveData> getProgressLiveData() { - return mProgressLiveData; - } - public void startReset(final String email) { - mProgressLiveData.setValue(Resource.forLoading()); + setResult(Resource.forLoading()); getAuth().sendPasswordResetEmail(email) .addOnCompleteListener(new OnCompleteListener() { @Override public void onComplete(@NonNull Task task) { - Resource state = task.isSuccessful() + Resource resource = task.isSuccessful() ? Resource.forSuccess(email) : Resource.forFailure(task.getException()); - mProgressLiveData.setValue(state); + setResult(resource); } }); } diff --git a/auth/src/main/java/com/firebase/ui/auth/viewmodel/email/WelcomeBackPasswordHandler.java b/auth/src/main/java/com/firebase/ui/auth/viewmodel/email/WelcomeBackPasswordHandler.java index febfcb254..198498e4a 100644 --- a/auth/src/main/java/com/firebase/ui/auth/viewmodel/email/WelcomeBackPasswordHandler.java +++ b/auth/src/main/java/com/firebase/ui/auth/viewmodel/email/WelcomeBackPasswordHandler.java @@ -1,8 +1,6 @@ package com.firebase.ui.auth.viewmodel.email; import android.app.Application; -import android.arch.lifecycle.LiveData; -import android.arch.lifecycle.MutableLiveData; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.annotation.RestrictTo; @@ -11,7 +9,7 @@ import com.firebase.ui.auth.data.model.Resource; import com.firebase.ui.auth.data.model.User; import com.firebase.ui.auth.data.remote.ProfileMerger; -import com.firebase.ui.auth.ui.TaskFailureLogger; +import com.firebase.ui.auth.util.data.TaskFailureLogger; import com.firebase.ui.auth.viewmodel.AuthViewModelBase; import com.google.android.gms.tasks.Continuation; import com.google.android.gms.tasks.OnCompleteListener; @@ -27,12 +25,9 @@ * SmartLock. */ @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) -public class WelcomeBackPasswordHandler extends AuthViewModelBase { - +public class WelcomeBackPasswordHandler extends AuthViewModelBase { private static final String TAG = "WBPasswordHandler"; - private MutableLiveData> mSignInLiveData = new MutableLiveData<>(); - private String mPendingPassword; public WelcomeBackPasswordHandler(Application application) { @@ -46,7 +41,7 @@ public void startSignIn(@NonNull final String email, @NonNull final String password, @NonNull final IdpResponse inputResponse, @Nullable final AuthCredential credential) { - mSignInLiveData.setValue(Resource.forLoading()); + setResult(Resource.forLoading()); // Store the password before signing in so it can be used for later credential building mPendingPassword = password; @@ -68,7 +63,6 @@ public void startSignIn(@NonNull final String email, // Kick off the flow including signing in, linking accounts, and saving with SmartLock getAuth().signInWithEmailAndPassword(email, password) - .addOnFailureListener(new TaskFailureLogger(TAG, "signInWithEmailAndPassword failed.")) .continueWithTask(new Continuation>() { @Override public Task then(@NonNull Task task) throws Exception { @@ -90,20 +84,15 @@ public Task then(@NonNull Task task) throws Exception { @Override public void onComplete(@NonNull Task task) { if (!task.isSuccessful()) { - mSignInLiveData.setValue(Resource.forFailure(task.getException())); + setResult(Resource.forFailure(task.getException())); return; } - setSuccess(outputResponse); + setResult(Resource.forSuccess(outputResponse)); } - }); - } - - /** - * Get the observable state of the sign in operation. - */ - public LiveData> getSignInOperation() { - return mSignInLiveData; + }) + .addOnFailureListener( + new TaskFailureLogger(TAG, "signInWithEmailAndPassword failed.")); } /** @@ -112,8 +101,4 @@ public LiveData> getSignInOperation() { public String getPendingPassword() { return mPendingPassword; } - - private void setSuccess(IdpResponse idpResponse) { - mSignInLiveData.setValue(Resource.forSuccess(idpResponse)); - } } diff --git a/auth/src/main/java/com/firebase/ui/auth/viewmodel/smartlock/SmartLockHandler.java b/auth/src/main/java/com/firebase/ui/auth/viewmodel/smartlock/SmartLockHandler.java index 232164b07..b1eb4bd24 100644 --- a/auth/src/main/java/com/firebase/ui/auth/viewmodel/smartlock/SmartLockHandler.java +++ b/auth/src/main/java/com/firebase/ui/auth/viewmodel/smartlock/SmartLockHandler.java @@ -2,19 +2,17 @@ import android.app.Activity; import android.app.Application; -import android.arch.lifecycle.LiveData; -import android.arch.lifecycle.MutableLiveData; -import android.content.Intent; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.annotation.RestrictTo; import android.util.Log; import com.firebase.ui.auth.ErrorCodes; import com.firebase.ui.auth.FirebaseUiException; +import com.firebase.ui.auth.data.model.PendingIntentRequiredException; import com.firebase.ui.auth.data.model.Resource; import com.firebase.ui.auth.util.CredentialsUtil; import com.firebase.ui.auth.viewmodel.AuthViewModelBase; -import com.firebase.ui.auth.viewmodel.PendingResolution; import com.firebase.ui.auth.viewmodel.ResolutionCodes; import com.google.android.gms.auth.api.credentials.Credential; import com.google.android.gms.common.api.ResolvableApiException; @@ -25,73 +23,50 @@ /** * ViewModel for initiating saves to the Credentials API (SmartLock). */ -public class SmartLockHandler extends AuthViewModelBase { - +public class SmartLockHandler extends AuthViewModelBase { private static final String TAG = "SmartLockViewModel"; - private MutableLiveData> mResultLiveData = new MutableLiveData<>(); - public SmartLockHandler(Application application) { super(application); } - /** - * Observe the status of the save operation initiated by - * {@link #saveCredentials(FirebaseUser, String, String)}. - */ - public LiveData> getSaveOperation() { - return mResultLiveData; - } - /** * Forward the result of a resolution from the Activity to the ViewModel. */ - @Override - public boolean onActivityResult(int requestCode, int resultCode, Intent data) { + public void onActivityResult(int requestCode, int resultCode) { if (requestCode == ResolutionCodes.RC_CRED_SAVE) { if (resultCode == Activity.RESULT_OK) { - mResultLiveData.setValue(Resource.forVoidSuccess()); + setResult(Resource.forVoidSuccess()); } else { Log.e(TAG, "SAVE: Canceled by user."); FirebaseUiException exception = new FirebaseUiException( ErrorCodes.UNKNOWN_ERROR, "Save canceled by user."); - mResultLiveData.setValue(Resource.forFailure(exception)); + setResult(Resource.forFailure(exception)); } - - return true; } - - return super.onActivityResult(requestCode, resultCode, data); } - /** - * Initialize saving a credential. Progress of the operation can be observed in - * {@link #getSaveOperation()}. - */ + /** @see #saveCredentials(Credential) */ + @RestrictTo(RestrictTo.Scope.TESTS) public void saveCredentials(FirebaseUser firebaseUser, @Nullable String password, @Nullable String accountType) { - - Credential credential = CredentialsUtil.buildCredential(firebaseUser, password, accountType); - saveCredentials(credential); + saveCredentials(CredentialsUtil.buildCredential(firebaseUser, password, accountType)); } - /** - * Initialize saving a credential. - */ + /** Initialize saving a credential. */ public void saveCredentials(Credential credential) { if (!getArguments().enableCredentials) { - mResultLiveData.setValue(Resource.forVoidSuccess()); + setResult(Resource.forVoidSuccess()); return; } - mResultLiveData.setValue(Resource.forLoading()); + setResult(Resource.forLoading()); if (credential == null) { - Exception exception = new FirebaseUiException(ErrorCodes.UNKNOWN_ERROR, - "Failed to build credential."); - mResultLiveData.setValue(Resource.forFailure(exception)); + setResult(Resource.forFailure(new FirebaseUiException(ErrorCodes.UNKNOWN_ERROR, + "Failed to build credential."))); return; } @@ -100,10 +75,11 @@ public void saveCredentials(Credential credential) { @Override public void onComplete(@NonNull Task task) { if (task.isSuccessful()) { - mResultLiveData.setValue(Resource.forVoidSuccess()); + setResult(Resource.forVoidSuccess()); } else if (task.getException() instanceof ResolvableApiException) { ResolvableApiException rae = (ResolvableApiException) task.getException(); - setPendingResolution(new PendingResolution(rae.getResolution(), ResolutionCodes.RC_CRED_SAVE)); + setResult(Resource.forFailure(new PendingIntentRequiredException( + rae.getResolution(), ResolutionCodes.RC_CRED_SAVE))); } else { Log.w(TAG, "Non-resolvable exception: " + task.getException()); @@ -111,10 +87,9 @@ public void onComplete(@NonNull Task task) { ErrorCodes.UNKNOWN_ERROR, "Error when saving credential.", task.getException()); - mResultLiveData.setValue(Resource.forFailure(exception)); + setResult(Resource.forFailure(exception)); } } }); } - } diff --git a/auth/src/test/java/com/firebase/ui/auth/viewmodel/RecoverPasswordHandlerTest.java b/auth/src/test/java/com/firebase/ui/auth/viewmodel/RecoverPasswordHandlerTest.java index ba9ee365e..4ee8f0e74 100644 --- a/auth/src/test/java/com/firebase/ui/auth/viewmodel/RecoverPasswordHandlerTest.java +++ b/auth/src/test/java/com/firebase/ui/auth/viewmodel/RecoverPasswordHandlerTest.java @@ -56,7 +56,7 @@ public void testReset_sendsRecoverEmail() { .thenReturn(AutoCompleteTask.forSuccess(null)); // Begin observation, then send the email - mHandler.getProgressLiveData().observeForever(mObserver); + mHandler.getOperation().observeForever(mObserver); mHandler.startReset(TestConstants.EMAIL); // Should get in-progress resource @@ -76,7 +76,7 @@ public void testReset_propagatesFailure() { .thenReturn(AutoCompleteTask.forFailure(new Exception("FAILED"))); // Begin observation, then send the email - mHandler.getProgressLiveData().observeForever(mObserver); + mHandler.getOperation().observeForever(mObserver); mHandler.startReset(TestConstants.EMAIL); // Should get in-progress resource diff --git a/auth/src/test/java/com/firebase/ui/auth/viewmodel/SmartLockHandlerTest.java b/auth/src/test/java/com/firebase/ui/auth/viewmodel/SmartLockHandlerTest.java index 4592e699e..d39a33ca6 100644 --- a/auth/src/test/java/com/firebase/ui/auth/viewmodel/SmartLockHandlerTest.java +++ b/auth/src/test/java/com/firebase/ui/auth/viewmodel/SmartLockHandlerTest.java @@ -4,6 +4,7 @@ import android.arch.lifecycle.Observer; import com.firebase.ui.auth.data.model.FlowParameters; +import com.firebase.ui.auth.data.model.PendingIntentRequiredException; import com.firebase.ui.auth.data.model.Resource; import com.firebase.ui.auth.testhelpers.AutoCompleteTask; import com.firebase.ui.auth.testhelpers.ResourceMatchers; @@ -42,7 +43,6 @@ public class SmartLockHandlerTest { @Mock FirebaseAuth mMockAuth; @Mock CredentialsClient mMockCredentials; @Mock Observer> mResultObserver; - @Mock Observer mResolutionObserver; private SmartLockHandler mHandler; @@ -61,7 +61,7 @@ public void setUp() { @Test public void testSaveCredentials_success() { - mHandler.getSaveOperation().observeForever(mResultObserver); + mHandler.getOperation().observeForever(mResultObserver); when(mMockCredentials.save(any(Credential.class))) .thenReturn(AutoCompleteTask.forSuccess(null)); @@ -74,8 +74,7 @@ public void testSaveCredentials_success() { @Test public void testSaveCredentials_resolution() { - mHandler.getSaveOperation().observeForever(mResultObserver); - mHandler.getPendingResolution().observeForever(mResolutionObserver); + mHandler.getOperation().observeForever(mResultObserver); // Mock credentials to throw an RAE ResolvableApiException mockRae = mock(ResolvableApiException.class); @@ -86,12 +85,13 @@ public void testSaveCredentials_resolution() { mHandler.saveCredentials(TestHelper.getMockFirebaseUser(), TestConstants.PASSWORD, null); // Make sure we get a resolution - ArgumentCaptor resolveCaptor = ArgumentCaptor.forClass(PendingResolution.class); - verify(mResolutionObserver).onChanged(resolveCaptor.capture()); + ArgumentCaptor> resolveCaptor = ArgumentCaptor.forClass(Resource.class); + verify(mResultObserver).onChanged(resolveCaptor.capture()); // Call activity result - PendingResolution pr = resolveCaptor.getValue(); - mHandler.onActivityResult(pr.getRequestCode(), Activity.RESULT_OK, null); + PendingIntentRequiredException e = + ((PendingIntentRequiredException) resolveCaptor.getValue().getException()); + mHandler.onActivityResult(e.getRequestCode(), Activity.RESULT_OK); // Make sure we get success verify(mResultObserver).onChanged(argThat(ResourceMatchers.isSuccess())); @@ -99,7 +99,7 @@ public void testSaveCredentials_resolution() { @Test public void testSaveCredentials_failure() { - mHandler.getSaveOperation().observeForever(mResultObserver); + mHandler.getOperation().observeForever(mResultObserver); when(mMockCredentials.save(any(Credential.class))) .thenReturn(AutoCompleteTask.forFailure(new Exception("FAILED"))); diff --git a/auth/src/test/java/com/firebase/ui/auth/viewmodel/WelcomeBackPasswordHandlerTest.java b/auth/src/test/java/com/firebase/ui/auth/viewmodel/WelcomeBackPasswordHandlerTest.java index ac46ceadf..40f2b8a3c 100644 --- a/auth/src/test/java/com/firebase/ui/auth/viewmodel/WelcomeBackPasswordHandlerTest.java +++ b/auth/src/test/java/com/firebase/ui/auth/viewmodel/WelcomeBackPasswordHandlerTest.java @@ -63,7 +63,7 @@ public void setUp() { @Test public void testSignIn_linksIdpCredential() { - mHandler.getSignInOperation().observeForever(mResponseObserver); + mHandler.getOperation().observeForever(mResponseObserver); // Fake social response from Facebook User user = new User.Builder(FacebookAuthProvider.PROVIDER_ID, TestConstants.EMAIL) @@ -110,7 +110,7 @@ public void testSignIn_linksIdpCredential() { @Test public void testSignIn_propagatesFailure() { - mHandler.getSignInOperation().observeForever(mResponseObserver); + mHandler.getOperation().observeForever(mResponseObserver); // Mock sign in to always fail when(mMockAuth.signInWithEmailAndPassword(any(String.class), any(String.class))) From 3325fda719cd10384bf5428d9d7b2d6d5f799fd7 Mon Sep 17 00:00:00 2001 From: Alex Saveau Date: Thu, 15 Mar 2018 17:01:55 -0700 Subject: [PATCH 2/8] Perf improvements Signed-off-by: Alex Saveau --- .../ui/auth/util/data/TaskFailureLogger.java | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/auth/src/main/java/com/firebase/ui/auth/util/data/TaskFailureLogger.java b/auth/src/main/java/com/firebase/ui/auth/util/data/TaskFailureLogger.java index 8fb062d26..91bb1e219 100644 --- a/auth/src/main/java/com/firebase/ui/auth/util/data/TaskFailureLogger.java +++ b/auth/src/main/java/com/firebase/ui/auth/util/data/TaskFailureLogger.java @@ -8,9 +8,24 @@ import com.google.android.gms.tasks.OnFailureListener; public class TaskFailureLogger implements OnFailureListener { + private static final boolean LOG; + private String mTag; private String mMessage; + static { + boolean log; + try { + Class buildConfigClass = Class.forName( + AuthUI.getApplicationContext().getPackageName() + "." + + BuildConfig.class.getSimpleName()); + log = buildConfigClass.getDeclaredField("DEBUG").getBoolean(null); + } catch (Exception ignored) { + log = false; + } + LOG = log; + } + public TaskFailureLogger(@NonNull String tag, @NonNull String message) { mTag = tag; mMessage = message; @@ -18,13 +33,6 @@ public TaskFailureLogger(@NonNull String tag, @NonNull String message) { @Override public void onFailure(@NonNull Exception e) { - try { - Class buildConfigClass = Class.forName( - AuthUI.getApplicationContext().getPackageName() + "." - + BuildConfig.class.getSimpleName()); - if (buildConfigClass.getDeclaredField("DEBUG").getBoolean(null)) { - Log.w(mTag, mMessage, e); - } - } catch (Exception ignored) {} + if (LOG) { Log.w(mTag, mMessage, e); } } } From fde1bcab3d44affad2b84eb24f549d2dc180b10a Mon Sep 17 00:00:00 2001 From: Alex Saveau Date: Thu, 15 Mar 2018 17:18:11 -0700 Subject: [PATCH 3/8] Fix loose ends Signed-off-by: Alex Saveau --- .../data/model/IntentRequiredException.java | 6 +----- .../model/PendingIntentRequiredException.java | 6 +----- .../ui/auth/data/model/StatefulException.java | 20 +++++++++++++++++++ .../firebase/ui/auth/util/ui/FlowUtils.java | 12 +++++++---- .../viewmodel/smartlock/SmartLockHandler.java | 2 -- .../auth/viewmodel/SmartLockHandlerTest.java | 3 ++- 6 files changed, 32 insertions(+), 17 deletions(-) create mode 100644 auth/src/main/java/com/firebase/ui/auth/data/model/StatefulException.java diff --git a/auth/src/main/java/com/firebase/ui/auth/data/model/IntentRequiredException.java b/auth/src/main/java/com/firebase/ui/auth/data/model/IntentRequiredException.java index 191ab022f..368c2a650 100644 --- a/auth/src/main/java/com/firebase/ui/auth/data/model/IntentRequiredException.java +++ b/auth/src/main/java/com/firebase/ui/auth/data/model/IntentRequiredException.java @@ -4,16 +4,12 @@ import android.support.annotation.NonNull; import android.support.annotation.RestrictTo; -import com.firebase.ui.auth.ErrorCodes; -import com.firebase.ui.auth.FirebaseUiException; - @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) -public class IntentRequiredException extends FirebaseUiException { +public class IntentRequiredException extends StatefulException { private final Intent mIntent; private final int mRequestCode; public IntentRequiredException(@NonNull Intent intent, int requestCode) { - super(ErrorCodes.UNKNOWN_ERROR); mIntent = intent; mRequestCode = requestCode; } diff --git a/auth/src/main/java/com/firebase/ui/auth/data/model/PendingIntentRequiredException.java b/auth/src/main/java/com/firebase/ui/auth/data/model/PendingIntentRequiredException.java index 0c6f17df2..0a8135d5e 100644 --- a/auth/src/main/java/com/firebase/ui/auth/data/model/PendingIntentRequiredException.java +++ b/auth/src/main/java/com/firebase/ui/auth/data/model/PendingIntentRequiredException.java @@ -4,16 +4,12 @@ import android.support.annotation.NonNull; import android.support.annotation.RestrictTo; -import com.firebase.ui.auth.ErrorCodes; -import com.firebase.ui.auth.FirebaseUiException; - @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) -public class PendingIntentRequiredException extends FirebaseUiException { +public class PendingIntentRequiredException extends StatefulException { private final PendingIntent mPendingIntent; private final int mRequestCode; public PendingIntentRequiredException(@NonNull PendingIntent pendingIntent, int requestCode) { - super(ErrorCodes.UNKNOWN_ERROR); mPendingIntent = pendingIntent; mRequestCode = requestCode; } diff --git a/auth/src/main/java/com/firebase/ui/auth/data/model/StatefulException.java b/auth/src/main/java/com/firebase/ui/auth/data/model/StatefulException.java new file mode 100644 index 000000000..a28726f77 --- /dev/null +++ b/auth/src/main/java/com/firebase/ui/auth/data/model/StatefulException.java @@ -0,0 +1,20 @@ +package com.firebase.ui.auth.data.model; + +import com.firebase.ui.auth.ErrorCodes; +import com.firebase.ui.auth.FirebaseUiException; + +public class StatefulException extends FirebaseUiException { + private boolean mUsed; + + public StatefulException() { + super(ErrorCodes.UNKNOWN_ERROR); + } + + public boolean isUsed() { + return mUsed; + } + + public void setUsed(boolean used) { + mUsed = used; + } +} diff --git a/auth/src/main/java/com/firebase/ui/auth/util/ui/FlowUtils.java b/auth/src/main/java/com/firebase/ui/auth/util/ui/FlowUtils.java index e22f0c809..5319f74aa 100644 --- a/auth/src/main/java/com/firebase/ui/auth/util/ui/FlowUtils.java +++ b/auth/src/main/java/com/firebase/ui/auth/util/ui/FlowUtils.java @@ -8,6 +8,7 @@ import com.firebase.ui.auth.IdpResponse; import com.firebase.ui.auth.data.model.IntentRequiredException; import com.firebase.ui.auth.data.model.PendingIntentRequiredException; +import com.firebase.ui.auth.data.model.StatefulException; import com.firebase.ui.auth.ui.HelperActivityBase; public final class FlowUtils { @@ -16,17 +17,20 @@ private FlowUtils() { } public static boolean handleError(@NonNull HelperActivityBase activity, @NonNull Exception e) { + if (!(e instanceof StatefulException) || ((StatefulException) e).isUsed()) { + return false; + } + ((StatefulException) e).setUsed(true); + if (e instanceof IntentRequiredException) { IntentRequiredException typed = (IntentRequiredException) e; activity.startActivityForResult(typed.getIntent(), typed.getRequestCode()); - return true; } else if (e instanceof PendingIntentRequiredException) { PendingIntentRequiredException typed = (PendingIntentRequiredException) e; startIntentSenderForResult(activity, typed.getPendingIntent(), typed.getRequestCode()); - return true; - } else { - return false; } + + return true; } private static void startIntentSenderForResult(HelperActivityBase activity, diff --git a/auth/src/main/java/com/firebase/ui/auth/viewmodel/smartlock/SmartLockHandler.java b/auth/src/main/java/com/firebase/ui/auth/viewmodel/smartlock/SmartLockHandler.java index b1eb4bd24..156e4b5da 100644 --- a/auth/src/main/java/com/firebase/ui/auth/viewmodel/smartlock/SmartLockHandler.java +++ b/auth/src/main/java/com/firebase/ui/auth/viewmodel/smartlock/SmartLockHandler.java @@ -60,10 +60,8 @@ public void saveCredentials(Credential credential) { setResult(Resource.forVoidSuccess()); return; } - setResult(Resource.forLoading()); - if (credential == null) { setResult(Resource.forFailure(new FirebaseUiException(ErrorCodes.UNKNOWN_ERROR, "Failed to build credential."))); diff --git a/auth/src/test/java/com/firebase/ui/auth/viewmodel/SmartLockHandlerTest.java b/auth/src/test/java/com/firebase/ui/auth/viewmodel/SmartLockHandlerTest.java index d39a33ca6..0b1b25af2 100644 --- a/auth/src/test/java/com/firebase/ui/auth/viewmodel/SmartLockHandlerTest.java +++ b/auth/src/test/java/com/firebase/ui/auth/viewmodel/SmartLockHandlerTest.java @@ -31,6 +31,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.argThat; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -86,7 +87,7 @@ public void testSaveCredentials_resolution() { // Make sure we get a resolution ArgumentCaptor> resolveCaptor = ArgumentCaptor.forClass(Resource.class); - verify(mResultObserver).onChanged(resolveCaptor.capture()); + verify(mResultObserver, times(2)).onChanged(resolveCaptor.capture()); // Call activity result PendingIntentRequiredException e = From 6f0e2c9adb8fec03358bdbeab7485ccfdf5d57ae Mon Sep 17 00:00:00 2001 From: Alex Saveau Date: Thu, 15 Mar 2018 17:32:29 -0700 Subject: [PATCH 4/8] Start addressing review feedback Signed-off-by: Alex Saveau --- .../ui/auth/util/data/TaskFailureLogger.java | 19 +---- .../ui/auth/viewmodel/SingleLiveEvent.java | 73 ------------------- 2 files changed, 1 insertion(+), 91 deletions(-) delete mode 100644 auth/src/main/java/com/firebase/ui/auth/viewmodel/SingleLiveEvent.java diff --git a/auth/src/main/java/com/firebase/ui/auth/util/data/TaskFailureLogger.java b/auth/src/main/java/com/firebase/ui/auth/util/data/TaskFailureLogger.java index 91bb1e219..5a36791c7 100644 --- a/auth/src/main/java/com/firebase/ui/auth/util/data/TaskFailureLogger.java +++ b/auth/src/main/java/com/firebase/ui/auth/util/data/TaskFailureLogger.java @@ -3,29 +3,12 @@ import android.support.annotation.NonNull; import android.util.Log; -import com.firebase.ui.auth.AuthUI; -import com.firebase.ui.auth.BuildConfig; import com.google.android.gms.tasks.OnFailureListener; public class TaskFailureLogger implements OnFailureListener { - private static final boolean LOG; - private String mTag; private String mMessage; - static { - boolean log; - try { - Class buildConfigClass = Class.forName( - AuthUI.getApplicationContext().getPackageName() + "." - + BuildConfig.class.getSimpleName()); - log = buildConfigClass.getDeclaredField("DEBUG").getBoolean(null); - } catch (Exception ignored) { - log = false; - } - LOG = log; - } - public TaskFailureLogger(@NonNull String tag, @NonNull String message) { mTag = tag; mMessage = message; @@ -33,6 +16,6 @@ public TaskFailureLogger(@NonNull String tag, @NonNull String message) { @Override public void onFailure(@NonNull Exception e) { - if (LOG) { Log.w(mTag, mMessage, e); } + Log.w(mTag, mMessage, e); } } diff --git a/auth/src/main/java/com/firebase/ui/auth/viewmodel/SingleLiveEvent.java b/auth/src/main/java/com/firebase/ui/auth/viewmodel/SingleLiveEvent.java deleted file mode 100644 index 74c73a08d..000000000 --- a/auth/src/main/java/com/firebase/ui/auth/viewmodel/SingleLiveEvent.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.firebase.ui.auth.viewmodel; - -import android.arch.lifecycle.LifecycleOwner; -import android.arch.lifecycle.MutableLiveData; -import android.arch.lifecycle.Observer; -import android.support.annotation.MainThread; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.util.Log; - -import java.util.concurrent.atomic.AtomicBoolean; - -/** - * A lifecycle-aware observable that sends only new updates after subscription, used for events like - * navigation and SnackBar messages. - *

- * This avoids a common problem with events: on configuration change (like rotation) an update - * can be emitted if the observer is active. This LiveData only calls the observable if there's an - * explicit call to setValue() or call(). - *

- * Note that only one observer is going to be notified of changes. - * - * This class only supports observing via lifecycle. May not be manually observed. - * - * Modified from: - * googlesamples/android-architecture - */ -public class SingleLiveEvent extends MutableLiveData { - private static final String TAG = "SingleLiveEvent"; - - private final AtomicBoolean mPending = new AtomicBoolean(false); - - @MainThread - public void observe(@NonNull LifecycleOwner owner, @NonNull final Observer observer) { - if (hasActiveObservers()) { - Log.w(TAG, "Multiple observers registered but only one will be notified of changes."); - } - - // Observe the internal MutableLiveData - super.observe(owner, new Observer() { - @Override - public void onChanged(@Nullable T t) { - if (mPending.compareAndSet(true, false)) { - observer.onChanged(t); - } - } - }); - } - - @MainThread - public void setValue(@Nullable T t) { - mPending.set(true); - super.setValue(t); - } - - @Deprecated - @Override - public void observeForever(@NonNull Observer observer) { - super.observeForever(observer); - } - - @Deprecated - @Override - public void removeObserver(@NonNull Observer observer) { - super.removeObserver(observer); - } - - @Deprecated - @Override - public void removeObservers(@NonNull LifecycleOwner owner) { - super.removeObservers(owner); - } -} From 624aa6e769d42c110cc8ea8c1e9554bacd2479a0 Mon Sep 17 00:00:00 2001 From: Alex Saveau Date: Thu, 15 Mar 2018 17:39:16 -0700 Subject: [PATCH 5/8] Move usage updates into getters Signed-off-by: Alex Saveau --- .../firebase/ui/auth/data/model/IntentRequiredException.java | 2 ++ .../ui/auth/data/model/PendingIntentRequiredException.java | 2 ++ .../java/com/firebase/ui/auth/data/model/StatefulException.java | 2 +- auth/src/main/java/com/firebase/ui/auth/util/ui/FlowUtils.java | 1 - 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/auth/src/main/java/com/firebase/ui/auth/data/model/IntentRequiredException.java b/auth/src/main/java/com/firebase/ui/auth/data/model/IntentRequiredException.java index 368c2a650..56d5c4fd0 100644 --- a/auth/src/main/java/com/firebase/ui/auth/data/model/IntentRequiredException.java +++ b/auth/src/main/java/com/firebase/ui/auth/data/model/IntentRequiredException.java @@ -16,10 +16,12 @@ public IntentRequiredException(@NonNull Intent intent, int requestCode) { @NonNull public Intent getIntent() { + setUsed(true); return mIntent; } public int getRequestCode() { + setUsed(true); return mRequestCode; } } diff --git a/auth/src/main/java/com/firebase/ui/auth/data/model/PendingIntentRequiredException.java b/auth/src/main/java/com/firebase/ui/auth/data/model/PendingIntentRequiredException.java index 0a8135d5e..b883a4de2 100644 --- a/auth/src/main/java/com/firebase/ui/auth/data/model/PendingIntentRequiredException.java +++ b/auth/src/main/java/com/firebase/ui/auth/data/model/PendingIntentRequiredException.java @@ -16,10 +16,12 @@ public PendingIntentRequiredException(@NonNull PendingIntent pendingIntent, int @NonNull public PendingIntent getPendingIntent() { + setUsed(true); return mPendingIntent; } public int getRequestCode() { + setUsed(true); return mRequestCode; } } diff --git a/auth/src/main/java/com/firebase/ui/auth/data/model/StatefulException.java b/auth/src/main/java/com/firebase/ui/auth/data/model/StatefulException.java index a28726f77..41ecc0d6b 100644 --- a/auth/src/main/java/com/firebase/ui/auth/data/model/StatefulException.java +++ b/auth/src/main/java/com/firebase/ui/auth/data/model/StatefulException.java @@ -14,7 +14,7 @@ public boolean isUsed() { return mUsed; } - public void setUsed(boolean used) { + protected void setUsed(boolean used) { mUsed = used; } } diff --git a/auth/src/main/java/com/firebase/ui/auth/util/ui/FlowUtils.java b/auth/src/main/java/com/firebase/ui/auth/util/ui/FlowUtils.java index 5319f74aa..fe3c98412 100644 --- a/auth/src/main/java/com/firebase/ui/auth/util/ui/FlowUtils.java +++ b/auth/src/main/java/com/firebase/ui/auth/util/ui/FlowUtils.java @@ -20,7 +20,6 @@ public static boolean handleError(@NonNull HelperActivityBase activity, @NonNull if (!(e instanceof StatefulException) || ((StatefulException) e).isUsed()) { return false; } - ((StatefulException) e).setUsed(true); if (e instanceof IntentRequiredException) { IntentRequiredException typed = (IntentRequiredException) e; From 3acea2daf6aef96b14f3f99b22352b1433e5ee7b Mon Sep 17 00:00:00 2001 From: Alex Saveau Date: Thu, 15 Mar 2018 22:14:00 -0700 Subject: [PATCH 6/8] Merge improvements from future PRs Signed-off-by: Alex Saveau --- .../ui/auth/data/model/IntentRequiredException.java | 2 -- .../data/model/PendingIntentRequiredException.java | 2 -- .../java/com/firebase/ui/auth/data/model/Resource.java | 8 ++++++++ .../firebase/ui/auth/data/model/StatefulException.java | 10 ---------- .../ui/auth/ui/credentials/CredentialSaveActivity.java | 3 ++- .../java/com/firebase/ui/auth/util/ui/FlowUtils.java | 4 +--- 6 files changed, 11 insertions(+), 18 deletions(-) diff --git a/auth/src/main/java/com/firebase/ui/auth/data/model/IntentRequiredException.java b/auth/src/main/java/com/firebase/ui/auth/data/model/IntentRequiredException.java index 56d5c4fd0..368c2a650 100644 --- a/auth/src/main/java/com/firebase/ui/auth/data/model/IntentRequiredException.java +++ b/auth/src/main/java/com/firebase/ui/auth/data/model/IntentRequiredException.java @@ -16,12 +16,10 @@ public IntentRequiredException(@NonNull Intent intent, int requestCode) { @NonNull public Intent getIntent() { - setUsed(true); return mIntent; } public int getRequestCode() { - setUsed(true); return mRequestCode; } } diff --git a/auth/src/main/java/com/firebase/ui/auth/data/model/PendingIntentRequiredException.java b/auth/src/main/java/com/firebase/ui/auth/data/model/PendingIntentRequiredException.java index b883a4de2..0a8135d5e 100644 --- a/auth/src/main/java/com/firebase/ui/auth/data/model/PendingIntentRequiredException.java +++ b/auth/src/main/java/com/firebase/ui/auth/data/model/PendingIntentRequiredException.java @@ -16,12 +16,10 @@ public PendingIntentRequiredException(@NonNull PendingIntent pendingIntent, int @NonNull public PendingIntent getPendingIntent() { - setUsed(true); return mPendingIntent; } public int getRequestCode() { - setUsed(true); return mRequestCode; } } diff --git a/auth/src/main/java/com/firebase/ui/auth/data/model/Resource.java b/auth/src/main/java/com/firebase/ui/auth/data/model/Resource.java index 9c006deca..05d343c50 100644 --- a/auth/src/main/java/com/firebase/ui/auth/data/model/Resource.java +++ b/auth/src/main/java/com/firebase/ui/auth/data/model/Resource.java @@ -17,6 +17,8 @@ public final class Resource { private final T mValue; private final Exception mException; + private boolean mUsed; + private Resource(State state, T value, Exception exception) { mState = state; mValue = value; @@ -62,14 +64,20 @@ public State getState() { @Nullable public final Exception getException() { + mUsed = true; return mException; } @Nullable public T getValue() { + mUsed = true; return mValue; } + public boolean isUsed() { + return mUsed; + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/auth/src/main/java/com/firebase/ui/auth/data/model/StatefulException.java b/auth/src/main/java/com/firebase/ui/auth/data/model/StatefulException.java index 41ecc0d6b..f916af728 100644 --- a/auth/src/main/java/com/firebase/ui/auth/data/model/StatefulException.java +++ b/auth/src/main/java/com/firebase/ui/auth/data/model/StatefulException.java @@ -4,17 +4,7 @@ import com.firebase.ui.auth.FirebaseUiException; public class StatefulException extends FirebaseUiException { - private boolean mUsed; - public StatefulException() { super(ErrorCodes.UNKNOWN_ERROR); } - - public boolean isUsed() { - return mUsed; - } - - protected void setUsed(boolean used) { - mUsed = used; - } } diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/credentials/CredentialSaveActivity.java b/auth/src/main/java/com/firebase/ui/auth/ui/credentials/CredentialSaveActivity.java index 99152c68a..93013db6f 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/credentials/CredentialSaveActivity.java +++ b/auth/src/main/java/com/firebase/ui/auth/ui/credentials/CredentialSaveActivity.java @@ -82,7 +82,8 @@ private void onSaveOperation(@NonNull Resource resource) { break; case SUCCESS: case FAILURE: - if (!FlowUtils.handleError(this, resource.getException())) { + if (!resource.isUsed() + && !FlowUtils.handleError(this, resource.getException())) { finish(RESULT_OK, mIdpResponse.toIntent()); } break; diff --git a/auth/src/main/java/com/firebase/ui/auth/util/ui/FlowUtils.java b/auth/src/main/java/com/firebase/ui/auth/util/ui/FlowUtils.java index fe3c98412..f9bb23bd5 100644 --- a/auth/src/main/java/com/firebase/ui/auth/util/ui/FlowUtils.java +++ b/auth/src/main/java/com/firebase/ui/auth/util/ui/FlowUtils.java @@ -17,9 +17,7 @@ private FlowUtils() { } public static boolean handleError(@NonNull HelperActivityBase activity, @NonNull Exception e) { - if (!(e instanceof StatefulException) || ((StatefulException) e).isUsed()) { - return false; - } + if (!(e instanceof StatefulException)) { return false; } if (e instanceof IntentRequiredException) { IntentRequiredException typed = (IntentRequiredException) e; From dd9ae698b8534fbf73437b04735085f107c552b3 Mon Sep 17 00:00:00 2001 From: Alex Saveau Date: Fri, 16 Mar 2018 10:06:03 -0700 Subject: [PATCH 7/8] Address review feedback Signed-off-by: Alex Saveau --- .../ui/auth/data/model/IntentRequiredException.java | 6 +++++- .../data/model/PendingIntentRequiredException.java | 6 +++++- .../firebase/ui/auth/data/model/StatefulException.java | 10 ---------- .../java/com/firebase/ui/auth/util/ui/FlowUtils.java | 7 +++---- 4 files changed, 13 insertions(+), 16 deletions(-) delete mode 100644 auth/src/main/java/com/firebase/ui/auth/data/model/StatefulException.java diff --git a/auth/src/main/java/com/firebase/ui/auth/data/model/IntentRequiredException.java b/auth/src/main/java/com/firebase/ui/auth/data/model/IntentRequiredException.java index 368c2a650..191ab022f 100644 --- a/auth/src/main/java/com/firebase/ui/auth/data/model/IntentRequiredException.java +++ b/auth/src/main/java/com/firebase/ui/auth/data/model/IntentRequiredException.java @@ -4,12 +4,16 @@ import android.support.annotation.NonNull; import android.support.annotation.RestrictTo; +import com.firebase.ui.auth.ErrorCodes; +import com.firebase.ui.auth.FirebaseUiException; + @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) -public class IntentRequiredException extends StatefulException { +public class IntentRequiredException extends FirebaseUiException { private final Intent mIntent; private final int mRequestCode; public IntentRequiredException(@NonNull Intent intent, int requestCode) { + super(ErrorCodes.UNKNOWN_ERROR); mIntent = intent; mRequestCode = requestCode; } diff --git a/auth/src/main/java/com/firebase/ui/auth/data/model/PendingIntentRequiredException.java b/auth/src/main/java/com/firebase/ui/auth/data/model/PendingIntentRequiredException.java index 0a8135d5e..0c6f17df2 100644 --- a/auth/src/main/java/com/firebase/ui/auth/data/model/PendingIntentRequiredException.java +++ b/auth/src/main/java/com/firebase/ui/auth/data/model/PendingIntentRequiredException.java @@ -4,12 +4,16 @@ import android.support.annotation.NonNull; import android.support.annotation.RestrictTo; +import com.firebase.ui.auth.ErrorCodes; +import com.firebase.ui.auth.FirebaseUiException; + @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) -public class PendingIntentRequiredException extends StatefulException { +public class PendingIntentRequiredException extends FirebaseUiException { private final PendingIntent mPendingIntent; private final int mRequestCode; public PendingIntentRequiredException(@NonNull PendingIntent pendingIntent, int requestCode) { + super(ErrorCodes.UNKNOWN_ERROR); mPendingIntent = pendingIntent; mRequestCode = requestCode; } diff --git a/auth/src/main/java/com/firebase/ui/auth/data/model/StatefulException.java b/auth/src/main/java/com/firebase/ui/auth/data/model/StatefulException.java deleted file mode 100644 index f916af728..000000000 --- a/auth/src/main/java/com/firebase/ui/auth/data/model/StatefulException.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.firebase.ui.auth.data.model; - -import com.firebase.ui.auth.ErrorCodes; -import com.firebase.ui.auth.FirebaseUiException; - -public class StatefulException extends FirebaseUiException { - public StatefulException() { - super(ErrorCodes.UNKNOWN_ERROR); - } -} diff --git a/auth/src/main/java/com/firebase/ui/auth/util/ui/FlowUtils.java b/auth/src/main/java/com/firebase/ui/auth/util/ui/FlowUtils.java index f9bb23bd5..95304c1d6 100644 --- a/auth/src/main/java/com/firebase/ui/auth/util/ui/FlowUtils.java +++ b/auth/src/main/java/com/firebase/ui/auth/util/ui/FlowUtils.java @@ -8,7 +8,6 @@ import com.firebase.ui.auth.IdpResponse; import com.firebase.ui.auth.data.model.IntentRequiredException; import com.firebase.ui.auth.data.model.PendingIntentRequiredException; -import com.firebase.ui.auth.data.model.StatefulException; import com.firebase.ui.auth.ui.HelperActivityBase; public final class FlowUtils { @@ -17,17 +16,17 @@ private FlowUtils() { } public static boolean handleError(@NonNull HelperActivityBase activity, @NonNull Exception e) { - if (!(e instanceof StatefulException)) { return false; } - if (e instanceof IntentRequiredException) { IntentRequiredException typed = (IntentRequiredException) e; activity.startActivityForResult(typed.getIntent(), typed.getRequestCode()); + return true; } else if (e instanceof PendingIntentRequiredException) { PendingIntentRequiredException typed = (PendingIntentRequiredException) e; startIntentSenderForResult(activity, typed.getPendingIntent(), typed.getRequestCode()); + return true; } - return true; + return false; } private static void startIntentSenderForResult(HelperActivityBase activity, From 887ae0d5bddd3e80cb7d649511a83fc115de5a17 Mon Sep 17 00:00:00 2001 From: Alex Saveau Date: Fri, 16 Mar 2018 10:26:11 -0700 Subject: [PATCH 8/8] Fancisize tests Signed-off-by: Alex Saveau --- .../ui/auth/viewmodel/SmartLockHandlerTest.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/auth/src/test/java/com/firebase/ui/auth/viewmodel/SmartLockHandlerTest.java b/auth/src/test/java/com/firebase/ui/auth/viewmodel/SmartLockHandlerTest.java index 0b1b25af2..c0fb7edcd 100644 --- a/auth/src/test/java/com/firebase/ui/auth/viewmodel/SmartLockHandlerTest.java +++ b/auth/src/test/java/com/firebase/ui/auth/viewmodel/SmartLockHandlerTest.java @@ -21,6 +21,7 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; +import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; @@ -30,8 +31,8 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.argThat; +import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -85,9 +86,13 @@ public void testSaveCredentials_resolution() { // Kick off save mHandler.saveCredentials(TestHelper.getMockFirebaseUser(), TestConstants.PASSWORD, null); + InOrder inOrder = inOrder(mResultObserver); + + inOrder.verify(mResultObserver).onChanged(argThat(ResourceMatchers.isLoading())); + // Make sure we get a resolution ArgumentCaptor> resolveCaptor = ArgumentCaptor.forClass(Resource.class); - verify(mResultObserver, times(2)).onChanged(resolveCaptor.capture()); + inOrder.verify(mResultObserver).onChanged(resolveCaptor.capture()); // Call activity result PendingIntentRequiredException e = @@ -95,7 +100,7 @@ public void testSaveCredentials_resolution() { mHandler.onActivityResult(e.getRequestCode(), Activity.RESULT_OK); // Make sure we get success - verify(mResultObserver).onChanged(argThat(ResourceMatchers.isSuccess())); + inOrder.verify(mResultObserver).onChanged(argThat(ResourceMatchers.isSuccess())); } @Test