-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Completely rewrite provider login with new architecture #1189
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a1c7dda
3325fda
fde1bca
6f0e2c9
624aa6e
3acea2d
dd9ae69
887ae0d
fdb9f94
5511513
1be0b8b
0a65776
f0dc341
057c561
7736254
4c2eec6
705b9b9
e17c101
27ff4d3
8732c11
95b024c
e233c82
3b901c5
e79388f
82d6af6
ff61518
b1f2356
6f5207a
bbc00f0
e8214a4
6b8eb7f
43a1d31
748cbc5
2fad171
e679f80
6fec29c
f4ec251
e947030
36a41f2
722f9c6
d111daa
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,7 +31,8 @@ | |
|
||
import com.facebook.login.LoginManager; | ||
import com.firebase.ui.auth.data.model.FlowParameters; | ||
import com.firebase.ui.auth.provider.TwitterProvider; | ||
import com.firebase.ui.auth.data.remote.FacebookSignInHandler; | ||
import com.firebase.ui.auth.data.remote.TwitterSignInHandler; | ||
import com.firebase.ui.auth.ui.idp.AuthMethodPickerActivity; | ||
import com.firebase.ui.auth.util.ExtraConstants; | ||
import com.firebase.ui.auth.util.GoogleApiUtils; | ||
|
@@ -59,6 +60,7 @@ | |
import com.google.firebase.auth.PhoneAuthProvider; | ||
import com.google.firebase.auth.TwitterAuthProvider; | ||
import com.google.firebase.auth.UserInfo; | ||
import com.twitter.sdk.android.core.TwitterCore; | ||
|
||
import java.lang.annotation.Retention; | ||
import java.lang.annotation.RetentionPolicy; | ||
|
@@ -177,10 +179,10 @@ public class AuthUI { | |
*/ | ||
public static final Set<String> SUPPORTED_PROVIDERS = | ||
Collections.unmodifiableSet(new HashSet<>(Arrays.asList( | ||
EmailAuthProvider.PROVIDER_ID, | ||
GoogleAuthProvider.PROVIDER_ID, | ||
FacebookAuthProvider.PROVIDER_ID, | ||
TwitterAuthProvider.PROVIDER_ID, | ||
EmailAuthProvider.PROVIDER_ID, | ||
PhoneAuthProvider.PROVIDER_ID | ||
))); | ||
|
||
|
@@ -276,7 +278,7 @@ public Task<Void> signOut(@NonNull Context context) { | |
.disableAutoSignIn() | ||
.continueWithTask(new Continuation<Void, Task<Void>>() { | ||
@Override | ||
public Task<Void> then(@NonNull Task<Void> task) throws Exception { | ||
public Task<Void> then(@NonNull Task<Void> task) { | ||
// We want to ignore a specific exception, since it's not a good reason | ||
// to fail (see Issue 1156). | ||
if (!task.isSuccessful() && (task.getException() instanceof ApiException)) { | ||
|
@@ -357,22 +359,12 @@ public Task<Void> then(@NonNull Task<Void> task) { | |
} | ||
|
||
private Task<Void> signOutIdps(@NonNull Context context) { | ||
try { | ||
if (FacebookSignInHandler.IS_AVAILABLE) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is much less scary |
||
LoginManager.getInstance().logOut(); | ||
} catch (NoClassDefFoundError e) { | ||
// Do nothing: this is perfectly fine if the dev doesn't include Facebook/Twitter | ||
// support | ||
} | ||
|
||
try { | ||
TwitterProvider.signOut(context); | ||
} catch (NoClassDefFoundError e) { | ||
// See comment above | ||
// Note: we need to have separate try/catch statements since devs can include | ||
// _either_ one of the providers. If one crashes, we still need to sign out of | ||
// the other one. | ||
if (TwitterSignInHandler.IS_AVAILABLE) { | ||
TwitterCore.getInstance().getSessionManager().clearActiveSession(); | ||
} | ||
|
||
return GoogleSignIn.getClient(context, GoogleSignInOptions.DEFAULT_SIGN_IN).signOut(); | ||
} | ||
|
||
|
@@ -787,17 +779,12 @@ public static final class FacebookBuilder extends Builder { | |
public FacebookBuilder() { | ||
//noinspection deprecation taking a hit for the backcompat team | ||
super(FacebookAuthProvider.PROVIDER_ID); | ||
|
||
try { | ||
//noinspection unused to possibly throw | ||
Class c = com.facebook.FacebookSdk.class; | ||
} catch (NoClassDefFoundError e) { | ||
if (!FacebookSignInHandler.IS_AVAILABLE) { | ||
throw new RuntimeException( | ||
"Facebook provider cannot be configured " + | ||
"without dependency. Did you forget to add " + | ||
"'com.facebook.android:facebook-login:VERSION' dependency?"); | ||
} | ||
|
||
Preconditions.checkConfigured(getApplicationContext(), | ||
"Facebook provider unconfigured. Make sure to add a" + | ||
" `facebook_application_id` string. See the docs for more info:" + | ||
|
@@ -830,17 +817,12 @@ public static final class TwitterBuilder extends Builder { | |
public TwitterBuilder() { | ||
//noinspection deprecation taking a hit for the backcompat team | ||
super(TwitterAuthProvider.PROVIDER_ID); | ||
|
||
try { | ||
//noinspection unused to possibly throw | ||
Class c = com.twitter.sdk.android.core.TwitterCore.class; | ||
} catch (NoClassDefFoundError e) { | ||
if (!TwitterSignInHandler.IS_AVAILABLE) { | ||
throw new RuntimeException( | ||
"Twitter provider cannot be configured " + | ||
"without dependency. Did you forget to add " + | ||
"'com.twitter.sdk.android:twitter-core:VERSION' dependency?"); | ||
} | ||
|
||
Preconditions.checkConfigured(getApplicationContext(), | ||
"Twitter provider unconfigured. Make sure to add your key and secret." + | ||
" See the docs for more info:" + | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,15 +12,15 @@ | |
*/ | ||
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) | ||
public final class Resource<T> { | ||
private State mState; | ||
private final boolean mUsable; | ||
|
||
private final State mState; | ||
private final T mValue; | ||
private final Exception mException; | ||
|
||
private boolean mUsed; | ||
|
||
private Resource(State state, T value, Exception exception) { | ||
private Resource(State state, boolean usable, T value, Exception exception) { | ||
mState = state; | ||
mUsable = usable; | ||
mValue = value; | ||
mException = exception; | ||
} | ||
|
@@ -30,31 +30,47 @@ private Resource(State state, T value, Exception exception) { | |
*/ | ||
@NonNull | ||
public static Resource<Void> forVoidSuccess() { | ||
return new Resource<>(State.SUCCESS, null, null); | ||
return new Resource<>(State.SUCCESS, false, null, null); | ||
} | ||
|
||
/** | ||
* Creates a successful resource containing a value. | ||
*/ | ||
@NonNull | ||
public static <T> Resource<T> forSuccess(@NonNull T value) { | ||
return new Resource<>(State.SUCCESS, value, null); | ||
return new Resource<>(State.SUCCESS, false, value, null); | ||
} | ||
|
||
/** | ||
* Similar to {@link #forSuccess(Object)}, but this resource can be used up. | ||
*/ | ||
@NonNull | ||
public static <T> Resource<T> forUsableSuccess(@NonNull T value) { | ||
return new Resource<>(State.SUCCESS, true, value, null); | ||
} | ||
|
||
/** | ||
* Creates a failed resource with an exception. | ||
*/ | ||
@NonNull | ||
public static <T> Resource<T> forFailure(@NonNull Exception e) { | ||
return new Resource<>(State.FAILURE, null, e); | ||
return new Resource<>(State.FAILURE, false, null, e); | ||
} | ||
|
||
/** | ||
* Similar to {@link #forFailure(Exception)}, but this resource can be used up. | ||
*/ | ||
@NonNull | ||
public static <T> Resource<T> forUsableFailure(@NonNull Exception e) { | ||
return new Resource<>(State.FAILURE, true, null, e); | ||
} | ||
|
||
/** | ||
* Creates a resource in the loading state, without a value or an exception. | ||
*/ | ||
@NonNull | ||
public static <T> Resource<T> forLoading() { | ||
return new Resource<>(State.LOADING, null, null); | ||
return new Resource<>(State.LOADING, false, null, null); | ||
} | ||
|
||
@NonNull | ||
|
@@ -64,20 +80,16 @@ public State getState() { | |
|
||
@Nullable | ||
public final Exception getException() { | ||
mUsed = true; | ||
if (mUsable) { mState = State.USED; } | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is sort of interesting. Previously, a How does this affect the pattern of listening to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, technically, the "resource" part is still immutable since the value and exception can't change. Also, the class is final so only we control the state's mutability, and for now, it can only go from There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems OK for now ... just something we may have to change in the future. |
||
return mException; | ||
} | ||
|
||
@Nullable | ||
public T getValue() { | ||
mUsed = true; | ||
if (mUsable) { mState = State.USED; } | ||
return mValue; | ||
} | ||
|
||
public boolean isUsed() { | ||
return mUsed; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package com.firebase.ui.auth.data.model; | ||
|
||
import android.support.annotation.RestrictTo; | ||
|
||
import com.firebase.ui.auth.ErrorCodes; | ||
import com.firebase.ui.auth.FirebaseUiException; | ||
|
||
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) | ||
public class UserCancellationException extends FirebaseUiException { | ||
public UserCancellationException() { | ||
super(ErrorCodes.UNKNOWN_ERROR); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
package com.firebase.ui.auth.data.remote; | ||
|
||
import android.app.Application; | ||
import android.content.Intent; | ||
import android.support.annotation.NonNull; | ||
import android.support.annotation.Nullable; | ||
import android.support.annotation.RestrictTo; | ||
|
||
import com.firebase.ui.auth.IdpResponse; | ||
import com.firebase.ui.auth.data.model.Resource; | ||
import com.firebase.ui.auth.data.model.UserCancellationException; | ||
import com.firebase.ui.auth.ui.HelperActivityBase; | ||
import com.firebase.ui.auth.ui.email.EmailActivity; | ||
import com.firebase.ui.auth.viewmodel.RequestCodes; | ||
import com.firebase.ui.auth.viewmodel.idp.ProviderSignInBase; | ||
|
||
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP) | ||
public class EmailSignInHandler extends ProviderSignInBase<Void> { | ||
public EmailSignInHandler(Application application) { | ||
super(application); | ||
} | ||
|
||
@Override | ||
public void startSignIn(@NonNull HelperActivityBase activity) { | ||
activity.startActivityForResult( | ||
EmailActivity.createIntent(activity, activity.getFlowParams()), | ||
RequestCodes.EMAIL_FLOW); | ||
} | ||
|
||
@Override | ||
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { | ||
if (requestCode == RequestCodes.EMAIL_FLOW) { | ||
IdpResponse response = IdpResponse.fromResultIntent(data); | ||
if (response == null) { | ||
setResult(Resource.<IdpResponse>forFailure(new UserCancellationException())); | ||
} else { | ||
setResult(Resource.forSuccess(response)); | ||
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did some linter tell you not to have
throws Exception
here? Does it actually change anything to remove it?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, IntelliJ has been removing these, not sure why, but it doesn't seem to matter.