Skip to content

Commit

Permalink
Merge pull request #218 from droibit/feature/refactoring
Browse files Browse the repository at this point in the history
Refactor session management; rename for clarity
  • Loading branch information
droibit authored Nov 23, 2024
2 parents cca602d + 8147b13 commit 28fd0c5
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 63 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,21 +31,19 @@
import com.github.droibit.flutter.plugins.customtabs.core.options.CustomTabsIntentOptions;
import com.github.droibit.flutter.plugins.customtabs.core.options.CustomTabsSessionOptions;
import com.github.droibit.flutter.plugins.customtabs.core.session.CustomTabsSessionController;
import com.github.droibit.flutter.plugins.customtabs.core.session.CustomTabsSessionFactory;
import com.github.droibit.flutter.plugins.customtabs.core.session.CustomTabsSessionManager;

import java.util.List;
import java.util.Map;
import java.util.Objects;

import io.flutter.Log;

@RestrictTo(RestrictTo.Scope.LIBRARY)
public class CustomTabsLauncher implements Messages.CustomTabsApi {
@VisibleForTesting
static final @NonNull String CODE_LAUNCH_ERROR = "LAUNCH_ERROR";

private final @NonNull CustomTabsIntentFactory customTabsIntentFactory;
private final @NonNull CustomTabsSessionFactory customTabsSessionFactory;
private final @NonNull CustomTabsSessionManager customTabsSessionManager;
private final @NonNull NativeAppLauncher nativeAppLauncher;
private final @NonNull ExternalBrowserLauncher externalBrowserLauncher;
private final @NonNull PartialCustomTabsLauncher partialCustomTabsLauncher;
Expand All @@ -54,7 +52,7 @@ public class CustomTabsLauncher implements Messages.CustomTabsApi {
CustomTabsLauncher() {
this(
new CustomTabsIntentFactory(),
new CustomTabsSessionFactory(),
new CustomTabsSessionManager(),
new NativeAppLauncher(),
new ExternalBrowserLauncher(),
new PartialCustomTabsLauncher()
Expand All @@ -64,20 +62,20 @@ public class CustomTabsLauncher implements Messages.CustomTabsApi {
@VisibleForTesting
CustomTabsLauncher(
@NonNull CustomTabsIntentFactory customTabsIntentFactory,
@NonNull CustomTabsSessionFactory customTabsSessionFactory,
@NonNull CustomTabsSessionManager customTabsSessionManager,
@NonNull NativeAppLauncher nativeAppLauncher,
@NonNull ExternalBrowserLauncher externalBrowserLauncher,
@NonNull PartialCustomTabsLauncher partialCustomTabsLauncher
) {
this.customTabsIntentFactory = customTabsIntentFactory;
this.customTabsSessionFactory = customTabsSessionFactory;
this.customTabsSessionManager = customTabsSessionManager;
this.nativeAppLauncher = nativeAppLauncher;
this.externalBrowserLauncher = externalBrowserLauncher;
this.partialCustomTabsLauncher = partialCustomTabsLauncher;
}

void setActivity(@Nullable Activity activity) {
customTabsSessionFactory.handleActivityChange(activity);
customTabsSessionManager.handleActivityChange(activity);
this.activity = activity;
}

Expand Down Expand Up @@ -107,7 +105,7 @@ public void launch(
final CustomTabsIntent customTabsIntent = customTabsIntentFactory.createIntent(
activity,
requireNonNull(customTabsOptions),
customTabsSessionFactory
customTabsSessionManager
);
if (partialCustomTabsLauncher.launch(activity, uri, customTabsIntent)) {
return;
Expand Down Expand Up @@ -178,9 +176,9 @@ public void closeAllIfPossible() {
return null;
}

final CustomTabsSessionOptions sessionOptions = customTabsSessionFactory
final CustomTabsSessionOptions sessionOptions = customTabsSessionManager
.createSessionOptions(options);
final Pair<String, CustomTabsSessionController> session = customTabsSessionFactory
final Pair<String, CustomTabsSessionController> session = customTabsSessionManager
.createSession(activity, sessionOptions);
if (session == null) {
return null;
Expand All @@ -196,7 +194,7 @@ public void closeAllIfPossible() {

@Override
public void mayLaunch(@NonNull List<String> urls, @NonNull String sessionPackageName) {
final CustomTabsSessionController controller = customTabsSessionFactory
final CustomTabsSessionController controller = customTabsSessionManager
.getSessionController(sessionPackageName);
if (controller == null) {
return;
Expand All @@ -206,6 +204,6 @@ public void mayLaunch(@NonNull List<String> urls, @NonNull String sessionPackage

@Override
public void invalidate(@NonNull String sessionPackageName) {
customTabsSessionFactory.invalidateSession(sessionPackageName);
customTabsSessionManager.invalidateSession(sessionPackageName);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import androidx.browser.customtabs.CustomTabColorSchemeParams;
import androidx.browser.customtabs.CustomTabsIntent;
import androidx.browser.customtabs.CustomTabsSession;
import androidx.core.util.Pair;

import com.droibit.android.customtabs.launcher.CustomTabsPackageProvider;
import com.github.droibit.flutter.plugins.customtabs.core.options.BrowserConfiguration;
Expand All @@ -26,8 +25,7 @@
import com.github.droibit.flutter.plugins.customtabs.core.options.CustomTabsColorSchemes;
import com.github.droibit.flutter.plugins.customtabs.core.options.CustomTabsIntentOptions;
import com.github.droibit.flutter.plugins.customtabs.core.options.PartialCustomTabsConfiguration;
import com.github.droibit.flutter.plugins.customtabs.core.session.CustomTabsSessionController;
import com.github.droibit.flutter.plugins.customtabs.core.session.CustomTabsSessionFactory;
import com.github.droibit.flutter.plugins.customtabs.core.session.CustomTabsSessionProvider;

import java.util.Map;

Expand All @@ -46,22 +44,22 @@ public CustomTabsIntentFactory() {
public @NonNull CustomTabsIntent createIntent(
@NonNull Context context,
@NonNull CustomTabsIntentOptions options,
@NonNull CustomTabsSessionFactory customTabsSessionFactory
@NonNull CustomTabsSessionProvider sessionProvider
) {
final BrowserConfiguration browserConfiguration;
if (options.getBrowser() != null) {
browserConfiguration = options.getBrowser();
} else {
browserConfiguration = new BrowserConfiguration();
}
final Pair<String, CustomTabsSession> session = customTabsSessionFactory
final CustomTabsSession session = sessionProvider
.getSession(browserConfiguration.getSessionPackageName());

final CustomTabsIntent.Builder builder;
if (session == null) {
builder = new CustomTabsIntent.Builder();
} else {
builder = new CustomTabsIntent.Builder(session.second);
builder = new CustomTabsIntent.Builder(session);
}

final CustomTabsColorSchemes colorSchemes = options.getColorSchemes();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,19 @@ public class CustomTabsSessionController extends CustomTabsServiceConnection {

private @Nullable Context context;
private @Nullable CustomTabsSession session;
private boolean boundCustomTabsService;
private boolean customTabsServiceBound;

public @Nullable CustomTabsSession getSession() {
return session;
}

@VisibleForTesting
boolean isBoundCustomTabsService() {
return boundCustomTabsService;
boolean isCustomTabsServiceBound() {
return customTabsServiceBound;
}

public boolean bindCustomTabsService(@NonNull Context context, @NonNull String packageName) {
if (boundCustomTabsService) {
if (customTabsServiceBound) {
Log.d(TAG, "Custom Tab(" + packageName + ") already bound.");
return true;
}
Expand All @@ -47,12 +47,12 @@ private boolean tryBindCustomTabsService(@NonNull Context context, @NonNull Stri
try {
final boolean bound = CustomTabsClient.bindCustomTabsService(context, packageName, this);
Log.d(TAG, "Custom Tab(" + packageName + ") bound: " + bound);
boundCustomTabsService = bound;
customTabsServiceBound = bound;
this.context = context;
} catch (SecurityException e) {
boundCustomTabsService = false;
customTabsServiceBound = false;
}
return boundCustomTabsService;
return customTabsServiceBound;
}

public void unbindCustomTabsService() {
Expand All @@ -61,7 +61,7 @@ public void unbindCustomTabsService() {
context.unbindService(this);
}
session = null;
boundCustomTabsService = false;
customTabsServiceBound = false;
Log.d(TAG, "Custom Tab unbound.");
}

Expand All @@ -75,7 +75,7 @@ public void onCustomTabsServiceConnected(@NonNull ComponentName name, @NonNull C
@Override
public void onServiceDisconnected(ComponentName name) {
session = null;
boundCustomTabsService = false;
customTabsServiceBound = false;

final String packageName = name != null ? name.getPackageName() : "unknown";
Log.d(TAG, "Custom Tab(" + packageName + ") disconnected.");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@
import java.util.HashMap;
import java.util.Map;

public class CustomTabsSessionFactory {
public class CustomTabsSessionManager implements CustomTabsSessionProvider {
private static final @NonNull String TAG = "CustomTabsAndroid";

private final @NonNull Map<String, CustomTabsSessionController> cachedSessions;

public CustomTabsSessionFactory() {
public CustomTabsSessionManager() {
this(new HashMap<>());
}

@VisibleForTesting
CustomTabsSessionFactory(@NonNull Map<String, CustomTabsSessionController> cachedSessions) {
CustomTabsSessionManager(@NonNull Map<String, CustomTabsSessionController> cachedSessions) {
this.cachedSessions = cachedSessions;
}

Expand Down Expand Up @@ -64,7 +64,8 @@ public CustomTabsSessionFactory() {
return cachedSessions.get(packageName);
}

public @Nullable Pair<String, CustomTabsSession> getSession(@Nullable String packageName) {
@Override
public @Nullable CustomTabsSession getSession(@Nullable String packageName) {
if (packageName == null) {
return null;
}
Expand All @@ -73,7 +74,7 @@ public CustomTabsSessionFactory() {
if (controller == null) {
return null;
}
return new Pair<>(packageName, controller.getSession());
return controller.getSession();
}

public void invalidateSession(@NonNull String packageName) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.github.droibit.flutter.plugins.customtabs.core.session;

import androidx.annotation.Nullable;
import androidx.browser.customtabs.CustomTabsSession;

public interface CustomTabsSessionProvider {
@Nullable
CustomTabsSession getSession(@Nullable String packageName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
import com.github.droibit.flutter.plugins.customtabs.core.options.CustomTabsIntentOptions;
import com.github.droibit.flutter.plugins.customtabs.core.options.CustomTabsSessionOptions;
import com.github.droibit.flutter.plugins.customtabs.core.session.CustomTabsSessionController;
import com.github.droibit.flutter.plugins.customtabs.core.session.CustomTabsSessionFactory;
import com.github.droibit.flutter.plugins.customtabs.core.session.CustomTabsSessionManager;

import org.junit.Rule;
import org.junit.Test;
Expand Down Expand Up @@ -63,7 +63,7 @@ public class CustomTabsLauncherTest {
private PartialCustomTabsLauncher partialCustomTabsLauncher;

@Mock
private CustomTabsSessionFactory customTabsSessionFactory;
private CustomTabsSessionManager customTabsSessionManager;

@InjectMocks
private CustomTabsLauncher launcher;
Expand Down Expand Up @@ -279,21 +279,21 @@ public void warmup_withSessionOptions_returnsPackageName() {
launcher.setActivity(activity);

final CustomTabsSessionOptions sessionOptions = mock(CustomTabsSessionOptions.class);
when(customTabsSessionFactory.createSessionOptions(any())).thenReturn(sessionOptions);
when(customTabsSessionManager.createSessionOptions(any())).thenReturn(sessionOptions);

final String expectedPackageName = "com.example.browser";
final CustomTabsSessionController controller = mock(CustomTabsSessionController.class);
when(controller.bindCustomTabsService(any(), any()))
.thenReturn(true);

when(customTabsSessionFactory.createSession(any(), any()))
when(customTabsSessionManager.createSession(any(), any()))
.thenReturn(new Pair<>(expectedPackageName, controller));

final Map<String, Object> options = Collections.emptyMap();
final String actualPackageName = launcher.warmup(options);
assertThat(actualPackageName).isEqualTo(expectedPackageName);

verify(customTabsSessionFactory).createSessionOptions(same(options));
verify(customTabsSessionManager).createSessionOptions(same(options));
verify(controller).bindCustomTabsService(any(), eq(expectedPackageName));
}

Expand All @@ -303,16 +303,16 @@ public void warmup_withSessionOptions_returnsNull() {
launcher.setActivity(activity);

final CustomTabsSessionOptions sessionOptions = mock(CustomTabsSessionOptions.class);
when(customTabsSessionFactory.createSessionOptions(any())).thenReturn(sessionOptions);
when(customTabsSessionManager.createSessionOptions(any())).thenReturn(sessionOptions);

when(customTabsSessionFactory.createSession(any(), any()))
when(customTabsSessionManager.createSession(any(), any()))
.thenReturn(null);

final Map<String, Object> options = Collections.emptyMap();
final String actualPackageName = launcher.warmup(options);
assertThat(actualPackageName).isNull();

verify(customTabsSessionFactory).createSessionOptions(same(options));
verify(customTabsSessionManager).createSessionOptions(same(options));
}

@Test
Expand All @@ -321,21 +321,21 @@ public void warmup_withSessionOptions_bindCustomTabsServiceReturnsFalse() {
launcher.setActivity(activity);

final CustomTabsSessionOptions sessionOptions = mock(CustomTabsSessionOptions.class);
when(customTabsSessionFactory.createSessionOptions(any())).thenReturn(sessionOptions);
when(customTabsSessionManager.createSessionOptions(any())).thenReturn(sessionOptions);

final String expectedPackageName = "com.example.browser";
final CustomTabsSessionController controller = mock(CustomTabsSessionController.class);
when(controller.bindCustomTabsService(any(), eq(expectedPackageName)))
.thenReturn(false);

when(customTabsSessionFactory.createSession(any(), any()))
when(customTabsSessionManager.createSession(any(), any()))
.thenReturn(new Pair<>(expectedPackageName, controller));

final Map<String, Object> options = Collections.emptyMap();
final String actualPackageName = launcher.warmup(options);
assertThat(actualPackageName).isNull();

verify(customTabsSessionFactory).createSessionOptions(same(options));
verify(customTabsSessionManager).createSessionOptions(same(options));
verify(controller).bindCustomTabsService(any(), eq(expectedPackageName));
}

Expand All @@ -346,15 +346,15 @@ public void warmup_withoutActivity_returnsNull() {
final String actualPackageName = launcher.warmup(Collections.emptyMap());
assertThat(actualPackageName).isNull();

verify(customTabsSessionFactory, never()).createSessionOptions(any());
verify(customTabsSessionFactory, never()).createSession(any(), any());
verify(customTabsSessionManager, never()).createSessionOptions(any());
verify(customTabsSessionManager, never()).createSession(any(), any());
}

@Test
public void invalidate_withValidPackageName_invokesInvalidateSession() throws Exception {
final String packageName = "com.example.browser";
launcher.invalidate(packageName);

verify(customTabsSessionFactory).invalidateSession(eq(packageName));
verify(customTabsSessionManager).invalidateSession(eq(packageName));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@
import com.github.droibit.flutter.plugins.customtabs.core.options.CustomTabsColorSchemes;
import com.github.droibit.flutter.plugins.customtabs.core.options.CustomTabsIntentOptions;
import com.github.droibit.flutter.plugins.customtabs.core.options.PartialCustomTabsConfiguration;
import com.github.droibit.flutter.plugins.customtabs.core.session.CustomTabsSessionFactory;
import com.github.droibit.flutter.plugins.customtabs.core.session.CustomTabsSessionProvider;

import org.junit.Rule;
import org.junit.Test;
Expand All @@ -87,7 +87,7 @@ public class CustomTabsIntentFactoryTest {
private ResourceFactory resources;

@Mock
private CustomTabsSessionFactory customTabsSessionFactory;
private CustomTabsSessionProvider sessionProvider;

@Mock
private Context context;
Expand Down Expand Up @@ -126,7 +126,7 @@ public void createIntent_completeOptions() {
doNothing().when(intentFactory).applyBrowserConfiguration(any(), any(), any());

final CustomTabsIntent customTabsIntent = intentFactory
.createIntent(context, options, customTabsSessionFactory);
.createIntent(context, options, sessionProvider);
final BundleSubject extras = assertThat(customTabsIntent.intent).extras();

final ArgumentCaptor<CustomTabsColorSchemes> colorSchemesCaptor = ArgumentCaptor.captor();
Expand Down Expand Up @@ -167,7 +167,7 @@ public void createIntent_minimumOptions() {
doNothing().when(intentFactory).applyBrowserConfiguration(any(), any(), any());

final CustomTabsIntent customTabsIntent = intentFactory
.createIntent(context, options, customTabsSessionFactory);
.createIntent(context, options, sessionProvider);
final BundleSubject extras = assertThat(customTabsIntent.intent).extras();
extras.doesNotContainKey(EXTRA_ENABLE_URLBAR_HIDING);
extras.doesNotContainKey(EXTRA_TITLE_VISIBILITY_STATE);
Expand Down
Loading

0 comments on commit 28fd0c5

Please sign in to comment.