Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(271)

Unified Diff: chrome/android/java/src/org/chromium/chrome/browser/Tab.java

Issue 834723002: Fix ChromeShell TabObservers and upstream more things (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/android/java/src/org/chromium/chrome/browser/Tab.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/Tab.java
index 44303f6b1f61093d6f9fcc6d3b5a2bdf47403ed3..1cb236912d7a9b819c60c8e4d2045917002fc33e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/Tab.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/Tab.java
@@ -24,6 +24,7 @@ import org.chromium.base.VisibleForTesting;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.TabState.WebContentsState;
import org.chromium.chrome.browser.banners.AppBannerManager;
+import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
import org.chromium.chrome.browser.contextmenu.ChromeContextMenuItemDelegate;
import org.chromium.chrome.browser.contextmenu.ChromeContextMenuPopulator;
import org.chromium.chrome.browser.contextmenu.ContextMenuParams;
@@ -53,6 +54,7 @@ import org.chromium.printing.PrintManagerDelegateImpl;
import org.chromium.printing.PrintingController;
import org.chromium.printing.PrintingControllerImpl;
import org.chromium.ui.base.Clipboard;
+import org.chromium.ui.base.LocalizationUtils;
import org.chromium.ui.base.PageTransition;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.gfx.DeviceDisplayInfo;
@@ -93,6 +95,7 @@ import java.util.concurrent.atomic.AtomicInteger;
*/
public class Tab {
public static final int INVALID_TAB_ID = -1;
+ private static final long INVALID_TIMESTAMP = -1;
/** Used for logging. */
private static final String TAG = "Tab";
@@ -227,6 +230,22 @@ public class Tab {
*/
private boolean mIsHidden = true;
+ /**
+ * The last time this tab was shown or the time of its initialization if it wasn't yet shown.
+ */
+ private long mTimestampMillis = INVALID_TIMESTAMP;
+
+ /**
+ * Title of the ContentViews webpage.Always update mTitle through updateTitle() so that it also
+ * updates mIsTitleDirectionRtl correctly.
+ */
+ private String mTitle;
+
+ /**
+ * Indicates if mTitle should be displayed from right to left.
+ */
+ private boolean mIsTitleDirectionRtl;
+
private FullscreenManager mFullscreenManager;
private float mPreviousFullscreenTopControlsOffsetY = Float.NaN;
private float mPreviousFullscreenContentOffsetY = Float.NaN;
@@ -385,6 +404,11 @@ public class Tab {
*/
protected class TabContentViewClient extends ContentViewClient {
@Override
+ public void onUpdateTitle(String title) {
+ updateTitle(title);
+ }
+
+ @Override
public void onContextualActionBarShown() {
for (TabObserver observer : mObservers) {
observer.onContextualActionBarVisibilityChanged(Tab.this, true);
@@ -432,6 +456,11 @@ public class Tab {
}
@Override
+ public void didFinishLoad(long frameId, String validatedUrl, boolean isMainFrame) {
+ if (isMainFrame) didFinishPageLoad();
+ }
+
+ @Override
public void didFailLoad(boolean isProvisionalLoad, boolean isMainFrame, int errorCode,
String description, String failingUrl) {
for (TabObserver observer : mObservers) {
@@ -444,6 +473,8 @@ public class Tab {
public void didStartProvisionalLoadForFrame(long frameId, long parentFrameId,
boolean isMainFrame, String validatedUrl, boolean isErrorPage,
boolean isIframeSrcdoc) {
+ if (isMainFrame) didStartPageLoad(validatedUrl, isErrorPage);
+
for (TabObserver observer : mObservers) {
observer.onDidStartProvisionalLoadForFrame(Tab.this, frameId, parentFrameId,
isMainFrame, validatedUrl, isErrorPage, isIframeSrcdoc);
@@ -453,15 +484,27 @@ public class Tab {
@Override
public void didCommitProvisionalLoadForFrame(long frameId, boolean isMainFrame, String url,
int transitionType) {
+ if (isMainFrame) {
+ mIsTabStateDirty = true;
+ updateTitle();
+ }
+
for (TabObserver observer : mObservers) {
observer.onDidCommitProvisionalLoadForFrame(
Tab.this, frameId, isMainFrame, url, transitionType);
}
+
+ notifyPageUrlChanged();
}
@Override
public void didNavigateMainFrame(String url, String baseUrl,
boolean isNavigationToDifferentPage, boolean isFragmentNavigation, int statusCode) {
+ FullscreenManager fullscreenManager = getFullscreenManager();
+ if (isNavigationToDifferentPage && fullscreenManager != null) {
+ fullscreenManager.setPersistentFullscreenMode(false);
+ }
+
for (TabObserver observer : mObservers) {
observer.onDidNavigateMainFrame(
Tab.this, url, baseUrl, isNavigationToDifferentPage,
@@ -479,6 +522,9 @@ public class Tab {
@Override
public void didAttachInterstitialPage() {
+ getInfoBarContainer().setVisibility(View.INVISIBLE);
+ showRenderedPage();
+
for (TabObserver observer : mObservers) {
observer.onDidAttachInterstitialPage(Tab.this);
}
@@ -486,6 +532,8 @@ public class Tab {
@Override
public void didDetachInterstitialPage() {
+ getInfoBarContainer().setVisibility(View.VISIBLE);
+
for (TabObserver observer : mObservers) {
observer.onDidDetachInterstitialPage(Tab.this);
}
@@ -573,7 +621,12 @@ public class Tab {
mFrozenContentsState = state.contentsState;
mSyncId = (int) state.syncId;
mShouldPreserve = state.shouldPreserve;
+ mTimestampMillis = state.timestampMillis;
mUrl = state.getVirtualUrlFromState();
+
+ mTitle = state.getDisplayTitleFromState();
+ mIsTitleDirectionRtl = LocalizationUtils.getFirstStrongCharacterDirection(mTitle)
+ == LocalizationUtils.RIGHT_TO_LEFT;
}
/**
@@ -744,6 +797,7 @@ public class Tab {
tabState.parentId = mParentId;
tabState.shouldPreserve = mShouldPreserve;
tabState.syncId = mSyncId;
+ tabState.timestampMillis = mTimestampMillis;
return tabState;
}
@@ -1011,6 +1065,10 @@ public class Tab {
if (mContentViewCore != null) mContentViewCore.onShow();
showInternal(type);
+
+ // Updating the timestamp has to happen after the showInternal() call since subclasses
+ // may use it for logging.
+ mTimestampMillis = System.currentTimeMillis();
} finally {
TraceEvent.end("Tab.show");
}
@@ -1076,6 +1134,8 @@ public class Tab {
* Hides the current {@link NativePage}, if any, and shows the {@link ContentViewCore}'s view.
*/
protected void showRenderedPage() {
+ updateTitle();
+
if (mNativePage == null) return;
NativePage previousNativePage = mNativePage;
mNativePage = null;
@@ -1084,10 +1144,95 @@ public class Tab {
}
/**
- * Initializes this {@link Tab}.
+ * Initializes the ChromeTab after construction.
+ * @param nativeWebContents native WebContents object if available or 0 when creating a brand
+ * new tab
+ * @param tabContentManager A TabContentManager instance or {@code null} if the layer should not
+ * be attached to one.
+ * @param initiallyHidden true iff the tab being initialized is created in background
*/
- public void initialize() {
- initializeNative();
+ public void initialize(long nativeWebContents, TabContentManager tabContentManager,
+ boolean initiallyHidden) {
+ try {
+ TraceEvent.begin("Tab.initialize");
+ initializeNative();
Ted C 2015/01/02 18:14:45 this should go in internalInit per offline discuss
gone 2015/01/02 18:23:01 Done.
+ internalInit(tabContentManager);
+
+ if (getFrozenContentsState() == null && getPendingLoadParams() == null) {
+ boolean existingWebContents = nativeWebContents != 0;
+ // There is no frozen WebContents state or pending lazy load, create new
+ // WebContents.
+ if (nativeWebContents == 0) {
+ nativeWebContents =
+ ContentViewUtil.createNativeWebContents(isIncognito(), initiallyHidden);
+ }
+ initContentViewCore(nativeWebContents);
+ if (existingWebContents) {
+ WebContents webContents = getWebContents();
+ assert webContents != null;
+ if (webContents.isLoadingToDifferentDocument()) {
+ didStartPageLoad(webContents.getUrl(), false);
+ }
+ }
+ }
+ if (mTimestampMillis == INVALID_TIMESTAMP) {
+ mTimestampMillis = System.currentTimeMillis();
+ }
+ } finally {
+ TraceEvent.end("Tab.initialize");
+ }
+ }
+
Ted C 2015/01/02 18:14:45 Looks like an extra blank line here
gone 2015/01/02 18:23:01 Done.
+
+ /**
+ * Handles common post-construction initialization.
+ * @param contentViewCore ContentViewCore object to attach to the tab.
+ * @param tabContentManager A TabContentManager instance or {@code null} if the layer should not
+ * be attached to one.
+ */
+ public void initialize(ContentViewCore contentViewCore, TabContentManager tabContentManager) {
+ try {
+ TraceEvent.begin("Tab.initialize");
+ internalInit(tabContentManager);
+ setContentViewCore(contentViewCore);
+ if (mTimestampMillis == INVALID_TIMESTAMP) {
+ mTimestampMillis = System.currentTimeMillis();
+ }
+ } finally {
+ TraceEvent.end("Tab.initialize");
+ }
+ }
+
+ /**
+ * Perform any subclass-specific initialization tasks.
+ */
+ protected void internalInit(TabContentManager tabContentManager) {
+ }
+
+ /**
+ * Called when a page has started loading.
+ * @param validatedUrl URL being loaded.
+ * @param showingErrorPage Whether an error page is being shown.
+ */
+ protected void didStartPageLoad(String validatedUrl, boolean showingErrorPage) {
+ updateTitle();
+ removeSadTabIfPresent();
+ mInfoBarContainer.onPageStarted();
+
+ if (getContentViewCore() != null) {
+ getContentViewCore().stopCurrentAccessibilityNotifications();
+ }
+
+ clearHungRendererState();
+ }
+
+ /**
+ * Called when a page has finished loading.
+ */
+ protected void didFinishPageLoad() {
+ mIsTabStateDirty = true;
+ updateTitle();
+ updateFullscreenEnabledState();
}
/**
@@ -1095,7 +1240,7 @@ public class Tab {
* subclass native counterparts instead. Subclasses should not call this via super and instead
* rely on the native class to create the JNI association.
*/
- protected void initializeNative() {
+ public void initializeNative() {
Ted C 2015/01/02 18:14:45 make protected per offline discussion
gone 2015/01/02 18:23:01 Added TODO since DocumentTabModelImpl needs access
if (mNativeTabAndroid == 0) nativeInit();
assert mNativeTabAndroid != 0;
}
@@ -1235,6 +1380,9 @@ public class Tab {
* this method is called. Once this call is made this {@link Tab} should no longer be used.
*/
public void destroy() {
+ // Update the title before destroying the tab. http://b/5783092
+ updateTitle();
+
for (TabObserver observer : mObservers) observer.onDestroyed(this);
mObservers.clear();
@@ -1290,9 +1438,67 @@ public class Tab {
*/
@CalledByNative
public String getTitle() {
- if (mNativePage != null) return mNativePage.getTitle();
- if (getWebContents() != null) return getWebContents().getTitle();
- return "";
+ if (mTitle == null) updateTitle();
+ return mTitle;
+ }
+
+ private void updateTitle() {
+ if (isFrozen()) return;
+
+ // When restoring the tabs, the title will no longer be populated, so request it from the
+ // ContentViewCore or NativePage (if present).
+ String title = "";
+ if (mNativePage != null) title = mNativePage.getTitle();
+ if (getWebContents() != null) title = getWebContents().getTitle();
+ updateTitle(title);
+ }
+
+ /**
+ * Cache the title for the current page.
+ *
+ * {@link ContentViewClient#onUpdateTitle} is unreliable, particularly for navigating backwards
+ * and forwards in the history stack, so pull the correct title whenever the page changes.
+ * onUpdateTitle is only called when the title of a navigation entry changes. When the user goes
+ * back a page the navigation entry exists with the correct title, thus the title is not
+ * actually changed, and no notification is sent.
+ * @param title Title of the page.
+ */
+ private void updateTitle(String title) {
+ if (TextUtils.equals(mTitle, title)) return;
+
+ mIsTabStateDirty = true;
+ mTitle = title;
+ mIsTitleDirectionRtl = LocalizationUtils.getFirstStrongCharacterDirection(title)
+ == LocalizationUtils.RIGHT_TO_LEFT;
+ notifyPageTitleChanged();
+ }
+
+ protected void notifyPageTitleChanged() {
+ RewindableIterator<TabObserver> observers = getTabObservers();
+ while (observers.hasNext()) {
+ observers.next().onTitleUpdated(this);
+ }
+ }
+
+ protected void notifyFaviconChanged() {
+ RewindableIterator<TabObserver> observers = getTabObservers();
+ while (observers.hasNext()) {
+ observers.next().onFaviconUpdated(this);
+ }
+ }
+
+ private void notifyPageUrlChanged() {
+ RewindableIterator<TabObserver> observers = getTabObservers();
+ while (observers.hasNext()) {
+ observers.next().onUrlUpdated(this);
+ }
+ }
+
+ /**
+ * @return True if the tab title should be displayed from right to left.
+ */
+ public boolean isTitleDirectionRtl() {
+ return mIsTitleDirectionRtl;
}
/**
@@ -1493,10 +1699,15 @@ public class Tab {
mInfoBarContainer.removeFromParentView();
}
mContentViewCore.destroy();
-
mContentViewCore = null;
+
mWebContentsDelegate = null;
- mWebContentsObserver = null;
+
+ if (mWebContentsObserver != null) {
+ mWebContentsObserver.detachFromWebContents();
+ mWebContentsObserver = null;
+ }
+
mVoiceSearchTabHelper = null;
assert mNativeTabAndroid != 0;
@@ -1731,6 +1942,13 @@ public class Tab {
}
/**
+ * @return See {@link #mTimestampMillis}.
+ */
+ protected long getTimestampMillis() {
+ return mTimestampMillis;
+ }
+
+ /**
* Validates {@code id} and increments the internal counter to make sure future ids don't
* collide.
* @param id The current id. Maybe {@link #INVALID_TAB_ID}.

Powered by Google App Engine
This is Rietveld 408576698