Commit 6ea010eb authored by Anna Malova's avatar Anna Malova Committed by Commit Bot

Move CCT Dynamic Module code out of CustomTabActivity.

Introduce DynamicModuleCoordinator which is instantiated via DI only
if Intent has correct dynamic module ComponentName.

ActivityDelegate is responsible of notifying dynamic module
on ActivityLifecycle events now.

Bug: 904826
Change-Id: I2e73cdb296db9aab83031bd4c8bf99457bc8973f
Reviewed-on: https://chromium-review.googlesource.com/c/1356961Reviewed-by: default avatarTed Choc <tedchoc@chromium.org>
Reviewed-by: default avatarMichael van Ouwerkerk <mvanouwerkerk@chromium.org>
Reviewed-by: default avatarPeter Conn <peconn@chromium.org>
Reviewed-by: default avatarPavel Shmakov <pshmakov@chromium.org>
Commit-Queue: Anna Malova <amalova@chromium.org>
Cr-Commit-Position: refs/heads/master@{#615645}
parent 92fa83d4
...@@ -28,6 +28,7 @@ import org.chromium.chrome.R; ...@@ -28,6 +28,7 @@ import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager;
import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager.OverlayPanelManagerObserver; import org.chromium.chrome.browser.compositor.bottombar.OverlayPanelManager.OverlayPanelManagerObserver;
import org.chromium.chrome.browser.dependency_injection.ActivityScope;
import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager; import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager.FullscreenListener; import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager.FullscreenListener;
import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.Tab;
...@@ -35,10 +36,13 @@ import org.chromium.ui.interpolators.BakedBezierInterpolator; ...@@ -35,10 +36,13 @@ import org.chromium.ui.interpolators.BakedBezierInterpolator;
import java.util.List; import java.util.List;
import javax.inject.Inject;
/** /**
* Delegate that manages bottom bar area inside of {@link CustomTabActivity}. * Delegate that manages bottom bar area inside of {@link CustomTabActivity}.
*/ */
class CustomTabBottomBarDelegate implements FullscreenListener { @ActivityScope
public class CustomTabBottomBarDelegate implements FullscreenListener {
private static final String TAG = "CustomTab"; private static final String TAG = "CustomTab";
private static final CachedMetrics.ActionEvent REMOTE_VIEWS_SHOWN = private static final CachedMetrics.ActionEvent REMOTE_VIEWS_SHOWN =
new CachedMetrics.ActionEvent("CustomTabsRemoteViewsShown"); new CachedMetrics.ActionEvent("CustomTabsRemoteViewsShown");
...@@ -70,6 +74,7 @@ class CustomTabBottomBarDelegate implements FullscreenListener { ...@@ -70,6 +74,7 @@ class CustomTabBottomBarDelegate implements FullscreenListener {
} }
}; };
@Inject
public CustomTabBottomBarDelegate(ChromeActivity activity, public CustomTabBottomBarDelegate(ChromeActivity activity,
CustomTabIntentDataProvider dataProvider, ChromeFullscreenManager fullscreenManager) { CustomTabIntentDataProvider dataProvider, ChromeFullscreenManager fullscreenManager) {
mActivity = activity; mActivity = activity;
......
...@@ -31,12 +31,14 @@ import org.chromium.base.VisibleForTesting; ...@@ -31,12 +31,14 @@ import org.chromium.base.VisibleForTesting;
import org.chromium.base.metrics.RecordUserAction; import org.chromium.base.metrics.RecordUserAction;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.ChromeApplication;
import org.chromium.chrome.browser.ChromeFeatureList; import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.ChromeSwitches; import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.ChromeVersionInfo; import org.chromium.chrome.browser.ChromeVersionInfo;
import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.IntentHandler;
import org.chromium.chrome.browser.UrlConstants; import org.chromium.chrome.browser.UrlConstants;
import org.chromium.chrome.browser.browserservices.BrowserSessionDataProvider; import org.chromium.chrome.browser.browserservices.BrowserSessionDataProvider;
import org.chromium.chrome.browser.customtabs.dynamicmodule.ModuleMetrics;
import org.chromium.chrome.browser.externalauth.ExternalAuthUtils; import org.chromium.chrome.browser.externalauth.ExternalAuthUtils;
import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings; import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
import org.chromium.chrome.browser.util.ColorUtils; import org.chromium.chrome.browser.util.ColorUtils;
...@@ -786,11 +788,42 @@ public class CustomTabIntentDataProvider extends BrowserSessionDataProvider { ...@@ -786,11 +788,42 @@ public class CustomTabIntentDataProvider extends BrowserSessionDataProvider {
return mIsTrustedWebActivity; return mIsTrustedWebActivity;
} }
/**
* @return Whether the Custom Tab should attempt to load a dynamic module, i.e.
* if the feature is enabled, the package is provided and package is Google-signed.
*
* Will return false if native is not initialized.
*/
public boolean isDynamicModuleEnabled() {
if (!ChromeFeatureList.isInitialized()) return false;
ComponentName componentName = getModuleComponentName();
// Return early if no component name was provided. It's important to do this before checking
// the feature experiment group, to avoid entering users into the experiment that do not
// even receive the extras for using the feature.
if (componentName == null) return false;
if (!ChromeFeatureList.isEnabled(ChromeFeatureList.CCT_MODULE)) {
Log.w(TAG, "The %s feature is disabled.", ChromeFeatureList.CCT_MODULE);
ModuleMetrics.recordLoadResult(ModuleMetrics.LoadResult.FEATURE_DISABLED);
return false;
}
ExternalAuthUtils authUtils = ChromeApplication.getComponent().resolveExternalAuthUtils();
if (!authUtils.isGoogleSigned(componentName.getPackageName())) {
Log.w(TAG, "The %s package is not Google-signed.", componentName.getPackageName());
ModuleMetrics.recordLoadResult(ModuleMetrics.LoadResult.NOT_GOOGLE_SIGNED);
return false;
}
return true;
}
/** /**
* @return The component name of the module entry point, or null if not specified. * @return The component name of the module entry point, or null if not specified.
*/ */
@Nullable @Nullable
ComponentName getModuleComponentName() { public ComponentName getModuleComponentName() {
return mModuleComponentName; return mModuleComponentName;
} }
...@@ -800,7 +833,7 @@ public class CustomTabIntentDataProvider extends BrowserSessionDataProvider { ...@@ -800,7 +833,7 @@ public class CustomTabIntentDataProvider extends BrowserSessionDataProvider {
* or null if not specified. * or null if not specified.
*/ */
@Nullable @Nullable
Pattern getExtraModuleManagedUrlsPattern() { public Pattern getExtraModuleManagedUrlsPattern() {
return mModuleManagedUrlsPattern; return mModuleManagedUrlsPattern;
} }
...@@ -809,7 +842,7 @@ public class CustomTabIntentDataProvider extends BrowserSessionDataProvider { ...@@ -809,7 +842,7 @@ public class CustomTabIntentDataProvider extends BrowserSessionDataProvider {
* @return The list of module managed hosts, or null if not specified. * @return The list of module managed hosts, or null if not specified.
*/ */
@Nullable @Nullable
List<String> getExtraModuleManagedHosts() { public List<String> getExtraModuleManagedHosts() {
return mModuleManagedHosts; return mModuleManagedHosts;
} }
...@@ -823,7 +856,7 @@ public class CustomTabIntentDataProvider extends BrowserSessionDataProvider { ...@@ -823,7 +856,7 @@ public class CustomTabIntentDataProvider extends BrowserSessionDataProvider {
/** /**
* @return Whether to hide CCT header on module managed URLs. * @return Whether to hide CCT header on module managed URLs.
*/ */
boolean shouldHideCctHeaderOnModuleManagedUrls() { public boolean shouldHideCctHeaderOnModuleManagedUrls() {
return mHideCctHeaderOnModuleManagedUrls; return mHideCctHeaderOnModuleManagedUrls;
} }
} }
...@@ -11,11 +11,15 @@ import android.view.ViewStub; ...@@ -11,11 +11,15 @@ import android.view.ViewStub;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.dependency_injection.ActivityScope;
import javax.inject.Inject;
/** /**
* Delegate that manages top bar area inside of {@link CustomTabActivity}. * Delegate that manages top bar area inside of {@link CustomTabActivity}.
*/ */
class CustomTabTopBarDelegate { @ActivityScope
public class CustomTabTopBarDelegate {
private final ChromeActivity mActivity; private final ChromeActivity mActivity;
private ViewGroup mTopBarView; private ViewGroup mTopBarView;
@Nullable @Nullable
...@@ -23,6 +27,7 @@ class CustomTabTopBarDelegate { ...@@ -23,6 +27,7 @@ class CustomTabTopBarDelegate {
@Nullable @Nullable
private Integer mTopBarHeight; private Integer mTopBarHeight;
@Inject
public CustomTabTopBarDelegate(ChromeActivity activity) { public CustomTabTopBarDelegate(ChromeActivity activity) {
mActivity = activity; mActivity = activity;
} }
......
...@@ -7,8 +7,11 @@ package org.chromium.chrome.browser.customtabs.dependency_injection; ...@@ -7,8 +7,11 @@ package org.chromium.chrome.browser.customtabs.dependency_injection;
import org.chromium.chrome.browser.browserservices.trustedwebactivityui.TrustedWebActivityCoordinator; import org.chromium.chrome.browser.browserservices.trustedwebactivityui.TrustedWebActivityCoordinator;
import org.chromium.chrome.browser.contextual_suggestions.ContextualSuggestionsModule; import org.chromium.chrome.browser.contextual_suggestions.ContextualSuggestionsModule;
import org.chromium.chrome.browser.customtabs.CloseButtonNavigator; import org.chromium.chrome.browser.customtabs.CloseButtonNavigator;
import org.chromium.chrome.browser.customtabs.CustomTabBottomBarDelegate;
import org.chromium.chrome.browser.customtabs.CustomTabDelegateFactory; import org.chromium.chrome.browser.customtabs.CustomTabDelegateFactory;
import org.chromium.chrome.browser.customtabs.CustomTabTopBarDelegate;
import org.chromium.chrome.browser.customtabs.TabObserverRegistrar; import org.chromium.chrome.browser.customtabs.TabObserverRegistrar;
import org.chromium.chrome.browser.customtabs.dynamicmodule.DynamicModuleCoordinator;
import org.chromium.chrome.browser.dependency_injection.ActivityScope; import org.chromium.chrome.browser.dependency_injection.ActivityScope;
import org.chromium.chrome.browser.dependency_injection.ChromeActivityCommonsModule; import org.chromium.chrome.browser.dependency_injection.ChromeActivityCommonsModule;
import org.chromium.chrome.browser.dependency_injection.ChromeActivityComponent; import org.chromium.chrome.browser.dependency_injection.ChromeActivityComponent;
...@@ -24,7 +27,11 @@ import dagger.Subcomponent; ...@@ -24,7 +27,11 @@ import dagger.Subcomponent;
@ActivityScope @ActivityScope
public interface CustomTabActivityComponent extends ChromeActivityComponent { public interface CustomTabActivityComponent extends ChromeActivityComponent {
TrustedWebActivityCoordinator resolveTrustedWebActivityCoordinator(); TrustedWebActivityCoordinator resolveTrustedWebActivityCoordinator();
DynamicModuleCoordinator resolveDynamicModuleCoordinator();
CloseButtonNavigator resolveCloseButtonNavigator(); CloseButtonNavigator resolveCloseButtonNavigator();
CustomTabDelegateFactory resolveTabDelegateFactory(); CustomTabDelegateFactory resolveTabDelegateFactory();
TabObserverRegistrar resolveTabObserverRegistrar(); TabObserverRegistrar resolveTabObserverRegistrar();
CustomTabTopBarDelegate resolveTobBarDelegate();
CustomTabBottomBarDelegate resolveBottomBarDelegate();
} }
...@@ -8,87 +8,163 @@ import android.os.Bundle; ...@@ -8,87 +8,163 @@ import android.os.Bundle;
import android.os.RemoteException; import android.os.RemoteException;
import org.chromium.base.VisibleForTesting; 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}. * A wrapper around a {@link IActivityDelegate}.
* *
* No {@link RemoteException} should ever be thrown as all of this code runs in the same process. * No {@link RemoteException} should ever be thrown as all of this code runs in the same process.
*/ */
public class ActivityDelegate { public class ActivityDelegate implements StartStopWithNativeObserver,
private final IActivityDelegate mActivityDelegate; PauseResumeWithNativeObserver, Destroyable,
SaveInstanceStateObserver, WindowFocusChangedObserver {
private IActivityDelegate mActivityDelegate;
private interface RemoteRunnable { void run() throws RemoteException; } private boolean mModuleOnStartPending;
private boolean mModuleOnResumePending;
private ChromeActivity mActivity;
private interface RemoteCallable<T> { T call() throws RemoteException; } private Bundle getSavedInstanceState() {
return mActivity.getSavedInstanceState();
private void safeRun(RemoteRunnable runnable) {
try {
runnable.run();
} catch (RemoteException e) {
assert false;
}
} }
private <T> T safeCall(RemoteCallable<T> callable, T defaultReturn) { @Inject
try { public ActivityDelegate(
return callable.call(); ChromeActivity chromeActivity,
} catch (RemoteException e) { ActivityLifecycleDispatcher activityLifecycleDispatcher) {
assert false;
}
return defaultReturn; mActivity = chromeActivity;
activityLifecycleDispatcher.register(this);
} }
public ActivityDelegate(IActivityDelegate activityDelegate) { public void setActivityDelegate(IActivityDelegate activityDelegate) {
mActivityDelegate = activityDelegate; mActivityDelegate = activityDelegate;
safeRun(() -> mActivityDelegate.onCreate(getSavedInstanceState()));
if (mModuleOnStartPending) startModule();
if (mModuleOnResumePending) resumeModule();
} }
public void onCreate(Bundle savedInstanceState) { private void startModule() {
safeRun(() -> mActivityDelegate.onCreate(savedInstanceState)); assert mActivityDelegate != null;
mModuleOnStartPending = false;
safeRun(() -> {
mActivityDelegate.onStart();
mActivityDelegate.onRestoreInstanceState(getSavedInstanceState());
mActivityDelegate.onPostCreate(getSavedInstanceState());
});
} }
public void onPostCreate(Bundle savedInstanceState) { private void resumeModule() {
safeRun(() -> mActivityDelegate.onPostCreate(savedInstanceState)); assert mActivityDelegate != null;
mModuleOnResumePending = false;
safeRun(mActivityDelegate::onResume);
} }
public void onStart() { @Override
safeRun(mActivityDelegate::onStart); public void destroy() {
if (mActivityDelegate != null) {
safeRun(mActivityDelegate::onDestroy);
mActivityDelegate = null;
}
} }
public void onStop() { @Override
safeRun(mActivityDelegate::onStop); public void onStartWithNative() {
if (mActivityDelegate != null) {
startModule();
} else {
mModuleOnStartPending = true;
}
} }
public void onWindowFocusChanged(boolean hasFocus) { @Override
safeRun(() -> mActivityDelegate.onWindowFocusChanged(hasFocus)); 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) { public void onSaveInstanceState(Bundle outState) {
safeRun(() -> mActivityDelegate.onSaveInstanceState(outState)); if (mActivityDelegate != null) {
safeRun(() -> mActivityDelegate.onSaveInstanceState(outState));
}
} }
public void onRestoreInstanceState(Bundle savedInstanceState) { @Override
safeRun(() -> mActivityDelegate.onRestoreInstanceState(savedInstanceState)); public void onWindowFocusChanged(boolean hasFocus) {
if (mActivityDelegate != null) {
safeRun(() -> mActivityDelegate.onWindowFocusChanged(hasFocus));
}
} }
public void onResume() { public void onBackPressedAsync(Runnable notHandledRunnable) {
safeRun(mActivityDelegate::onResume); if (mActivityDelegate != null) {
safeRun(() -> mActivityDelegate.onBackPressedAsync(
ObjectWrapper.wrap(notHandledRunnable)));
}
} }
public void onPause() { @VisibleForTesting
safeRun(mActivityDelegate::onPause); public IActivityDelegate getActivityDelegateForTesting() {
return mActivityDelegate;
} }
public void onDestroy() { private interface RemoteRunnable { void run() throws RemoteException; }
safeRun(mActivityDelegate::onDestroy);
private interface RemoteCallable<T> { T call() throws RemoteException; }
private void safeRun(RemoteRunnable runnable) {
try {
runnable.run();
} catch (RemoteException e) {
assert false;
}
} }
public boolean onBackPressed() { private <T> T safeCall(RemoteCallable<T> callable, T defaultReturn) {
return safeCall(mActivityDelegate::onBackPressed, false); try {
return callable.call();
} catch (RemoteException e) {
assert false;
}
return defaultReturn;
} }
public void onBackPressedAsync(Runnable notHandledRunnable) { public void onRestoreInstanceState(Bundle savedInstanceState) {
safeRun(() -> mActivityDelegate.onBackPressedAsync(ObjectWrapper.wrap(notHandledRunnable))); safeRun(() -> mActivityDelegate.onRestoreInstanceState(savedInstanceState));
} }
public void onNavigationEvent(int navigationEvent, Bundle extras) { public void onNavigationEvent(int navigationEvent, Bundle extras) {
...@@ -102,9 +178,4 @@ public class ActivityDelegate { ...@@ -102,9 +178,4 @@ public class ActivityDelegate {
public void onPostMessage(String message) { public void onPostMessage(String message) {
safeRun(() -> mActivityDelegate.onPostMessage(message)); safeRun(() -> mActivityDelegate.onPostMessage(message));
} }
@VisibleForTesting
public IActivityDelegate getIActivityDelegateForTesting() {
return mActivityDelegate;
}
} }
// 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.content.Context;
import android.os.Bundle;
import android.support.customtabs.PostMessageBackend;
/**
* A {@link PostMessageBackend} which delegates incoming notifications to the {@link
* ActivityDelegate} from the dynamic module.
*
* <p>If the dynamic module is not loaded, we ignore incoming notifications and always return
* false.
*/
public class ActivityDelegatePostMessageBackend implements PostMessageBackend {
private final ActivityDelegate mActivityDelegate;
ActivityDelegatePostMessageBackend(ActivityDelegate activityDelegate) {
mActivityDelegate = activityDelegate;
}
@Override
public boolean onPostMessage(String message, Bundle extras) {
if (mActivityDelegate != null) {
mActivityDelegate.onPostMessage(message);
return true;
}
return false;
}
@Override
public boolean onNotifyMessageChannelReady(Bundle extras) {
if (mActivityDelegate != null) {
mActivityDelegate.onMessageChannelReady();
return true;
}
return false;
}
@Override
public void onDisconnectChannel(Context appContext) {
// Nothing to do.
}
}
\ No newline at end of file
...@@ -7,60 +7,58 @@ package org.chromium.chrome.browser.customtabs.dynamicmodule; ...@@ -7,60 +7,58 @@ package org.chromium.chrome.browser.customtabs.dynamicmodule;
import android.net.Uri; import android.net.Uri;
import android.view.View; import android.view.View;
import org.chromium.chrome.browser.customtabs.CustomTabActivity;
/** /**
* The implementation of {@link IActivityHost}. * The implementation of {@link IActivityHost}.
*/ */
public class ActivityHostImpl extends BaseActivityHost { public class ActivityHostImpl extends BaseActivityHost {
private final CustomTabActivity mActivity; private final DynamicModuleCoordinator mModuleCoordinator;
public ActivityHostImpl(CustomTabActivity activity) { public ActivityHostImpl(DynamicModuleCoordinator moduleCoordinator) {
mActivity = activity; mModuleCoordinator = moduleCoordinator;
} }
@Override @Override
public IObjectWrapper getActivityContext() { public IObjectWrapper getActivityContext() {
return ObjectWrapper.wrap(mActivity); return ObjectWrapper.wrap(mModuleCoordinator.getActivityContext());
} }
@Override @Override
public void setBottomBarView(IObjectWrapper bottomBarView) { public void setBottomBarView(IObjectWrapper bottomBarView) {
mActivity.setBottomBarContentView(ObjectWrapper.unwrap(bottomBarView, View.class)); mModuleCoordinator.setBottomBarContentView(ObjectWrapper.unwrap(bottomBarView, View.class));
} }
@Override @Override
public void setOverlayView(IObjectWrapper overlayView) { public void setOverlayView(IObjectWrapper overlayView) {
mActivity.setOverlayView(ObjectWrapper.unwrap(overlayView, View.class)); mModuleCoordinator.setOverlayView(ObjectWrapper.unwrap(overlayView, View.class));
} }
@Override @Override
public void setBottomBarHeight(int height) { public void setBottomBarHeight(int height) {
mActivity.setBottomBarHeight(height); mModuleCoordinator.setBottomBarHeight(height);
} }
@Override @Override
public void loadUri(Uri uri) { public void loadUri(Uri uri) {
mActivity.loadUri(uri); mModuleCoordinator.loadUri(uri);
} }
@Override @Override
public void setTopBarView(IObjectWrapper topBarView) { public void setTopBarView(IObjectWrapper topBarView) {
mActivity.setTopBarContentView(ObjectWrapper.unwrap(topBarView, View.class)); mModuleCoordinator.setTopBarContentView(ObjectWrapper.unwrap(topBarView, View.class));
} }
@Override @Override
public boolean requestPostMessageChannel(Uri postMessageOrigin) { public boolean requestPostMessageChannel(Uri postMessageOrigin) {
return mActivity.requestPostMessageChannel(postMessageOrigin); return mModuleCoordinator.requestPostMessageChannel(postMessageOrigin);
} }
@Override @Override
public int postMessage(String message) { public int postMessage(String message) {
return mActivity.postMessage(message); return mModuleCoordinator.postMessage(message);
} }
@Override @Override
public void setTopBarHeight(int heightInPx) { public void setTopBarHeight(int heightInPx) {
mActivity.setTopBarHeight(heightInPx); mModuleCoordinator.setTopBarHeight(heightInPx);
} }
} }
...@@ -12,4 +12,9 @@ public class DynamicModuleConstants { ...@@ -12,4 +12,9 @@ public class DynamicModuleConstants {
* The module version when {@link IActivityDelegate#onNavigationEvent} is introduced. * The module version when {@link IActivityDelegate#onNavigationEvent} is introduced.
*/ */
public static final int ON_NAVIGATION_EVENT_MODULE_API_VERSION = 4; public static final int ON_NAVIGATION_EVENT_MODULE_API_VERSION = 4;
/**
* The module version when {@link IActivityDelegate#onBackPressedAsync} is introduced.
*/
public static final int ON_BACK_PRESSED_ASYNC_API_VERSION = 2;
} }
\ No newline at end of file
...@@ -45,9 +45,9 @@ public class ModuleEntryPoint { ...@@ -45,9 +45,9 @@ public class ModuleEntryPoint {
return -1; return -1;
} }
public ActivityDelegate createActivityDelegate(ActivityHostImpl activityHost) { public IActivityDelegate createActivityDelegate(IActivityHost.Stub activityHost) {
try { try {
return new ActivityDelegate(mEntryPoint.createActivityDelegate(activityHost)); return mEntryPoint.createActivityDelegate(activityHost);
} catch (RemoteException e) { } catch (RemoteException e) {
assert false; assert false;
} }
......
...@@ -4,13 +4,17 @@ ...@@ -4,13 +4,17 @@
package org.chromium.chrome.browser.init; package org.chromium.chrome.browser.init;
import android.os.Bundle;
import org.chromium.base.ObserverList; import org.chromium.base.ObserverList;
import org.chromium.chrome.browser.lifecycle.Destroyable; import org.chromium.chrome.browser.lifecycle.Destroyable;
import org.chromium.chrome.browser.lifecycle.InflationObserver; import org.chromium.chrome.browser.lifecycle.InflationObserver;
import org.chromium.chrome.browser.lifecycle.LifecycleObserver; import org.chromium.chrome.browser.lifecycle.LifecycleObserver;
import org.chromium.chrome.browser.lifecycle.NativeInitObserver; import org.chromium.chrome.browser.lifecycle.NativeInitObserver;
import org.chromium.chrome.browser.lifecycle.PauseResumeWithNativeObserver; 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.StartStopWithNativeObserver;
import org.chromium.chrome.browser.lifecycle.WindowFocusChangedObserver;
/** /**
* Dispatches lifecycle events of activities extending {@link AsyncInitializationActivity} to * Dispatches lifecycle events of activities extending {@link AsyncInitializationActivity} to
...@@ -24,6 +28,10 @@ public class ActivityLifecycleDispatcher { ...@@ -24,6 +28,10 @@ public class ActivityLifecycleDispatcher {
private final ObserverList<StartStopWithNativeObserver> mStartStopObservers = private final ObserverList<StartStopWithNativeObserver> mStartStopObservers =
new ObserverList<>(); new ObserverList<>();
private final ObserverList<Destroyable> mDestroyables = new ObserverList<>(); private final ObserverList<Destroyable> mDestroyables = new ObserverList<>();
private final ObserverList<SaveInstanceStateObserver> mSaveInstanceStateObservers =
new ObserverList<>();
private final ObserverList<WindowFocusChangedObserver> mWindowFocusChangesObservers =
new ObserverList<>();
/** /**
* Registers an observer. * Registers an observer.
...@@ -46,6 +54,12 @@ public class ActivityLifecycleDispatcher { ...@@ -46,6 +54,12 @@ public class ActivityLifecycleDispatcher {
if (observer instanceof Destroyable) { if (observer instanceof Destroyable) {
mDestroyables.addObserver((Destroyable) observer); mDestroyables.addObserver((Destroyable) observer);
} }
if (observer instanceof SaveInstanceStateObserver) {
mSaveInstanceStateObservers.addObserver((SaveInstanceStateObserver) observer);
}
if (observer instanceof WindowFocusChangedObserver) {
mWindowFocusChangesObservers.addObserver((WindowFocusChangedObserver) observer);
}
} }
/** /**
...@@ -67,6 +81,12 @@ public class ActivityLifecycleDispatcher { ...@@ -67,6 +81,12 @@ public class ActivityLifecycleDispatcher {
if (observer instanceof Destroyable) { if (observer instanceof Destroyable) {
mDestroyables.removeObserver((Destroyable) observer); mDestroyables.removeObserver((Destroyable) observer);
} }
if (observer instanceof SaveInstanceStateObserver) {
mSaveInstanceStateObservers.removeObserver((SaveInstanceStateObserver) observer);
}
if (observer instanceof WindowFocusChangedObserver) {
mWindowFocusChangesObservers.removeObserver((WindowFocusChangedObserver) observer);
}
} }
void dispatchPreInflationStartup() { void dispatchPreInflationStartup() {
...@@ -116,4 +136,16 @@ public class ActivityLifecycleDispatcher { ...@@ -116,4 +136,16 @@ public class ActivityLifecycleDispatcher {
destroyable.destroy(); destroyable.destroy();
} }
} }
void dispatchOnSaveInstanceState(Bundle outBundle) {
for (SaveInstanceStateObserver observer: mSaveInstanceStateObservers) {
observer.onSaveInstanceState(outBundle);
}
}
void dispatchOnWindowFocusChanged(boolean hasFocus) {
for (WindowFocusChangedObserver observer: mWindowFocusChangesObservers) {
observer.onWindowFocusChanged(hasFocus);
}
}
} }
...@@ -440,7 +440,7 @@ public abstract class AsyncInitializationActivity extends AppCompatActivity impl ...@@ -440,7 +440,7 @@ public abstract class AsyncInitializationActivity extends AppCompatActivity impl
/** /**
* @return The saved bundle for the last recorded state. * @return The saved bundle for the last recorded state.
*/ */
protected Bundle getSavedInstanceState() { public Bundle getSavedInstanceState() {
return mSavedInstanceState; return mSavedInstanceState;
} }
...@@ -643,6 +643,16 @@ public abstract class AsyncInitializationActivity extends AppCompatActivity impl ...@@ -643,6 +643,16 @@ public abstract class AsyncInitializationActivity extends AppCompatActivity impl
protected void onSaveInstanceState(Bundle outState) { protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState); super.onSaveInstanceState(outState);
if (mWindowAndroid != null) mWindowAndroid.saveInstanceState(outState); if (mWindowAndroid != null) mWindowAndroid.saveInstanceState(outState);
mLifecycleDispatcher.dispatchOnSaveInstanceState(outState);
}
@CallSuper
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
mLifecycleDispatcher.dispatchOnWindowFocusChanged(hasFocus);
} }
/** /**
......
// 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.lifecycle;
import android.os.Bundle;
import org.chromium.chrome.browser.init.ActivityLifecycleDispatcher;
/**
* Implement this interface and register in {@link ActivityLifecycleDispatcher} to receive
* onSaveInstanceState events.
*/
public interface SaveInstanceStateObserver extends LifecycleObserver {
/**
* Called before activity begins to stop.
*/
void onSaveInstanceState(Bundle outState);
}
\ No newline at end of file
// 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.lifecycle;
import org.chromium.chrome.browser.init.ActivityLifecycleDispatcher;
/**
* Implement this interface and register in {@link ActivityLifecycleDispatcher} to receive
* onWindowFocusChange events.
*/
public interface WindowFocusChangedObserver extends LifecycleObserver {
/**
* Called when the current Window of the activity gains or loses focus.
*/
void onWindowFocusChanged(boolean hasFocus);
}
\ No newline at end of file
...@@ -452,8 +452,10 @@ chrome_java_sources = [ ...@@ -452,8 +452,10 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityComponent.java", "java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityComponent.java",
"java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityModule.java", "java/src/org/chromium/chrome/browser/customtabs/dependency_injection/CustomTabActivityModule.java",
"java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityDelegate.java", "java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityDelegate.java",
"java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityDelegatePostMessageBackend.java",
"java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityHostImpl.java", "java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ActivityHostImpl.java",
"java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleConstants.java", "java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleConstants.java",
"java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleCoordinator.java",
"java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleNavigationEventObserver.java", "java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/DynamicModuleNavigationEventObserver.java",
"java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleEntryPoint.java", "java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleEntryPoint.java",
"java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleHostImpl.java", "java/src/org/chromium/chrome/browser/customtabs/dynamicmodule/ModuleHostImpl.java",
...@@ -834,7 +836,9 @@ chrome_java_sources = [ ...@@ -834,7 +836,9 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/lifecycle/LifecycleObserver.java", "java/src/org/chromium/chrome/browser/lifecycle/LifecycleObserver.java",
"java/src/org/chromium/chrome/browser/lifecycle/NativeInitObserver.java", "java/src/org/chromium/chrome/browser/lifecycle/NativeInitObserver.java",
"java/src/org/chromium/chrome/browser/lifecycle/PauseResumeWithNativeObserver.java", "java/src/org/chromium/chrome/browser/lifecycle/PauseResumeWithNativeObserver.java",
"java/src/org/chromium/chrome/browser/lifecycle/SaveInstanceStateObserver.java",
"java/src/org/chromium/chrome/browser/lifecycle/StartStopWithNativeObserver.java", "java/src/org/chromium/chrome/browser/lifecycle/StartStopWithNativeObserver.java",
"java/src/org/chromium/chrome/browser/lifecycle/WindowFocusChangedObserver.java",
"java/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelper.java", "java/src/org/chromium/chrome/browser/locale/DefaultSearchEngineDialogHelper.java",
"java/src/org/chromium/chrome/browser/locale/DefaultSearchEnginePromoDialog.java", "java/src/org/chromium/chrome/browser/locale/DefaultSearchEnginePromoDialog.java",
"java/src/org/chromium/chrome/browser/locale/LocaleChangedBroadcastReceiver.java", "java/src/org/chromium/chrome/browser/locale/LocaleChangedBroadcastReceiver.java",
......
...@@ -99,7 +99,8 @@ public class CustomTabsDynamicModuleNavigationTest { ...@@ -99,7 +99,8 @@ public class CustomTabsDynamicModuleNavigationTest {
CustomTabsDynamicModuleTestUtils.FakeCCTActivityDelegate activityDelegate = CustomTabsDynamicModuleTestUtils.FakeCCTActivityDelegate activityDelegate =
(CustomTabsDynamicModuleTestUtils.FakeCCTActivityDelegate) (CustomTabsDynamicModuleTestUtils.FakeCCTActivityDelegate)
cctActivity.getActivityDelegateForTesting(); cctActivity.getComponent()
.resolveDynamicModuleCoordinator().getActivityDelegateForTesting();
activityDelegate.waitForNavigationEvent(CustomTabsCallback.NAVIGATION_STARTED, activityDelegate.waitForNavigationEvent(CustomTabsCallback.NAVIGATION_STARTED,
0, 3); 0, 3);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment