Skip to content

Add custom tabs options to the available Lock settings [SDK-1974] #601

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

Merged
merged 2 commits into from
Nov 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ dependencies {
implementation 'com.google.code.gson:gson:2.8.6'
implementation 'com.squareup.okhttp:okhttp:2.7.5'
implementation 'com.squareup:otto:1.3.8'
api 'com.auth0.android:auth0:1.26.1'
api 'com.auth0.android:auth0:1.29.0'
testImplementation 'junit:junit:4.12'
testImplementation 'org.hamcrest:hamcrest-library:1.3'
testImplementation 'org.robolectric:robolectric:4.0.2'
Expand Down
13 changes: 13 additions & 0 deletions lib/src/main/java/com/auth0/android/lock/Lock.java
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
import com.auth0.android.lock.utils.LockException;
import com.auth0.android.lock.utils.SignUpField;
import com.auth0.android.provider.AuthHandler;
import com.auth0.android.provider.CustomTabsOptions;
import com.auth0.android.util.Telemetry;

import java.util.ArrayList;
Expand Down Expand Up @@ -559,6 +560,18 @@ public Builder withAudience(@NonNull String audience) {
return this;
}

/**
* Specify style and other additional configuration for when the Web Auth flow is used with Custom Tabs.
*
* @param customTabsOptions to use in the Web Auth flow.
* @return the current builder instance
*/
@NonNull
public Builder withCustomTabsOptions(@NonNull CustomTabsOptions customTabsOptions) {
options.withCustomTabsOptions(customTabsOptions);
return this;
}

/**
* Specify a custom Scheme for the redirect url used to send the Web Auth results. Default redirect url scheme is 'https'.
*
Expand Down
13 changes: 13 additions & 0 deletions lib/src/main/java/com/auth0/android/lock/PasswordlessLock.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import com.auth0.android.lock.provider.AuthResolver;
import com.auth0.android.lock.utils.LockException;
import com.auth0.android.provider.AuthHandler;
import com.auth0.android.provider.CustomTabsOptions;
import com.auth0.android.util.Telemetry;

import java.util.Arrays;
Expand Down Expand Up @@ -425,6 +426,18 @@ public Builder withScheme(@NonNull String scheme) {
return this;
}

/**
* Specify style and other additional configuration for when the Web Auth flow is used with Custom Tabs.
*
* @param customTabsOptions to use in the Web Auth flow.
* @return the current builder instance
*/
@NonNull
public Builder withCustomTabsOptions(@NonNull CustomTabsOptions customTabsOptions) {
options.withCustomTabsOptions(customTabsOptions);
return this;
}

/**
* Sets the url of your support page for your application that will be used when an error occurs and Lock is unable to handle it. In this case it will show an error screen and if there is a support url will also show a button to open that page in the browser.
*
Expand Down
5 changes: 5 additions & 0 deletions lib/src/main/java/com/auth0/android/lock/WebProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import com.auth0.android.lock.internal.configuration.Options;
import com.auth0.android.provider.AuthCallback;
import com.auth0.android.provider.CustomTabsOptions;
import com.auth0.android.provider.WebAuthProvider;

import java.util.HashMap;
Expand Down Expand Up @@ -69,6 +70,10 @@ public void start(@NonNull Activity activity, @NonNull String connection, @Nulla
if (scheme != null) {
builder.withScheme(scheme);
}
final CustomTabsOptions customTabsOptions = options.getCustomTabsOptions();
if (customTabsOptions != null) {
builder.withCustomTabsOptions(customTabsOptions);
}
//noinspection deprecation
builder.start(activity, callback, requestCode);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
import com.auth0.android.lock.InitialScreen;
import com.auth0.android.lock.UsernameStyle;
import com.auth0.android.lock.utils.SignUpField;
import com.auth0.android.provider.CustomTabsOptions;

import java.util.ArrayList;
import java.util.HashMap;
Expand Down Expand Up @@ -88,6 +89,7 @@ public class Options implements Parcelable {
private int initialScreen;
private int visibleSignUpFieldsthreshold;
private Theme theme;
private CustomTabsOptions customTabsOptions;
private String privacyURL;
private String termsURL;
private String supportURL;
Expand Down Expand Up @@ -139,6 +141,7 @@ protected Options(@NonNull Parcel in) {
initialScreen = in.readInt();
visibleSignUpFieldsthreshold = in.readInt();
theme = in.readParcelable(Theme.class.getClassLoader());
customTabsOptions = in.readParcelable(CustomTabsOptions.class.getClassLoader());
privacyURL = in.readString();
termsURL = in.readString();
supportURL = in.readString();
Expand Down Expand Up @@ -220,6 +223,7 @@ public void writeToParcel(@NonNull Parcel dest, int flags) {
dest.writeInt(initialScreen);
dest.writeInt(visibleSignUpFieldsthreshold);
dest.writeParcelable(theme, flags);
dest.writeParcelable(customTabsOptions, flags);
dest.writeString(privacyURL);
dest.writeString(termsURL);
dest.writeString(supportURL);
Expand Down Expand Up @@ -580,4 +584,13 @@ public void setVisibleSignUpFieldsThreshold(int threshold) {
public int visibleSignUpFieldsThreshold() {
return visibleSignUpFieldsthreshold;
}

public void withCustomTabsOptions(@NonNull CustomTabsOptions customTabsOptions) {
this.customTabsOptions = customTabsOptions;
}

@Nullable
public CustomTabsOptions getCustomTabsOptions() {
return customTabsOptions;
}
}
52 changes: 36 additions & 16 deletions lib/src/test/java/com/auth0/android/lock/WebProviderTest.java
Original file line number Diff line number Diff line change
@@ -1,18 +1,21 @@
package com.auth0.android.lock;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import com.auth0.android.Auth0;
import com.auth0.android.authentication.AuthenticationException;
import com.auth0.android.lock.internal.configuration.Options;
import com.auth0.android.provider.AuthCallback;
import com.auth0.android.provider.AuthenticationActivity;
import com.auth0.android.provider.CustomTabsOptions;

import org.junit.Before;
import org.junit.Rule;
Expand All @@ -24,7 +27,10 @@
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent;
Expand All @@ -33,9 +39,11 @@
import static android.support.test.espresso.intent.matcher.UriMatchers.hasScheme;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.notNullValue;
import static org.hamcrest.Matchers.isOneOf;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.intThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
Expand All @@ -58,7 +66,7 @@ public void setUp() {
.start()
.resume()
.get());
prepareBrowserApp(true);
setupBrowserContext(activity, Collections.singletonList("com.auth0.browser"));
}

@Test
Expand All @@ -74,7 +82,7 @@ public void shouldStart() {

@Test
public void shouldFailWhenBrowserAppIsMissing() {
prepareBrowserApp(false);
setupBrowserContext(activity, Collections.<String>emptyList());

Options options = new Options();
options.setAccount(new Auth0("clientId", "domain.auth0.com"));
Expand Down Expand Up @@ -168,6 +176,8 @@ public void shouldStartBrowserWithOptions() {
options.withConnectionScope("my-connection", "the connection scope");
options.setUseBrowser(true);
options.withScheme("auth0");
CustomTabsOptions customTabsOptions = CustomTabsOptions.newBuilder().build();
options.withCustomTabsOptions(customTabsOptions);

AuthCallback callback = mock(AuthCallback.class);
WebProvider webProvider = new WebProvider(options);
Expand All @@ -194,6 +204,7 @@ public void shouldStartBrowserWithOptions() {
assertThat(authorizeUri, hasParamWithValue("scope", "email profile photos"));
assertThat(authorizeUri, hasParamWithValue("connection_scope", "the connection scope"));
assertThat(intent.hasExtra("com.auth0.android.EXTRA_USE_BROWSER"), is(true));
assertThat(intent.getParcelableExtra("com.auth0.android.EXTRA_CT_OPTIONS"), is(notNullValue()));
assertThat(intent.getBooleanExtra("com.auth0.android.EXTRA_USE_BROWSER", false), is(true));
assertThat(intent, hasComponent(AuthenticationActivity.class.getName()));
}
Expand Down Expand Up @@ -258,21 +269,30 @@ public void shouldResumeWithCodesAndIntent() {
assertThat(webProvider.resume(1, Activity.RESULT_CANCELED, intent), is(false));
}


private void prepareBrowserApp(boolean isAppInstalled) {
/**
* Sets up a given context for using browsers.
* If the list passed is empty, then no browser packages would be available.
*/
static void setupBrowserContext(@NonNull Context context, @NonNull List<String> browserPackages) {
PackageManager pm = mock(PackageManager.class);
ResolveInfo info = null;
if (isAppInstalled) {
info = mock(ResolveInfo.class);
ApplicationInfo appInfo = mock(ApplicationInfo.class);
appInfo.packageName = "com.auth0.test";
ActivityInfo actInfo = mock(ActivityInfo.class);
actInfo.applicationInfo = appInfo;
actInfo.name = "Auth0 Browser";
info.activityInfo = actInfo;
when(context.getPackageManager()).thenReturn(pm);

List<ResolveInfo> allBrowsers = new ArrayList<>();
for (String browser : browserPackages) {
ResolveInfo info = resolveInfoForPackageName(browser);
allBrowsers.add(info);
}
when(pm.queryIntentActivities(any(Intent.class), intThat(isOneOf(0, PackageManager.MATCH_ALL)))).thenReturn(allBrowsers);
}

private static ResolveInfo resolveInfoForPackageName(@Nullable String packageName) {
if (packageName == null) {
return null;
}
when(pm.resolveActivity(any(Intent.class), eq(PackageManager.MATCH_DEFAULT_ONLY))).thenReturn(info);
when(activity.getPackageManager()).thenReturn(pm);
ResolveInfo resInfo = mock(ResolveInfo.class);
resInfo.activityInfo = new ActivityInfo();
resInfo.activityInfo.packageName = packageName;
return resInfo;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.auth0.android.lock.utils.CustomField;
import com.auth0.android.lock.utils.CustomField.FieldType;
import com.auth0.android.lock.utils.SignUpField;
import com.auth0.android.provider.CustomTabsOptions;

import org.junit.Before;
import org.junit.Rule;
Expand Down Expand Up @@ -605,6 +606,20 @@ public void shouldSetScheme() {
assertThat(parceledOptions.getScheme(), is("auth0"));
}

@Test
public void shouldSetCustomTabsOptions() {
CustomTabsOptions ctOptions = CustomTabsOptions.newBuilder().build();
options.withCustomTabsOptions(ctOptions);

Parcel parcel = Parcel.obtain();
options.writeToParcel(parcel, 0);
parcel.setDataPosition(0);

Options parceledOptions = Options.CREATOR.createFromParcel(parcel);
assertThat(options.getCustomTabsOptions(), is(equalTo(ctOptions)));
assertThat(parceledOptions.getCustomTabsOptions(), is(notNullValue()));
}

@SuppressWarnings("ResourceType")
@Test
public void shouldAddAuthStyles() {
Expand Down Expand Up @@ -716,6 +731,7 @@ public void shouldSetDefaultValues() {
assertThat(options.getScope(), is(nullValue()));
assertThat(options.getAudience(), is(nullValue()));
assertThat(options.getScheme(), is(nullValue()));
assertThat(options.getCustomTabsOptions(), is(nullValue()));
assertThat(options.usernameStyle(), is(equalTo(UsernameStyle.DEFAULT)));
assertThat(options.visibleSignUpFieldsThreshold(), is(equalTo(2)));
assertThat(options.getTheme(), is(notNullValue()));
Expand Down