diff --git a/auth/src/main/java/com/firebase/ui/auth/KickoffActivity.java b/auth/src/main/java/com/firebase/ui/auth/KickoffActivity.java index d09fd514b..d3993a44b 100644 --- a/auth/src/main/java/com/firebase/ui/auth/KickoffActivity.java +++ b/auth/src/main/java/com/firebase/ui/auth/KickoffActivity.java @@ -1,21 +1,58 @@ package com.firebase.ui.auth; import android.content.Context; +import android.content.DialogInterface; import android.content.Intent; +import android.net.ConnectivityManager; import android.os.Bundle; +import android.util.Log; import com.firebase.ui.auth.ui.ActivityHelper; import com.firebase.ui.auth.ui.AppCompatBase; import com.firebase.ui.auth.ui.ExtraConstants; import com.firebase.ui.auth.ui.FlowParameters; +import com.firebase.ui.auth.util.PlayServicesHelper; import com.firebase.ui.auth.util.signincontainer.SignInDelegate; public class KickoffActivity extends AppCompatBase { + private static final String TAG = "KickoffActivity"; + private static final String IS_WAITING_FOR_PLAY_SERVICES = "is_waiting_for_play_services"; + private static final int RC_PLAY_SERVICES = 1; + + private boolean mIsWaitingForPlayServices = false; + + public static Intent createIntent(Context context, FlowParameters flowParams) { + return ActivityHelper.createBaseIntent(context, KickoffActivity.class, flowParams); + } + @Override protected void onCreate(Bundle savedInstance) { super.onCreate(savedInstance); - if (savedInstance == null) { - SignInDelegate.delegate(this, mActivityHelper.getFlowParams()); + if (savedInstance == null || savedInstance.getBoolean(IS_WAITING_FOR_PLAY_SERVICES)) { + if (isOffline()) { + Log.d(TAG, "No network connection"); + finish(ErrorCodes.NO_NETWORK, + IdpResponse.getErrorCodeIntent(ErrorCodes.NO_NETWORK)); + return; + } + + boolean isPlayServicesAvailable = PlayServicesHelper.makePlayServicesAvailable( + this, + RC_PLAY_SERVICES, + new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + finish(ResultCodes.CANCELED, + IdpResponse.getErrorCodeIntent( + ErrorCodes.UNKNOWN_ERROR)); + } + }); + + if (isPlayServicesAvailable) { + SignInDelegate.delegate(KickoffActivity.this, mActivityHelper.getFlowParams()); + } else { + mIsWaitingForPlayServices = true; + } } } @@ -23,19 +60,37 @@ protected void onCreate(Bundle savedInstance) { public void onSaveInstanceState(Bundle outState) { // It doesn't matter what we put here, we just don't want outState to be empty outState.putBoolean(ExtraConstants.HAS_EXISTING_INSTANCE, true); + outState.putBoolean(IS_WAITING_FOR_PLAY_SERVICES, mIsWaitingForPlayServices); super.onSaveInstanceState(outState); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - SignInDelegate delegate = SignInDelegate.getInstance(this); - if (delegate != null) { - delegate.onActivityResult(requestCode, resultCode, data); + if (requestCode == RC_PLAY_SERVICES) { + if (resultCode == ResultCodes.OK) { + SignInDelegate.delegate(KickoffActivity.this, mActivityHelper.getFlowParams()); + } else { + finish(ResultCodes.CANCELED, + IdpResponse.getErrorCodeIntent(ErrorCodes.UNKNOWN_ERROR)); + } + } else { + SignInDelegate delegate = SignInDelegate.getInstance(this); + if (delegate != null) delegate.onActivityResult(requestCode, resultCode, data); } } - public static Intent createIntent(Context context, FlowParameters flowParams) { - return ActivityHelper.createBaseIntent(context, KickoffActivity.class, flowParams); + /** + * Check if there is an active or soon-to-be-active network connection. + * + * @return true if there is no network connection, false otherwise. + */ + private boolean isOffline() { + ConnectivityManager manager = + (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); + + return !(manager != null + && manager.getActiveNetworkInfo() != null + && manager.getActiveNetworkInfo().isConnectedOrConnecting()); } } diff --git a/auth/src/main/java/com/firebase/ui/auth/ui/email/CheckEmailFragment.java b/auth/src/main/java/com/firebase/ui/auth/ui/email/CheckEmailFragment.java index 765e1ace5..32648cc5b 100644 --- a/auth/src/main/java/com/firebase/ui/auth/ui/email/CheckEmailFragment.java +++ b/auth/src/main/java/com/firebase/ui/auth/ui/email/CheckEmailFragment.java @@ -22,8 +22,13 @@ import com.firebase.ui.auth.ui.TaskFailureLogger; import com.firebase.ui.auth.ui.User; import com.firebase.ui.auth.ui.email.fieldvalidators.EmailFieldValidator; -import com.firebase.ui.auth.util.FirebaseAuthWrapperFactory; +import com.firebase.ui.auth.util.GoogleApiConstants; +import com.google.android.gms.auth.api.Auth; import com.google.android.gms.auth.api.credentials.Credential; +import com.google.android.gms.auth.api.credentials.CredentialPickerConfig; +import com.google.android.gms.auth.api.credentials.HintRequest; +import com.google.android.gms.common.ConnectionResult; +import com.google.android.gms.common.api.GoogleApiClient; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.OnSuccessListener; import com.google.android.gms.tasks.Task; @@ -216,18 +221,36 @@ public void onSuccess(ProviderQueryResult result) { } private void showEmailAutoCompleteHint() { - PendingIntent hintIntent = FirebaseAuthWrapperFactory - .getFirebaseAuthWrapper(mHelper.getAppName()) - .getEmailHintIntent(getActivity()); - if (hintIntent != null) { - try { - startIntentSenderForResult(hintIntent.getIntentSender(), RC_HINT, null, 0, 0, 0, null); - } catch (IntentSender.SendIntentException e) { - Log.e(TAG, "Unable to start hint intent", e); - } + try { + startIntentSenderForResult(getEmailHintIntent().getIntentSender(), RC_HINT, null, 0, 0, 0, null); + } catch (IntentSender.SendIntentException e) { + Log.e(TAG, "Unable to start hint intent", e); } } + private PendingIntent getEmailHintIntent() { + GoogleApiClient client = new GoogleApiClient.Builder(getContext()) + .addApi(Auth.CREDENTIALS_API) + .enableAutoManage(getActivity(), GoogleApiConstants.AUTO_MANAGE_ID3, + new GoogleApiClient.OnConnectionFailedListener() { + @Override + public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { + Log.e(TAG, + "Client connection failed: " + connectionResult.getErrorMessage()); + } + }) + .build(); + + HintRequest hintRequest = new HintRequest.Builder() + .setHintPickerConfig(new CredentialPickerConfig.Builder() + .setShowCancelButton(true) + .build()) + .setEmailAddressIdentifierSupported(true) + .build(); + + return Auth.CredentialsApi.getHintPickerIntent(client, hintRequest); + } + @Override public void onClick(View view) { int id = view.getId(); diff --git a/auth/src/main/java/com/firebase/ui/auth/util/FirebaseAuthWrapper.java b/auth/src/main/java/com/firebase/ui/auth/util/FirebaseAuthWrapper.java deleted file mode 100644 index 32f3b1828..000000000 --- a/auth/src/main/java/com/firebase/ui/auth/util/FirebaseAuthWrapper.java +++ /dev/null @@ -1,76 +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.util; - - -import android.app.PendingIntent; -import android.content.Context; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.WorkerThread; -import android.support.v4.app.FragmentActivity; - -import com.google.firebase.auth.AuthCredential; -import com.google.firebase.auth.FirebaseUser; - -import java.util.List; -import java.util.concurrent.ExecutionException; - -/** - * Abstraction layer for the Firebase Auth APIs ({@code com.google.firebase.auth}), that - * provides synchronous convenience methods and facilitates mock testing. - */ -public interface FirebaseAuthWrapper { - - @WorkerThread - boolean isExistingAccount(@Nullable String email); - - @WorkerThread - @NonNull - List getProvidersForEmail(@Nullable String email); - - @WorkerThread - boolean resetPasswordForEmail(@NonNull String email); - - @WorkerThread - @Nullable - FirebaseUser signInWithEmailPassword(@NonNull String email, @NonNull String password); - - @WorkerThread - @Nullable - FirebaseUser signInWithCredential(@NonNull AuthCredential credential); - - @WorkerThread - @Nullable - FirebaseUser getCurrentUser(); - - @WorkerThread - @Nullable - FirebaseUser createUserWithEmailAndPassword(@NonNull String email, @NonNull String password) - throws ExecutionException, InterruptedException; - - @WorkerThread - FirebaseUser linkWithCredential( - FirebaseUser user, - AuthCredential credential) - throws ExecutionException; - - boolean isPlayServicesAvailable(Context context); - - PendingIntent getEmailHintIntent(FragmentActivity context); - - void setTimeOut(long timeoutMs); - -} diff --git a/auth/src/main/java/com/firebase/ui/auth/util/FirebaseAuthWrapperFactory.java b/auth/src/main/java/com/firebase/ui/auth/util/FirebaseAuthWrapperFactory.java deleted file mode 100644 index b67111812..000000000 --- a/auth/src/main/java/com/firebase/ui/auth/util/FirebaseAuthWrapperFactory.java +++ /dev/null @@ -1,38 +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.util; - -import com.google.firebase.FirebaseApp; -import com.google.firebase.auth.FirebaseAuth; - -/** - * Utility class for producing instances of {@link FirebaseAuthWrapper}. - */ -public class FirebaseAuthWrapperFactory { - - /** - * Produces a {@link FirebaseAuthWrapper} given the Firebase application name. - */ - public static FirebaseAuthWrapper getFirebaseAuthWrapper(String appName) { - return getFirebaseAuthWrapper(FirebaseApp.getInstance(appName)); - } - - /** - * Produces a {@link FirebaseAuthWrapper} given a {@link FirebaseApp} instance. - */ - public static FirebaseAuthWrapper getFirebaseAuthWrapper(FirebaseApp firebaseApp) { - return new FirebaseAuthWrapperImpl(FirebaseAuth.getInstance(firebaseApp)); - } -} diff --git a/auth/src/main/java/com/firebase/ui/auth/util/FirebaseAuthWrapperImpl.java b/auth/src/main/java/com/firebase/ui/auth/util/FirebaseAuthWrapperImpl.java deleted file mode 100644 index 94d855ad5..000000000 --- a/auth/src/main/java/com/firebase/ui/auth/util/FirebaseAuthWrapperImpl.java +++ /dev/null @@ -1,210 +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.util; - -import android.app.PendingIntent; -import android.content.Context; -import android.os.Bundle; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.WorkerThread; -import android.support.v4.app.FragmentActivity; -import android.util.Log; - -import com.google.android.gms.auth.api.Auth; -import com.google.android.gms.auth.api.credentials.CredentialPickerConfig; -import com.google.android.gms.auth.api.credentials.HintRequest; -import com.google.android.gms.common.ConnectionResult; -import com.google.android.gms.common.api.GoogleApiClient; -import com.google.android.gms.common.api.GoogleApiClient.OnConnectionFailedListener; -import com.google.android.gms.tasks.Task; -import com.google.android.gms.tasks.Tasks; -import com.google.firebase.auth.AuthCredential; -import com.google.firebase.auth.AuthResult; -import com.google.firebase.auth.FirebaseAuth; -import com.google.firebase.auth.FirebaseUser; -import com.google.firebase.auth.ProviderQueryResult; - -import java.util.Collections; -import java.util.List; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - -public class FirebaseAuthWrapperImpl - implements FirebaseAuthWrapper, GoogleApiClient.ConnectionCallbacks { - - private static final String TAG = "FirebaseAuthWrapperImpl"; - - private static final long DEFAULT_TIMEOUT = TimeUnit.SECONDS.toMillis(2); - - private final FirebaseAuth mFirebaseAuth; - - private long mTimeoutMs = DEFAULT_TIMEOUT; - - public FirebaseAuthWrapperImpl(@NonNull FirebaseAuth firebaseAuth) { - if (firebaseAuth == null) { - throw new IllegalArgumentException("firebaseAuth must not be null"); - } - mFirebaseAuth = firebaseAuth; - } - - @Override - @WorkerThread - public boolean isExistingAccount(@Nullable final String email) { - return email != null && hasProviders(await(mFirebaseAuth.fetchProvidersForEmail(email))); - } - - @Override - @WorkerThread - @NonNull - public List getProvidersForEmail(@Nullable String emailAddress) { - if (emailAddress == null) { - return Collections.emptyList(); - } - - ProviderQueryResult result = - await(mFirebaseAuth.fetchProvidersForEmail(emailAddress)); - if (hasProviders(result)) { - return result.getProviders(); - } - - return Collections.emptyList(); - } - - @Override - @WorkerThread - public boolean resetPasswordForEmail(@NonNull String emailAddress) { - Task curTask = mFirebaseAuth.sendPasswordResetEmail(emailAddress); - try { - Tasks.await(curTask); - } catch (ExecutionException | InterruptedException e) { - Log.w(TAG, "attempt to reset password failed", e); - return false; - } - return true; - } - - @Override - @WorkerThread - @Nullable - public FirebaseUser signInWithEmailPassword( - @NonNull String emailAddress, - @NonNull String password) { - AuthResult authResult = - await(mFirebaseAuth.signInWithEmailAndPassword(emailAddress, password)); - return authResult == null ? null : authResult.getUser(); - } - - @Override - @WorkerThread - @Nullable - public FirebaseUser signInWithCredential(@NonNull AuthCredential credential) { - Task curTask = mFirebaseAuth.signInWithCredential(credential); - AuthResult authResult = await(curTask); - return authResult == null ? null : authResult.getUser(); - } - - @Override - @WorkerThread - @Nullable - public FirebaseUser getCurrentUser() { - return mFirebaseAuth.getCurrentUser(); - } - - @Override - @WorkerThread - @Nullable - public FirebaseUser createUserWithEmailAndPassword( - @NonNull String emailAddress, - @NonNull String password) throws ExecutionException, InterruptedException { - Task curTask; - curTask = mFirebaseAuth.createUserWithEmailAndPassword(emailAddress, password); - Tasks.await(curTask); - return curTask.getResult().getUser(); - } - - @Override - public boolean isPlayServicesAvailable(Context context) { - return PlayServicesHelper.getInstance(context).isPlayServicesAvailable(); - } - - @Override - public PendingIntent getEmailHintIntent(FragmentActivity fragmentActivity) { - if (!isPlayServicesAvailable(fragmentActivity)) { - return null; - } - - GoogleApiClient client = new GoogleApiClient.Builder(fragmentActivity) - .addConnectionCallbacks(this) - .addApi(Auth.CREDENTIALS_API) - .enableAutoManage(fragmentActivity, GoogleApiConstants.AUTO_MANAGE_ID3, - new OnConnectionFailedListener() { - @Override - public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { - Log.e(TAG, - "Client connection failed: " + connectionResult.getErrorMessage()); - } - }) - .build(); - - HintRequest hintRequest = new HintRequest.Builder() - .setHintPickerConfig(new CredentialPickerConfig.Builder() - .setShowCancelButton(true) - .build()) - .setEmailAddressIdentifierSupported(true) - .build(); - - return Auth.CredentialsApi.getHintPickerIntent(client, hintRequest); - } - - @Override - public void setTimeOut(long timeoutMs) { - this.mTimeoutMs = timeoutMs; - } - - @Override - @WorkerThread - @Nullable - public FirebaseUser linkWithCredential( - @NonNull FirebaseUser user, - @NonNull AuthCredential credential) - throws ExecutionException { - AuthResult linkResult = await(user.linkWithCredential(credential)); - return linkResult == null ? null : linkResult.getUser(); - } - - @Override - public void onConnected(@Nullable Bundle bundle) {} - - @Override - public void onConnectionSuspended(int cause) {} - - private T await(@NonNull Task curTask) { - try { - Tasks.await(curTask, mTimeoutMs, TimeUnit.MILLISECONDS); - return curTask.getResult(); - } catch (ExecutionException | InterruptedException | TimeoutException e) { - Log.w(TAG, "API request dispatch failed", e); - return null; - } - } - - private boolean hasProviders(@Nullable ProviderQueryResult result) { - return result != null - && result.getProviders() != null - && result.getProviders().size() > 0; - } -} diff --git a/auth/src/main/java/com/firebase/ui/auth/util/PlayServicesHelper.java b/auth/src/main/java/com/firebase/ui/auth/util/PlayServicesHelper.java index 78b5dfb78..bdfb54ac2 100644 --- a/auth/src/main/java/com/firebase/ui/auth/util/PlayServicesHelper.java +++ b/auth/src/main/java/com/firebase/ui/auth/util/PlayServicesHelper.java @@ -2,103 +2,45 @@ import android.app.Activity; import android.app.Dialog; -import android.content.Context; -import android.support.annotation.NonNull; -import android.support.annotation.Nullable; -import android.support.annotation.VisibleForTesting; -import android.util.Log; +import android.content.DialogInterface; -import com.google.android.gms.common.ConnectionResult; import com.google.android.gms.common.GoogleApiAvailability; /** * Helper class wrapping {@link GoogleApiAvailability}. Used internally but can also be used * by client application */ -public final class PlayServicesHelper { +public class PlayServicesHelper { + private static GoogleApiAvailability mApiAvailability; - private static final String TAG = "PlayServicesHelper"; - - @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) - public static GoogleApiAvailability sApiAvailability = GoogleApiAvailability.getInstance(); - - private final Context mContext; - - public static PlayServicesHelper getInstance(Context context) { - return new PlayServicesHelper(context); - } - - private PlayServicesHelper(Context context) { - this.mContext = context; - } - - /** - * Returns {@code true} if Google Play Services is available and at the correct version, - * false otherwise. - */ - public boolean isPlayServicesAvailable() { - int playServicesAvailable = sApiAvailability.isGooglePlayServicesAvailable(mContext); - return playServicesAvailable == ConnectionResult.SUCCESS; - } - - /** - * Returns {@code true} if Google Play Services is either already available or can be made - * available with user action, {@code false} otherwise. - */ - public boolean canMakePlayServicesAvailable() { - // Check if already available - if (isPlayServicesAvailable()) { - return true; + public static GoogleApiAvailability getGoogleApiAvailability() { + if (mApiAvailability == null) { + mApiAvailability = GoogleApiAvailability.getInstance(); } - - // Check if error is resolvable - int availabilityCode = sApiAvailability.isGooglePlayServicesAvailable(mContext); - boolean isUserResolvable = sApiAvailability.isUserResolvableError(availabilityCode); - - // Although the API considers SERVICE_INVALID to be resolvable, it can cause crashes - // on devices with no GmsCore installed at all (like emulators) and therefore we will - // avoid trying to resolve it. - return (isUserResolvable && availabilityCode != ConnectionResult.SERVICE_INVALID); + return mApiAvailability; } /** - * Kick off the process to make Play Services available if necessary and possible. - * @param activity the Activity that will host necessary dialogs. - * @param requestCode a request code to be used to return results to the Activity. - * @param cancelListener (optional) a Dialog listener if the user cancels the recommended action. - * @return {@code true} if a resolution is launched or if a resolution was not necessary, - * {@code false otherwise}. + * @param activity The Activity that will host necessary dialogs. + * @param requestCode A request code to be used to return results to the Activity. + * @param cancelListener A Dialog listener if the user cancels the recommended action. + * @return true if play services is available, false otherwise. */ - public boolean makePlayServicesAvailable( - @NonNull Activity activity, - int requestCode, - @Nullable Dialog.OnCancelListener cancelListener) { - - // Check if already available - if (isPlayServicesAvailable()) { - return true; - } - - // Check if error is resolvable - if (!canMakePlayServicesAvailable()) { - return false; - } - - // Get an error dialog for the error code - int errorCode = sApiAvailability.isGooglePlayServicesAvailable(activity); - Dialog dialog = sApiAvailability.getErrorDialog(activity, errorCode, requestCode, cancelListener); - - // Display the dialog, if possible - if (dialog != null) { - dialog.show(); + public static boolean makePlayServicesAvailable(Activity activity, + int requestCode, + DialogInterface.OnCancelListener cancelListener) { + Dialog errorDialog = getGoogleApiAvailability().getErrorDialog( + activity, + getGoogleApiAvailability().isGooglePlayServicesAvailable(activity), + requestCode, + cancelListener); + + // The error dialog will be null if isGooglePlayServicesAvailable returned SUCCESS + if (errorDialog == null) { return true; } else { - // The documentation says the dialog should never be null for a non-SUCCESS - // connection result, but add these warnings just in case. - Log.w(TAG, "apiAvailability.getErrorDialog() was null!"); - Log.w(TAG, "errorCode=" + errorCode); + errorDialog.show(); return false; } } - } diff --git a/auth/src/main/java/com/firebase/ui/auth/util/signincontainer/SaveSmartLock.java b/auth/src/main/java/com/firebase/ui/auth/util/signincontainer/SaveSmartLock.java index 949fffc89..dd0ab3d3c 100644 --- a/auth/src/main/java/com/firebase/ui/auth/util/signincontainer/SaveSmartLock.java +++ b/auth/src/main/java/com/firebase/ui/auth/util/signincontainer/SaveSmartLock.java @@ -38,7 +38,6 @@ import com.google.android.gms.auth.api.Auth; import com.google.android.gms.auth.api.credentials.Credential; import com.google.android.gms.common.ConnectionResult; -import com.google.android.gms.common.GoogleApiAvailability; import com.google.android.gms.common.api.GoogleApiClient.Builder; import com.google.android.gms.common.api.Status; import com.google.firebase.auth.FirebaseUser; @@ -93,8 +92,7 @@ public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { Toast.makeText(getContext(), R.string.general_error, Toast.LENGTH_SHORT).show(); PendingIntent resolution = - GoogleApiAvailability - .getInstance() + PlayServicesHelper.getGoogleApiAvailability() .getErrorResolutionPendingIntent(getContext(), connectionResult.getErrorCode(), RC_UPDATE_SERVICE); @@ -172,8 +170,7 @@ public void saveCredentialsOrFinish(FirebaseUser firebaseUser, @Nullable IdpResponse response) { mResponse = response; - if (!mHelper.getFlowParams().smartLockEnabled - || !PlayServicesHelper.getInstance(getContext()).isPlayServicesAvailable()) { + if (!mHelper.getFlowParams().smartLockEnabled) { finish(); return; } 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 7abaaa8bf..ee7106e32 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 @@ -1,10 +1,7 @@ package com.firebase.ui.auth.util.signincontainer; -import android.content.Context; -import android.content.DialogInterface; import android.content.Intent; import android.content.IntentSender; -import android.net.ConnectivityManager; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -15,7 +12,6 @@ import android.util.Log; import com.firebase.ui.auth.AuthUI; -import com.firebase.ui.auth.ErrorCodes; import com.firebase.ui.auth.IdpResponse; import com.firebase.ui.auth.R; import com.firebase.ui.auth.ResultCodes; @@ -28,7 +24,6 @@ import com.firebase.ui.auth.ui.idp.AuthMethodPickerActivity; import com.firebase.ui.auth.util.CredentialsApiHelper; import com.firebase.ui.auth.util.GoogleApiConstants; -import com.firebase.ui.auth.util.PlayServicesHelper; import com.google.android.gms.auth.api.Auth; import com.google.android.gms.auth.api.credentials.Credential; import com.google.android.gms.auth.api.credentials.CredentialRequest; @@ -65,7 +60,6 @@ public class SignInDelegate extends SmartLockBase { private static final int RC_IDP_SIGNIN = 3; private static final int RC_AUTH_METHOD_PICKER = 4; private static final int RC_EMAIL_FLOW = 5; - private static final int RC_PLAY_SERVICES = 6; private Credential mCredential; @@ -77,34 +71,6 @@ public void onCreate(Bundle savedInstance) { return; } - if (!hasNetworkConnection()) { - Log.d(TAG, "No network connection"); - finish(ErrorCodes.NO_NETWORK, IdpResponse.getErrorCodeIntent(ErrorCodes.NO_NETWORK)); - return; - } - - // Make Google Play Services available at the correct version, if possible - boolean madeAvailable = - PlayServicesHelper - .getInstance(getActivity()) - .makePlayServicesAvailable(getActivity(), RC_PLAY_SERVICES, - new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialogInterface) { - Log.w(TAG, - "playServices:dialog.onCancel()"); - finish(ResultCodes.CANCELED, - IdpResponse.getErrorCodeIntent(ErrorCodes.UNKNOWN_ERROR)); - } - }); - - if (!madeAvailable - || !PlayServicesHelper.getInstance(getActivity()).isPlayServicesAvailable()) { - Log.w(TAG, "playServices: could not make available."); - finish(ResultCodes.CANCELED, IdpResponse.getErrorCodeIntent(ErrorCodes.UNKNOWN_ERROR)); - return; - } - if (mHelper.getFlowParams().smartLockEnabled) { mHelper.showLoadingDialog(R.string.progress_dialog_loading); @@ -186,9 +152,6 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) { case RC_EMAIL_FLOW: finish(resultCode, data); break; - case RC_PLAY_SERVICES: - if (resultCode != ResultCodes.OK) finish(resultCode, data); - break; default: IdpSignInContainer signInContainer = IdpSignInContainer.getInstance(getActivity()); if (signInContainer != null) { @@ -358,18 +321,6 @@ private void redirectToIdpSignIn(String email, String accountType) { } } - /** - * Check if there is an active or soon-to-be-active network connection. - */ - private boolean hasNetworkConnection() { - ConnectivityManager manager = - (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE); - - return manager != null - && manager.getActiveNetworkInfo() != null - && manager.getActiveNetworkInfo().isConnectedOrConnecting(); - } - public static void delegate(FragmentActivity activity, FlowParameters params) { FragmentManager fm = activity.getSupportFragmentManager(); Fragment fragment = fm.findFragmentByTag(TAG); diff --git a/auth/src/test/java/com/firebase/ui/auth/testhelpers/CustomRobolectricGradleTestRunner.java b/auth/src/test/java/com/firebase/ui/auth/testhelpers/CustomRobolectricGradleTestRunner.java index cbd8086f6..12344596d 100644 --- a/auth/src/test/java/com/firebase/ui/auth/testhelpers/CustomRobolectricGradleTestRunner.java +++ b/auth/src/test/java/com/firebase/ui/auth/testhelpers/CustomRobolectricGradleTestRunner.java @@ -19,8 +19,6 @@ import com.firebase.ui.auth.provider.GoogleProvider; import com.firebase.ui.auth.ui.ActivityHelper; import com.firebase.ui.auth.ui.BaseHelper; -import com.firebase.ui.auth.util.FirebaseAuthWrapperFactory; -import com.firebase.ui.auth.util.FirebaseAuthWrapperImpl; import org.junit.runners.model.InitializationError; import org.robolectric.RobolectricTestRunner; @@ -36,10 +34,8 @@ public CustomRobolectricGradleTestRunner(Class klass) throws InitializationEr public InstrumentationConfiguration createClassLoaderConfig(Config config) { InstrumentationConfiguration.Builder builder = InstrumentationConfiguration.newBuilder(); - builder.addInstrumentedClass(FirebaseAuthWrapperFactory.class.getName()); builder.addInstrumentedClass(BaseHelper.class.getName()); builder.addInstrumentedClass(ActivityHelper.class.getName()); - builder.addInstrumentedClass(FirebaseAuthWrapperImpl.class.getName()); builder.addInstrumentedClass(FacebookProvider.class.getName()); builder.addInstrumentedClass(GoogleProvider.class.getName()); builder.addInstrumentedClass(LoginManager.class.getName()); diff --git a/auth/src/test/java/com/firebase/ui/auth/testhelpers/FirebaseAuthWrapperImplShadow.java b/auth/src/test/java/com/firebase/ui/auth/testhelpers/FirebaseAuthWrapperImplShadow.java deleted file mode 100644 index ed7f94e13..000000000 --- a/auth/src/test/java/com/firebase/ui/auth/testhelpers/FirebaseAuthWrapperImplShadow.java +++ /dev/null @@ -1,39 +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.testhelpers; - -import android.app.PendingIntent; -import android.content.Context; -import android.support.v4.app.FragmentActivity; - -import com.firebase.ui.auth.util.FirebaseAuthWrapperImpl; - -import org.robolectric.annotation.Implementation; -import org.robolectric.annotation.Implements; - -@Implements(FirebaseAuthWrapperImpl.class) -public class FirebaseAuthWrapperImplShadow { - - @Implementation - public boolean isPlayServicesAvailable(Context context) { - return true; - } - - @Implementation - public PendingIntent getEmailHintIntent(FragmentActivity fragmentActivity) { - return null; - } - -} diff --git a/auth/src/test/java/com/firebase/ui/auth/testhelpers/TestHelper.java b/auth/src/test/java/com/firebase/ui/auth/testhelpers/TestHelper.java index 4db59f374..4d3383999 100644 --- a/auth/src/test/java/com/firebase/ui/auth/testhelpers/TestHelper.java +++ b/auth/src/test/java/com/firebase/ui/auth/testhelpers/TestHelper.java @@ -20,8 +20,6 @@ import com.firebase.ui.auth.AuthUI.IdpConfig; import com.firebase.ui.auth.IdpResponse; import com.firebase.ui.auth.ui.FlowParameters; -import com.google.android.gms.common.ConnectionResult; -import com.google.android.gms.common.GoogleApiAvailability; import com.google.firebase.FirebaseApp; import com.google.firebase.FirebaseOptions; import com.google.firebase.auth.FirebaseUser; @@ -33,7 +31,6 @@ import static junit.framework.Assert.assertEquals; import static junit.framework.Assert.assertNull; -import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -79,14 +76,6 @@ public static FirebaseUser makeMockFirebaseUser() { return mockFirebaseUser; } - public static GoogleApiAvailability makeMockGoogleApiAvailability() { - GoogleApiAvailability availability = mock(GoogleApiAvailability.class); - when(availability.isGooglePlayServicesAvailable(any(Context.class))) - .thenReturn(ConnectionResult.SUCCESS); - - return availability; - } - public static void verifySmartLockSave(String providerId, String email, String password) { ArgumentCaptor userArgumentCaptor = ArgumentCaptor.forClass(FirebaseUser.class); diff --git a/auth/src/test/java/com/firebase/ui/auth/ui/email/RegisterEmailActivityTest.java b/auth/src/test/java/com/firebase/ui/auth/ui/email/RegisterEmailActivityTest.java index 06ce18dda..4f6d3e623 100644 --- a/auth/src/test/java/com/firebase/ui/auth/ui/email/RegisterEmailActivityTest.java +++ b/auth/src/test/java/com/firebase/ui/auth/ui/email/RegisterEmailActivityTest.java @@ -15,6 +15,7 @@ package com.firebase.ui.auth.ui.email; import android.content.Intent; +import android.os.Bundle; import android.support.design.widget.TextInputLayout; import android.widget.Button; import android.widget.EditText; @@ -27,11 +28,9 @@ import com.firebase.ui.auth.testhelpers.BaseHelperShadow; import com.firebase.ui.auth.testhelpers.CustomRobolectricGradleTestRunner; import com.firebase.ui.auth.testhelpers.FakeAuthResult; -import com.firebase.ui.auth.testhelpers.FirebaseAuthWrapperImplShadow; import com.firebase.ui.auth.testhelpers.TestConstants; import com.firebase.ui.auth.testhelpers.TestHelper; import com.firebase.ui.auth.ui.User; -import com.firebase.ui.auth.util.PlayServicesHelper; import com.google.firebase.auth.AuthResult; import com.google.firebase.auth.EmailAuthProvider; import com.google.firebase.auth.FirebaseUser; @@ -62,7 +61,7 @@ private RegisterEmailActivity createActivity() { TestHelper.getFlowParameters(Collections.singletonList(AuthUI.EMAIL_PROVIDER))); return Robolectric.buildActivity(RegisterEmailActivity.class) .withIntent(startIntent) - .create() + .create(new Bundle()) .start() .visible() .get(); @@ -71,13 +70,9 @@ private RegisterEmailActivity createActivity() { @Before public void setUp() { TestHelper.initializeApp(RuntimeEnvironment.application); - PlayServicesHelper.sApiAvailability = TestHelper.makeMockGoogleApiAvailability(); } @Test - @Config(shadows = { - FirebaseAuthWrapperImplShadow.class - }) public void testSignUpButton_validatesFields() { RegisterEmailActivity registerEmailActivity = createActivity(); @@ -109,8 +104,7 @@ public void testSignUpButton_validatesFields() { @Test @Config(shadows = { BaseHelperShadow.class, - ActivityHelperShadow.class, - FirebaseAuthWrapperImplShadow.class + ActivityHelperShadow.class }) public void testSignUpButton_successfulRegistrationShouldContinueToSaveCredentials() { // init mocks diff --git a/auth/src/test/java/com/firebase/ui/auth/ui/email/WelcomeBackPasswordPromptTest.java b/auth/src/test/java/com/firebase/ui/auth/ui/email/WelcomeBackPasswordPromptTest.java index cf5f51aee..78d26fac1 100644 --- a/auth/src/test/java/com/firebase/ui/auth/ui/email/WelcomeBackPasswordPromptTest.java +++ b/auth/src/test/java/com/firebase/ui/auth/ui/email/WelcomeBackPasswordPromptTest.java @@ -27,11 +27,9 @@ import com.firebase.ui.auth.testhelpers.BaseHelperShadow; import com.firebase.ui.auth.testhelpers.CustomRobolectricGradleTestRunner; import com.firebase.ui.auth.testhelpers.FakeAuthResult; -import com.firebase.ui.auth.testhelpers.FirebaseAuthWrapperImplShadow; import com.firebase.ui.auth.testhelpers.TestConstants; import com.firebase.ui.auth.testhelpers.TestHelper; import com.firebase.ui.auth.ui.accountlink.WelcomeBackPasswordPrompt; -import com.firebase.ui.auth.util.PlayServicesHelper; import com.google.firebase.auth.AuthResult; import com.google.firebase.auth.EmailAuthProvider; import com.google.firebase.auth.FirebaseUser; @@ -61,7 +59,6 @@ public class WelcomeBackPasswordPromptTest { @Before public void setUp() { TestHelper.initializeApp(RuntimeEnvironment.application); - PlayServicesHelper.sApiAvailability = TestHelper.makeMockGoogleApiAvailability(); } private WelcomeBackPasswordPrompt createActivity() { @@ -96,7 +93,7 @@ public void testSignInButton_validatesFields() { } @Test - @Config(shadows = {BaseHelperShadow.class, ActivityHelperShadow.class, FirebaseAuthWrapperImplShadow.class}) + @Config(shadows = {BaseHelperShadow.class, ActivityHelperShadow.class}) public void testSignInButton_signsInAndSavesCredentials() { // initialize mocks new ActivityHelperShadow(); diff --git a/auth/src/test/java/com/firebase/ui/auth/ui/idp/AuthMethodPickerActivityTest.java b/auth/src/test/java/com/firebase/ui/auth/ui/idp/AuthMethodPickerActivityTest.java index 67efcd14f..053ddd0d3 100644 --- a/auth/src/test/java/com/firebase/ui/auth/ui/idp/AuthMethodPickerActivityTest.java +++ b/auth/src/test/java/com/firebase/ui/auth/ui/idp/AuthMethodPickerActivityTest.java @@ -28,13 +28,11 @@ import com.firebase.ui.auth.testhelpers.CustomRobolectricGradleTestRunner; import com.firebase.ui.auth.testhelpers.FacebookProviderShadow; import com.firebase.ui.auth.testhelpers.FakeAuthResult; -import com.firebase.ui.auth.testhelpers.FirebaseAuthWrapperImplShadow; import com.firebase.ui.auth.testhelpers.GoogleProviderShadow; import com.firebase.ui.auth.testhelpers.LoginManagerShadow; import com.firebase.ui.auth.testhelpers.TestConstants; import com.firebase.ui.auth.testhelpers.TestHelper; import com.firebase.ui.auth.ui.email.RegisterEmailActivity; -import com.firebase.ui.auth.util.PlayServicesHelper; import com.google.firebase.auth.AuthCredential; import com.google.firebase.auth.AuthResult; import com.google.firebase.auth.FacebookAuthProvider; @@ -42,7 +40,6 @@ import com.google.firebase.auth.GoogleAuthProvider; import com.google.firebase.auth.TwitterAuthProvider; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.Robolectric; @@ -65,18 +62,11 @@ @RunWith(CustomRobolectricGradleTestRunner.class) @Config(constants = BuildConfig.class, shadows = { - FirebaseAuthWrapperImplShadow.class, GoogleProviderShadow.class, FacebookProviderShadow.class, LoginManagerShadow.class }, sdk = 23) public class AuthMethodPickerActivityTest { - - @Before - public void setUp() { - PlayServicesHelper.sApiAvailability = TestHelper.makeMockGoogleApiAvailability(); - } - @Test public void testAllProvidersArePopulated() { List providers = Arrays.asList( diff --git a/auth/src/test/java/com/firebase/ui/auth/ui/idp/CredentialSignInHandlerTest.java b/auth/src/test/java/com/firebase/ui/auth/ui/idp/CredentialSignInHandlerTest.java index ccbfdaa73..c96e7d288 100644 --- a/auth/src/test/java/com/firebase/ui/auth/ui/idp/CredentialSignInHandlerTest.java +++ b/auth/src/test/java/com/firebase/ui/auth/ui/idp/CredentialSignInHandlerTest.java @@ -32,7 +32,6 @@ import com.firebase.ui.auth.ui.User; import com.firebase.ui.auth.ui.accountlink.WelcomeBackIdpPrompt; import com.firebase.ui.auth.ui.accountlink.WelcomeBackPasswordPrompt; -import com.firebase.ui.auth.util.PlayServicesHelper; import com.firebase.ui.auth.util.signincontainer.SaveSmartLock; import com.google.android.gms.tasks.Task; import com.google.android.gms.tasks.Tasks; @@ -71,7 +70,6 @@ public class CredentialSignInHandlerTest { public void setUp() { MockitoAnnotations.initMocks(this); TestHelper.initializeApp(RuntimeEnvironment.application); - PlayServicesHelper.sApiAvailability = TestHelper.makeMockGoogleApiAvailability(); } @Test diff --git a/auth/src/test/java/com/firebase/ui/auth/util/HeadlessAPIWrapperImplTest.java b/auth/src/test/java/com/firebase/ui/auth/util/HeadlessAPIWrapperImplTest.java deleted file mode 100644 index 939bdc928..000000000 --- a/auth/src/test/java/com/firebase/ui/auth/util/HeadlessAPIWrapperImplTest.java +++ /dev/null @@ -1,93 +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.util; - -import com.firebase.ui.auth.BuildConfig; -import com.firebase.ui.auth.testhelpers.CustomRobolectricGradleTestRunner; -import com.firebase.ui.auth.testhelpers.TestHelper; -import com.google.android.gms.common.ConnectionResult; -import com.google.android.gms.common.GoogleApiAvailability; -import com.google.firebase.auth.FirebaseAuth; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.robolectric.RuntimeEnvironment; -import org.robolectric.annotation.Config; - -import static junit.framework.Assert.assertFalse; -import static junit.framework.Assert.assertTrue; -import static org.mockito.Mockito.when; - -@RunWith(CustomRobolectricGradleTestRunner.class) -@Config(constants = BuildConfig.class, sdk = 23) -public class HeadlessAPIWrapperImplTest { - - private FirebaseAuthWrapperImpl mHeadlessAPIWrapperImpl; - - @Mock - private FirebaseAuth mMockFirebaseAuth; - - @Mock - private GoogleApiAvailability mMockGoogleApiAvailability; - - @Before - public void setUp() { - MockitoAnnotations.initMocks(this); - mHeadlessAPIWrapperImpl = new FirebaseAuthWrapperImpl(mMockFirebaseAuth); - PlayServicesHelper.sApiAvailability = TestHelper.makeMockGoogleApiAvailability(); - } - - @Test - public void testIsPlayServicesAvailable() { - when(PlayServicesHelper.sApiAvailability.isGooglePlayServicesAvailable( - RuntimeEnvironment.application)) - .thenReturn(ConnectionResult.SERVICE_UPDATING); - assertFalse(mHeadlessAPIWrapperImpl.isPlayServicesAvailable( - RuntimeEnvironment.application)); - - when(PlayServicesHelper.sApiAvailability.isGooglePlayServicesAvailable( - RuntimeEnvironment.application)) - .thenReturn(ConnectionResult.SERVICE_MISSING); - assertFalse(mHeadlessAPIWrapperImpl.isPlayServicesAvailable( - RuntimeEnvironment.application)); - - when(PlayServicesHelper.sApiAvailability.isGooglePlayServicesAvailable( - RuntimeEnvironment.application)) - .thenReturn(ConnectionResult.SERVICE_DISABLED); - assertFalse(mHeadlessAPIWrapperImpl.isPlayServicesAvailable( - RuntimeEnvironment.application)); - - when(PlayServicesHelper.sApiAvailability.isGooglePlayServicesAvailable( - RuntimeEnvironment.application)) - .thenReturn(ConnectionResult.SERVICE_INVALID); - assertFalse(mHeadlessAPIWrapperImpl.isPlayServicesAvailable( - RuntimeEnvironment.application)); - - when(PlayServicesHelper.sApiAvailability.isGooglePlayServicesAvailable( - RuntimeEnvironment.application)) - .thenReturn(ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED); - assertFalse(mHeadlessAPIWrapperImpl.isPlayServicesAvailable( - RuntimeEnvironment.application)); - - when(PlayServicesHelper.sApiAvailability.isGooglePlayServicesAvailable( - RuntimeEnvironment.application)) - .thenReturn(ConnectionResult.SUCCESS); - assertTrue(mHeadlessAPIWrapperImpl.isPlayServicesAvailable( - RuntimeEnvironment.application)); - } -} diff --git a/library/quality/findbugs-filter.xml b/library/quality/findbugs-filter.xml index 19babcf9a..3accc8353 100644 --- a/library/quality/findbugs-filter.xml +++ b/library/quality/findbugs-filter.xml @@ -1,8 +1,3 @@ - - - - - \ No newline at end of file