Commit f0773554 authored by Jinsuk Kim's avatar Jinsuk Kim Committed by Commit Bot

Android: Refactor Tab's native page methods

- Introduces |setNativePage| and remove |freezeNativePage|
- Factors common logic hiding the current native page into
  |Tab.hideNativePage|.
- Replaces |NativePage instanceof FrozenNativePage| with a
  new method |isFrozen| in NativePage interface.

Bug: 925242, 995903
Change-Id: I531003e7c880cabdf2ff05489145135d1206eb3c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1861442
Commit-Queue: Jinsuk Kim <jinsukkim@chromium.org>
Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Cr-Commit-Position: refs/heads/master@{#708937}
parent 6141983f
...@@ -70,6 +70,11 @@ public class FrozenNativePage implements NativePage { ...@@ -70,6 +70,11 @@ public class FrozenNativePage implements NativePage {
public void updateForUrl(String url) { public void updateForUrl(String url) {
} }
@Override
public boolean isFrozen() {
return true;
}
@Override @Override
public void destroy() { public void destroy() {
} }
......
...@@ -45,6 +45,13 @@ public interface NativePage { ...@@ -45,6 +45,13 @@ public interface NativePage {
*/ */
void updateForUrl(String url); void updateForUrl(String url);
/**
* @return {@code true} if the native page is in inactive/frozen state.
*/
default boolean isFrozen() {
return false;
}
/** /**
* Called after a page has been removed from the view hierarchy and will no longer be used. * Called after a page has been removed from the view hierarchy and will no longer be used.
*/ */
......
...@@ -84,12 +84,6 @@ public class NativePageAssassin { ...@@ -84,12 +84,6 @@ public class NativePageAssassin {
} }
private void freeze(Tab tab) { private void freeze(Tab tab) {
if (tab == null) return; if (tab != null) tab.freezeNativePage();
NativePage pageToFreeze = tab.getNativePage();
if (pageToFreeze == null || pageToFreeze instanceof FrozenNativePage
|| pageToFreeze.getView().getParent() != null) {
return;
}
tab.freezeNativePage();
} }
} }
\ No newline at end of file
...@@ -727,7 +727,7 @@ public class Tab { ...@@ -727,7 +727,7 @@ public class Tab {
// If the NativePage was frozen while in the background (see NativePageAssassin), // If the NativePage was frozen while in the background (see NativePageAssassin),
// recreate the NativePage now. // recreate the NativePage now.
NativePage nativePage = getNativePage(); NativePage nativePage = getNativePage();
if (nativePage instanceof FrozenNativePage) { if (nativePage != null && nativePage.isFrozen()) {
maybeShowNativePage(nativePage.getUrl(), true); maybeShowNativePage(nativePage.getUrl(), true);
} }
NativePageAssassin.getInstance().tabShown(this); NativePageAssassin.getInstance().tabShown(this);
...@@ -783,18 +783,15 @@ public class Tab { ...@@ -783,18 +783,15 @@ public class Tab {
* @param nativePage The {@link NativePage} to show. * @param nativePage The {@link NativePage} to show.
*/ */
private void showNativePage(NativePage nativePage) { private void showNativePage(NativePage nativePage) {
assert nativePage != null;
if (mNativePage == nativePage) return; if (mNativePage == nativePage) return;
NativePage previousNativePage = mNativePage; hideNativePage(true, () -> {
if (mNativePage != null && !(mNativePage instanceof FrozenNativePage)) { mNativePage = nativePage;
mNativePage.getView().removeOnAttachStateChangeListener(mAttachStateChangeListener); if (!mNativePage.isFrozen()) {
} mNativePage.getView().addOnAttachStateChangeListener(mAttachStateChangeListener);
mNativePage = nativePage; }
if (mNativePage != null && !(mNativePage instanceof FrozenNativePage)) { pushNativePageStateToNavigationEntry();
mNativePage.getView().addOnAttachStateChangeListener(mAttachStateChangeListener); });
}
pushNativePageStateToNavigationEntry();
notifyContentChanged();
destroyNativePageInternal(previousNativePage);
} }
/** /**
...@@ -802,8 +799,10 @@ public class Tab { ...@@ -802,8 +799,10 @@ public class Tab {
* to reduce memory pressure. * to reduce memory pressure.
*/ */
public void freezeNativePage() { public void freezeNativePage() {
if (mNativePage == null || mNativePage instanceof FrozenNativePage) return; if (mNativePage == null || mNativePage.isFrozen()
assert mNativePage.getView().getParent() == null : "Cannot freeze visible native page"; || mNativePage.getView().getParent() == null) {
return;
}
mNativePage = FrozenNativePage.freeze(mNativePage); mNativePage = FrozenNativePage.freeze(mNativePage);
updateInteractableState(); updateInteractableState();
} }
...@@ -813,14 +812,25 @@ public class Tab { ...@@ -813,14 +812,25 @@ public class Tab {
*/ */
protected void showRenderedPage() { protected void showRenderedPage() {
updateTitle(); updateTitle();
hideNativePage(true, null);
}
if (mNativePage == null) return; /**
* Hide and destroy the native page if it was being shown.
* @param notify {@code true} to trigger {@link #onContentChanged} event.
* @param postHideTask {@link Runnable} task to run before actually destroying the
* native page. This is necessary to keep the tasks to perform in order.
*/
private void hideNativePage(boolean notify, Runnable postHideTask) {
NativePage previousNativePage = mNativePage; NativePage previousNativePage = mNativePage;
if (!(mNativePage instanceof FrozenNativePage)) { if (mNativePage != null) {
mNativePage.getView().removeOnAttachStateChangeListener(mAttachStateChangeListener); if (!mNativePage.isFrozen()) {
mNativePage.getView().removeOnAttachStateChangeListener(mAttachStateChangeListener);
}
mNativePage = null;
} }
mNativePage = null; if (postHideTask != null) postHideTask.run();
notifyContentChanged(); if (notify) notifyContentChanged();
destroyNativePageInternal(previousNativePage); destroyNativePageInternal(previousNativePage);
} }
...@@ -894,7 +904,7 @@ public class Tab { ...@@ -894,7 +904,7 @@ public class Tab {
* Set {@link TabDelegateFactory} instance and updates the references. * Set {@link TabDelegateFactory} instance and updates the references.
* @param factory TabDelegateFactory instance. * @param factory TabDelegateFactory instance.
*/ */
public void setDelegateFactory(TabDelegateFactory factory) { private void setDelegateFactory(TabDelegateFactory factory) {
// Update the delegate factory, then recreate and propagate all delegates. // Update the delegate factory, then recreate and propagate all delegates.
mDelegateFactory = factory; mDelegateFactory = factory;
...@@ -908,10 +918,25 @@ public class Tab { ...@@ -908,10 +918,25 @@ public class Tab {
} }
/** /**
* Notify observers of the new attachment state to activity. * Notify observers of the new attachment state to activity. If attached, {@link WindowAndroid}
* @param attached {@code true} if the tab gets attached. * and {@link TabDelegateFactory} for the new activity are provided. Passing {@code null}
* for both indicates that the tab is not attached.
* @param window A new {@link WindowAndroid} to attach the tab to.
* @param tabDelegateFactory The new delegate factory this tab should be using.
*/ */
public void notifyActivityAttachmentChanged(boolean attached) { public void notifyActivityAttachmentChanged(
@Nullable WindowAndroid window, @Nullable TabDelegateFactory tabDelegateFactory) {
boolean attached = (window != null && tabDelegateFactory != null);
assert attached || (window == null && tabDelegateFactory == null);
if (attached) {
updateWindowAndroid(window);
setDelegateFactory(tabDelegateFactory);
// Reload the NativePage (if any), since the old NativePage has a reference to the old
// activity.
maybeShowNativePage(getUrl(), true);
}
for (TabObserver observer : mObservers) { for (TabObserver observer : mObservers) {
observer.onActivityAttachmentChanged(this, attached); observer.onActivityAttachmentChanged(this, attached);
} }
...@@ -1049,9 +1074,7 @@ public class Tab { ...@@ -1049,9 +1074,7 @@ public class Tab {
mContentView = cv; mContentView = cv;
webContents.initialize(PRODUCT_VERSION, new TabViewAndroidDelegate(this, cv), cv, webContents.initialize(PRODUCT_VERSION, new TabViewAndroidDelegate(this, cv), cv,
getWindowAndroid(), WebContents.createDefaultInternalsHolder()); getWindowAndroid(), WebContents.createDefaultInternalsHolder());
NativePage previousNativePage = mNativePage; hideNativePage(false, null);
mNativePage = null;
destroyNativePageInternal(previousNativePage);
if (oldWebContents != null) { if (oldWebContents != null) {
oldWebContents.setImportance(ChildProcessImportance.NORMAL); oldWebContents.setImportance(ChildProcessImportance.NORMAL);
...@@ -1091,7 +1114,7 @@ public class Tab { ...@@ -1091,7 +1114,7 @@ public class Tab {
* matches the URL. * matches the URL.
* @return True, if a native page was displayed for url. * @return True, if a native page was displayed for url.
*/ */
public boolean maybeShowNativePage(String url, boolean forceReload) { boolean maybeShowNativePage(String url, boolean forceReload) {
// While detached for reparenting we don't have an owning Activity, or TabModelSelector, // While detached for reparenting we don't have an owning Activity, or TabModelSelector,
// so we can't create the native page. The native page will be created once reparenting is // so we can't create the native page. The native page will be created once reparenting is
// completed. // completed.
...@@ -1144,10 +1167,7 @@ public class Tab { ...@@ -1144,10 +1167,7 @@ public class Tab {
mObservers.clear(); mObservers.clear();
mUserDataHost.destroy(); mUserDataHost.destroy();
hideNativePage(false, null);
NativePage currentNativePage = mNativePage;
mNativePage = null;
destroyNativePageInternal(currentNativePage);
destroyWebContents(true); destroyWebContents(true);
TabImportanceManager.tabDestroyed(this); TabImportanceManager.tabDestroyed(this);
...@@ -1518,40 +1538,32 @@ public class Tab { ...@@ -1518,40 +1538,32 @@ public class Tab {
/** This is currently called when committing a pre-rendered page. */ /** This is currently called when committing a pre-rendered page. */
void swapWebContents(WebContents webContents, boolean didStartLoad, boolean didFinishLoad) { void swapWebContents(WebContents webContents, boolean didStartLoad, boolean didFinishLoad) {
int originalWidth = 0; boolean hasWebContents = mContentView != null && mWebContents != null;
int originalHeight = 0; Rect original = hasWebContents
if (mContentView != null && mWebContents != null) { ? new Rect(0, 0, mContentView.getWidth(), mContentView.getHeight())
originalWidth = mContentView.getWidth(); : new Rect();
originalHeight = mContentView.getHeight(); if (hasWebContents) mWebContents.onHide();
mWebContents.onHide(); Rect bounds = original.isEmpty()
} ? ExternalPrerenderHandler.estimateContentSize(getApplicationContext(), false)
: null;
Rect bounds = new Rect(); if (bounds != null) original.set(bounds);
if (originalWidth == 0 && originalHeight == 0) {
bounds = ExternalPrerenderHandler.estimateContentSize(getApplicationContext(), false);
originalWidth = bounds.right - bounds.left;
originalHeight = bounds.bottom - bounds.top;
}
destroyWebContents(false /* do not delete native web contents */); destroyWebContents(false /* do not delete native web contents */);
NativePage previousNativePage = mNativePage; hideNativePage(false, () -> {
mNativePage = null; // Size of the new content is zero at this point. Set the view size in advance
// so that next onShow() call won't send a resize message with zero size
// Size of the new content is zero at this point. Set the view size in advance // to the renderer process. This prevents the size fluttering that may confuse
// so that next onShow() call won't send a resize message with zero size // Blink and break rendered result (see http://crbug.com/340987).
// to the renderer process. This prevents the size fluttering that may confuse webContents.setSize(original.width(), original.height());
// Blink and break rendered result (see http://crbug.com/340987).
webContents.setSize(originalWidth, originalHeight); if (bounds != null) {
assert mNativeTabAndroid != 0;
if (!bounds.isEmpty()) { TabJni.get().onPhysicalBackingSizeChanged(
assert mNativeTabAndroid != 0; mNativeTabAndroid, Tab.this, webContents, bounds.right, bounds.bottom);
TabJni.get().onPhysicalBackingSizeChanged( }
mNativeTabAndroid, Tab.this, webContents, bounds.right, bounds.bottom); webContents.onShow();
} initWebContents(webContents);
webContents.onShow(); });
initWebContents(webContents);
destroyNativePageInternal(previousNativePage);
String url = getUrl(); String url = getUrl();
......
...@@ -118,7 +118,7 @@ public class ReparentingTask implements UserData { ...@@ -118,7 +118,7 @@ public class ReparentingTask implements UserData {
// TabModelSelector of this Tab, if present, gets notified to remove the tab from // TabModelSelector of this Tab, if present, gets notified to remove the tab from
// the TabModel it belonged to. // the TabModel it belonged to.
tab.notifyActivityAttachmentChanged(false); tab.notifyActivityAttachmentChanged(null, null);
} }
/** /**
...@@ -144,20 +144,12 @@ public class ReparentingTask implements UserData { ...@@ -144,20 +144,12 @@ public class ReparentingTask implements UserData {
* java and native sides. * java and native sides.
* *
* @param window A new {@link WindowAndroid} to attach the tab to. * @param window A new {@link WindowAndroid} to attach the tab to.
* @param activity The new activity this tab should be associated with.
* @param tabDelegateFactory The new delegate factory this tab should be using. * @param tabDelegateFactory The new delegate factory this tab should be using.
*/ */
private void attach(WindowAndroid window, TabDelegateFactory tabDelegateFactory) { private void attach(WindowAndroid window, TabDelegateFactory tabDelegateFactory) {
assert Tab.isDetached(mTab); assert Tab.isDetached(mTab);
mTab.updateWindowAndroid(window); mTab.notifyActivityAttachmentChanged(window, tabDelegateFactory);
mTab.setDelegateFactory(tabDelegateFactory);
// Reload the NativePage (if any), since the old NativePage has a reference to the old
// activity.
mTab.maybeShowNativePage(mTab.getUrl(), true);
ReparentingTaskJni.get().attachTab(mTab.getWebContents()); ReparentingTaskJni.get().attachTab(mTab.getWebContents());
mTab.notifyActivityAttachmentChanged(true);
} }
@NativeMethods @NativeMethods
......
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