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

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

Issue 1436743002: Integrate new Reader Mode panel (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@scene-layer-changes
Patch Set: Created 5 years, 1 month 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/dom_distiller/ReaderModeManager.java
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
index d1c7dfa4eac9fd9c97007e5d07f09ce1e94d2b61..891be760b3eb2ee428b9547196b3d4eebd2a4a3d 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/dom_distiller/ReaderModeManager.java
@@ -4,7 +4,6 @@
package org.chromium.chrome.browser.dom_distiller;
-import android.app.Activity;
import android.content.Context;
import android.text.TextUtils;
@@ -14,124 +13,223 @@ import org.chromium.base.metrics.RecordHistogram;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeActivity;
import org.chromium.chrome.browser.ChromeSwitches;
-import org.chromium.chrome.browser.contextualsearch.ContextualSearchManager;
-import org.chromium.chrome.browser.contextualsearch.ContextualSearchObserver;
-import org.chromium.chrome.browser.dom_distiller.ReaderModePanel.ReaderModePanelHost;
-import org.chromium.chrome.browser.gsa.GSAContextDisplaySelection;
+import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason;
+import org.chromium.chrome.browser.compositor.bottombar.readermode.ReaderModePanel;
import org.chromium.chrome.browser.infobar.InfoBar;
import org.chromium.chrome.browser.infobar.InfoBarContainer;
import org.chromium.chrome.browser.infobar.InfoBarContainer.InfoBarContainerObserver;
-import org.chromium.chrome.browser.tab.EmptyTabObserver;
import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
+import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver;
import org.chromium.components.dom_distiller.content.DistillablePageUtils;
import org.chromium.components.dom_distiller.core.DomDistillerUrlUtils;
+import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.WebContentsObserver;
import org.chromium.ui.base.DeviceFormFactor;
+import org.chromium.ui.base.PageTransition;
+
+import java.util.HashMap;
+import java.util.Map;
/**
* Manages UI effects for reader mode including hiding and showing the
* reader mode and reader mode preferences toolbar icon and hiding the
* top controls when a reader mode page has finished loading.
*/
-public class ReaderModeManager extends EmptyTabObserver
- implements ContextualSearchObserver, InfoBarContainerObserver, ReaderModePanelHost {
+public class ReaderModeManager extends TabModelSelectorTabObserver
+ implements InfoBarContainerObserver, ReaderModeManagerDelegate {
/**
- * Observer for changes to the current status of reader mode.
+ * URL scheme for dom-distiller.
*/
- public static interface ReaderModeManagerObserver {
- /**
- * Triggered on changes to the reader mode status for the owning tab.
- *
- * @param readerModeStatus The current status of reader mode.
- * @see ReaderModeManager#POSSIBLE
- * @see ReaderModeManager#NOT_POSSIBLE
- * @see ReaderModeManager#STARTED
- */
- void onReaderModeStatusChanged(int readerModeStatus);
- }
+ public static final String DOM_DISTILLER_SCHEME = "chrome-distiller";
/**
* POSSIBLE means reader mode can be entered.
*/
public static final int POSSIBLE = 0;
+
/**
* NOT_POSSIBLE means reader mode cannot be entered.
*/
public static final int NOT_POSSIBLE = 1;
+
/**
* STARTED means reader mode is currently in reader mode.
*/
public static final int STARTED = 2;
- /**
- * The url of the last page visited if the last page was reader mode page. Otherwise null.
- */
+ // The url of the last page visited if the last page was reader mode page. Otherwise null.
private String mReaderModePageUrl;
- /**
- * Whether the page is an article or not.
- */
- private int mReaderModeStatus = NOT_POSSIBLE;
+ // Whether the fact that the current web page was distillable or not has been recorded.
+ private boolean mIsUmaRecorded;
+
+ // The per-tab state of distillation.
+ private Map<Tab, ReaderModeTabInfo> mTabStatusMap;
David Trainor- moved to gerrit 2015/11/11 16:20:22 Can you just map id -> ReaderModeTabInfo? Would p
mdjones 2015/11/12 03:43:43 Done.
+
+ // The current tab. This will change as the user switches between tabs.
+ private Tab mTab;
David Trainor- moved to gerrit 2015/11/11 16:20:22 Do you need to hold this or can you query this on
mdjones 2015/11/12 03:43:43 Done.
+
+ // The ReaderModePanel that this class is managing.
+ private ReaderModePanel mReaderModePanel;
+
+ // The ChromeActivity that this panel exists in.
+ private ChromeActivity mChromeActivity;
/**
- * Whether the fact that the current web page was distillable or not has been recorded.
+ * This class tracks the tab state of reader mode.
*/
- private boolean mIsUmaRecorded;
+ private static class ReaderModeTabInfo {
aurimas (slooooooooow) 2015/11/11 19:00:39 I think it would be fine pulling this out into a s
mdjones 2015/11/12 03:43:44 Done.
+ // The WebContentsObserver responsible for updates to the distillation status of the tab.
+ private WebContentsObserver mWebContentsObserver;
- private WebContentsObserver mWebContentsObserver;
+ // The distillation status of the tab.
+ private int mStatus;
- private final Tab mTab;
+ // If the panel was closed due to the close button.
+ private boolean mIsDismissed;
- private final ReaderModePanel mReaderModePanel;
+ // The URL that distiller is using for this tab. This is used to check if a result comes
+ // back from distiller and the user has already loaded a new URL.
+ private String mCurrentUrl;
- private final int mHeaderBackgroundColor;
+ public void setWebContentsObserver(WebContentsObserver observer) {
+ mWebContentsObserver = observer;
+ }
- public ReaderModeManager(Tab tab, Context context) {
- mTab = tab;
- mTab.addObserver(this);
- mReaderModePanel = isEnabled(context) ? new ReaderModePanel(this, context) : null;
- mHeaderBackgroundColor = context != null
+ public WebContentsObserver getWebContentsObserver() {
+ return mWebContentsObserver;
+ }
+
+ public void setStatus(int status) {
+ mStatus = status;
+ }
+
+ public int getStatus() {
+ return mStatus;
+ }
+
+ public boolean isDismissed() {
+ return mIsDismissed;
+ }
+
+ public void setIsDismissed(boolean dismissed) {
+ mIsDismissed = dismissed;
+ }
+
+ public void setUrl(String url) {
+ mCurrentUrl = url;
+ }
+
+ public String getUrl() {
+ return mCurrentUrl;
+ }
+ }
+
+ private final int mHeaderBackgroundColor;
+ private boolean mIsFullscreenModeEntered;
+ private boolean mIsInfobarContainerShown;
+
+ public ReaderModeManager(TabModelSelector selector, ChromeActivity activity) {
+ super(selector);
+ mChromeActivity = activity;
+ mTabStatusMap = new HashMap<>();
+ mHeaderBackgroundColor = activity != null
? ApiCompatibilityUtils.getColor(
- context.getResources(), R.color.reader_mode_header_bg)
+ activity.getResources(), R.color.reader_mode_header_bg)
: 0;
}
- // EmptyTabObserver:
+ // TabModelSelectorTabObserver:
+
@Override
- public void onDestroyed(Tab tab) {
- ContextualSearchManager contextualSearchManager = getContextualSearchManager(tab);
- if (contextualSearchManager != null) contextualSearchManager.removeObserver(this);
+ public void onShown(Tab tab) {
+ // If the reader panel was dismissed, stop here.
+ if (mTabStatusMap.containsKey(mTab) && mTabStatusMap.get(mTab).isDismissed()) return;
- if (mTab.getInfoBarContainer() != null) mTab.getInfoBarContainer().removeObserver(this);
+ // Remove the infobar observer from the previous tab and attach it to the current one.
+ if (mTab != null && mTab.getInfoBarContainer() != null) {
+ mTab.getInfoBarContainer().removeObserver(this);
+ }
+
+ // Only perform operations on the currently active tab.
+ mTab = tab;
+ if (mTab.getInfoBarContainer() != null) {
+ mTab.getInfoBarContainer().addObserver(this);
+ }
+
+ // If there is no state info for this tab, create it.
+ ReaderModeTabInfo tabInfo = mTabStatusMap.get(mTab);
+ if (tabInfo == null) {
+ tabInfo = new ReaderModeTabInfo();
+ tabInfo.setStatus(NOT_POSSIBLE);
+ tabInfo.setUrl(mTab.getUrl());
+ mTabStatusMap.put(mTab, tabInfo);
+ }
- if (mReaderModePanel != null) mReaderModePanel.onDestroy();
+ // Make sure there is a WebContentsObserver on this tab's WebContents.
+ if (tabInfo.getWebContentsObserver() == null) {
+ tabInfo.setWebContentsObserver(createWebContentsObserver(mTab.getWebContents()));
+ }
+
+ requestReaderPanelShow(StateChangeReason.UNKNOWN);
+ }
+
+ @Override
+ public void onHidden(Tab tab) {
+ mReaderModePanel.closePanel(StateChangeReason.UNKNOWN, false);
+ }
- if (mWebContentsObserver != null) {
- mWebContentsObserver.destroy();
- mWebContentsObserver = null;
+ @Override
+ public void onDestroyed(Tab tab) {
David Trainor- moved to gerrit 2015/11/11 16:20:22 if (mTab == tab) { // clean up mTab and associated
mdjones 2015/11/12 03:43:43 No longer storing a tab object in this class (usin
+ if (tab.getInfoBarContainer() != null) {
+ tab.getInfoBarContainer().removeObserver(this);
}
+ removeTabState(tab);
+ }
- destroyReaderModeControl();
+ /**
+ * Clean up the state associated with a tab.
+ * @param tab The target tab.
+ */
+ private void removeTabState(Tab tab) {
+ if (!mTabStatusMap.containsKey(tab)) return;
+ ReaderModeTabInfo tabInfo = mTabStatusMap.get(tab);
+ if (tabInfo.getWebContentsObserver() != null) {
+ tabInfo.getWebContentsObserver().destroy();
+ }
+ mTabStatusMap.remove(tab);
}
@Override
public void onContentChanged(Tab tab) {
- if (mWebContentsObserver != null) {
- mWebContentsObserver.destroy();
- mWebContentsObserver = null;
+ // Only listen to events on the currently active tab.
+ if (tab != mTab) return;
+
+ if (mTabStatusMap.containsKey(mTab)) {
+ // If the panel was closed using the "x" icon, don't show it again for this tab.
+ if (mTabStatusMap.get(mTab).isDismissed()) return;
+ removeTabState(mTab);
}
+
+ ReaderModeTabInfo tabInfo = new ReaderModeTabInfo();
+ tabInfo.setStatus(NOT_POSSIBLE);
+ tabInfo.setUrl(tab.getUrl());
+ mTabStatusMap.put(tab, tabInfo);
+
if (tab.getWebContents() != null) {
- mWebContentsObserver = createWebContentsObserver(tab.getWebContents());
+ tabInfo.setWebContentsObserver(createWebContentsObserver(tab.getWebContents()));
David Trainor- moved to gerrit 2015/11/11 16:20:22 Do you have to destroy the old observer?
mdjones 2015/11/12 03:43:43 Not necessarily; I think it makes sense to destroy
if (DomDistillerUrlUtils.isDistilledPage(tab.getUrl())) {
- mReaderModeStatus = STARTED;
+ tabInfo.setStatus(STARTED);
+ tabInfo.setWebContentsObserver(tabInfo.getWebContentsObserver());
mReaderModePageUrl = tab.getUrl();
- if (mReaderModePanel != null) mReaderModePanel.updateBottomButtonBar();
+ mReaderModePanel.closePanel(StateChangeReason.CONTENT_CHANGED, true);
}
}
- ContextualSearchManager contextualSearchManager = getContextualSearchManager(tab);
- if (contextualSearchManager != null) contextualSearchManager.addObserver(this);
if (tab.getInfoBarContainer() != null) tab.getInfoBarContainer().addObserver(this);
}
@@ -140,36 +238,37 @@ public class ReaderModeManager extends EmptyTabObserver
public void onToggleFullscreenMode(Tab tab, boolean enable) {
if (mReaderModePanel == null) return;
+ // Temporarily hide the reader mode panel while a video is shown.
David Trainor- moved to gerrit 2015/11/11 16:20:22 might not be a video. could be HTML5 fullscreen A
mdjones 2015/11/12 03:43:44 Done.
if (enable) {
- mReaderModePanel.onEnterFullscreen();
+ mIsFullscreenModeEntered = true;
+ mReaderModePanel.closePanel(StateChangeReason.FULLSCREEN_ENTERED, false);
} else {
- mReaderModePanel.onExitFullscreen();
+ mIsFullscreenModeEntered = false;
+ requestReaderPanelShow(StateChangeReason.FULLSCREEN_EXITED);
}
}
- // ContextualSearchObserver:
- @Override
- public void onShowContextualSearch(GSAContextDisplaySelection selectionContext) {
- if (mReaderModePanel != null) mReaderModePanel.hideButtonBar();
- }
-
- @Override
- public void onHideContextualSearch() {
- if (mReaderModePanel != null) mReaderModePanel.unhideButtonBar();
- }
-
// InfoBarContainerObserver:
+
@Override
public void onAddInfoBar(InfoBarContainer container, InfoBar infoBar, boolean isFirst) {
- if (isFirst && mReaderModePanel != null) mReaderModePanel.onShowInfobarContainer();
+ // Temporarily hides the reader mode button while the infobars are shown.
+ if (isFirst && mReaderModePanel != null) {
+ mIsInfobarContainerShown = true;
+ mReaderModePanel.closePanel(StateChangeReason.INFOBAR_SHOWN, false);
+ }
}
@Override
public void onRemoveInfoBar(InfoBarContainer container, InfoBar infoBar, boolean isLast) {
- if (isLast && mReaderModePanel != null) mReaderModePanel.onHideInfobarContainer();
+ // Re-shows the reader mode button if necessary once the infobars are dismissed.
+ if (isLast && mReaderModePanel != null && !mIsFullscreenModeEntered) {
+ mIsInfobarContainerShown = false;
+ requestReaderPanelShow(StateChangeReason.INFOBAR_HIDDEN);
+ }
}
- // ReaderModePanelHost:
+ // ReaderModeManagerDelegate:
@Override
public int getReaderModeHeaderBackgroundColor() {
@@ -178,50 +277,45 @@ public class ReaderModeManager extends EmptyTabObserver
@Override
public int getReaderModeStatus() {
- return mReaderModeStatus;
+ if (!mTabStatusMap.containsKey(mTab)) return NOT_POSSIBLE;
+ return mTabStatusMap.get(mTab).getStatus();
}
@Override
- public Tab getTab() {
- return mTab;
+ public void setReaderModePanel(ReaderModePanel panel) {
+ mReaderModePanel = panel;
}
@Override
- public boolean isInsideDismissButton(float x, float y) {
- ReaderModeActivityDelegate delegate = getReaderModeActivityDelegate();
- if (delegate == null) return false;
- return delegate.getReaderModeControl().isInsideDismissButton(x, y);
+ public ChromeActivity getChromeActivity() {
+ return mChromeActivity;
}
@Override
- public void createReaderModeControl() {
- ReaderModeActivityDelegate delegate = getReaderModeActivityDelegate();
- if (delegate != null) delegate.getReaderModeControl();
+ public void onCloseButtonPressed() {
+ if (!mTabStatusMap.containsKey(mTab)) return;
+ ReaderModeTabInfo tabInfo = mTabStatusMap.get(mTab);
+ tabInfo.setIsDismissed(true);
+ if (tabInfo.getWebContentsObserver() != null) {
+ tabInfo.getWebContentsObserver().destroy();
+ }
}
@Override
- public void destroyReaderModeControl() {
- ReaderModeActivityDelegate delegate = getReaderModeActivityDelegate();
- if (delegate != null) delegate.destroyReaderModeControl();
- }
-
- /**
- * @return The panel associated with the managed tab.
- */
- public ReaderModePanel getReaderModePanel() {
- return mReaderModePanel;
- }
-
- private ReaderModeActivityDelegate getReaderModeActivityDelegate() {
- return mTab.getReaderModeActivityDelegate();
+ public void onPanelPeek() {
+ String distillerUrl = DomDistillerUrlUtils.getDistillerViewUrlFromUrl(
+ DOM_DISTILLER_SCHEME, mTab.getUrl());
+ // Load the distilled page URL when the visibility of the panel changes.
+ mReaderModePanel.loadUrlInPanel(distillerUrl, false);
}
private WebContentsObserver createWebContentsObserver(WebContents webContents) {
+ final Tab mCurrentTab = mTab;
David Trainor- moved to gerrit 2015/11/11 16:20:22 Don't prefix with m. Storing a strong reference t
mdjones 2015/11/12 03:43:43 I chose to store the ID; unit tests are in the wor
return new WebContentsObserver(webContents) {
@Override
public void didFinishLoad(long frameId, String validatedUrl, boolean isMainFrame) {
if (!isMainFrame) return;
- if (DomDistillerUrlUtils.isDistilledPage(mTab.getUrl())) return;
+ if (DomDistillerUrlUtils.isDistilledPage(mCurrentTab.getUrl())) return;
updateStatusBasedOnReaderModeCriteria(true);
}
@@ -229,7 +323,7 @@ public class ReaderModeManager extends EmptyTabObserver
public void didFailLoad(boolean isProvisionalLoad, boolean isMainFrame, int errorCode,
String description, String failingUrl, boolean wasIgnoredByHandler) {
if (!isMainFrame) return;
- if (DomDistillerUrlUtils.isDistilledPage(mTab.getUrl())) return;
+ if (DomDistillerUrlUtils.isDistilledPage(mCurrentTab.getUrl())) return;
updateStatusBasedOnReaderModeCriteria(true);
}
@@ -238,9 +332,10 @@ public class ReaderModeManager extends EmptyTabObserver
boolean isMainFrame, String validatedUrl, boolean isErrorPage,
boolean isIframeSrcdoc) {
if (!isMainFrame) return;
+ mTabStatusMap.get(mTab).setUrl(validatedUrl);
if (DomDistillerUrlUtils.isDistilledPage(validatedUrl)) {
- mReaderModeStatus = STARTED;
- if (mReaderModePanel != null) mReaderModePanel.updateBottomButtonBar();
+ mTabStatusMap.get(mCurrentTab).setStatus(STARTED);
+ mReaderModePanel.closePanel(StateChangeReason.UNKNOWN, true);
mReaderModePageUrl = validatedUrl;
}
}
@@ -254,53 +349,102 @@ public class ReaderModeManager extends EmptyTabObserver
if (isNavigationInPage) return;
if (DomDistillerUrlUtils.isDistilledPage(url)) return;
- mReaderModeStatus = POSSIBLE;
+ mTabStatusMap.get(mCurrentTab).setStatus(POSSIBLE);
if (!TextUtils.equals(url,
DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(
mReaderModePageUrl))) {
- mReaderModeStatus = NOT_POSSIBLE;
+ mTabStatusMap.get(mCurrentTab).setStatus(NOT_POSSIBLE);
mIsUmaRecorded = false;
// Do not call updateStatusBasedOnReaderModeCriteria here.
// For ADABOOST_MODEL, it is unlikely to get valid info at this event.
}
mReaderModePageUrl = null;
- if (mReaderModePanel != null) mReaderModePanel.updateBottomButtonBar();
+ if (mTabStatusMap.containsKey(mCurrentTab)
+ && mTabStatusMap.get(mCurrentTab).getStatus() != POSSIBLE) {
+ mReaderModePanel.closePanel(StateChangeReason.UNKNOWN, false);
+ } else {
+ requestReaderPanelShow(StateChangeReason.UNKNOWN);
+ }
}
};
}
+ /**
+ * This is a wrapper for "requestPanelShow" that checks if reader mode is possible before
+ * showing.
+ * @param reason The reason the panel is requesting to be shown.
+ */
+ private void requestReaderPanelShow(StateChangeReason reason) {
+ if (mReaderModePanel == null || mTab == null || !mTabStatusMap.containsKey(mTab)
+ || mTabStatusMap.get(mTab).getStatus() == NOT_POSSIBLE
+ || mTabStatusMap.get(mTab).isDismissed()) {
+ return;
+ }
+ mReaderModePanel.requestPanelShow(reason);
+ }
+
+ /**
+ * Orientation change event handler. Simply close the panel.
+ */
+ public void onOrientationChange() {
+ if (mReaderModePanel == null || mIsFullscreenModeEntered) return;
+ mReaderModePanel.closePanel(StateChangeReason.UNKNOWN, false);
+ requestReaderPanelShow(StateChangeReason.UNKNOWN);
+ }
+
+ /**
+ * Open a link from the panel in a new tab.
+ * @param url The URL to load.
+ */
+ public void createNewTab(String url) {
+ if (mTab == null || mChromeActivity == null) return;
+
+ TabCreatorManager.TabCreator tabCreator =
+ mChromeActivity.getTabCreator(mTab.isIncognito());
+ if (tabCreator == null) return;
+
+ tabCreator.createNewTab(new LoadUrlParams(url, PageTransition.LINK),
+ TabModel.TabLaunchType.FROM_LINK, mChromeActivity.getActivityTab());
+ }
+
// Updates reader mode status based on whether or not the page should be viewed in reader mode.
private void updateStatusBasedOnReaderModeCriteria(final boolean forceRecord) {
if (mTab.getWebContents() == null) return;
if (mTab.getContentViewCore() == null) return;
+ final Tab mCurrentTab = mTab;
David Trainor- moved to gerrit 2015/11/11 16:20:22 Don't prefix with m for a local var.
mdjones 2015/11/12 03:43:44 Done.
DistillablePageUtils.isPageDistillable(mTab.getWebContents(),
mTab.getContentViewCore().getIsMobileOptimizedHint(),
new DistillablePageUtils.PageDistillableCallback() {
@Override
public void onIsPageDistillableResult(boolean isDistillable) {
+ if (!mTabStatusMap.containsKey(mCurrentTab)) return;
+ ReaderModeTabInfo tabInfo = mTabStatusMap.get(mCurrentTab);
+
+ // Make sure the page didn't navigate while waiting for a response.
+ if (!mCurrentTab.getUrl().equals(tabInfo.getUrl())) return;
+
if (isDistillable) {
- mReaderModeStatus = POSSIBLE;
+ tabInfo.setStatus(POSSIBLE);
+ // The user may have changed tabs.
+ if (mCurrentTab == mTab) {
+ // TODO(mdjones): Add reason DISTILLER_STATE_CHANGE.
+ requestReaderPanelShow(StateChangeReason.UNKNOWN);
+ }
} else {
- mReaderModeStatus = NOT_POSSIBLE;
+ tabInfo.setStatus(NOT_POSSIBLE);
}
- if (!mIsUmaRecorded && (mReaderModeStatus == POSSIBLE || forceRecord)) {
+ if (!mIsUmaRecorded
+ && (tabInfo.getStatus() == POSSIBLE || forceRecord)) {
mIsUmaRecorded = true;
RecordHistogram.recordBooleanHistogram(
- "DomDistiller.PageDistillable", mReaderModeStatus == POSSIBLE);
+ "DomDistiller.PageDistillable",
+ tabInfo.getStatus() == POSSIBLE);
}
- if (mReaderModePanel != null) mReaderModePanel.updateBottomButtonBar();
}
});
}
- private ContextualSearchManager getContextualSearchManager(Tab tab) {
- if (tab == null || tab.getWindowAndroid() == null) return null;
- Activity activity = tab.getWindowAndroid().getActivity().get();
- if (!(activity instanceof ChromeActivity)) return null;
- return ((ChromeActivity) activity).getContextualSearchManager();
- }
-
/**
* @return Whether Reader mode and its new UI are enabled.
* @param context A context

Powered by Google App Engine
This is Rietveld 408576698