Skip to content

Commit 2ef0595

Browse files
SUPERCILEXsamtstern
authored andcommitted
Completely rewrite provider login with new architecture (#1189)
1 parent 01cadaf commit 2ef0595

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1490
-1775
lines changed

app/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ android {
3838
dependencies {
3939
implementation "com.google.firebase:firebase-core:$firebaseVersion"
4040
implementation "com.android.support:design:$supportLibraryVersion"
41-
implementation 'com.android.support:multidex:1.0.2'
41+
implementation 'com.android.support:multidex:1.0.3'
4242

4343
implementation project(path: ':auth')
4444
implementation project(path: ':firestore')

auth/src/main/AndroidManifest.xml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,17 @@
2323
android:exported="false"
2424
android:theme="@style/FirebaseUI.Transparent" />
2525

26+
<activity
27+
android:name=".ui.idp.SingleSignInActivity"
28+
android:label=""
29+
android:exported="false"
30+
android:theme="@style/FirebaseUI.Transparent" />
31+
2632
<activity
2733
android:name=".ui.email.RecoverPasswordActivity"
2834
android:label="@string/fui_title_recover_password_activity"
29-
android:exported="false" />
35+
android:exported="false"
36+
android:windowSoftInputMode="adjustResize" />
3037

3138
<activity
3239
android:name=".ui.email.EmailActivity"
@@ -43,7 +50,8 @@
4350
<activity
4451
android:name=".ui.idp.WelcomeBackIdpPrompt"
4552
android:label="@string/fui_title_welcome_back_idp_prompt"
46-
android:exported="false" />
53+
android:exported="false"
54+
android:windowSoftInputMode="adjustResize" />
4755

4856
<activity
4957
android:name=".ui.email.WelcomeBackPasswordPrompt"

auth/src/main/java/com/firebase/ui/auth/AuthUI.java

Lines changed: 10 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@
3131

3232
import com.facebook.login.LoginManager;
3333
import com.firebase.ui.auth.data.model.FlowParameters;
34-
import com.firebase.ui.auth.provider.TwitterProvider;
34+
import com.firebase.ui.auth.data.remote.FacebookSignInHandler;
35+
import com.firebase.ui.auth.data.remote.TwitterSignInHandler;
3536
import com.firebase.ui.auth.ui.idp.AuthMethodPickerActivity;
3637
import com.firebase.ui.auth.util.ExtraConstants;
3738
import com.firebase.ui.auth.util.GoogleApiUtils;
@@ -59,6 +60,7 @@
5960
import com.google.firebase.auth.PhoneAuthProvider;
6061
import com.google.firebase.auth.TwitterAuthProvider;
6162
import com.google.firebase.auth.UserInfo;
63+
import com.twitter.sdk.android.core.TwitterCore;
6264

6365
import java.lang.annotation.Retention;
6466
import java.lang.annotation.RetentionPolicy;
@@ -177,10 +179,10 @@ public class AuthUI {
177179
*/
178180
public static final Set<String> SUPPORTED_PROVIDERS =
179181
Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
180-
EmailAuthProvider.PROVIDER_ID,
181182
GoogleAuthProvider.PROVIDER_ID,
182183
FacebookAuthProvider.PROVIDER_ID,
183184
TwitterAuthProvider.PROVIDER_ID,
185+
EmailAuthProvider.PROVIDER_ID,
184186
PhoneAuthProvider.PROVIDER_ID
185187
)));
186188

@@ -276,7 +278,7 @@ public Task<Void> signOut(@NonNull Context context) {
276278
.disableAutoSignIn()
277279
.continueWithTask(new Continuation<Void, Task<Void>>() {
278280
@Override
279-
public Task<Void> then(@NonNull Task<Void> task) throws Exception {
281+
public Task<Void> then(@NonNull Task<Void> task) {
280282
// We want to ignore a specific exception, since it's not a good reason
281283
// to fail (see Issue 1156).
282284
if (!task.isSuccessful() && (task.getException() instanceof ApiException)) {
@@ -357,22 +359,12 @@ public Task<Void> then(@NonNull Task<Void> task) {
357359
}
358360

359361
private Task<Void> signOutIdps(@NonNull Context context) {
360-
try {
362+
if (FacebookSignInHandler.IS_AVAILABLE) {
361363
LoginManager.getInstance().logOut();
362-
} catch (NoClassDefFoundError e) {
363-
// Do nothing: this is perfectly fine if the dev doesn't include Facebook/Twitter
364-
// support
365364
}
366-
367-
try {
368-
TwitterProvider.signOut(context);
369-
} catch (NoClassDefFoundError e) {
370-
// See comment above
371-
// Note: we need to have separate try/catch statements since devs can include
372-
// _either_ one of the providers. If one crashes, we still need to sign out of
373-
// the other one.
365+
if (TwitterSignInHandler.IS_AVAILABLE) {
366+
TwitterCore.getInstance().getSessionManager().clearActiveSession();
374367
}
375-
376368
return GoogleSignIn.getClient(context, GoogleSignInOptions.DEFAULT_SIGN_IN).signOut();
377369
}
378370

@@ -787,17 +779,12 @@ public static final class FacebookBuilder extends Builder {
787779
public FacebookBuilder() {
788780
//noinspection deprecation taking a hit for the backcompat team
789781
super(FacebookAuthProvider.PROVIDER_ID);
790-
791-
try {
792-
//noinspection unused to possibly throw
793-
Class c = com.facebook.FacebookSdk.class;
794-
} catch (NoClassDefFoundError e) {
782+
if (!FacebookSignInHandler.IS_AVAILABLE) {
795783
throw new RuntimeException(
796784
"Facebook provider cannot be configured " +
797785
"without dependency. Did you forget to add " +
798786
"'com.facebook.android:facebook-login:VERSION' dependency?");
799787
}
800-
801788
Preconditions.checkConfigured(getApplicationContext(),
802789
"Facebook provider unconfigured. Make sure to add a" +
803790
" `facebook_application_id` string. See the docs for more info:" +
@@ -830,17 +817,12 @@ public static final class TwitterBuilder extends Builder {
830817
public TwitterBuilder() {
831818
//noinspection deprecation taking a hit for the backcompat team
832819
super(TwitterAuthProvider.PROVIDER_ID);
833-
834-
try {
835-
//noinspection unused to possibly throw
836-
Class c = com.twitter.sdk.android.core.TwitterCore.class;
837-
} catch (NoClassDefFoundError e) {
820+
if (!TwitterSignInHandler.IS_AVAILABLE) {
838821
throw new RuntimeException(
839822
"Twitter provider cannot be configured " +
840823
"without dependency. Did you forget to add " +
841824
"'com.twitter.sdk.android:twitter-core:VERSION' dependency?");
842825
}
843-
844826
Preconditions.checkConfigured(getApplicationContext(),
845827
"Twitter provider unconfigured. Make sure to add your key and secret." +
846828
" See the docs for more info:" +

auth/src/main/java/com/firebase/ui/auth/ErrorCodes.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ public final class ErrorCodes {
1616
UNKNOWN_ERROR,
1717
NO_NETWORK,
1818
PLAY_SERVICES_UPDATE_CANCELLED,
19-
DEVELOPER_ERROR
19+
DEVELOPER_ERROR,
20+
PROVIDER_ERROR
2021
})
2122
@Retention(RetentionPolicy.SOURCE)
2223
public @interface Code {}
@@ -41,6 +42,11 @@ public final class ErrorCodes {
4142
*/
4243
public static final int DEVELOPER_ERROR = 3;
4344

45+
/**
46+
* An external sign-in provider error occurred.
47+
*/
48+
public static final int PROVIDER_ERROR = 4;
49+
4450
private ErrorCodes() {
4551
throw new AssertionError("No instance for you!");
4652
}

auth/src/main/java/com/firebase/ui/auth/IdpResponse.java

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import android.support.annotation.RestrictTo;
2424
import android.text.TextUtils;
2525

26+
import com.firebase.ui.auth.data.model.Resource;
2627
import com.firebase.ui.auth.data.model.User;
2728
import com.firebase.ui.auth.util.ExtraConstants;
2829
import com.google.firebase.auth.GoogleAuthProvider;
@@ -97,20 +98,33 @@ public static IdpResponse fromResultIntent(@Nullable Intent resultIntent) {
9798
}
9899
}
99100

101+
@NonNull
100102
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
101-
public static Intent getErrorIntent(@NonNull Exception e) {
102-
return fromError(e).toIntent();
103+
public static IdpResponse from(@NonNull Resource<IdpResponse> resource) {
104+
IdpResponse response = resource.getValue();
105+
if (resource.getException() != null) {
106+
response = from(resource.getException());
107+
}
108+
return response;
103109
}
104110

111+
@NonNull
105112
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
106-
public static IdpResponse fromError(@NonNull Exception e) {
113+
public static IdpResponse from(@NonNull Exception e) {
107114
if (e instanceof FirebaseUiException) {
108115
return new IdpResponse((FirebaseUiException) e);
109116
} else {
110117
return new IdpResponse(new FirebaseUiException(ErrorCodes.UNKNOWN_ERROR, e));
111118
}
112119
}
113120

121+
@NonNull
122+
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
123+
public static Intent getErrorIntent(@NonNull Exception e) {
124+
return from(e).toIntent();
125+
}
126+
127+
@NonNull
114128
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
115129
public Intent toIntent() {
116130
return new Intent().putExtra(ExtraConstants.EXTRA_IDP_RESPONSE, this);

auth/src/main/java/com/firebase/ui/auth/KickoffActivity.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@
1313
import com.firebase.ui.auth.util.ExtraConstants;
1414
import com.firebase.ui.auth.util.PlayServicesHelper;
1515
import com.firebase.ui.auth.util.signincontainer.SignInDelegate;
16+
import com.firebase.ui.auth.viewmodel.RequestCodes;
1617

1718
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
1819
public class KickoffActivity extends HelperActivityBase {
1920
private static final String TAG = "KickoffActivity";
2021
private static final String IS_WAITING_FOR_PLAY_SERVICES = "is_waiting_for_play_services";
21-
private static final int RC_PLAY_SERVICES = 1;
2222

2323
private boolean mIsWaitingForPlayServices = false;
2424

@@ -40,7 +40,7 @@ protected void onCreate(Bundle savedInstance) {
4040

4141
boolean isPlayServicesAvailable = PlayServicesHelper.makePlayServicesAvailable(
4242
this,
43-
RC_PLAY_SERVICES,
43+
RequestCodes.PLAY_SERVICES_CHECK,
4444
new DialogInterface.OnCancelListener() {
4545
@Override
4646
public void onCancel(DialogInterface dialog) {
@@ -68,7 +68,7 @@ public void onSaveInstanceState(Bundle outState) {
6868
@Override
6969
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
7070
super.onActivityResult(requestCode, resultCode, data);
71-
if (requestCode == RC_PLAY_SERVICES) {
71+
if (requestCode == RequestCodes.PLAY_SERVICES_CHECK) {
7272
if (resultCode == RESULT_OK) {
7373
start();
7474
} else {

auth/src/main/java/com/firebase/ui/auth/data/model/Resource.java

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@
1212
*/
1313
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
1414
public final class Resource<T> {
15+
private State mState;
16+
private final boolean mUsable;
1517

16-
private final State mState;
1718
private final T mValue;
1819
private final Exception mException;
1920

20-
private boolean mUsed;
21-
22-
private Resource(State state, T value, Exception exception) {
21+
private Resource(State state, boolean usable, T value, Exception exception) {
2322
mState = state;
23+
mUsable = usable;
2424
mValue = value;
2525
mException = exception;
2626
}
@@ -30,31 +30,47 @@ private Resource(State state, T value, Exception exception) {
3030
*/
3131
@NonNull
3232
public static Resource<Void> forVoidSuccess() {
33-
return new Resource<>(State.SUCCESS, null, null);
33+
return new Resource<>(State.SUCCESS, false, null, null);
3434
}
3535

3636
/**
3737
* Creates a successful resource containing a value.
3838
*/
3939
@NonNull
4040
public static <T> Resource<T> forSuccess(@NonNull T value) {
41-
return new Resource<>(State.SUCCESS, value, null);
41+
return new Resource<>(State.SUCCESS, false, value, null);
42+
}
43+
44+
/**
45+
* Similar to {@link #forSuccess(Object)}, but this resource can be used up.
46+
*/
47+
@NonNull
48+
public static <T> Resource<T> forUsableSuccess(@NonNull T value) {
49+
return new Resource<>(State.SUCCESS, true, value, null);
4250
}
4351

4452
/**
4553
* Creates a failed resource with an exception.
4654
*/
4755
@NonNull
4856
public static <T> Resource<T> forFailure(@NonNull Exception e) {
49-
return new Resource<>(State.FAILURE, null, e);
57+
return new Resource<>(State.FAILURE, false, null, e);
58+
}
59+
60+
/**
61+
* Similar to {@link #forFailure(Exception)}, but this resource can be used up.
62+
*/
63+
@NonNull
64+
public static <T> Resource<T> forUsableFailure(@NonNull Exception e) {
65+
return new Resource<>(State.FAILURE, true, null, e);
5066
}
5167

5268
/**
5369
* Creates a resource in the loading state, without a value or an exception.
5470
*/
5571
@NonNull
5672
public static <T> Resource<T> forLoading() {
57-
return new Resource<>(State.LOADING, null, null);
73+
return new Resource<>(State.LOADING, false, null, null);
5874
}
5975

6076
@NonNull
@@ -64,20 +80,16 @@ public State getState() {
6480

6581
@Nullable
6682
public final Exception getException() {
67-
mUsed = true;
83+
if (mUsable) { mState = State.USED; }
6884
return mException;
6985
}
7086

7187
@Nullable
7288
public T getValue() {
73-
mUsed = true;
89+
if (mUsable) { mState = State.USED; }
7490
return mValue;
7591
}
7692

77-
public boolean isUsed() {
78-
return mUsed;
79-
}
80-
8193
@Override
8294
public boolean equals(Object o) {
8395
if (this == o) return true;

auth/src/main/java/com/firebase/ui/auth/data/model/State.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44

55
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
66
public enum State {
7-
SUCCESS, FAILURE, LOADING
7+
SUCCESS, FAILURE, LOADING, USED
88
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.firebase.ui.auth.data.model;
2+
3+
import android.support.annotation.RestrictTo;
4+
5+
import com.firebase.ui.auth.ErrorCodes;
6+
import com.firebase.ui.auth.FirebaseUiException;
7+
8+
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
9+
public class UserCancellationException extends FirebaseUiException {
10+
public UserCancellationException() {
11+
super(ErrorCodes.UNKNOWN_ERROR);
12+
}
13+
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.firebase.ui.auth.data.remote;
2+
3+
import android.app.Application;
4+
import android.content.Intent;
5+
import android.support.annotation.NonNull;
6+
import android.support.annotation.Nullable;
7+
import android.support.annotation.RestrictTo;
8+
9+
import com.firebase.ui.auth.IdpResponse;
10+
import com.firebase.ui.auth.data.model.Resource;
11+
import com.firebase.ui.auth.data.model.UserCancellationException;
12+
import com.firebase.ui.auth.ui.HelperActivityBase;
13+
import com.firebase.ui.auth.ui.email.EmailActivity;
14+
import com.firebase.ui.auth.viewmodel.RequestCodes;
15+
import com.firebase.ui.auth.viewmodel.idp.ProviderSignInBase;
16+
17+
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
18+
public class EmailSignInHandler extends ProviderSignInBase<Void> {
19+
public EmailSignInHandler(Application application) {
20+
super(application);
21+
}
22+
23+
@Override
24+
public void startSignIn(@NonNull HelperActivityBase activity) {
25+
activity.startActivityForResult(
26+
EmailActivity.createIntent(activity, activity.getFlowParams()),
27+
RequestCodes.EMAIL_FLOW);
28+
}
29+
30+
@Override
31+
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
32+
if (requestCode == RequestCodes.EMAIL_FLOW) {
33+
IdpResponse response = IdpResponse.fromResultIntent(data);
34+
if (response == null) {
35+
setResult(Resource.<IdpResponse>forFailure(new UserCancellationException()));
36+
} else {
37+
setResult(Resource.forSuccess(response));
38+
}
39+
}
40+
}
41+
}

0 commit comments

Comments
 (0)