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

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: findbugs and low-end devices 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..db6840cbe8ba356be7b13afe0c77aa46e9d4d596 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,134 +4,208 @@
package org.chromium.chrome.browser.dom_distiller;
-import android.app.Activity;
import android.content.Context;
import android.text.TextUtils;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.base.CommandLine;
+import org.chromium.base.SysUtils;
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.
- */
+ // Whether the fact that the current web page was distillable or not has been recorded.
private boolean mIsUmaRecorded;
- private WebContentsObserver mWebContentsObserver;
+ // The per-tab state of distillation.
+ private Map<Integer, ReaderModeTabInfo> mTabStatusMap;
- private final Tab mTab;
+ // The current tab ID. This will change as the user switches between tabs.
+ private int mTabId;
- private final ReaderModePanel mReaderModePanel;
+ // The ReaderModePanel that this class is managing.
+ private ReaderModePanel mReaderModePanel;
- private final int mHeaderBackgroundColor;
+ // The ChromeActivity that this panel exists in.
+ private ChromeActivity mChromeActivity;
+
+ // The primary means of getting the currently active tab.
+ private TabModelSelector mTabModelSelector;
- public ReaderModeManager(Tab tab, Context context) {
- mTab = tab;
- mTab.addObserver(this);
- mReaderModePanel = isEnabled(context) ? new ReaderModePanel(this, context) : null;
- mHeaderBackgroundColor = context != null
+ private final int mHeaderBackgroundColor;
+ private boolean mIsFullscreenModeEntered;
+ private boolean mIsInfobarContainerShown;
+
+ public ReaderModeManager(TabModelSelector selector, ChromeActivity activity) {
+ super(selector);
+ mTabId = Tab.INVALID_TAB_ID;
+ mTabModelSelector = 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:
+ /**
+ * Clear the status map and references to other objects.
+ */
+ public void destroy() {
+ for (Map.Entry<Integer, ReaderModeTabInfo> e : mTabStatusMap.entrySet()) {
+ if (e.getValue().getWebContentsObserver() != null) {
+ e.getValue().getWebContentsObserver().destroy();
+ }
+ }
+ mTabStatusMap.clear();
+ mChromeActivity = null;
+ mReaderModePanel = null;
+ mTabModelSelector = null;
+ }
+
+ // TabModelSelectorTabObserver:
+
@Override
- public void onDestroyed(Tab tab) {
- ContextualSearchManager contextualSearchManager = getContextualSearchManager(tab);
- if (contextualSearchManager != null) contextualSearchManager.removeObserver(this);
+ public void onShown(Tab shownTab) {
+ int shownTabId = shownTab.getId();
- if (mTab.getInfoBarContainer() != null) mTab.getInfoBarContainer().removeObserver(this);
+ Tab previousTab = mTabModelSelector.getTabById(mTabId);
+ mTabId = shownTabId;
- if (mReaderModePanel != null) mReaderModePanel.onDestroy();
+ // If the reader panel was dismissed, stop here.
+ if (mTabStatusMap.containsKey(shownTabId)
+ && mTabStatusMap.get(shownTabId).isDismissed()) {
+ return;
+ }
+
+ // Remove the infobar observer from the previous tab and attach it to the current one.
+ if (previousTab != null && previousTab.getInfoBarContainer() != null) {
+ previousTab.getInfoBarContainer().removeObserver(this);
+ }
+
+ if (shownTab.getInfoBarContainer() != null) {
+ shownTab.getInfoBarContainer().addObserver(this);
+ }
+
+ // If there is no state info for this tab, create it.
+ ReaderModeTabInfo tabInfo = mTabStatusMap.get(shownTabId);
+ if (tabInfo == null) {
+ tabInfo = new ReaderModeTabInfo();
+ tabInfo.setStatus(NOT_POSSIBLE);
+ tabInfo.setUrl(shownTab.getUrl());
+ mTabStatusMap.put(shownTabId, tabInfo);
+ }
+
+ // Make sure there is a WebContentsObserver on this tab's WebContents.
+ if (tabInfo.getWebContentsObserver() == null) {
+ tabInfo.setWebContentsObserver(createWebContentsObserver(shownTab.getWebContents()));
+ }
+
+ requestReaderPanelShow(StateChangeReason.UNKNOWN);
+ }
- if (mWebContentsObserver != null) {
- mWebContentsObserver.destroy();
- mWebContentsObserver = null;
+ @Override
+ public void onHidden(Tab tab) {
+ mReaderModePanel.closePanel(StateChangeReason.UNKNOWN, false);
+ }
+
+ @Override
+ public void onDestroyed(Tab tab) {
+ if (tab.getInfoBarContainer() != null) {
+ tab.getInfoBarContainer().removeObserver(this);
}
+ removeTabState(tab.getId());
+ }
- destroyReaderModeControl();
+ /**
+ * Clean up the state associated with a tab.
+ * @param tabId The target tab ID.
+ */
+ private void removeTabState(int tabId) {
+ if (!mTabStatusMap.containsKey(tabId)) return;
+ ReaderModeTabInfo tabInfo = mTabStatusMap.get(tabId);
+ if (tabInfo.getWebContentsObserver() != null) {
+ tabInfo.getWebContentsObserver().destroy();
+ }
+ mTabStatusMap.remove(tabId);
}
@Override
public void onContentChanged(Tab tab) {
- if (mWebContentsObserver != null) {
- mWebContentsObserver.destroy();
- mWebContentsObserver = null;
+ // Only listen to events on the currently active tab.
+ if (tab.getId() != mTabId) return;
+
+ if (mTabStatusMap.containsKey(mTabId)) {
+ // If the panel was closed using the "x" icon, don't show it again for this tab.
+ if (mTabStatusMap.get(mTabId).isDismissed()) return;
+ removeTabState(mTabId);
}
+
+ ReaderModeTabInfo tabInfo = new ReaderModeTabInfo();
+ tabInfo.setStatus(NOT_POSSIBLE);
+ tabInfo.setUrl(tab.getUrl());
+ mTabStatusMap.put(tab.getId(), tabInfo);
+
if (tab.getWebContents() != null) {
- mWebContentsObserver = createWebContentsObserver(tab.getWebContents());
+ tabInfo.setWebContentsObserver(createWebContentsObserver(tab.getWebContents()));
if (DomDistillerUrlUtils.isDistilledPage(tab.getUrl())) {
- mReaderModeStatus = STARTED;
+ tabInfo.setStatus(STARTED);
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 +214,37 @@ public class ReaderModeManager extends EmptyTabObserver
public void onToggleFullscreenMode(Tab tab, boolean enable) {
if (mReaderModePanel == null) return;
+ // Temporarily hide the reader mode panel while fullscreen is enabled.
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) {
+ mIsInfobarContainerShown = false;
+ requestReaderPanelShow(StateChangeReason.INFOBAR_HIDDEN);
+ }
}
- // ReaderModePanelHost:
+ // ReaderModeManagerDelegate:
@Override
public int getReaderModeHeaderBackgroundColor() {
@@ -178,50 +253,56 @@ public class ReaderModeManager extends EmptyTabObserver
@Override
public int getReaderModeStatus() {
- return mReaderModeStatus;
- }
+ int currentTabId = mTabModelSelector.getCurrentTabId();
+ if (currentTabId == Tab.INVALID_TAB_ID) return NOT_POSSIBLE;
- @Override
- public Tab getTab() {
- return mTab;
+ if (!mTabStatusMap.containsKey(currentTabId)) return NOT_POSSIBLE;
+ return mTabStatusMap.get(currentTabId).getStatus();
}
@Override
- public boolean isInsideDismissButton(float x, float y) {
- ReaderModeActivityDelegate delegate = getReaderModeActivityDelegate();
- if (delegate == null) return false;
- return delegate.getReaderModeControl().isInsideDismissButton(x, y);
+ public void setReaderModePanel(ReaderModePanel panel) {
+ mReaderModePanel = panel;
}
@Override
- public void createReaderModeControl() {
- ReaderModeActivityDelegate delegate = getReaderModeActivityDelegate();
- if (delegate != null) delegate.getReaderModeControl();
+ public ChromeActivity getChromeActivity() {
+ return mChromeActivity;
}
@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;
+ public void onCloseButtonPressed() {
+ int currentTabId = mTabModelSelector.getCurrentTabId();
+ if (currentTabId == Tab.INVALID_TAB_ID) return;
+
+ if (!mTabStatusMap.containsKey(currentTabId)) return;
+ ReaderModeTabInfo tabInfo = mTabStatusMap.get(currentTabId);
+ tabInfo.setIsDismissed(true);
+ if (tabInfo.getWebContentsObserver() != null) {
+ tabInfo.getWebContentsObserver().destroy();
+ }
}
- private ReaderModeActivityDelegate getReaderModeActivityDelegate() {
- return mTab.getReaderModeActivityDelegate();
+ @Override
+ public void onPanelPeek() {
+ String distillerUrl = DomDistillerUrlUtils.getDistillerViewUrlFromUrl(
+ DOM_DISTILLER_SCHEME, mTabModelSelector.getCurrentTab().getUrl());
+ // Load the distilled page URL when the visibility of the panel changes.
+ mReaderModePanel.loadUrlInPanel(distillerUrl, false);
}
private WebContentsObserver createWebContentsObserver(WebContents webContents) {
+ final int readerTabId = mTabModelSelector.getCurrentTabId();
+ if (readerTabId == Tab.INVALID_TAB_ID) return null;
+
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(
+ mTabModelSelector.getTabById(readerTabId).getUrl())) {
+ return;
+ }
updateStatusBasedOnReaderModeCriteria(true);
}
@@ -229,7 +310,10 @@ 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(
+ mTabModelSelector.getTabById(readerTabId).getUrl())) {
+ return;
+ }
updateStatusBasedOnReaderModeCriteria(true);
}
@@ -238,9 +322,10 @@ public class ReaderModeManager extends EmptyTabObserver
boolean isMainFrame, String validatedUrl, boolean isErrorPage,
boolean isIframeSrcdoc) {
if (!isMainFrame) return;
+ mTabStatusMap.get(readerTabId).setUrl(validatedUrl);
if (DomDistillerUrlUtils.isDistilledPage(validatedUrl)) {
- mReaderModeStatus = STARTED;
- if (mReaderModePanel != null) mReaderModePanel.updateBottomButtonBar();
+ mTabStatusMap.get(readerTabId).setStatus(STARTED);
+ mReaderModePanel.closePanel(StateChangeReason.UNKNOWN, true);
mReaderModePageUrl = validatedUrl;
}
}
@@ -254,53 +339,115 @@ public class ReaderModeManager extends EmptyTabObserver
if (isNavigationInPage) return;
if (DomDistillerUrlUtils.isDistilledPage(url)) return;
- mReaderModeStatus = POSSIBLE;
+ mTabStatusMap.get(readerTabId).setStatus(POSSIBLE);
if (!TextUtils.equals(url,
DomDistillerUrlUtils.getOriginalUrlFromDistillerUrl(
mReaderModePageUrl))) {
- mReaderModeStatus = NOT_POSSIBLE;
+ mTabStatusMap.get(readerTabId).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(readerTabId)
+ && mTabStatusMap.get(readerTabId).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) {
+ int currentTabId = mTabModelSelector.getCurrentTabId();
+ if (currentTabId == Tab.INVALID_TAB_ID) return;
+
+ if (mReaderModePanel == null || !mTabStatusMap.containsKey(currentTabId)
+ || mTabStatusMap.get(currentTabId).getStatus() == NOT_POSSIBLE
+ || mTabStatusMap.get(currentTabId).isDismissed()
+ || mIsInfobarContainerShown
+ || mIsFullscreenModeEntered) {
+ return;
+ }
+ mReaderModePanel.requestPanelShow(reason);
+ }
+
+ /**
+ * Orientation change event handler. Simply close the panel.
+ */
+ public void onOrientationChange() {
+ if (mReaderModePanel == null) return;
+ // Close to reset the panel then immediately show again.
+ 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 (mChromeActivity == null) return;
+
+ Tab currentTab = mTabModelSelector.getCurrentTab();
+ if (currentTab == null) return;
+
+ TabCreatorManager.TabCreator tabCreator =
+ mChromeActivity.getTabCreator(currentTab.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;
+ Tab currentTab = mTabModelSelector.getCurrentTab();
+ if (currentTab == null || currentTab.getWebContents() == null
+ || currentTab.getContentViewCore() == null) {
+ return;
+ }
- DistillablePageUtils.isPageDistillable(mTab.getWebContents(),
- mTab.getContentViewCore().getIsMobileOptimizedHint(),
+ final int readerTabId = currentTab.getId();
+ DistillablePageUtils.isPageDistillable(currentTab.getWebContents(),
+ currentTab.getContentViewCore().getIsMobileOptimizedHint(),
new DistillablePageUtils.PageDistillableCallback() {
@Override
public void onIsPageDistillableResult(boolean isDistillable) {
+ if (!mTabStatusMap.containsKey(readerTabId)) return;
+ ReaderModeTabInfo tabInfo = mTabStatusMap.get(readerTabId);
+
+ Tab readerTab = mTabModelSelector.getTabById(readerTabId);
+ // Make sure the page didn't navigate while waiting for a response.
+ if (!readerTab.getUrl().equals(tabInfo.getUrl())) return;
+
if (isDistillable) {
- mReaderModeStatus = POSSIBLE;
+ tabInfo.setStatus(POSSIBLE);
+ // The user may have changed tabs.
+ if (readerTabId == mTabModelSelector.getCurrentTabId()) {
+ // 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
@@ -312,7 +459,8 @@ public class ReaderModeManager extends EmptyTabObserver
&& !CommandLine.getInstance().hasSwitch(
ChromeSwitches.DISABLE_READER_MODE_BOTTOM_BAR)
&& !DeviceFormFactor.isTablet(context)
- && DomDistillerTabUtils.isDistillerHeuristicsEnabled();
+ && DomDistillerTabUtils.isDistillerHeuristicsEnabled()
+ && !SysUtils.isLowEndDevice();
return enabled;
}
}

Powered by Google App Engine
This is Rietveld 408576698