Skip to content

Commit

Permalink
Refactor IntentFactory to CustomTabsIntentFactory
Browse files Browse the repository at this point in the history
This commit refactors the `IntentFactory` class to `CustomTabsIntentFactory`.
This change better reflects the class's purpose of creating Custom Tabs intents.
  • Loading branch information
droibit committed Jul 27, 2024
1 parent 4be9ae0 commit 04aea5c
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 151 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
import androidx.browser.customtabs.CustomTabsIntent;
import androidx.core.content.ContextCompat;

import com.github.droibit.flutter.plugins.customtabs.core.IntentFactory;
import com.github.droibit.flutter.plugins.customtabs.Messages.FlutterError;
import com.github.droibit.flutter.plugins.customtabs.core.CustomTabsIntentFactory;
import com.github.droibit.flutter.plugins.customtabs.core.ExternalBrowserLauncher;
import com.github.droibit.flutter.plugins.customtabs.core.NativeAppLauncher;
import com.github.droibit.flutter.plugins.customtabs.core.PartialCustomTabsLauncher;
Expand All @@ -34,15 +35,15 @@ public class CustomTabsLauncher implements Messages.CustomTabsApi {
@VisibleForTesting
static final String CODE_LAUNCH_ERROR = "LAUNCH_ERROR";

private final @NonNull IntentFactory intentFactory;
private final @NonNull CustomTabsIntentFactory customTabsIntentFactory;
private final @NonNull NativeAppLauncher nativeAppLauncher;
private final @NonNull ExternalBrowserLauncher externalBrowserLauncher;
private final @NonNull PartialCustomTabsLauncher partialCustomTabsLauncher;
private @Nullable Activity activity;

CustomTabsLauncher() {
this(
new IntentFactory(),
new CustomTabsIntentFactory(),
new NativeAppLauncher(),
new ExternalBrowserLauncher(),
new PartialCustomTabsLauncher()
Expand All @@ -51,12 +52,12 @@ public class CustomTabsLauncher implements Messages.CustomTabsApi {

@VisibleForTesting
CustomTabsLauncher(
@NonNull IntentFactory intentFactory,
@NonNull CustomTabsIntentFactory customTabsIntentFactory,
@NonNull NativeAppLauncher nativeAppLauncher,
@NonNull ExternalBrowserLauncher externalBrowserLauncher,
@NonNull PartialCustomTabsLauncher partialCustomTabsLauncher
) {
this.intentFactory = intentFactory;
this.customTabsIntentFactory = customTabsIntentFactory;
this.nativeAppLauncher = nativeAppLauncher;
this.externalBrowserLauncher = externalBrowserLauncher;
this.partialCustomTabsLauncher = partialCustomTabsLauncher;
Expand All @@ -74,7 +75,7 @@ public void launch(
) {
final Activity activity = this.activity;
if (activity == null) {
throw new Messages.FlutterError(CODE_LAUNCH_ERROR, "Launching a custom tab requires a foreground activity.", null);
throw new FlutterError(CODE_LAUNCH_ERROR, "Launching a custom tab requires a foreground activity.", null);
}

final Uri uri = Uri.parse(urlString);
Expand All @@ -89,14 +90,14 @@ public void launch(
return;
}

final CustomTabsIntent customTabsIntent = intentFactory
.createCustomTabsIntent(activity, requireNonNull(customTabsOptions));
final CustomTabsIntent customTabsIntent = customTabsIntentFactory
.createIntent(activity, requireNonNull(customTabsOptions));
if (partialCustomTabsLauncher.launch(activity, uri, customTabsIntent)) {
return;
}
customTabsIntent.launchUrl(activity, uri);
} catch (ActivityNotFoundException e) {
throw new Messages.FlutterError(CODE_LAUNCH_ERROR, e.getMessage(), null);
throw new FlutterError(CODE_LAUNCH_ERROR, e.getMessage(), null);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import static com.github.droibit.flutter.plugins.customtabs.core.ResourceFactory.INVALID_RESOURCE_ID;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.provider.Browser;
Expand All @@ -30,38 +29,19 @@
import java.util.List;
import java.util.Map;

public class IntentFactory {
public class CustomTabsIntentFactory {
private final @NonNull ResourceFactory resources;

public IntentFactory() {
public CustomTabsIntentFactory() {
this(new ResourceFactory());
}

@VisibleForTesting
IntentFactory(@NonNull ResourceFactory resources) {
CustomTabsIntentFactory(@NonNull ResourceFactory resources) {
this.resources = resources;
}

public @Nullable Intent createExternalBrowserIntent(@Nullable CustomTabsIntentOptions options) {
final Intent intent = new Intent(Intent.ACTION_VIEW);
if (options == null) {
return intent;
}

final BrowserConfiguration browserOptions = options.getBrowser();
if (browserOptions == null || !browserOptions.getPrefersExternalBrowser()) {
return null;
}

final Map<String, String> headers = browserOptions.getHeaders();
if (headers != null) {
final Bundle bundleHeaders = extractBundle(headers);
intent.putExtra(Browser.EXTRA_HEADERS, bundleHeaders);
}
return intent;
}

public @NonNull CustomTabsIntent createCustomTabsIntent(
public @NonNull CustomTabsIntent createIntent(
@NonNull Context context,
@NonNull CustomTabsIntentOptions options
) {
Expand Down Expand Up @@ -256,7 +236,7 @@ void applyBrowserConfiguration(
return dest;
}

public @Nullable CustomTabsIntentOptions createCustomTabsIntentOptions(@Nullable Map<String, Object> options) {
public @Nullable CustomTabsIntentOptions createIntentOptions(@Nullable Map<String, Object> options) {
if (options == null) {
return null;
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.github.droibit.flutter.plugins.customtabs;

import static androidx.test.ext.truth.content.IntentSubject.assertThat;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
Expand All @@ -15,14 +15,14 @@

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;

import androidx.browser.customtabs.CustomTabsIntent;
import androidx.test.ext.junit.runners.AndroidJUnit4;

import com.github.droibit.flutter.plugins.customtabs.Messages.FlutterError;
import com.github.droibit.flutter.plugins.customtabs.core.IntentFactory;
import com.github.droibit.flutter.plugins.customtabs.core.CustomTabsIntentFactory;
import com.github.droibit.flutter.plugins.customtabs.core.ExternalBrowserLauncher;
import com.github.droibit.flutter.plugins.customtabs.core.NativeAppLauncher;
import com.github.droibit.flutter.plugins.customtabs.core.PartialCustomTabsLauncher;
import com.github.droibit.flutter.plugins.customtabs.core.options.CustomTabsIntentOptions;
Expand All @@ -47,7 +47,7 @@ public class CustomTabsLauncherTest {
public MockitoRule mockitoRule = MockitoJUnit.rule();

@Mock
private IntentFactory intentFactory;
private CustomTabsIntentFactory customTabsIntentFactory;

@Mock
private NativeAppLauncher nativeAppLauncher;
Expand Down Expand Up @@ -94,24 +94,24 @@ public void launchNativeAppSuccess() {
fail(e.getMessage());
}

verify(intentFactory, never()).createExternalBrowserIntent(any());
verify(intentFactory, never()).createCustomTabsIntent(any(), any());
verify(externalBrowserLauncher, never()).launch(any(), any(), any());
verify(customTabsIntentFactory, never()).createIntent(any(), any());
}

@Test
public void launchExternalBrowserSuccess() {
final Activity activity = mock(Activity.class);
launcher.setActivity(activity);

when(intentFactory.createCustomTabsIntentOptions(any())).thenReturn(null);
when(customTabsIntentFactory.createIntentOptions(any())).thenReturn(null);
when(externalBrowserLauncher.launch(any(), any(), any())).thenReturn(true);

try {
final Uri expUrl = Uri.parse("https://example.com");
launcher.launch(expUrl.toString(), false, null);

verify(intentFactory, never()).createCustomTabsIntent(any(), any());
verify(externalBrowserLauncher).launch(any(), eq(expUrl), isNull());
verify(customTabsIntentFactory, never()).createIntent(any(), any());
} catch (Exception e) {
fail(e.getMessage());
}
Expand All @@ -122,7 +122,6 @@ public void launchExternalBrowserFailure() {
final Activity activity = mock(Activity.class);
launcher.setActivity(activity);

when(intentFactory.createCustomTabsIntentOptions(any())).thenReturn(null);
when(customTabsIntentFactory.createIntentOptions(any())).thenReturn(null);

final ActivityNotFoundException anf = mock(ActivityNotFoundException.class);
Expand All @@ -139,34 +138,33 @@ public void launchExternalBrowserFailure() {
assertThat(actualError.code).isEqualTo(CustomTabsLauncher.CODE_LAUNCH_ERROR);
}

verify(intentFactory, never()).createCustomTabsIntent(any(), any());
verify(externalBrowserLauncher).launch(any(), eq(uri), isNull());
verify(customTabsIntentFactory, never()).createIntent(any(), any());
}


@Test
public void launchPartialCustomTabsSuccess() {
final Activity activity = mock(Activity.class);
launcher.setActivity(activity);

final CustomTabsIntentOptions intentOptions = mock(CustomTabsIntentOptions.class);
when(intentFactory.createCustomTabsIntentOptions(any())).thenReturn(intentOptions);
when(customTabsIntentFactory.createIntentOptions(any())).thenReturn(intentOptions);
when(externalBrowserLauncher.launch(any(), any(), any())).thenReturn(false);

final CustomTabsIntent customTabsIntent = spy(
new CustomTabsIntent.Builder()
.setInitialActivityHeightPx(100)
.build()
);
when(intentFactory.createCustomTabsIntent(any(), any())).thenReturn(customTabsIntent);
when(customTabsIntentFactory.createIntent(any(), any())).thenReturn(customTabsIntent);
when(partialCustomTabsLauncher.launch(any(), any(), any())).thenReturn(true);

try {
final String expUrl = "https://example.com";
final Map<String, Object> options = Collections.emptyMap();
launcher.launch(expUrl, false, options);

verify(intentFactory).createCustomTabsIntent(any(), same(intentOptions));
verify(customTabsIntentFactory).createIntent(any(), same(intentOptions));
verify(partialCustomTabsLauncher).launch(any(), any(), same(customTabsIntent));
verify(customTabsIntent, never()).launchUrl(any(), any());
} catch (Exception e) {
Expand All @@ -180,13 +178,13 @@ public void launchPartialCustomTabsFailure() {
launcher.setActivity(activity);

final CustomTabsIntentOptions intentOptions = mock(CustomTabsIntentOptions.class);
when(intentFactory.createCustomTabsIntentOptions(any())).thenReturn(intentOptions);
when(customTabsIntentFactory.createIntentOptions(any())).thenReturn(intentOptions);
when(externalBrowserLauncher.launch(any(), any(), any())).thenReturn(false);

final CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder()
.setInitialActivityHeightPx(100)
.build();
when(intentFactory.createCustomTabsIntent(any(), any())).thenReturn(customTabsIntent);
when(customTabsIntentFactory.createIntent(any(), any())).thenReturn(customTabsIntent);

final ActivityNotFoundException anf = mock(ActivityNotFoundException.class);
doThrow(anf).when(partialCustomTabsLauncher).launch(any(), any(), any());
Expand All @@ -203,7 +201,7 @@ public void launchPartialCustomTabsFailure() {
assertThat(actualError.code).isEqualTo(CustomTabsLauncher.CODE_LAUNCH_ERROR);
}

verify(intentFactory).createCustomTabsIntent(any(), same(intentOptions));
verify(customTabsIntentFactory).createIntent(any(), same(intentOptions));
verify(partialCustomTabsLauncher).launch(any(), any(), same(customTabsIntent));
}

Expand All @@ -213,11 +211,11 @@ public void launchCustomTabsSuccess() {
launcher.setActivity(activity);

final CustomTabsIntentOptions intentOptions = mock(CustomTabsIntentOptions.class);
when(intentFactory.createCustomTabsIntentOptions(any())).thenReturn(intentOptions);
when(customTabsIntentFactory.createIntentOptions(any())).thenReturn(intentOptions);
when(externalBrowserLauncher.launch(any(), any(), any())).thenReturn(false);

final CustomTabsIntent customTabsIntent = spy(new CustomTabsIntent.Builder().build());
when(intentFactory.createCustomTabsIntent(any(), any())).thenReturn(customTabsIntent);
when(customTabsIntentFactory.createIntent(any(), any())).thenReturn(customTabsIntent);
when(partialCustomTabsLauncher.launch(any(), any(), any())).thenReturn(false);

try {
Expand All @@ -231,7 +229,7 @@ public void launchCustomTabsSuccess() {
final Uri actualUrl = urlCaptor.getValue();
assertThat(actualUrl).isEqualTo(Uri.parse(expUrl));

verify(intentFactory).createCustomTabsIntent(any(), same(intentOptions));
verify(customTabsIntentFactory).createIntent(any(), same(intentOptions));
} catch (Exception e) {
fail(e.getMessage());
}
Expand All @@ -243,11 +241,11 @@ public void launchCustomTabsFailure() {
launcher.setActivity(activity);

final CustomTabsIntentOptions intentOptions = mock(CustomTabsIntentOptions.class);
when(intentFactory.createCustomTabsIntentOptions(any())).thenReturn(intentOptions);
when(customTabsIntentFactory.createIntentOptions(any())).thenReturn(intentOptions);
when(externalBrowserLauncher.launch(any(), any(), any())).thenReturn(false);

final CustomTabsIntent customTabsIntent = spy(new CustomTabsIntent.Builder().build());
when(intentFactory.createCustomTabsIntent(any(), any())).thenReturn(customTabsIntent);
when(customTabsIntentFactory.createIntent(any(), any())).thenReturn(customTabsIntent);

final ActivityNotFoundException anf = mock(ActivityNotFoundException.class);
doThrow(anf).when(customTabsIntent).launchUrl(any(), any());
Expand All @@ -265,6 +263,6 @@ public void launchCustomTabsFailure() {
assertThat(actualError.code).isEqualTo(CustomTabsLauncher.CODE_LAUNCH_ERROR);
}

verify(intentFactory).createCustomTabsIntent(any(), same(intentOptions));
verify(customTabsIntentFactory).createIntent(any(), same(intentOptions));
}
}
Loading

0 comments on commit 04aea5c

Please sign in to comment.