blob: dd2db69cc8d3f0a243874d0162abe2d40ffd4cf7 [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.customtabs.dynamicmodule;
import android.os.Bundle;
import android.os.RemoteException;
import org.chromium.base.VisibleForTesting;
import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.init.ActivityLifecycleDispatcher;
import org.chromium.chrome.browser.lifecycle.Destroyable;
import org.chromium.chrome.browser.lifecycle.PauseResumeWithNativeObserver;
import org.chromium.chrome.browser.lifecycle.SaveInstanceStateObserver;
import org.chromium.chrome.browser.lifecycle.StartStopWithNativeObserver;
import org.chromium.chrome.browser.lifecycle.WindowFocusChangedObserver;
import javax.inject.Inject;
/**
* A wrapper around a {@link IActivityDelegate}.
*
* No {@link RemoteException} should ever be thrown as all of this code runs in the same process.
*/
public class ActivityDelegate implements StartStopWithNativeObserver,
PauseResumeWithNativeObserver, Destroyable,
SaveInstanceStateObserver, WindowFocusChangedObserver {
private IActivityDelegate mActivityDelegate;
private boolean mModuleOnStartPending;
private boolean mModuleOnResumePending;
private ChromeActivity mActivity;
private Bundle getSavedInstanceState() {
return mActivity.getSavedInstanceState();
}
@Inject
public ActivityDelegate(
ChromeActivity chromeActivity,
ActivityLifecycleDispatcher activityLifecycleDispatcher) {
mActivity = chromeActivity;
activityLifecycleDispatcher.register(this);
}
public void setActivityDelegate(IActivityDelegate activityDelegate) {
mActivityDelegate = activityDelegate;
safeRun(() -> mActivityDelegate.onCreate(getSavedInstanceState()));
if (mModuleOnStartPending) startModule();
if (mModuleOnResumePending) resumeModule();
}
private void startModule() {
assert mActivityDelegate != null;
mModuleOnStartPending = false;
safeRun(() -> {
mActivityDelegate.onStart();
mActivityDelegate.onRestoreInstanceState(getSavedInstanceState());
mActivityDelegate.onPostCreate(getSavedInstanceState());
});
}
private void resumeModule() {
assert mActivityDelegate != null;
mModuleOnResumePending = false;
safeRun(mActivityDelegate::onResume);
}
@Override
public void destroy() {
if (mActivityDelegate != null) {
safeRun(mActivityDelegate::onDestroy);
mActivityDelegate = null;
}
}
@Override
public void onStartWithNative() {
if (mActivityDelegate != null) {
startModule();
} else {
mModuleOnStartPending = true;
}
}
@Override
public void onStopWithNative() {
if (mActivityDelegate != null) {
safeRun(mActivityDelegate::onStop);
}
mModuleOnStartPending = false;
}
@Override
public void onResumeWithNative() {
if (mActivityDelegate != null) {
resumeModule();
} else {
mModuleOnResumePending = true;
}
}
@Override
public void onPauseWithNative() {
if (mActivityDelegate != null) {
safeRun(mActivityDelegate::onPause);
}
mModuleOnResumePending = false;
}
@Override
public void onSaveInstanceState(Bundle outState) {
if (mActivityDelegate != null) {
safeRun(() -> mActivityDelegate.onSaveInstanceState(outState));
}
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
if (mActivityDelegate != null) {
safeRun(() -> mActivityDelegate.onWindowFocusChanged(hasFocus));
}
}
public void onBackPressedAsync(Runnable notHandledRunnable) {
if (mActivityDelegate != null) {
safeRun(() -> mActivityDelegate.onBackPressedAsync(
ObjectWrapper.wrap(notHandledRunnable)));
}
}
@VisibleForTesting
public IActivityDelegate getActivityDelegateForTesting() {
return mActivityDelegate;
}
private interface RemoteRunnable { void run() throws RemoteException; }
private interface RemoteCallable<T> { T call() throws RemoteException; }
private void safeRun(RemoteRunnable runnable) {
try {
runnable.run();
} catch (RemoteException e) {
assert false;
}
}
private <T> T safeCall(RemoteCallable<T> callable, T defaultReturn) {
try {
return callable.call();
} catch (RemoteException e) {
assert false;
}
return defaultReturn;
}
public void onRestoreInstanceState(Bundle savedInstanceState) {
safeRun(() -> mActivityDelegate.onRestoreInstanceState(savedInstanceState));
}
public void onNavigationEvent(int navigationEvent, Bundle extras) {
safeRun(() -> mActivityDelegate.onNavigationEvent(navigationEvent, extras));
}
public void onMessageChannelReady() {
safeRun(mActivityDelegate::onMessageChannelReady);
}
public void onPostMessage(String message) {
safeRun(() -> mActivityDelegate.onPostMessage(message));
}
}